You are here

mass_contact.module in Mass Contact 7

This is the main code file for the Mass Contact module.

This is primarily where all the hooks are implemented.

File

mass_contact.module
View source
<?php

/**
 * @file
 * This is the main code file for the Mass Contact module.
 *
 * This is primarily where all the hooks are implemented.
 */

/**
 * Implements hook_help().
 */
function mass_contact_help($path, $arg) {
  $output = '';
  switch ($path) {
    case 'admin/help#mass_contact':
      $output .= '<h3>' . t('Related tasks:') . '</h3><ul><li>' . l(t('Configure the module'), 'admin/config/system/mass_contact/settings') . '</li><li>' . l(t('Add new category'), 'admin/config/system/mass_contact/add') . '</li><li>' . l(t('List current categories'), 'admin/config/system/mass_contact') . '</li><li>' . l(t('Set permissions'), 'admin/people/permissions', array(
        'fragment' => 'module-mass_contact',
      )) . '</li><li>' . l(t('Send a mass email message'), 'mass_contact') . '</li></ul>';
      $output .= '<h3>' . t('Configuration and setup') . '</h3>';
      $output .= '<p>' . t('While an attempt has been made at setting sensible defaults, the configuration should be reviewed and tweaked before sending any messages.') . '</p>';
      $output .= '<p>' . t('Before sending any mass email messages, at least one category needs to be created, which can be done at the same location where the administrative settings are.') . '</p>';
      $output .= '<p>' . t("By default, the email messages are sent as plain text. If the Mime Mail module is enabled, the email messages may be sent as HTML and may include one or more binary file attachments (if permitted by admin).") . '</p>';
      $output .= '<h3>' . t('Miscelaneous information') . '</h3>';
      $output .= '<p>' . t("This module works by sending a single email to your mail server with all of the recipients' email addresses in either the 'To:' or 'Bcc:' field. The mail server is then responsible for parsing out the recipients' addresses and forwarding the message along to everyone.") . '</p>';
      $output .= '<p>' . t("When using the Bcc option, recipients are not potentially left open to abuse due to their email addresses being visible to all other recipients.") . '</p>';
      $output .= '<h3>' . t('Menu structure') . '</h3>';
      $output .= '<p>' . t('Here is a description of the menu items and links Mass Contact provides:') . '</p>';
      $output .= '<table><thead>';
      $output .= '<tr><th>' . t('URL') . '</th><th>' . t('Label') . '</th><th>' . t('Description') . '</th><th>' . t('To have access to this URL, users must have this permission') . '</th></tr></thead>';
      $output .= '<tbody><tr><td>' . t('/admin/config/system/mass_contact') . '</td><td>' . t('Mass Contact') . '</td><td>' . t('The main administrative interface, which defaults to the Category listing page.') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/admin/config/system/mass_contact/list') . '</td><td>' . t('Category list') . '</td><td>' . t('List the currently defined categories.') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/admin/config/system/mass_contact/add') . '</td><td>' . t('Add category') . '</td><td>' . t('Add a new category.') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/admin/config/system/mass_contact/edit/$category_id') . '</td><td>' . t("Edit Mass Contact category (the 'edit' operation in the Category list)") . '</td><td>' . t('Edit an existing category') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/admin/config/system/mass_contact/delete/$category_id') . '</td><td>' . t("Delete Mass Contact category (the 'delete' operation in the Category list)") . '</td><td>' . t('Delete an existing category.') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/admin/config/system/mass_contact/settings') . '</td><td>' . t('Settings') . '</td><td>' . t('Administrative settings to modify how Mass Contact operates. There are three sub pages under this one: Miscellaneous, Message header and Message body.') . '</td><td>' . t('administer mass contact') . '</td></tr>';
      $output .= '<tr><td>' . t('/mass_contact') . '</td><td>' . t('Mass Contact') . '</td><td>' . t('The main Mass Contact form for sending messages.') . '</td><td>' . t('send mass contact email messages') . '</td></tr>';
      $output .= '<tr><td>' . t('/node/add/mass_contact') . '</td><td>' . t('Mass Contact') . '</td><td>' . t('The add content page for adding a Mass Contact content item. This is not really useful on its own.') . '</td><td>' . t('create mass_contact content') . '</td></tr>';
      $output .= '</tbody></table>';
      $output .= '<h3>' . t('Troubleshooting') . '</h3>';
      $output .= '<p>' . t('Verify the permission set correctly.') . '</p>';
      $output .= '<p>' . t('When sending messages as Bcc (hiding the recipients from each other) and breaking up a large recipient list into smaller chunks or sending to multiple categories while retaining the category name in the subject, keep in mind that the sender will receive a copy of the message for every group of recipients the list is broken up into. That is normal behavior and cannot be changed.') . '</p>';
      $output .= '<p>' . t('If your category permissions are not showing up correctly, check your category name and make sure you do not have any stray characters or any characters that Drupal does not allow.') . '</p>';
      $output .= '<p>' . t('If you experience "return-path" errors when sending email, you can try the !returnpath module to see if that solves your problem.', array(
        '!returnpath' => l(t('Return-Path'), 'http://drupal.org/project/returnpath'),
      )) . '</p>';
      if (user_access('view site reports')) {
        $drupal_logs = t("Drupal's !logs in the !reports.", array(
          '!logs' => l(t('log messages'), 'admin/reports/dblog'),
          '!reports' => l(t('Reports section'), 'admin/reports'),
        ));
      }
      else {
        $drupal_logs = t("Drupal's log messages in the Reports section.");
      }
      $output .= '<p>' . t("If PHP's mail() function encounters an error, it just returns FALSE and Drupal presents a message like this: 'Unable to send email. Contact the site administrator if the problem persists.' To find what the cause of the error is, you may need to reference a number of logs:") . '<ul><li>' . $drupal_logs . '</li><li>' . t("The host server's system logs. For most Linux systems, the log files are usually stored in /var/log. The system messages are usually stored in /var/log/messages or /var/log/syslog.") . '</li><li>' . t("The HTTP server software's logs. For Apache on Linux, it's log files are usually found in /var/log/httpd, /var/log/apache or /var/log/apache2.") . '</li><li>' . t("The mail server software's logs. Most mail servers store thier logs in /var/log/mail*, where 'mail*' might be a directory or it might be a number of files in /var/log, including (but not limited to) mail.log, mail.info, mail.warn and mail.err.") . '</li></ul></p>';
      $output .= '<p>' . t('If you are also using other mail related modules on your Drupal installation (i.e.: !htmlmail module, !mimemail module, !phpmailer module, !smtp module, etc.), be sure to check the issue queues for those modules for solutions, as well.', array(
        '!htmlmail' => l(t('HTML Mail'), 'http://drupal.org/project/htmlmail'),
        '!mimemail' => l(t('Mime Mail'), 'http://drupal.org/project/mimemail'),
        '!phpmailer' => l(t('PHPMailer'), 'http://drupal.org/project/phpmailer'),
        '!smtp' => l(t('SMTP Authentication Support'), 'http://drupal.org/project/smtp'),
      )) . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_permission().
 */
function mass_contact_permission() {
  $permissions = array(
    'mass contact administer' => array(
      'title' => t('Administer Mass Contact'),
      'description' => t('Allows the user to add, change & delete categories and to change the administrative settings of Mass Contact.'),
    ),
    'mass contact archive messages' => array(
      'title' => t('Archive messages as content'),
      'description' => t('Allows the message sender to save an archive copy of the message as a node.'),
    ),
    'mass contact include attachments' => array(
      'title' => t('Attach files to messages'),
      'description' => t('Allows the message sender to include attachments with the message.'),
    ),
    'mass contact change default sender information' => array(
      'title' => t('Change default sender information'),
      'description' => t('Allows the message sender to change the default sender name and email address.'),
    ),
    'mass contact override archiving' => array(
      'title' => t('Override message archival setting'),
      'description' => t('Allows the message sender to override the "Archive messages by saving a copy as a node" administrative setting when creating the message.'),
    ),
    'mass contact override bcc' => array(
      'title' => t('Override BCC setting'),
      'description' => t('Allows the message sender to override the "Send as BCC (hide recipients) by default" administrative setting when creating the message.'),
    ),
    'mass contact override text format' => array(
      'title' => t('Override default text format'),
      'description' => t("Allows the message sender to override the message body's default text format when creating the message."),
    ),
    'mass contact send messages' => array(
      'title' => t('Send messages with Mass Contact'),
      'description' => t('Allows the user to send messages with the Mass Contact.'),
    ),
  );
  $result = db_select('mass_contact', 'mc')
    ->fields('mc', array(
    'category',
  ))
    ->execute();
  if (!empty($result)) {
    foreach ($result as $category) {
      $permission = 'mass contact send to users in the ' . $category->category . ' category';
      $permissions[$permission] = array(
        'title' => t('Send to users in the @category category', array(
          '@category' => $category->category,
        )),
        'description' => t('Allows the user to send messages to the users in the @category category', array(
          '@category' => $category->category,
        )),
      );
    }
  }
  return $permissions;
}

/**
 * Implements hook_menu().
 */
function mass_contact_menu() {
  $items = array();
  $items['admin/config/system/mass_contact'] = array(
    'title' => 'Mass Contact',
    'page callback' => 'mass_contact_admin_categories',
    'access arguments' => array(
      'mass contact administer',
    ),
    'description' => 'Configure Mass Contact and set up categories of people to send mail to.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/list'] = array(
    'title' => 'Category list',
    'page callback' => 'mass_contact_admin_categories',
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'description' => 'A listing of all existing categories.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/add'] = array(
    'title' => 'Add category',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_edit',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'description' => 'Add a new category.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/edit'] = array(
    'title' => 'Edit Mass Contact category',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_edit',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_CALLBACK,
    'description' => 'Modify an existing category.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/delete'] = array(
    'title' => 'Delete Mass Contact category',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_delete',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_CALLBACK,
    'description' => 'Remove an existing category.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/settings'] = array(
    'title' => 'Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_settings_misc',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'description' => 'Configuration options for Mass Contact.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/settings/misc'] = array(
    'title' => 'Miscellaneous',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_settings_misc',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'description' => 'Miscellaneous configuration options for Mass Contact.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/settings/header'] = array(
    'title' => 'Message header',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_settings_header',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'description' => 'Configuration options for the headers of the messages to be sent.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['admin/config/system/mass_contact/settings/body'] = array(
    'title' => 'Message body',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mass_contact_admin_settings_body',
    ),
    'access arguments' => array(
      'mass contact administer',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'description' => 'Configuration options for the bodies of the messages to be sent.',
    'file' => 'mass_contact.admin.inc',
  );
  $items['mass_contact'] = array(
    'title' => 'Mass Contact',
    'page callback' => 'mass_contact_site_page',
    'access arguments' => array(
      'mass contact send messages',
    ),
    'description' => 'Send an email message to multiple users of this website.',
    'file' => 'mass_contact.page.inc',
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function mass_contact_menu_alter(&$items) {
  if (!empty($items['node/add/mass-contact'])) {
    $items['node/add/mass-contact']['access callback'] = FALSE;
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for user_profile_form.
 */
function mass_contact_form_user_profile_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#user_category'] == 'account') {
    $account = $form['#user'];

    // The admin allows a blanket opt out of all mass mailings.
    if (variable_get('mass_contact_optout_d', 0) == 1) {
      $form['mass_contact'] = array(
        '#type' => 'fieldset',
        '#title' => t('Mass contact settings'),
        '#weight' => 5,
        '#collapsible' => TRUE,
      );
      $form['mass_contact']['mass_contact_optout'] = array(
        '#type' => 'checkbox',
        '#title' => t('Opt-out of mass email messages'),
        '#default_value' => !empty($account->data['mass_contact_optout']) ? $account->data['mass_contact_optout'] : 0,
        '#description' => variable_get('mass_contact_optout_message', t('Allows you to opt-out of receiving mass email messages from privileged users. Note that site administrators are able to include you in mass email messages even if you choose not to enable this feature, and the ability to opt-out may be removed by the administrator at any time.')),
      );
    }
    elseif (variable_get('mass_contact_optout_d', 0) == 2) {
      $form['mass_contact'] = array(
        '#type' => 'fieldset',
        '#title' => t('Mass contact settings'),
        '#weight' => 5,
        '#collapsible' => TRUE,
        '#description' => variable_get('mass_contact_optout_message', t('Allows you to opt-out of receiving mass email messages from privileged users. Note that site administrators are able to include you in mass email messages even if you choose not to enable this feature, and the ability to opt-out may be removed by the administrator at any time.')),
      );
      $included_categories = array();
      $all_included_categories = array();

      // Add form elements provided by grouping_method plugins.
      ctools_include('plugins');

      // Get the information about all plugins that implemnent this type of
      // plugin.
      $plugins = ctools_get_plugins('mass_contact', 'grouping_method');
      foreach ($plugins as $plugin) {

        // Get the admin edit function name for this particular implementation.
        $function = ctools_plugin_get_function($plugin, 'mass_contact_user_edit');

        // Call the plugin function to add the form snippet(s).
        $included_categories = $function($form['#user']);
        if (!empty($included_categories)) {
          $all_included_categories += $included_categories;
        }
      }
      if (!empty($all_included_categories)) {

        // Eliminate duplicates.
        $all_included_categories = array_unique($all_included_categories);

        // Sort the contents, naturally and case insensitively.
        natcasesort($all_included_categories);
        foreach ($all_included_categories as $category_cid => $category_category) {

          // If the user is in the category, show the option to opt out of it.
          $form['mass_contact']['mass_contact_optout_' . $category_cid] = array(
            '#type' => 'checkbox',
            '#title' => t('Opt-out of mass email messages to the %category category.', array(
              '%category' => $category_category,
            )),
            '#default_value' => !empty($account->data['mass_contact_optout_' . $category_cid]) ? $account->data['mass_contact_optout_' . $category_cid] : 0,
          );
        }
      }
    }
  }
}

/**
 * Implements hook_user_presave().
 */
function mass_contact_user_presave(&$edit, $account, $category) {

  // Remove any previously saved category opt out data.
  if (!empty($edit['data'])) {
    foreach ($edit['data'] as $key => $value) {
      if (substr($key, 0, 19) == 'mass_contact_optout') {
        unset($key);
      }
    }
  }

  // Get all Mass Contact categories.
  $categories = db_select('mass_contact', 'mc')
    ->fields('mc', array(
    'cid',
    'category',
    'recipients',
  ))
    ->execute();

  // Iterate through each category.
  foreach ($categories as $category) {

    // If the item is either 0 or 1, then save its setting. This will allow
    // users to opt back in, after opting out.
    if (isset($edit['mass_contact_optout_' . $category->cid]) && $edit['mass_contact_optout_' . $category->cid] == 0) {

      // Set the new values, which will unset any that were opted back in.
      unset($edit['data']['mass_contact_optout_' . $category->cid]);
    }
    elseif (isset($edit['mass_contact_optout_' . $category->cid]) && $edit['mass_contact_optout_' . $category->cid] == 1) {

      // Set the new values, which will unset any that were opted back in.
      $edit['data']['mass_contact_optout_' . $category->cid] = $edit['mass_contact_optout_' . $category->cid];
    }
  }

  // Do the same for the global setting to opt out.
  // If the item is either 0 or 1, then save its setting. This will allow
  // users to opt back in, after opting out.
  if (isset($edit['mass_contact_optout']) && $edit['mass_contact_optout'] == 0) {

    // Set the new values, which will unset any that were opted back in.
    unset($edit['data']['mass_contact_optout']);
  }
  elseif (isset($edit['mass_contact_optout']) && $edit['mass_contact_optout'] == 1) {

    // Set the new values, which will unset any that were opted back in.
    $edit['data']['mass_contact_optout'] = $edit['mass_contact_optout'];
  }
}

/**
 * Implements hook_mail().
 */
function mass_contact_mail($key, &$message, $params) {
  if (!empty($params['headers'])) {
    foreach ($params['headers'] as $key => $value) {
      $message['headers'][$key] = $params['headers'][$key];
    }
  }
  $message['subject'] = $params['subject'];
  $message['body'] = $params['body'];
}

/**
 * Implements hook_cron_queue_info().
 */
function mass_contact_cron() {

  // Get the Mass Contact queue, if there is one.
  $queue = DrupalQueue::get('mass_contact');

  // Get the next item in the queue.
  $message = $queue
    ->claimItem();

  // If there are no items, nothing will happen.
  if (!empty($message)) {

    // Send the current message item.
    _mass_contact_prepare_message_for_sending($message);

    // Now that it is sent, delete it.
    $queue
      ->deleteItem($message);
  }
}

/**
 * This is for preparing a message that has been queued for sending.
 *
 * @param array $message
 *   The message to be sent.
 */
function _mass_contact_prepare_message_for_sending(array $message) {
  if (!empty($message)) {
    _mass_contact_send_message($message->data['message_key'], $message->data['to'], $message->data['params'], $message->data['from_email'], $message->data['success_message']);
  }
}

/**
 * Sends the message.
 *
 * @param string $message_key
 *   A key to identify the email sent.
 * @param string $to
 *   To whom the message will be delivered.
 * @param array $params
 *   The message array.
 * @param string $from_email
 *   The message sender's email address.
 * @param string $success_message
 *   The message that will be displayed to the user, if sending is successful.
 *
 * @return bool
 *   The result of the call to drupal_mail():
 *     The $message array structure containing all details of the message. If
 *     already sent ($send = TRUE), then the 'result' element will contain the
 *     success indicator of the email, failure being already written to the
 *     watchdog. (Success means nothing more than the message being accepted at
 *     php-level, which still doesn't guarantee it to be delivered.)
 */
function _mass_contact_send_message($message_key, $to, array &$params, $from_email, $success_message) {
  $success = drupal_mail('mass_contact', $message_key, $to, language_default(), $params, $from_email);

  // Capture the rate limiting information.
  $recipient_limit = variable_get('mass_contact_recipient_limit', 0);
  $wait_time = variable_get('mass_contact_wait_time', 0);
  if ($success['result']) {
    if (empty($recipient_limit) && empty($wait_time)) {
      drupal_set_message(t($success_message));
    }
    else {
      watchdog('mass_contact', $success_message);
    }
  }
  return $success['result'];
}

/**
 * Implements hook_ctools_plugin_type().
 */
function mass_contact_ctools_plugin_type() {
  return array(
    // The plugin type. This one uses a default configuration.
    'grouping_method' => array(),
  );
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function mass_contact_ctools_plugin_directory($module, $plugin) {
  if ($module == 'mass_contact' && $plugin == 'grouping_method') {

    // The directory the plugins are stored in.
    return 'plugins';
  }
}