You are here

mailchimp.module in Mailchimp 7

Mailchimp module.

File

mailchimp.module
View source
<?php

/**
 * @file
 * Mailchimp module.
 */
define('MAILCHIMP_LISTTYPE_REQUIRED', 'required');
define('MAILCHIMP_LISTTYPE_OPTIN', 'optin');
define('MAILCHIMP_LISTTYPE_OPTOUT', 'optout');
define('MAILCHIMP_USERSTATUS_PENDING', 'pending');
define('MAILCHIMP_USERSTATUS_CURRENT', 'current');

/**
 * Implements hook_form_FORM_ID_alter().
 *   Add newsletter fields to registration form.
 */
function mailchimp_form_user_register_form_alter(&$form, &$form_state, $form_id) {
  $account = $form['#user'];
  $category = $form['#user_category'];
  if (variable_get('mailchimp_user_register', TRUE)) {
    $account->roles = array(
      2 => 'authenticated',
    );
    if (count(_mailchimp_get_available_lists($account)) > 0) {

      // wrap in a fieldset
      $form['mailchimp_lists'] = array(
        '#type' => 'fieldset',
        '#title' => t('Newsletters'),
      );
      $form['mailchimp_lists'][] = mailchimp_subscribe_auth_form(NULL, NULL, $account, FALSE);
    }
  }
}

/**
 * Implements hook_user_insert().
 */
function mailchimp_user_insert(&$edit, $account, $category) {
  if ($q = _mailchimp_get_api_object()) {
    foreach ((array) _mailchimp_get_available_lists($account) as $list) {

      // first deal with all required lists
      if ($list->listtype == MAILCHIMP_LISTTYPE_REQUIRED) {

        // process immediately
        if (!variable_get('mailchimp_cron', FALSE)) {

          // determine if a user is allowed in a given list
          $is_allowed = FALSE;
          $roles = $edit['roles'];
          if (!is_array($roles)) {
            $roles = $account->roles;
          }
          foreach ($list->roles as $key => $value) {
            if (array_key_exists($key, $roles)) {
              $is_allowed = TRUE;
              break;
            }
          }

          // they are allowed, update or subscribe
          if ($is_allowed) {
            $userinfo = _mailchimp_load_user_list_mergevars($account, $list->id);
            $userinfo['EMAIL'] = $edit['mail'];
            _mailchimp_subscribe_user($list, $account->mail, $userinfo, FALSE, $q);
          }
          else {
            _mailchimp_unsubscribe_user($list, $account->mail, FALSE, $q);
          }
        }
        else {
          $result = db_query("SELECT uid FROM {mailchimp_user} WHERE uid = :uid", array(
            ':uid' => $account->uid,
          ));
          if ($result
            ->rowCount() == 0) {
            db_insert('mailchimp_user')
              ->fields(array(
              'uid' => $account->uid,
              'status' => MAILCHIMP_USERSTATUS_PENDING,
            ))
              ->execute();
          }
        }
      }
      else {
        $ret = TRUE;
        $selected = @$edit['mailchimp_list_' . $list->id];
        if ($selected) {
          $merge_vars = _mailchimp_load_user_list_mergevars($account, $list->id);

          // include interest groups
          if (!empty($edit['mailchimp_list_' . $list->id . '_INTERESTS'])) {
            $merge_vars['INTERESTS'] = implode(',', array_filter($edit['mailchimp_list_' . $list->id . '_INTERESTS']));
          }
          $ret = _mailchimp_subscribe_user($list, $account->mail, $merge_vars, TRUE, $q);
        }
        if (!$ret) {
          drupal_set_message(t('There was a problem with your newsletter signup: @msg', array(
            '@msg' => $q->errorMessage,
          )));
        }
      }
    }
  }
}

/**
 * Implements hook_user_delete().
 */
function mailchimp_user_delete($account) {
  if ($q = _mailchimp_get_api_object()) {

    // remove a user from all required lists.
    foreach ((array) _mailchimp_get_required_lists() as $list) {
      db_delete('mailchimp_user')
        ->condition('uid', $account->uid)
        ->execute();
      _mailchimp_unsubscribe_user($list, $account->mail, FALSE, $q);
    }
  }
}

/**
 * Implements hook_user_update().
 */
function mailchimp_user_update(&$edit, $account, $category) {
  if ($q = _mailchimp_get_api_object()) {
    foreach ((array) _mailchimp_get_required_lists() as $list) {

      // update a users newsletter subscription immediately
      if (!variable_get('mailchimp_cron', FALSE)) {

        // determine if a user is allowed in a given list
        $is_allowed = FALSE;
        $roles = $account->roles;
        foreach ($list->roles as $key => $value) {
          if (array_key_exists($key, $roles)) {
            $is_allowed = TRUE;
            break;
          }
        }

        // they are allowed, update or subscribe
        if ($is_allowed) {
          $userinfo = _mailchimp_load_user_list_mergevars($account, $list->id);
          if (isset($edit['mail'])) {
            $userinfo['EMAIL'] = $edit['mail'];
          }
          _mailchimp_subscribe_user($list, $account->mail, $userinfo, FALSE, $q);
        }
        else {
          _mailchimp_unsubscribe_user($list, $account->mail, FALSE, $q);
        }
      }
      else {
        db_update('mailchimp_user')
          ->fields(array(
          'status' => MAILCHIMP_USERSTATUS_PENDING,
        ))
          ->condition('uid', $account->uid)
          ->execute();
      }
    }
  }
}

/**
 * Add mailchimp form fields to account and registration forms
 */
function mailchimp_subscribe_auth_form($form, $form_state, $account, $standalone = TRUE, $list = NULL) {
  $form = array();

  // get all available non-required lists
  $lists = !empty($list) ? array(
    $list,
  ) : _mailchimp_get_available_lists($account, TRUE);
  if (count($lists) == 0) {
    $form['value'] = array(
      '#markup' => t('There are no available newsletters subscriptions.'),
      '#prefix' => '<div>',
      '#suffix' => '</div>',
    );
  }
  else {
    if ($q = _mailchimp_get_api_object()) {
      if ($account->uid > 0) {
        $form['uid'] = array(
          '#type' => 'hidden',
          '#value' => $account->uid,
        );
      }
      else {

        // user registration or admin creating new user
        $account->roles = array(
          2 => 'authenticated',
        );
      }
      foreach ($lists as $list) {
        mailchimp_auth_newsletter_form($form, $list, $account, $q);
      }
      if ($standalone) {
        $form['submit'] = array(
          '#type' => 'submit',
          '#value' => t('save settings'),
          '#weight' => 100,
        );
      }
    }
  }
  return $form;
}

/**
 * Return a form element for a single newsletter.
 */
function mailchimp_auth_newsletter_form(&$form, $list, $account, $q) {
  $is_subscribed = FALSE;
  if ($account && $account->uid > 0) {
    $memberinfo = $q
      ->listMemberInfo($list->id, $account->mail);
    $is_subscribed = $memberinfo['status'] == 'subscribed';
    $default_value = $is_subscribed;
  }
  else {
    $default_value = $list->listtype == MAILCHIMP_LISTTYPE_OPTOUT ? TRUE : FALSE;
  }

  // wrap in a div
  $form['wrapper' . $list->id] = array(
    '#prefix' => '<div class="mailchimp-newsletter-wrapper">',
    '#suffix' => '</div>',
  );
  $form['wrapper' . $list->id]['mailchimp_list_' . $list->id] = array(
    '#type' => 'checkbox',
    '#title' => $list->label ? t($list->label) : t('Subscribe to the @newsletter newsletter', array(
      '@newsletter' => $list->name,
    )),
    '#default_value' => $default_value,
    '#description' => $list->description,
    '#attributes' => array(
      'class' => array(
        'mailchimp-newsletter-checkbox-' . $list->id,
      ),
    ),
  );

  // present interest groups
  if (variable_get('mailchimp_interest_groups_user_forms', FALSE)) {
    if ($intgroup = $q
      ->listInterestGroups($list->id)) {
      switch ($intgroup['form_field']) {
        case 'radio':
          $field_type = 'radios';
          break;
        case 'checkbox':
          $field_type = 'checkboxes';
          break;
        default:
          $field_type = $intgroup['form_field'];
      }
      $options = array();
      foreach ((array) $intgroup['groups'] as $group) {
        $options[$group] = $group;
      }
      $form['wrapper' . $list->id]['mailchimp_list_' . $list->id . '_INTERESTS'] = array(
        '#type' => $field_type,
        '#title' => $intgroup['name'],
        '#options' => $options,
        '#default_value' => $is_subscribed ? explode(",", str_replace(', ', ',', $memberinfo['merges']['INTERESTS'])) : array(),
        '#attributes' => array(
          'class' => array(
            'mailchimp-newsletter-interests-' . $list->id,
          ),
        ),
      );
      drupal_add_js('$(document).ready(function(){
        if($(".mailchimp-newsletter-checkbox-' . $list->id . '").attr("checked")){
          $(".mailchimp-newsletter-interests-' . $list->id . '").parent(".form-item").show();
        } else {
          $(".mailchimp-newsletter-interests-' . $list->id . '").parent(".form-item").hide();
        }
        $(".mailchimp-newsletter-checkbox-' . $list->id . '").click(function(){ $(".mailchimp-newsletter-interests-' . $list->id . '").parent(".form-item").toggle("slow");});
      });', 'inline');
    }
  }
  return $form;
}

/**
 * Submit handler to add users to lists when editing/creating a user
 */
function mailchimp_subscribe_auth_form_submit($form, &$form_state) {
  if ($q = _mailchimp_get_api_object()) {
    $account = new stdClass();
    if (!empty($form_state['values']['uid'])) {
      $account = user_load($form_state['values']['uid']);
    }
    else {
      $account = $form_state['user'];
    }
    $lists = _mailchimp_get_available_lists($account);
    foreach ($lists as $list) {

      // ignore required lists, they are handled via hook_user
      if ($list->listtype !== MAILCHIMP_LISTTYPE_REQUIRED) {
        $is_subscribed = _mailchimp_is_subscribed($list->id, $account->mail, $q);
        $ret = TRUE;
        $selected = @$form_state['values']['mailchimp_list_' . $list->id];

        // unsubscribe a subscribed user who unchecked the box when not registering
        if ($is_subscribed && !$selected && $form['#id'] != 'user-register') {
          $ret = _mailchimp_unsubscribe_user($list, $account->mail, TRUE, $q);
        }
        elseif ($selected) {

          // subscribe the user if they are not previously subscribed or update existing subscriptions
          $merge_vars = _mailchimp_load_user_list_mergevars($account, $list->id);

          // include updated email address if already subscribed
          if (!empty($form_state['values']['mail']) && $is_subscribed) {
            $merge_vars['EMAIL'] = $form_state['values']['mail'];
          }

          // include interest groups
          if (!empty($form_state['values']['mailchimp_list_' . $list->id . '_INTERESTS'])) {
            $merge_vars['INTERESTS'] = implode(',', array_filter($form_state['values']['mailchimp_list_' . $list->id . '_INTERESTS']));
          }
          $ret = _mailchimp_subscribe_user($list, $account->mail, $merge_vars, TRUE, $q);
        }
        if (!$ret) {
          drupal_set_message(t('There was a problem with your newsletter signup: @msg', array(
            '@msg' => $q->errorMessage,
          )));
        }
      }
    }
  }
}

/**
 * Implements hook_cron().
 *
 * Resubscribes all users to the required lists if the user has chosen to do so.
 */
function mailchimp_cron() {
  if (variable_get('mailchimp_cron', FALSE) && ($q = _mailchimp_get_api_object())) {
    $sql = "SELECT uid FROM {mailchimp_user} WHERE status = :status";
    $result = db_query_range($sql, 0, variable_get('mailchimp_batch_limit', 100), array(
      ':status' => MAILCHIMP_USERSTATUS_PENDING,
    ));
    if ($result) {
      $lists = _mailchimp_get_required_lists();
      $batches = array();
      foreach ($result as $row) {
        if ($account = user_load($row->uid)) {
          db_query('UPDATE {mailchimp_user} SET status = :status WHERE uid = :uid', array(
            ':status' => MAILCHIMP_USERSTATUS_CURRENT,
            ':uid' => $account->uid,
          ));

          // We don't update people if their status = 0 (but perhaps we could unsubscribe them?)
          if ($account->status) {
            foreach ($lists as $key => $list) {
              foreach ($account->roles as $rid => $info) {
                if (isset($list->roles[$rid])) {
                  $batches[$list->id][] = _mailchimp_load_user_list_mergevars($account, $list->id);
                  break;
                }
              }
            }
          }
        }
        else {

          // user exists in mc_user table even though they don't have an account, remove
          db_query('DELETE FROM {mailchimp_user} WHERE uid = :uid', array(
            ':uid' => $account->uid,
          ));
        }
      }
      $count = 0;
      $ret = array();
      foreach ($batches as $listid => $batch) {
        if (count($batch)) {
          $ret = $q
            ->listBatchSubscribe($listid, $batch, FALSE, TRUE);
          if ($ret['error_count'] > 0) {
            foreach ((array) $ret['errors'] as $error) {
              watchdog('mailchimp', 'MCAPI Error: %errmsg', array(
                '!errmsg' => $error['message'],
              ), WATCHDOG_ERROR);
            }
          }
        }
        $count += $ret['success_count'];
      }
      watchdog('mailchimp', 'Updated !count records in MailChimp', array(
        '!count' => $count,
      ), WATCHDOG_NOTICE);
    }
  }
}

/**
 * Implements hook_menu().
 */
function mailchimp_menu() {
  $items = array();
  $items['user/%user/mailchimp'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_subscribe_auth_form',
      1,
    ),
    'title' => 'Newsletter Subscriptions',
    'type' => MENU_LOCAL_TASK,
    'access callback' => 'mailchimp_user_edit_access',
    'access arguments' => array(
      1,
    ),
    'tab_parent' => 'user/%/edit',
  );
  $items['mailchimp/subscribe'] = array(
    'page callback' => 'mailchimp_subscribe_page',
    'title' => 'Newsletter Subscription',
    'type' => MENU_NORMAL_ITEM,
    'access arguments' => array(
      'access content',
    ),
  );
  $items['mailchimp/unsubscribe'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_unsubscribe_form',
    ),
    'title' => 'Newsletter Unsubscribe',
    'type' => MENU_CALLBACK,
    'access callback' => TRUE,
  );
  $items['mailchimp/unsubscribe/success'] = array(
    'page callback' => 'mailchimp_unsubscribe_success',
    'title' => 'Unsubscription Confirmed',
    'type' => MENU_CALLBACK,
    'access callback' => TRUE,
  );
  $items['mailchimp/unsubscribe/failure'] = array(
    'page callback' => 'mailchimp_unsubscribe_failure',
    'title' => 'Unsubscription Failed',
    'type' => MENU_CALLBACK,
    'access callback' => TRUE,
  );
  $items['admin/config/services/mailchimp'] = array(
    'title' => 'MailChimp',
    'description' => 'Manage MailChimp Settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_admin_settings',
    ),
    'access arguments' => array(
      'administer mailchimp',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'mailchimp.admin.inc',
  );
  $items['mailchimp/rebuild'] = array(
    'title' => 'Rebuild Users Table',
    'page callback' => 'mailchimp_rebuild_users',
    'access arguments' => array(
      'administer mailchimp',
    ),
    'weight' => 10,
  );
  return $items;
}

/**
 * Access callback for editing newsletter subscriptions.
 */
function mailchimp_user_edit_access($user) {
  if (variable_get('mailchimp_user_edit', TRUE) && user_edit_access($user)) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

/**
 * Implements hook_permission().
 */
function mailchimp_permission() {
  return array(
    'administer mailchimp' => array(
      'title' => t('administer mailchimp'),
      'description' => t('TODO Add a description for administer mailchimp'),
    ),
  );
}

/**
 * Return all available MC lists a given user can subscribe to
 *
 * @global <type> $user
 * @return <type> page content of all available MC lists for a given user
 */
function mailchimp_subscribe_page() {
  global $user;
  $ret = '';
  if ($user->uid) {
    $ret = drupal_get_form('mailchimp_subscribe_auth_form', $user);
  }
  elseif ($q = _mailchimp_get_api_object()) {
    $ret = drupal_get_form('mailchimp_subscribe_anon_form_all', $q);
  }
  return $ret;
}

/**
 * Return a form for all available MC lists
 *
 * @param <type> $form_state
 * @param <type> $list MC list object
 * @param <type> $q MC object
 * @return <type> form array
 */
function mailchimp_subscribe_anon_form_all($form, $form_state, $q) {
  $form = array(
    '#tree' => TRUE,
  );
  global $user;
  $lists = _mailchimp_get_available_lists($user);
  foreach ($lists as $list) {
    $form['mailchimp_lists'][$list->id] = array(
      '#type' => 'fieldset',
      '#title' => t('@name', array(
        '@name' => $list->name,
      )),
      '#description' => t('@desc', array(
        '@desc' => $list->description,
      )),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    _mailchimp_subscribe_anon_form($list, $q, $form['mailchimp_lists'][$list->id]);

    // for anonymous sign up forms, we want to force email to be optional
    if ($form['mailchimp_lists'][$list->id]['EMAIL']) {
      $form['mailchimp_lists'][$list->id]['EMAIL']['#required'] = FALSE;
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Sign Up!'),
    '#weight' => 100,
  );
  $form['#submit'][] = 'mailchimp_subscribe_anon_form_submit';
  return $form;
}

/**
 * Submit handler for anonymous subscription form
 *
 * @param <type> $form_state
 * @param <type> $q - MC API object
 */
function mailchimp_subscribe_anon_form_submit($form, &$form_state) {
  $lists = $form_state['values']['mailchimp_lists'];
  foreach ($lists as $list) {
    if (!empty($list['EMAIL'])) {
      $success = FALSE;

      // filter our interest groups and return in an comma delimited string
      if (!empty($list['INTERESTS'])) {
        $list['INTERESTS'] = implode(',', array_filter($list['INTERESTS']));
      }
      $success = _mailchimp_subscribe_user($list['list'], $list['EMAIL'], $list, TRUE);
      if ($success) {
        $msg = variable_get('mailchimp_subscription_success_message', t('Thank you, you have been successfully subscribed.'));
      }
      else {
        $msg = variable_get('mailchimp_subscription_failure_message', t('We were unable to subscribe you at this time. Please try again later.'));
      }
      drupal_set_message($msg);
    }
  }
}

/**
 * Return a form for a given MC list
 *
 * @param <type> $form_state
 * @param <type> $list MC list object
 * @param <type> $q MC object
 * @return <type> form array
 */
function mailchimp_subscribe_anon_form($form, $form_state, $list, $q) {
  $form += array(
    '#tree' => TRUE,
    '#id' => 'mailchimp_subscribe_anon_form_' . $list->id,
  );
  $form['description'] = array(
    '#value' => $list->description,
  );
  _mailchimp_subscribe_anon_form($list, $q, $form['mailchimp_lists'][$list->id]);
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Sign Up!'),
    '#weight' => 100,
  );
  return $form;
}

/**
 * Helper function to return form elements for a single anon newsletter
 *
 * @param string $list
 * @param string $q
 * @param string $form
 * @return void
 */
function _mailchimp_subscribe_anon_form($list, $q, &$form) {
  $form['list'] = array(
    '#type' => 'value',
    '#value' => $list,
  );

  // grab any default values for authenticated users
  global $user;
  $mergevalues = NULL;
  if ($user->uid) {
    $mergevalues = _mailchimp_load_user_list_mergevars($user, $list->id);
  }
  foreach ((array) $q
    ->listMergeVars($list->id) as $mergevar) {

    // set the default value for merge fields if we have it
    if ($mergevalues && isset($mergevalues[$mergevar['tag']]) && $mergevalues[$mergevar['tag']]) {
      $mergevar['default'] = $mergevalues[$mergevar['tag']];
    }
    $form[$mergevar['tag']] = _mailchimp_insert_drupal_form_tag($mergevar);
  }

  // present interest groups
  if ($intgroup = $q
    ->listInterestGroups($list->id)) {
    switch ($intgroup['form_field']) {
      case 'radio':
        $field_type = 'radios';
        break;
      case 'checkbox':
        $field_type = 'checkboxes';
        break;
      default:
        $field_type = $intgroup['form_field'];
    }
    foreach ((array) $intgroup['groups'] as $group) {
      $options[$group] = $group;
    }
    $form['INTERESTS'] = array(
      '#type' => $field_type,
      '#title' => $intgroup['name'],
      '#options' => $options,
    );
  }
}

/**
 * Convert mailchimp form elements to Drupal Form API
 *
 * @param <type> $mergevar
 * @return <type>
 */
function _mailchimp_insert_drupal_form_tag($mergevar) {

  // Insert common FormAPI properties
  $input = array(
    '#title' => $mergevar['name'],
    '#weight' => $mergevar['order'],
    '#required' => $mergevar['req'],
    '#default_value' => $mergevar['default'],
  );
  switch ($mergevar['field_type']) {
    case 'dropdown':

      // dropdown is mapped to <select> element in Drupal Form API
      $input['#type'] = 'select';

      // Creates options, we must delete array keys to have revealant information
      // on MailChimp
      foreach ($mergevar['choices'] as $choice) {
        $choices[$choice] = $choice;
      }
      $input['#options'] = $choices;
      break;
    case 'radio':

      // radio is mapped to <input type='radio' /> i.e. 'radios' element in Drupal Form API
      $input['#type'] = 'radios';

      // Creates options, we must delete array keys to have revealant information
      // on MailChimp
      foreach ($mergevar['choices'] as $choice) {
        $choices[$choice] = $choice;
      }
      $input['#options'] = $choices;
      break;
    default:

      // This is a standard input[type=text] or something we can't handle with Drupal FormAPI
      $input['#type'] = 'textfield';
      $input['#size'] = $mergevar['size'];
      break;
  }

  // Special cases for MailChimp hidden defined fields
  if ($mergevar['public'] == FALSE) {
    $input['#type'] = 'hidden';
  }
  return $input;
}

/**
 * MailChimp unsubscribe form
 *
 * @param <type> $form_values
 * @return <type>
 */
function mailchimp_unsubscribe_form($form, $form_state) {
  $form = array();
  $form['intro'] = array(
    '#type' => 'markup',
    '#value' => t('Use this form to unsubscribe from all of our newsletters.'),
  );
  $form['EMAIL'] = array(
    '#type' => 'textfield',
    '#title' => t('Email Address'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Unsubscribe'),
  );
  return $form;
}

/**
 * submit handler for unsubscribe form
 *
 * @param <type> $form
 * @param <type> $form_state
 */
function mailchimp_unsubscribe_form_submit($form, &$form_state) {
  if ($q = _mailchimp_get_api_object()) {
    $success = TRUE;
    foreach ((array) $q
      ->lists() as $list) {
      $success = $success && _mailchimp_unsubscribe_user($list, $form_state['values']['EMAIL'], TRUE, $q);
      if ($success) {
        drupal_set_message(variable_get('mailchimp_unsubscription_success_message', t('Thank you, you have been successfully unsubscribed.')));
      }
      else {
        drupal_set_message(variable_get('mailchimp_unsubscription_failure_message', t('We were unable to unsubscribe you at this time. Please try again later.')));
      }
    }
  }
}

/**
 * validate unsubscribe form
 *
 * @param <type> $form
 * @param <type> $form_state
 */
function mailchimp_unsubscribe_form_validate($form, &$form_state) {
  if (!$form_state['values']['EMAIL']) {
    form_set_error('EMAIL', t('Please enter your email address.'));
  }
  else {
    if ($q = _mailchimp_get_api_object()) {
      $subscribed = FALSE;
      foreach ((array) $q
        ->lists() as $list) {
        $subscribed = $subscribed || _mailchimp_is_subscribed($list['id'], $form_state['values']['EMAIL'], $q);
      }
      if (!$subscribed) {
        form_set_error('', t('That email address could not be found.'));
      }
    }
    else {
      form_set_error('', t('There was an error processing your request. Please try again later.'));
    }
  }
}

/**
 * Get the relevant merge vars for the given user for the given list
 */
function _mailchimp_load_user_list_mergevars($account, $list_id) {
  $values = array();
  $lists = variable_get('mailchimp_lists', array());
  $list = $lists[$list_id];

  // grab the saved list merge vars and filter out unset values
  if (!empty($list->mergevars)) {
    $mergevars = array_filter($list->mergevars);
    $mergevars = array_flip($mergevars);

    // match with token values
    $values = token_generate('user', $mergevars, array(
      'user' => $account,
    ));

    // strip out any HTML, profile at least, seems to allow it in text fields.
    foreach ($values as $key => $value) {
      $values[$key] = strip_tags($value);
    }

    // always add email
    $values += array(
      'EMAIL' => $account->mail,
    );
  }
  return $values;
}

/**
 * Check if the given user is subscribed to the given list
 */
function _mailchimp_is_subscribed($listid, $mail, $q = NULL) {
  $is_subscribed = FALSE;
  if ($q || ($q = _mailchimp_get_api_object())) {
    $sub_info = $q
      ->listMemberInfo($listid, $mail);
    $is_subscribed = @$sub_info['status'] == 'subscribed';
  }
  return $is_subscribed;
}

/**
 * Subscribe or update a user in a given list
 */
function _mailchimp_subscribe_user($list, $email, $merge_vars, $message = TRUE, $q = NULL) {
  if ($q || ($q = _mailchimp_get_api_object())) {
    $double_optin = $list->doublein;

    // required by MC API. An empty array will fail.
    if (empty($merge_vars)) {
      $merge_vars = '';
    }
    if (_mailchimp_is_subscribed($list->id, $email, $q)) {
      $action = 'updated in';
      $success = $q
        ->listUpdateMember($list->id, $email, $merge_vars);
      if ($success && $message) {
        drupal_set_message(t('You have updated your settings in %list.', array(
          '%list' => $list->name,
        )));
      }
    }
    else {
      $action = 'subscribed to';
      $success = $q
        ->listSubscribe($list->id, $email, $merge_vars, 'html', $double_optin, TRUE);
      if ($message && $success && $double_optin) {
        drupal_set_message(t('You have chosen to subscribe to %list. An email will be sent to your address. Click the link in the email to confirm the subscription.', array(
          '%list' => $list->name,
        )));
      }
      elseif ($message && $success) {
        drupal_set_message(t('You have subscribed to %list.', array(
          '%list' => $list->name,
        )));
      }
    }
  }
  if ($success) {
    watchdog('mailchimp', '@email was @action list @list.', array(
      '@action' => $action,
      '@email' => $merge_vars['EMAIL'],
      '@list' => $list->name,
    ), WATCHDOG_NOTICE);
  }
  else {
    watchdog('mailchimp', 'A problem occurred subscribing @email to list @list. Message: @msg', array(
      '@email' => $merge_vars['EMAIL'],
      '@list' => $list->name,
      '@msg' => $q->errorMessage,
    ), WATCHDOG_WARNING);
  }
  return $success;
}

/**
 * Unsubscribe the given user from the given list
 */
function _mailchimp_unsubscribe_user($list, $mail, $message = TRUE, $q = NULL) {
  $success = FALSE;
  if ($q || ($q = _mailchimp_get_api_object())) {
    if (_mailchimp_is_subscribed($list->id, $mail, $q)) {
      $success = $q
        ->listUnsubscribe($list->id, $mail, FALSE, FALSE, FALSE);
      if ($message && $success) {
        drupal_set_message(t('You have unsubscribed from %list.', array(
          '%list' => $list->name,
        )));
      }
    }
  }
  return $success;
}

/**
 * Get all of the lists that the given user can subscribe to.
 *
 * @param object $user 
 * @param bool $exclude_required 
 * @return Array of available lists
 */
function _mailchimp_get_available_lists($user, $exclude_required = FALSE) {
  $all_lists = variable_get('mailchimp_lists', NULL);
  $available_lists = array();
  if (is_array($all_lists)) {
    foreach ($all_lists as $key => $list) {

      // Continue if we only want non-required lists
      if ($exclude_required && $list->listtype === MAILCHIMP_LISTTYPE_REQUIRED) {
        continue;
      }
      foreach ($user->roles as $rid => $info) {
        if (!empty($list->roles[$rid])) {
          $available_lists[$list->id] = $list;
          break;
        }
      }
    }
  }
  return $available_lists;
}

/**
 * Return an array of all required lists.
 */
function _mailchimp_get_required_lists() {
  $lists = variable_get('mailchimp_lists', NULL);
  if (is_array($lists)) {
    foreach ($lists as $key => $list) {
      if ($list->listtype !== MAILCHIMP_LISTTYPE_REQUIRED) {
        unset($lists[$key]);
      }
    }
  }
  return $lists;
}

/**
 * Get a Mailchimp API object for communication with the mailchimp server
 */
function _mailchimp_get_api_object() {
  module_load_include('php', 'mailchimp', 'MCAPI.class');
  $q = new MCAPI(variable_get('mailchimp_api_key', ''));

  // set the timeout to something reasonable to avoid taking down the Drupal site
  $q
    ->setTimeout(60);
  if ($q->errorCode) {
    watchdog('mailchimp', 'MCAPI Error: %errmsg', array(
      '!errmsg' => $q->errorMessage,
    ), WATCHDOG_ERROR);
    return NULL;
  }
  return $q;
}

/**
 * Implements hook_block_info.
 */
function mailchimp_block_info() {
  $blocks = array();
  $all_lists = variable_get('mailchimp_lists', NULL);
  if (is_array($all_lists)) {
    foreach ($all_lists as $key => $list) {

      // exclude required lists
      if ($list->listtype !== MAILCHIMP_LISTTYPE_REQUIRED) {
        $blocks[$list->id] = array(
          'info' => t('Mailchimp Subscription Form: @name', array(
            '@name' => $list->name,
          )),
          'cache' => DRUPAL_CACHE_PER_USER,
        );
      }
    }
  }
  return $blocks;
}

/**
 * Implements hook_block_view().
 * Provides a block for each available list for a given user
 */
function mailchimp_block_view($delta = '') {
  global $user;
  $block = array();
  $lists = _mailchimp_get_available_lists($user);
  $list = isset($lists[$delta]) ? $lists[$delta] : array();
  if (!empty($list) && ($q = _mailchimp_get_api_object())) {
    $block['subject'] = t('Subscribe to @title', array(
      '@title' => $list->name,
    ));
    $block['content'] = drupal_get_form('mailchimp_subscribe_anon_form', $list, $q);
  }
  return $block;
}

/**
 * Rebuild the MailChimp users's table.
 */
function mailchimp_rebuild_users() {
  db_query("DELETE FROM {mailchimp_user}");
  db_query("INSERT INTO {mailchimp_user} (uid, status) SELECT uid, '" . MAILCHIMP_USERSTATUS_PENDING . "' FROM {users} WHERE uid > 0");
  drupal_set_message('The MailChimp User\'s Table has been rebuilt with all user\'s status set to pending.', 'status');
  drupal_goto('admin/config/services/mailchimp');
}

Functions

Namesort descending Description
mailchimp_auth_newsletter_form Return a form element for a single newsletter.
mailchimp_block_info Implements hook_block_info.
mailchimp_block_view Implements hook_block_view(). Provides a block for each available list for a given user
mailchimp_cron Implements hook_cron().
mailchimp_form_user_register_form_alter Implements hook_form_FORM_ID_alter(). Add newsletter fields to registration form.
mailchimp_menu Implements hook_menu().
mailchimp_permission Implements hook_permission().
mailchimp_rebuild_users Rebuild the MailChimp users's table.
mailchimp_subscribe_anon_form Return a form for a given MC list
mailchimp_subscribe_anon_form_all Return a form for all available MC lists
mailchimp_subscribe_anon_form_submit Submit handler for anonymous subscription form
mailchimp_subscribe_auth_form Add mailchimp form fields to account and registration forms
mailchimp_subscribe_auth_form_submit Submit handler to add users to lists when editing/creating a user
mailchimp_subscribe_page Return all available MC lists a given user can subscribe to
mailchimp_unsubscribe_form MailChimp unsubscribe form
mailchimp_unsubscribe_form_submit submit handler for unsubscribe form
mailchimp_unsubscribe_form_validate validate unsubscribe form
mailchimp_user_delete Implements hook_user_delete().
mailchimp_user_edit_access Access callback for editing newsletter subscriptions.
mailchimp_user_insert Implements hook_user_insert().
mailchimp_user_update Implements hook_user_update().
_mailchimp_get_api_object Get a Mailchimp API object for communication with the mailchimp server
_mailchimp_get_available_lists Get all of the lists that the given user can subscribe to.
_mailchimp_get_required_lists Return an array of all required lists.
_mailchimp_insert_drupal_form_tag Convert mailchimp form elements to Drupal Form API
_mailchimp_is_subscribed Check if the given user is subscribed to the given list
_mailchimp_load_user_list_mergevars Get the relevant merge vars for the given user for the given list
_mailchimp_subscribe_anon_form Helper function to return form elements for a single anon newsletter
_mailchimp_subscribe_user Subscribe or update a user in a given list
_mailchimp_unsubscribe_user Unsubscribe the given user from the given list

Constants