Hi. When a user visits their profile they get a tab (menu_local_task) for "Newsletter Subscriptions" that lets them edit their newsletter subscriptions. I would like to move this form directly onto the user's edit profile page (so no more tab)... what would be the best way to go about this?

Comments

JordanMagnuson’s picture

Okay, I think I've figured this out. Can anyone verify whether this is the correct implementation?

Also, would you be open to a patch which would allow this placement as an option in the mailchimp settings, in addition to the tab placement?

First, alter the user profile form, ala the way Mailchimp alters the user registration form:

function custom_helper_form_user_profile_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#user_category'] == 'account') {
    $account = $form['#user'];

    $lists = mailchimp_lists_get_available_lists($account, MAILCHIMP_LISTTYPE_OPTIONAL);

    if (!empty($lists)) {
      // wrap in a fieldset
      $form['mailchimp_lists'] = array(
        '#type' => 'fieldset',
        '#title' => t('Newsletter Subscriptions'),
        '#tree' => TRUE
      );
      foreach ($lists as $list) {
        mailchimp_lists_auth_newsletter_form($form['mailchimp_lists'], $list, $account);
      }
    }
  }
}

Then implement hook_user_presave to actually save the list information when the user saves their profile:

function custom_helper_user_presave(&$edit, $account, $category) {
  if (isset($edit['mailchimp_lists']) && count($edit['mailchimp_lists'] > 0)) {
    $mcapi = mailchimp_get_api_object();
    foreach ($edit['mailchimp_lists'] as $form_list) {
      $list = $form_list['list'];
      $ret = TRUE;

      // unsubscribe a subscribed user who unchecked a list
      if ($form_list['subscribe']) {
        $is_subscribed = mailchimp_is_subscribed($list->mc_list_id, $account->mail);

        // grab merge values
        $mergevars = mailchimp_lists_load_user_mergevars($account, $list);

        // include interest groups
        if (!empty($form_list['interest_groups'])) {
          $groupings = array();
          foreach ($form_list['interest_groups'] as $key => $group) {
            $groups = is_array($group) ? implode(',', array_filter($group)) : $group;
            $groupings[] = array('id' => $key, 'groups' => $groups);
          }
          $mergevars['GROUPINGS'] = $groupings;
        }

        if ($is_subscribed) {
          $ret = mailchimp_update_user($list, $account->mail, $mergevars, TRUE, $mcapi);
        }
        else {
          $ret = mailchimp_subscribe_user($list, $account->mail, $mergevars, TRUE, $mcapi);
        }
      }

      if (!$ret) {
        drupal_set_message(t('There was a problem with your newsletter signup: @msg',
          array('@msg' => $mcapi->errorMessage)));
      }
    }
  }

  // handle required lists
  mailchimp_lists_user_sync($account);
}
JordanMagnuson’s picture

Hm... seems to be working to subscribe a user, not not to unsubscribe... any thoughts?

JordanMagnuson’s picture

Stupid me. Instead of using hook_user_presave, I should have just added a submit handler to the user profile form. Here is my updated code, which seems to be working as desired:

/**
 * Implements hook_form_FORM_ID_alter to alter the user profile form
 */
function custom_helper_form_user_profile_form_alter(&$form, &$form_state, $form_id) {
  // Add mailchimp lists to user profile form
  // See mailchimp_lists_form_user_register_form_alter()
  if ($form['#user_category'] == 'account') {
    $account = $form['#user'];

    $lists = mailchimp_lists_get_available_lists($account, MAILCHIMP_LISTTYPE_OPTIONAL);

    if (!empty($lists)) {
      // wrap in a fieldset
      $form['mailchimp_lists'] = array(
        '#type' => 'fieldset',
        '#title' => t('Newsletter Subscriptions'),
        '#tree' => TRUE
      );
      foreach ($lists as $list) {
        mailchimp_lists_auth_newsletter_form($form['mailchimp_lists'], $list, $account);
      }
    }

    $form['#submit'][] = 'custom_helper_user_profile_form_submit';
  }
}

/**
 * Submit handler for user profile form.
 */
function custom_helper_user_profile_form_submit($form, &$form_state) {
  // Save mailchimp subscription settings when user saves their profile
  // See mailchimp_lists_user_subscribe_form_submit()
  $account = $form['#user'];
  $mcapi = mailchimp_get_api_object();
  foreach ($form_state['values']['mailchimp_lists'] as $form_list) {
    $list = $form_list['list'];
    $ret = TRUE;
    $selected = FALSE;
    if ($list->list_type == MAILCHIMP_LISTTYPE_OPTIONAL) {
      $mail = $account->mail;
      $selected = $form_list['subscribe'];
      $mergevars = mailchimp_lists_load_user_mergevars($account, $list);
    }
    else {
      $mail = $form_list['mergevars']['EMAIL'];
      $mergevars = $form_list['mergevars'];
    }

    $is_subscribed = mailchimp_is_subscribed($list->mc_list_id, $mail);

    // unsubscribe a subscribed user who unchecked a list
    if ($is_subscribed && !$selected && $list->list_type == MAILCHIMP_LISTTYPE_OPTIONAL) {
      $ret = mailchimp_unsubscribe_user($list, $account->mail, TRUE, $mcapi);
    }
    elseif (($selected && $list->list_type == MAILCHIMP_LISTTYPE_OPTIONAL) || $list->list_type == MAILCHIMP_LISTTYPE_FREEFORM) {
      // include interest groups
      if (!empty($form_list['interest_groups'])) {
        $groupings = array();
        foreach ($form_list['interest_groups'] as $key => $group) {
          $group = preg_replace('/,/', '\,', $group);
          $groups = is_array($group) ? implode(',', array_filter($group)) : $group;
          $groupings[] = array('id' => $key, 'groups' => $groups);
        }
        $mergevars['GROUPINGS'] = $groupings;
      }

      if ($is_subscribed) {
        $ret = mailchimp_update_user($list, $mail, $mergevars, TRUE, $mcapi);
      }
      else {
        $ret = mailchimp_subscribe_user($list, $mail, $mergevars, TRUE, $mcapi);
      }
    }

    if (!$ret) {
      drupal_set_message(t('There was a problem with your newsletter signup: @msg', array('@msg' => $mcapi->errorMessage)));
    }
  }
}
nagiek’s picture

@Jordan,

I'm doing the same thing and going about it the same way. However, you should try to standardize the form submits. Can't you write GlueCode instead?

function overrides_mailchimp_submit($form, $form_state) {
  global $user;
  $form_state['values']['account'] = $user;
  mailchimp_lists_user_subscribe_form_submit($form, $form_state);
}
JordanMagnuson’s picture

Good point nagiek, though I think the user account should be taken from the form, rather than using global $user, in case an admin is submitting the form for another user, or something. So:

function custom_helper_user_profile_form_submit($form, &$form_state) {
  $account = $form['#user'];
  $form_state['values']['account'] = $account;
  mailchimp_lists_user_subscribe_form_submit($form, $form_state);
}
JordanMagnuson’s picture

@nagiek: are you getting "You have updated your settings in list x" every time a user saves their profile, regardless of whether they change their mailchimp settings?

I think this is a bug that becomes apparent in our use case, and have opened an issue at http://drupal.org/node/1788916

Khumbu’s picture

could this me coded as an option in the mailchimp settings...so the non so technical guys can use this too...

anyway thx

gcb’s picture

Category: support » feature

Moving this to feature request queue -- seems more accurate at this point.

gcb’s picture

Status: Active » Closed (duplicate)