mailchimp_lists.module in Mailchimp 7.2
Mailchimp lists module.
File
modules/mailchimp_lists/mailchimp_lists.moduleView source
<?php
/**
* @file
* Mailchimp lists module.
*/
define('MAILCHIMP_TESTLIST_REQUIRED', 'required');
define('MAILCHIMP_TESTLIST_OPTIONAL', 'optional');
define('MAILCHIMP_TESTLIST_ANONYMOUS', 'anonymous');
define('MAILCHIMP_QUEUE_CRON', 'mailchimp_cron');
/**
* Implements hook_menu().
*/
function mailchimp_lists_menu() {
$items = array();
$items['admin/config/services/mailchimp/lists'] = array(
'title' => 'Lists and Users',
'description' => 'Manage MailChimp Lists and user settings.',
'page callback' => 'mailchimp_lists_overview_page',
'access arguments' => array(
'administer mailchimp',
),
'type' => MENU_LOCAL_TASK,
'file' => 'includes/mailchimp_lists.admin.inc',
'weight' => -10,
);
$items['admin/config/services/mailchimp/lists/add'] = array(
'title' => 'Add a list',
'description' => 'Add a new MailChimp list.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_list_form',
),
'access arguments' => array(
'administer mailchimp',
),
'file' => 'includes/mailchimp_lists.admin.inc',
'type' => MENU_LOCAL_ACTION,
);
$items['admin/config/services/mailchimp/lists/refresh'] = array(
'title' => 'Refresh lists from MailChimp',
'description' => 'Refresh lists from MailChimp.',
'page callback' => 'mailchimp_lists_refresh_page',
'access arguments' => array(
'administer mailchimp',
),
'type' => MENU_LOCAL_ACTION,
'file' => 'includes/mailchimp_lists.admin.inc',
);
$items['admin/config/services/mailchimp/lists/%mailchimp_lists/edit'] = array(
'title' => 'Edit a list',
'description' => 'Edit a new MailChimp list.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_list_form',
5,
),
'load arguments' => array(
5,
),
'access arguments' => array(
'administer mailchimp',
),
'file' => 'includes/mailchimp_lists.admin.inc',
'type' => MENU_CALLBACK,
);
$items['admin/config/services/mailchimp/lists/%mailchimp_lists/delete'] = array(
'title' => 'Delete list',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_delete_list_form',
5,
),
'access arguments' => array(
'administer mailchimp',
),
'file' => 'includes/mailchimp_lists.admin.inc',
);
$items['user/%user/mailchimp'] = array(
'page callback' => 'mailchimp_lists_user_subscribe_page',
'page arguments' => array(
1,
),
'title' => 'Newsletter Subscriptions',
'type' => MENU_LOCAL_TASK,
'access callback' => 'mailchimp_lists_user_subscribe_page_access',
'access arguments' => array(
1,
),
);
$items['mailchimp/subscribe'] = array(
'title' => 'Newsletter Subscription',
'description' => 'Present all available free form newsletter subscriptions.',
'page callback' => 'mailchimp_lists_freeform_subscribe_page',
'access callback' => 'mailchimp_lists_freeform_subscribe_page_access',
'type' => MENU_SUGGESTED_ITEM,
);
$items['mailchimp/lists/%mailchimp_lists/queue_existing'] = array(
'title' => 'Queue existing users',
'description' => 'Add existing users to a required lists queue.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_queue_existing_form',
2,
),
'access callback' => 'mailchimp_lists_queue_existing_access',
'access arguments' => array(
2,
),
'file' => 'includes/mailchimp_lists.admin.inc',
);
return $items;
}
/**
* Access callback for mailchimp_lists_user_subscribe_page().
*/
function mailchimp_lists_user_subscribe_page_access($user) {
$lists = mailchimp_lists_get_available_lists($user, array(
'show_account_form' => 1,
));
return count($lists) > 0 & user_edit_access($user);
}
/**
* Access callback for mailchimp_lists_queue_existing_form().
*/
function mailchimp_lists_queue_existing_access($list) {
$ret = FALSE;
if ($list->settings['cron'] && user_access('administer mailchimp')) {
$ret = TRUE;
}
return $ret;
}
/**
* Access callback for mailchimp_lists_freeform_subscribe_page().
*/
function mailchimp_lists_freeform_subscribe_page_access() {
$ret = user_access('administer mailchimp');
if (!$ret) {
global $user;
$lists = mailchimp_lists_get_available_lists($user);
$ret = count($lists) > 0;
}
return $ret;
}
/**
* Implements hook_cron().
*
* Process all records in the mailchimp cron queue.
*/
function mailchimp_lists_cron() {
$queue = DrupalQueue::get(MAILCHIMP_QUEUE_CRON);
$queue
->createQueue();
$queue_count = $queue
->numberOfItems();
// Claim items off the queue and organize them into batches:
if ($queue_count > 0) {
$lists_by_mc_id = array();
$batches_add = array();
$batches_rem = array();
$count = 0;
$batch_limit = variable_get('mailchimp_batch_limit', 100);
$batch_size = $queue_count < $batch_limit ? $queue_count : $batch_limit;
while ($count < $batch_size) {
if ($item = $queue
->claimItem()) {
$list = mailchimp_lists_load($item->data['list_id']);
$mc_list_id = $list->mc_list_id;
// Store this list object so we can reference it later by its MC ID.
$lists_by_mc_id[$mc_list_id] = $list;
// If all we have is an anonymous email, load it. We check for a value
// first to be backwards-compatible with versions that didn't pass the
// raw email into the queue item.
if (isset($item->data['email'])) {
$email = $item->data['email'];
}
$mergevars = NULL;
// If there is a valid account, load data from it:
if (!empty($item->data['uid'])) {
$account = user_load($item->data['uid']);
$email = $account->mail;
$mergevars = mailchimp_lists_load_user_mergevars($account, $list);
}
switch ($item->data['op']) {
case 'add':
// @todo: test behavior of 'update' operations here
case 'update':
// If $mergevars are empty here, populate with the basic element:
if (empty($mergevars)) {
$mergevars = array(
'EMAIL' => $email,
);
}
if (!empty($item->data['groupings'])) {
$mergevars['GROUPINGS'] = $item->data['groupings'];
}
$batches_add[$mc_list_id][] = $mergevars;
break;
case 'remove':
$batches_rem[$mc_list_id][] = $email;
break;
}
$queue
->deleteItem($item);
}
$count++;
}
// Now we process our batches:
$mcapi = mailchimp_get_api_object();
// Remove if necessary:
$rem_count = 0;
$ret = array();
foreach ($batches_rem as $listid => $batch) {
if (count($batch)) {
// @todo: consider if the delete flag should be true or false
$ret = $mcapi
->listBatchUnsubscribe($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);
}
}
else {
$rem_count++;
}
}
}
watchdog('mailchimp', 'Removed !rem_count records in MailChimp', array(
'!rem_count' => $rem_count,
), WATCHDOG_NOTICE);
// Add if necessary:
$add_count = $update_count = 0;
foreach ($batches_add as $listid => $batch) {
if (count($batch)) {
$list_settings = $lists_by_mc_id[$listid]->settings;
$double_opt_in = $list_settings['doublein'];
$ret = $mcapi
->listBatchSubscribe($listid, $batch, $double_opt_in, TRUE);
if ($ret['error_count'] > 0) {
foreach ((array) $ret['errors'] as $error) {
watchdog('mailchimp', 'MCAPI Error: %errmsg', array(
'%errmsg' => $error['message'],
), WATCHDOG_ERROR);
}
}
}
$add_count += $ret['add_count'];
$update_count += $ret['update_count'];
}
watchdog('mailchimp', 'Added !add_count, updated !update_count records in MailChimp', array(
'!add_count' => $add_count,
'!update_count' => $update_count,
), WATCHDOG_NOTICE);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Add newsletter fields to registration form.
*/
function mailchimp_lists_form_user_register_form_alter(&$form, &$form_state, $form_id) {
$account = $form['#user'];
// Need to force feed the authenticated role to this account object so the
// right newsletters are available:
$account->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
$lists = mailchimp_lists_get_available_lists($account, array(
'show_register_form' => 1,
));
if (!empty($lists)) {
// Wrap in a fieldset.
$form['mailchimp_lists'] = array(
'#type' => 'fieldset',
'#title' => t('Newsletters'),
'#tree' => TRUE,
);
foreach ($lists as $list) {
mailchimp_lists_auth_newsletter_form($form['mailchimp_lists'], $list, $account, $list->settings['required']);
}
}
}
/**
* Implements hook_user_insert().
*
* Subscribe new users to optional and required newsletters.
*/
function mailchimp_lists_user_insert(&$edit, $account, $category) {
// @todo: pay attention to user status.
if (isset($edit['mailchimp_lists']) && count($edit['mailchimp_lists']) > 0) {
// Remove MailChimp list option values unless a user has chosen to
// subscribe.
// This avoids unsubscribing users from lists they have have subscribed
// to before creating an account.
foreach ($edit['mailchimp_lists'] as $key => $list_options) {
if ($list_options['subscribe'] !== 1) {
unset($edit['mailchimp_lists'][$key]);
}
}
if (!empty($edit['mailchimp_lists'])) {
mailchimp_lists_process_subscribe_form_choices($edit['mailchimp_lists'], $account);
}
}
// Handle required lists:
mailchimp_lists_user_sync($account);
}
/**
* Implements hook_user_delete().
*/
function mailchimp_lists_user_delete($account) {
// Unsubscribe a user from all required & optional lists:
// Load any lists that they have access to by role:
$lists = mailchimp_lists_get_available_lists($account);
if (!empty($lists)) {
foreach ($lists as $list) {
// @todo: after we have local preference tracking, remove only lists
// that are required or opted in.
mailchimp_lists_execute_change('remove', $list, $account->mail);
}
}
}
/**
* Implements hook_user_update().
*/
function mailchimp_lists_user_update(&$edit, $account, $category) {
if (isset($edit['roles'])) {
if ($category == 'account') {
$removed_roles = array_diff_key($edit['original']->roles, $edit['roles']);
mailchimp_lists_user_sync($account, isset($edit['original']) ? $edit['original']->mail : '', isset($edit['mail']) ? $edit['mail'] : '', !empty($removed_roles));
}
}
}
/**
* Update a user's setting in all required lists or add to cron queue.
*
* @account $account
* @email string $old_email
* @email string $new_email
* @array $removed_roles
*/
function mailchimp_lists_user_sync($account, $old_email = '', $new_email = '', $roles_removed = FALSE) {
// Remove subscriptions if necessary:
// @todo: account for account status?
if ($roles_removed && !empty($old_email)) {
// Get a list of existing subscriptions:
$all_lists = mailchimp_lists_load_multiple();
foreach ($all_lists as $list) {
if (mailchimp_is_subscribed($list->mc_list_id, $old_email)) {
// Check if user still has a valid role for this list.
$valid_role = FALSE;
foreach ($account->roles as $role_id => $role_label) {
if (array_key_exists($role_id, $list->settings['roles'])) {
$valid_role = TRUE;
}
}
// Remove the user if they do not have a valid role:
if (!$valid_role) {
mailchimp_lists_execute_change('remove', $list, $account->mail);
}
}
}
}
// Add/update subscriptions if necessary:
$lists = mailchimp_lists_get_available_lists($account);
if (!empty($lists) && $account->status) {
// @todo: what about inactive accounts that are still registering?
$mcapi = mailchimp_get_api_object();
$lookup_email = !empty($old_email) ? $old_email : $account->mail;
$proper_email = !empty($new_email) ? $new_email : $account->mail;
foreach ($lists as $list) {
// Now we are ready to update or add this subscription.
// Was this account already subscribed?
if (mailchimp_is_subscribed($list->mc_list_id, $lookup_email)) {
// If so, we call for an update.
$mergevars = _mailchimp_lists_build_update_mergevars($account, $list, $lookup_email, $proper_email);
mailchimp_lists_execute_change('update', $list, $lookup_email, $mergevars, NULL, $mcapi);
}
elseif ($list->settings['required']) {
// This is a new account or required list that the account isn't already
// subscribed to, so we add them...
$mergevars = _mailchimp_lists_build_update_mergevars($account, $list, $lookup_email, $proper_email);
mailchimp_lists_execute_change('add', $list, $proper_email, $mergevars, $account, $mcapi);
}
}
}
}
/**
* Helper function for mailchimp_lists_user_sync().
*
* @user $account
* @mailchimp_list $list
* @email null $new_email
* @email null $old_email
*
* @return array
* The mergevars with all values inserted.
*/
function _mailchimp_lists_build_update_mergevars($account, $list, $lookup_email = NULL, $new_email = NULL) {
$mergevars = mailchimp_lists_load_user_mergevars($account, $list);
// Set the EMAIL merge var if an email address is being updated:
if (!empty($new_email)) {
$mergevars['EMAIL'] = $new_email;
}
// Include interest groups:
// @todo: can we use the $interest_groups argument
// in mailchimp_lists_load_user_mergevars?
if (!empty($lookup_email) && !empty($list->settings['include_interest_groups'])) {
$memberinfo = mailchimp_get_memberinfo($list->mc_list_id, $lookup_email);
$mergevars['GROUPINGS'] = $memberinfo['merges']['GROUPINGS'];
}
return $mergevars;
}
/**
* Page callback for a user newsletter subscription page.
*/
function mailchimp_lists_user_subscribe_page($account) {
// Get all available non-required lists:
$non_required_lists = mailchimp_lists_get_available_lists($account, array(
'show_account_form' => 1,
'required' => FALSE,
));
$required_lists_with_interest_groups = mailchimp_lists_get_available_lists($account, array(
'required' => 1,
'include_interest_groups' => 1,
));
$lists = array_merge($non_required_lists, $required_lists_with_interest_groups);
if (count($lists) == 0) {
return t('There are no available newsletter subscriptions.');
}
$form = drupal_get_form('mailchimp_lists_user_subscribe_form', $lists, $account);
$form['submit']['#value'] = t('Save');
return $form;
}
/**
* Page callback for a freeform newsletter subscription page.
*/
function mailchimp_lists_freeform_subscribe_page() {
// Get all available freeform lists:
global $user;
$lists = mailchimp_lists_get_available_lists($user, array(
'allow_anonymous' => TRUE,
));
if (count($lists) == 0) {
return t('There are no available newsletter subscriptions.');
}
return drupal_get_form('mailchimp_lists_user_subscribe_form', $lists, $user);
}
/**
* Returns a subscription form, or forms, for a given user as a single form.
*
* If there are multiple lists, this generates a single form for all of them.
*/
function mailchimp_lists_user_subscribe_form($form, &$form_state, $lists, $account) {
$form['#attributes'] = array(
'class' => array(
'mailchimp-lists-user-subscribe-form',
),
);
$form['account'] = array(
'#type' => 'value',
'#value' => $account,
);
$form['mailchimp_lists'] = array(
'#tree' => TRUE,
);
$multiple_lists = count($lists) != 1;
foreach ($lists as $list) {
$include_header = FALSE;
if ($list->settings['required'] && $multiple_lists) {
$include_header = TRUE;
}
mailchimp_lists_auth_newsletter_form($form['mailchimp_lists'], $list, $account, $include_header);
}
$submit_label = 'Subscribe';
if (!$multiple_lists && isset($lists[0]->settings['submit_label'])) {
$submit_label = $lists[0]->settings['submit_label'];
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t($submit_label),
);
return $form;
}
/**
* Return a form element for a single newsletter.
*/
function mailchimp_lists_auth_newsletter_form(&$form, $list, $account, $add_header = FALSE) {
// Determine if a user is subscribed to the list.
$is_subscribed = FALSE;
$default_subscribed = FALSE;
$is_anonymous = !empty($account->roles[DRUPAL_ANONYMOUS_RID]) && empty($account->roles[DRUPAL_AUTHENTICATED_RID]);
if ($account && $account->uid > 0) {
$is_subscribed = mailchimp_is_subscribed($list->mc_list_id, $account->mail);
}
elseif (!$list->settings['required']) {
$default_subscribed = !empty($list->settings['default_register_form_optin']);
}
// Wrap in a div:
$wrapper_key = 'mailchimp_' . $list->name;
$form[$wrapper_key] = array(
'#prefix' => '<div id="mailchimp-newsletter-' . $list->name . '" class="mailchimp-newsletter-wrapper">',
'#suffix' => '</div>',
);
$form[$wrapper_key]['list'] = array(
'#type' => 'value',
'#value' => $list,
);
// Add the title and description to lists for anonymous users or if requested:
if ($add_header || $list->settings['allow_anonymous'] && $is_anonymous) {
$label_text = isset($list->settings['form_label']) ? $list->settings['form_label'] : 'Sign up for ' . $list
->label();
$label = html_entity_decode(check_plain($label_text, ENT_QUOTES, 'UTF-8'));
$form[$wrapper_key]['title'] = array(
'#type' => 'item',
'#markup' => $label,
'#description' => t('@mc_list_description', array(
'@mc_list_description' => $list->description,
)),
);
}
// Add merge vars for anonymous forms:
if ($list->settings['allow_anonymous'] && $is_anonymous) {
$mergevalues = NULL;
$mc_list = mailchimp_get_list($list->mc_list_id);
if (!empty($mc_list['mergevars'])) {
foreach ($mc_list['mergevars'] as $mergevar) {
if (!empty($list->settings['mergefields_display'][$mergevar['tag']])) {
$form[$wrapper_key]['mergevars'][$mergevar['tag']] = mailchimp_lists_insert_drupal_form_tag($mergevar);
}
}
}
}
elseif (!$list->settings['required']) {
$form[$wrapper_key]['subscribe'] = array(
'#type' => 'checkbox',
'#title' => isset($list->settings['form_label']) ? t($list->settings['form_label']) : t('Subscribe to the @newsletter newsletter', array(
'@newsletter' => $list
->label(),
)),
'#default_value' => $default_subscribed && !$account->uid || $is_subscribed,
'#description' => $list->description,
);
}
elseif (!$add_header) {
$form[$wrapper_key]['description'] = array(
'#markup' => $list->description,
);
}
// Present interest groups:
if ($list->settings['include_interest_groups']) {
$mc_list = mailchimp_get_list($list->mc_list_id);
// Perform test in case error comes back from MCAPI when getting groups:
if (is_array($mc_list['intgroups'])) {
$form[$wrapper_key]['interest_groups'] = array(
'#type' => 'fieldset',
'#title' => isset($list->settings['interest_groups_label']) ? t($list->settings['interest_groups_label']) : t('Interest Groups'),
'#weight' => 100,
'#states' => array(
'collapsed' => array(
':input[name="mailchimp_lists[mailchimp_' . $list->name . '][subscribe]"]' => array(
'checked' => FALSE,
),
),
),
);
foreach ($mc_list['intgroups'] as $group) {
// Ignore hidden fields:
// @todo: consider merging to hidden values.
if ($group['form_field'] == 'hidden') {
continue;
}
// Set the form field type:
switch ($group['form_field']) {
case 'radio':
$field_type = 'radios';
break;
case 'dropdown':
$field_type = 'select';
break;
default:
$field_type = $group['form_field'];
}
// Extract the field options:
$options = array();
foreach ((array) $group['groups'] as $option) {
$options[$option['name']] = $option['name'];
}
// Grab the default values for this group:
// @todo: find a better way.
$default_merge_values = array();
$default_opt_in = FALSE;
if ($account->uid) {
$memberinfo = mailchimp_get_memberinfo($list->mc_list_id, $account->mail);
if (isset($memberinfo['merges']['GROUPINGS'])) {
foreach ($memberinfo['merges']['GROUPINGS'] as $membergroup) {
if ($membergroup['id'] == $group['id']) {
$default_merge_values = preg_split('#(?<!\\\\)\\,#', str_replace(', ', ',', $membergroup['groups']));
$default_merge_values = str_replace('\\,', ', ', $default_merge_values);
break;
}
}
}
}
elseif (isset($list->settings['opt_in_interest_groups']) && $list->settings['opt_in_interest_groups']) {
$default_opt_in = TRUE;
$default_merge_values = $options;
}
$form[$wrapper_key]['interest_groups'][$group['id']] = array(
'#type' => $field_type,
'#title' => $group['name'],
'#options' => $options,
'#default_value' => $is_subscribed || $default_opt_in ? $default_merge_values : array(),
'#attributes' => array(
'class' => array(
'mailchimp-newsletter-interests-' . $list->id,
),
),
);
}
}
}
return $form;
}
/**
* Submit handler to add users to lists when editing/creating a user.
*/
function mailchimp_lists_user_subscribe_form_submit($form, &$form_state) {
$account = $form_state['values']['account'];
mailchimp_lists_process_subscribe_form_choices($form_state['values']['mailchimp_lists'], $account);
}
/**
* Processor for various list form submissions.
*
* Subscription blocks, user settings, and new user creation.
*
* @array $list_forms: an array of mailchimp_list form values, as generated
* by mailchimp_lists_list_form()
* @account null $account: the user account to subscribe, if available.
* Otherwise, operations will be run with the ['mergevars']['EMAIL'] value.
*/
function mailchimp_lists_process_subscribe_form_choices($list_forms, $account = NULL) {
$mcapi = mailchimp_get_api_object();
foreach ($list_forms as $form_list) {
$list = $form_list['list'];
$selected = FALSE;
$is_anonymous = !$account || !$account->uid;
$mergevars = NULL;
$function = '';
$ret = FALSE;
$interest_groups = !empty($form_list['interest_groups']) ? $form_list['interest_groups'] : NULL;
if (!$is_anonymous) {
$mail = $account->mail;
$selected = !empty($form_list['subscribe']);
$mergevars = mailchimp_lists_load_user_mergevars($account, $list, $interest_groups);
}
else {
$mail = $form_list['mergevars']['EMAIL'];
$mergevars = $form_list['mergevars'];
// Include interest groups if present:
if (!empty($interest_groups)) {
$mergevars['GROUPINGS'] = _mailchimp_lists_reformat_groupings($interest_groups);
}
}
$is_subscribed = mailchimp_is_subscribed($list->mc_list_id, $mail);
// Determine what function is appropriate.
// Unsubscribe a subscribed user who unchecked an Optional list:
if ($is_subscribed && !$selected && !$list->settings['required']) {
$function = 'remove';
}
elseif ($selected || $list->settings['required'] || $is_anonymous) {
if ($is_subscribed) {
$function = 'update';
}
else {
$function = "add";
}
}
if (!empty($function)) {
$ret = mailchimp_lists_execute_change($function, $list, $mail, $mergevars, $account, $mcapi);
if (!$ret) {
drupal_set_message(t('There was a problem with your newsletter signup: @msg', array(
'@msg' => $mcapi->errorMessage,
)), 'warning');
}
}
}
}
/**
* Calls the appropriate API function, or adds to the queue, as appropriate.
*
* @string $function - 'add', 'remove', or 'update'. Matches Queue operations.
* @mailchimp_lists $list - the list to update
* @string $mail - email address to update on the list
* @array $mergevars - merge variables array formatted for mailchimp API
* @account null $account - account that $mail came from, if non-anonymous call
* @mcapi_entity null &$mcapi - api object if loaded, to avoid extra API calls
* @queue null &$queue - the cron queue. If passed, this will force use of cron.
*
* @return <boolean>
* Indicates whether the operation was successful.
*/
function mailchimp_lists_execute_change($function, $list, $mail, $mergevars = NULL, $account = NULL, $mcapi = NULL, &$queue = NULL) {
// If cron is enabled for this list, queue the function.
if ($list->settings['cron'] || isset($queue)) {
if (!isset($queue)) {
$queue = DrupalQueue::get(MAILCHIMP_QUEUE_CRON);
$queue
->createQueue();
}
$queue
->createItem(array(
'uid' => isset($account) ? $account->uid : NULL,
'email' => $mail,
'list_id' => $list->id,
'op' => $function,
'groupings' => isset($mergevars['GROUPINGS']) ? $mergevars['GROUPINGS'] : NULL,
));
$ret = TRUE;
}
else {
if (empty($mcapi)) {
$mcapi = mailchimp_get_api_object();
}
switch ($function) {
case 'add':
$ret = mailchimp_subscribe_user($list, $mail, $mergevars, TRUE, $mcapi);
break;
case 'remove':
$ret = mailchimp_unsubscribe_user($list, $mail, TRUE, $mcapi);
break;
case 'update':
$ret = mailchimp_update_user($list, $mail, $mergevars, TRUE, $mcapi);
break;
}
}
return $ret;
}
/**
* Return an array of available user tokens.
*/
function mailchimp_lists_get_merge_tokens() {
$out = array(
'' => t('-- Select --'),
);
// Invoke hook to get all merge tokens:
$tokens = module_invoke_all('mailchimp_lists_merge_tokens');
foreach ($tokens as $key => $token) {
$out[$key] = t('!field', array(
'!field' => $token['name'],
));
}
return $out;
}
/**
* Implements hook_mailchimp_lists_merge_tokens().
*/
function mailchimp_lists_mailchimp_lists_merge_tokens() {
$tokens = array();
// Grab user tokens. Support nested tokens of one level.
$token_info = token_info();
if (!empty($token_info['tokens']['user'])) {
$tokens = $token_info['tokens']['user'];
foreach ($tokens as $key => $info) {
if (isset($info['type']) && isset($token_info['tokens'][$info['type']])) {
foreach ($token_info['tokens'][$info['type']] as $key2 => $info2) {
// Add in nested tokens.
$info2['name'] = $info['name'] . ' - ' . $info2['name'];
$tokens[$key . ':' . $key2] = $info2;
}
}
}
}
return $tokens;
}
/**
* Get the relevant merge vars for the given user for the given list.
*
* @account $account
* @mailchimp_list $list
* @array null $interest_groups
*
* @return <array>
* mergevars array formatted for the MCAPI
*/
function mailchimp_lists_load_user_mergevars($account, $list, $interest_groups = NULL) {
$values = array();
// Grab the saved list merge vars and filter out unset values:
if (!empty($list->settings['mergefields'])) {
$mergevars = array_filter($list->settings['mergefields']);
// We have to filter one-by-one, since an array_flip would munch any
// duplicate values.
foreach ($mergevars as $name => $token) {
// Match with token values:
$replaced = module_invoke_all('mailchimp_lists_merge_values', array(
$token => $name,
), $account, $list);
// Only populate our merge variables if the replacement was successful,
// some configured tokens might not always be available.
if (isset($replaced[$name])) {
$values[$name] = $replaced[$name];
}
}
// Always add email:
$values += array(
'EMAIL' => $account->mail,
);
}
// Format interest groups if present:
if (!empty($interest_groups)) {
$values['GROUPINGS'] = _mailchimp_lists_reformat_groupings($interest_groups);
}
return $values;
}
/**
* Implements hook_mailchimp_lists_merge_values().
*/
function mailchimp_lists_mailchimp_lists_merge_values($mergevars, $account, $list) {
return token_generate('user', $mergevars, array(
'user' => $account,
));
}
/**
* Return all available lists for a given user.
*
* @param <drupal_user> $account
* Optional account to get available lists for. Otherwise returns lists
* available to the currently authenticated user.
* @param <array> $conditions
* List settings to filter the results by (uses logical "AND").
* Options include the following (see mailchimp_lists_list_form_submit()):
* 'allow_anonymous' => boolean
* 'required' => boolean
* 'doublein' => boolean
* 'cron' => boolean
* 'webhooks' => boolean
* 'show_account_form' => boolean
* 'show_register_form' => boolean
* 'default_register_form_optin' => boolean
* 'include_interest_groups' => boolean
* 'form_label' => string
* 'submit_label' => string
* 'interest_groups_label' => string
*
* @return <array>
* An array of appropriate mailchimp_list objects.
*/
function mailchimp_lists_get_available_lists($account = NULL, $conditions = array()) {
if (empty($account)) {
global $user;
$account = $user;
}
$lists = mailchimp_lists_load_multiple(array());
$user_lists = array();
foreach ($lists as $lid => $list) {
foreach ($account->roles as $rid => $role) {
if (isset($list->settings['roles'][$rid]) && $list->settings['roles'][$rid]) {
$pass = TRUE;
if (!empty($conditions)) {
foreach ($conditions as $key => $condition) {
if (!isset($list->settings[$key]) || $list->settings[$key] != $condition) {
$pass = FALSE;
}
}
}
if ($pass) {
$user_lists[$lid] = $list;
}
break;
}
}
}
return $user_lists;
}
/**
* Implements hook_block_info().
*/
function mailchimp_lists_block_info() {
$blocks = array();
$lists = mailchimp_lists_load_multiple_by_name();
foreach ($lists as $name => $list) {
$blocks[$name] = array(
'info' => t('Mailchimp Subscription Form: @name', array(
'@name' => $list
->label(),
)),
'cache' => DRUPAL_CACHE_PER_USER,
);
}
return $blocks;
}
/**
* Implements hook_block_view().
*
* Provides a block for each available list for a given user
*/
function mailchimp_lists_block_view($delta = '') {
$block = array();
global $user;
$list = mailchimp_lists_load($delta);
$useful = FALSE;
// @todo: figure out why were getting a block with the delta "freeform" here
// and once we know, eliminate this 'if' clause.
if (!empty($list)) {
$useful = $list->settings['allow_anonymous'] && !empty($user->roles[DRUPAL_ANONYMOUS_RID]) || $list->settings['include_interest_groups'] || !$list->settings['required'];
}
foreach ($user->roles as $rid => $role) {
$accessable = isset($list->settings['roles'][$rid]) && $list->settings['roles'][$rid];
if ($accessable && $useful) {
$block['subject'] = $list->settings['required'] ? t('@title Subscription Settings', array(
'@title' => $list->label,
)) : t('Subscribe to @title', array(
'@title' => $list
->label(),
));
$block['content'] = drupal_get_form('mailchimp_lists_user_subscribe_form_' . $list->name, array(
$list,
), $user);
break;
}
}
return $block;
}
/**
* Convert mailchimp form elements to Drupal Form API.
*
* @param <mailchimp_form_element> $mergevar
* The mailchimp-formatted form element to convert.
*
* @return <drupal_form_element>
* A properly formatted drupal form element.
*/
function mailchimp_lists_insert_drupal_form_tag($mergevar) {
// Insert common FormAPI properties:
$input = array(
'#title' => t('@mergevar', array(
'@mergevar' => $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 relevant 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 relevant information
// on MailChimp.
foreach ($mergevar['choices'] as $choice) {
$choices[$choice] = $choice;
}
$input['#options'] = $choices;
break;
case 'email':
if (element_info_property('emailfield', '#type')) {
// Set to an HTML5 email type if 'emailfield' is supported:
$input['#type'] = 'emailfield';
}
else {
// Set to standard text type if 'emailfield' isn't defined:
$input['#type'] = 'textfield';
}
$input['#size'] = $mergevar['size'];
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;
}
/**
* Implements hook_forms().
*/
function mailchimp_lists_forms($form_id, $args) {
// Map all instances of mailchimp_lists_user_subscribe_form to a single form
// factory. Needed in case more than one block appears on a single page.
if (strpos($form_id, 'mailchimp_lists_user_subscribe_form') !== FALSE) {
$forms[$form_id] = array(
'callback' => 'mailchimp_lists_user_subscribe_form',
);
return $forms;
}
}
/**
* Queue existing users in a list. Optionally, queue users to remove.
*
* @mailchimp_list $list
*
* @boolean $queue_removals
* If set to TRUE, will queue anyone who should be removed from the list.
*
* @return int
* Number of users queued.
*/
function mailchimp_lists_queue_existing($list, $queue_removals = FALSE) {
// Grab our queue:
$queue = DrupalQueue::get(MAILCHIMP_QUEUE_CRON);
$queue
->createQueue();
// Get a list of active users:
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'user')
->propertyCondition('status', 1);
$result = $query
->execute();
$users = user_load_multiple(array_keys($result['user']));
// If the user belongs in the list, add to queue.
// @todo Use the batch system to avoid timeouts for lots of users.
$count = 0;
foreach ($users as $user) {
$intersect = array_intersect(array_keys($user->roles), $list->settings['roles']);
if (!empty($intersect)) {
if ($list->settings['required']) {
$merge_vars = mailchimp_lists_load_user_mergevars($user, $list);
mailchimp_lists_execute_change('add', $list, $user->mail, $merge_vars, $user, NULL, $queue);
$count++;
}
}
elseif ($queue_removals) {
if (mailchimp_is_subscribed($list->mc_list_id, $user->mail)) {
mailchimp_lists_execute_change('remove', $list, $user->mail, NULL, $user, NULL, $queue);
$count++;
}
}
}
return $count;
}
/**
* Helper function to make an API-ready array from an interest group form.
*/
function _mailchimp_lists_reformat_groupings($interest_groups) {
$groupings = array();
foreach ($interest_groups as $key => $group) {
$group = preg_replace('/,/', '\\,', $group);
$groups = is_array($group) ? implode(',', array_filter($group)) : $group;
$groupings[] = array(
'id' => $key,
'groups' => $groups,
);
}
return $groupings;
}
/**
* Implements hook_entity_info().
*/
function mailchimp_lists_entity_info() {
$return = array(
'mailchimp_list' => array(
'label' => t('MailChimp List'),
'plural label' => t('MailChimp Lists'),
'entity class' => 'MailchimpList',
'controller class' => 'EntityAPIControllerExportable',
'base table' => 'mailchimp_lists',
'uri callback' => 'mailchimp_list_uri',
'fieldable' => FALSE,
'exportable' => TRUE,
'label callback' => 'entity_class_label',
'module' => 'mailchimp_lists',
'entity keys' => array(
'id' => 'id',
'name' => 'name',
),
'bundles' => array(
'mailchimp_list' => array(
'label' => t('MailChimp List'),
),
),
'view modes' => array(
'full' => array(
'label' => t('Complete List'),
'custom settings' => FALSE,
),
),
),
);
return $return;
}
/**
* Loads a list by ID.
*/
function mailchimp_lists_load($list_id) {
$lists = mailchimp_lists_load_multiple(array(
$list_id,
), array());
return $lists ? reset($lists) : FALSE;
}
/**
* Loads multiple registrations by ID or based on a set of matching conditions.
*
* @see entity_load()
*
* @array $list_ids
* Array of list IDS to load.
* @array $conditions
* An array of conditions on the {mailchimp_list} table in the form
* 'field' => $value.
* @bool $reset
* Whether to reset the internal contact loading cache.
*
* @return array
* An array of contact objects indexed by registration_id.
*/
function mailchimp_lists_load_multiple($list_ids = array(), $conditions = array(), $reset = FALSE) {
if (empty($list_ids)) {
$list_ids = FALSE;
}
return entity_load('mailchimp_list', $list_ids, $conditions, $reset);
}
/**
* Gets an array of all lists, keyed by the list name.
*
* @string $name
* If set, the list with the given name is returned.
*
* @return MailchimpList[]
* Depending whether $name isset, an array of lists or a single one.
*/
function mailchimp_lists_load_multiple_by_name($name = NULL) {
$lists = entity_load_multiple_by_name('mailchimp_list', isset($name) ? array(
$name,
) : FALSE);
return isset($name) ? reset($lists) : $lists;
}
/**
* Deletes multiple lists by ID.
*
* @array $list_ids
* An array of contact IDs to delete.
*
* @return bool
* TRUE on success, FALSE otherwise.
*/
function mailchimp_lists_delete_multiple($list_ids) {
return entity_get_controller('mailchimp_list')
->delete($list_ids);
}
/**
* Saves a list.
*
* @MailchimpList $list
* The full list object to save.
*
* @return MailchimpList
* The saved list object.
*/
function mailchimp_lists_save(MailchimpList $list) {
return $list
->save();
}
/**
* Create a new Mailchimp List object.
*
* @param array $values
* Associative array of values. At least include array('type' => $type)
*
* @return MailchimpList
* New MailchimpList entity.
*/
function mailchimp_list_create(array $values = array()) {
return entity_get_controller('mailchimp_list')
->create($values);
}
/**
* Implements hook_mollom_form_list().
*
* Enable Mollom integration for user subscription forms.
*/
function mailchimp_lists_mollom_form_list() {
$forms = array();
$forms['mailchimp_lists_user_subscribe_form'] = array(
'title' => t('User newsletter subscription'),
);
return $forms;
}
/**
* Implements hook_mollom_form_info().
*/
function mailchimp_lists_mollom_form_info($form_id) {
// Set mollom form info.
$form_info = array(
'bypass access' => array(
'administer mailchimp',
),
'mode' => MOLLOM_MODE_CAPTCHA,
);
return $form_info;
}
Functions
Constants
Name![]() |
Description |
---|---|
MAILCHIMP_QUEUE_CRON | |
MAILCHIMP_TESTLIST_ANONYMOUS | |
MAILCHIMP_TESTLIST_OPTIONAL | |
MAILCHIMP_TESTLIST_REQUIRED | @file Mailchimp lists module. |