Comments

mollux’s picture

I made a patch to support Mailchimp 7.x-3.x
These changes were necessary because Mailchimp 3.x uses the MailChimp API library v2, and the API changed.
I only tested the subscription and the passthrough of groups, so other functionality (mergefields an interestfields) can still be broken.

This isn't an ideal solution, as it breaks Mailchimp 7.x-2.x support. Maybe this module should have a 3.x branch that supports webform 4.x and Mailchimp 3.x?

I think these issues are also related to the API change:
#1697874-21: Webform 4.x compatibility
#2295247: Call to undefined method DrupalMailchimp::listSubscribe()

kbentham’s picture

I have also patched the 7.x-1.x version for those of us still using webform 3.x.

jordanmagnuson’s picture

Status: Active » Needs work

I can confirm that #1 provides basic working functionality for the Mailchimp module 3.x branch.

It would be nice to potentially send out any available merge vars as well.

(One point to note is that the patch file currently conflicts with the double opt-in patch, as they are targeting the same line of code.)

joelpittet’s picture

Status: Needs work » Needs review
StatusFileSize
new1.22 KB

Re-rolling this patch as it doesn't apply any longer.

mducharme’s picture

Status: Needs review » Reviewed & tested by the community

Confirmed that the re-roll fixes this issue in 2.x as well. Thanks

knalstaaf’s picture

I'm still getting this error after patching (#1, #2 and #4):

Mailchimp_HttpError: MailChimp API call to <em class="placeholder">lists/subscribe</em> failed: Internal Server Error in DrupalMailchimp->call() (regel 87 van /home/mysite/domains/mysite.com/public_html/sites/all/modules/mailchimp/includes/mailchimp.inc).

I'm using Webform 7.x-3.21 (latest), Webform Mailchimp 7.x-1.0-rc2 and Mailchimp 7.x-3.2.

mducharme’s picture

And you do have the Mailchimp API Library downloaded and configured as per https://www.drupal.org/documentation/modules/mailchimp ?

This is the library you should have installed: https://bitbucket.org/mailchimp/mailchimp-api-php/get/2.0.4.zip

just.andy.shilton’s picture

Hi all,

Ok, firstly this is a major work in progress, but I'm hoping by posting here it might help some others and get me some help to turn this into proper patch files and test it all etc. (Spare time is what I'm lacking, sorry all).

In short, I needed to support webform 4 with the latest Mailchimp api (I'm using 2.0.6), but I hit major issues with hidden fields, single fields for groups, the renaming of the functions in the api (eg listsubscribe changing to lists->subscribe) and a few other things....so I set about trying to enhance the code in this module rather than write my own and i'm hoping some of you will help me finish testing it and completing the bits I'm not quite there on.

The following code replaces the entire webform_mailchimp.module code:

<?php

/**
 * @file
 * Webform Mailchimp integrates mailchimp into the webforms module.
 */

/**
 * Implements hook_webform_component_info().
 */
function webform_mailchimp_webform_component_info() {
  $components = array();

  $components['mailchimp'] = array(
    'label' => t('Mailchimp'),
    'description' => t('Sign up to a newsletter.'),
    'features' => array(
      'csv' => TRUE,
      'email' => TRUE,
      'email_address' => FALSE,
      'email_name' => FALSE,
      'required' => TRUE,
      'conditional' => FALSE,
      'group' => FALSE,
      'attachment' => FALSE,
    ),
    'file' => 'webform_mailchimp.inc',
  );

  return $components;
}

/**
 * Implements hook_webform_submission_insert().
 */
function webform_mailchimp_webform_submission_insert($node, $submission) {
  global $user;
  $mailchimp_lists = array();
  $email_address = '';

  if (!empty($node->webform['components'])) {
    foreach ($node->webform['components'] as $key => $field) {
      if ($field['type'] == 'mailchimp') {
        $mailchimp_lists[] = $field['extra']['mailchimp_list'];
        // Need to know if we should look for our own email field or another.
        if ($field['extra']['use_existing_email_field'] != 'mailchimp_field') {
          if (!empty($submission->data[$key][0])) {
            // Loop through components again to find our email field.
            foreach ($node->webform['components'] as $key2 => $field2) {
              if ($field2['form_key'] == $field['extra']['use_existing_email_field']) {
                $email_address = $submission->data[$key2][0];
              }
            }
          }
          // Visitor provided an email address but opted out of subscription.
          else {
            $email_address = '';
          }
        }
        // We have our own email field.
        else {
          $email_address = $submission->data[$key][0];
        }

        // Retrieve mergefields and create a merge array with key webform key
        // and value Mailchimp merge tag.
        if (!empty($field['extra']['mergefields'])) {
          $mergefields_key_array = array();
          $keyvaluepairs = explode("\n", $field['extra']['mergefields']);

          foreach ($keyvaluepairs as $keyvalue) {
            $keyvalue = trim($keyvalue);
            $keyvalue = explode('|', $keyvalue);
            if (is_array($keyvalue) && !empty($keyvalue[0]) && !empty($keyvalue[1])) {
              $mergefields_key_array[$keyvalue[1]] = $keyvalue[0];
            }
          }
        }

        // Retrieve interestfields and create a merge array with key webform key
        // and value Mailchimp group name.
        if (!empty($field['extra']['interestfields'])) {
          $groupfields_key_array = array();
          $keyvaluepairs = explode("\n", $field['extra']['interestfields']);

          foreach ($keyvaluepairs as $keyvalue) {
            $keyvalue = trim($keyvalue);
            $keyvalue = explode('|', $keyvalue);
            if (is_array($keyvalue) && !empty($keyvalue[0]) && !empty($keyvalue[1])) {
              $groupfields_key_array[$keyvalue[1]] = $keyvalue[0];
            }
          }
        }
      }
    }

    $mergefields_replacements = array();
    // Create the mergefield array.
    if (!empty($mergefields_key_array) && is_array($mergefields_key_array)) {
      foreach ($node->webform['components'] as $key => $field) {
        if (!empty($mergefields_key_array[$field['form_key']])) {
          // This is probably a bit to easy... The delta value is not taken
          // into account.
          $value = 0;
          if (isset($submission->data[$key][0])) {
            $value = $submission->data[$key][0];
          }
          $mergefields_replacements[$mergefields_key_array[$field['form_key']]] = $value;
        }
      }
    }

    $groupfields_replacements = array();
    // Create the mergefield array.
    if (!empty($groupfields_key_array) && is_array($groupfields_key_array)) {
      foreach ($node->webform['components'] as $key => $field) {
        if (!empty($groupfields_key_array[$field['form_key']])) {
          if (!empty($field['extra']['items'])) {
            // We are dealing with checkboxes, dropdowns and have received the id
            // instead of the raw value. So we need to extract the value and send
            // that instead.
            $choices = explode("\n", $field['extra']['items']);
            $sorted_choices = array();
            foreach ($choices as $choice_key => $choice_val) {
              $id_name = explode('|', trim($choice_val));
              $sorted_choices[$id_name[0]] = $id_name[1];
            }
            foreach ($submission->data[$key] as $filled_out_value) {
              $groupfields_replacements[$groupfields_key_array[$field['form_key']]][] = str_replace(",", "\,", $sorted_choices[$filled_out_value]);
            }
          }
          else {
            $groupfields_replacements[$groupfields_key_array[$field['form_key']]][] = reset($submission->data[$key]);
          }
        }
      }
      foreach ($groupfields_replacements as $groupname => $values_array) {
        $mergefields_replacements['groupings'][] = array(
          'name' => $groupname,
          //  'groups' => implode(',', $values_array),
          'groups' => $values_array,
        );
      }
    }

    // If we have an email address and a list is set, try to subscribe the user.
    if ($email_address != '' && !empty($mailchimp_lists)) {
      $q = mailchimp_get_api_object();
      if ($q) {

        foreach ($mailchimp_lists as $mailchimp_list) {
          $lists = $q->lists->interestGroupings($mailchimp_list);
          _webform_mailchimp_check_group($q, $mailchimp_list, $mergefields_replacements['groupings']);
          $success = $q->lists->subscribe($mailchimp_list, array('email' => $email_address), $mergefields_replacements, 'html', FALSE, TRUE, FALSE);
          if ($success) {
            watchdog('webform_mailchimp', 'E-mail subscribed: %email', array('%email' => $email_address), WATCHDOG_INFO);
          }
          else {
            watchdog('webform_mailchimp', 'E-mail not subscribed: %email Error: %error_code <br> %error_message', array('%email' => $email_address, '%error_message' => $q->errorMessage, '%error_code' => $q->errorCode), WATCHDOG_ERROR);
          }
        }
      }
      else {
        watchdog('webform_mailchimp', 'Could not get the Mailchimp API object.', array(), WATCHDOG_ERROR);
      }
    }
  }
}

function _webform_mailchimp_check_group($q, $mailchimp_list, $groups) {
  //$q = mailchimp object
  //$mailchimp_list = list id
  //$groups = array or groups ticked
  $lists = $q->lists->interestGroupings($mailchimp_list);


  $groupname = $groups[0]['groups'][0];
  $grouplistname = $groups[0]['name'];

  $grouplist = array();
  foreach ($lists as $list) {
    if ($list['name'] == $grouplistname) {
      foreach ($list['groups'] as $group) {
        $grouplist[] = $group['name'];
      }
    }
  }

  if (!in_array($groupname, $grouplist)) {
    if (count($grouplist)<60){
      $q->lists->interestGroupAdd($mailchimp_list, $groupname);
    }else{
      drupal_set_message('Sorry, I cannot add you to the mailing list at this time.','error');
          
    }
  }
  
}

This should stop the errors with the new api, but also stops this module from over writing existing subscribers with groups already selected. If you now subscribe to a different group, the code above will append that group selection.

Furthermore, the code above will create the group for you if it doesn't exist (see the new function added _webform_mailchimp_check_group). Note, it will only add it if there aren't 60 groups present already.

Todo: I need some help turning it into patch files for the maintainers to apply to the existing code, plus it needs testing (and probably some additional code) to cope with groups that are checkboxes (I think this will only submit one group, not multiples) and do some better error handling when there are 60 groups already.

Anyway, I hope it helps some of you. If it doesn't, just ignore me, but if it does that's great :)

Andy.

mducharme’s picture

@d33jay - I'd recommend opening a new issue that targets the 4.x branch. This issue is specific to 3.x and the current patch is RTBC.

joelpittet’s picture

+++ b/webform_mailchimp.module
@@ -130,9 +130,9 @@ function webform_mailchimp_webform_submission_insert($node, $submission) {
-        $mergefields_replacements['GROUPINGS'][] = array(
+        $mergefields_replacements['groupings'][] = array(

I've tested this and it seems GROUPINGS vs groupings doesn't affect the API call. Maybe worth leaving it uppercase unless we are going to change all instances?

just.andy.shilton’s picture

@mducharme, good point. It's not very clear what's going on there I must admit. Is this module going to split for 3 and 4?

kerasai’s picture

Confirming patch in #4 works with the following:

  • Drupal 7.36
  • Webform 7.x-4.3
  • MailChimp 7.x-3.2
  • Webform MailChimp 7.x-2.0-beta1+1-dev
  • With and without the double opt-in patch from #1664582-26: No confirmation emails?, no conflicts
sam152’s picture

#4 is working for me. +1 to RTBC.

sam152’s picture

I don't know if exceptions are new in this API, but we should consider catching them in $q->lists->subscribe. The MailChimp SDK throws exceptions on errors from the gateway. You can imagine why you wouldn't want exceptions in the critical patch of a webform submission.

sam152’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.78 KB

This patches fixes the error handling to work with the new API. Also doesn't kill the page request when something goes wrong on the MailChimp side.

das-peter’s picture

Status: Needs review » Needs work

I think this needs re-factoring in terms to not break backward compatibility.
As the project page states there are already branches related to the Webform branches.
Adding another branch that is related to the Mailchimp module branch seems to make things quite confusing.
Especially since the API diff, seems quite minor and should be coverable easily - as it stands now.

Is there a way to determine the API version? If so I'd say we go with conditional code execution for now.

joelpittet’s picture

@das-peter how about just a

method_exists ( mixed $object , string $method_name )?

There is no version information on the MailChimp class.

joelpittet’s picture

Status: Needs work » Needs review
StatusFileSize
new1.69 KB

Like this?

  • das-peter committed e82d5e8 on 7.x-2.x authored by joelpittet
    Issue #2301419 by joelpittet, Sam152, kbentham, mollux: Support...
das-peter’s picture

Status: Needs review » Fixed

@joelpittet: Yes, looks good to me. I couldn't apply the patch - I guess it wasn't created using the latest dev. However, I applied the changes manually.

+++ b/webform_mailchimp.module
@@ -130,9 +130,9 @@ function webform_mailchimp_webform_submission_insert($node, $submission) {
-          'groups' => implode(',', $values_array),
+          'groups' => $values_array,

What about this change? Not necessary?
If it is necessary, I'd suggest we create a function that returns information about the mailchimp API used based on the method_exists() approach. That should help to unify the version handling for further API diffs.
As for now I mark this as fixed - please feel free to re-set the state if this change has to go in.

sam152’s picture

StatusFileSize
new3.73 KB

The v2 API doesn't throw exceptions. That means in the current implementation if you are using v2 you will never get a watchdog message informing you that a user wasn't subscribed. I almost think the try/catch block should only exist when calling out to v3 and the status should be handled for v2. We could move the watchdogs into a method to keep it DRY. Also ->errorMessage and ->errorCode are methods and not properties in v3, so logging a v3 error will fail also.

Something like the following? Needs testing.

sam152’s picture

Status: Fixed » Needs work
joelpittet’s picture

Status: Needs work » Needs review

@Sam152 thanks for catching that.

Your patch needs reviews, so changing the status. May have went a bit far on the DRY but I like the idea behind it.

  • das-peter committed 3e8ddcf on 7.x-2.x authored by Sam152
    Issue #2301419 by Sam152, joelpittet, kbentham, mollux: Support...
das-peter’s picture

Status: Needs review » Fixed

Looks good to me, found just some nitpicks but fixed them myself.
The nitpicks found with the handy code sniffer from the coder module:

  1. +++ b/webform_mailchimp.module
    @@ -142,40 +142,60 @@ function webform_mailchimp_webform_submission_insert($node, $submission) {
    +          } catch (Exception $e) {
    

    Expected newline after closing brace

  2. +++ b/webform_mailchimp.module
    @@ -142,40 +142,60 @@ function webform_mailchimp_webform_submission_insert($node, $submission) {
    + * @param boolean $status
    

    Expected "bool" but found "boolean" for parameter type

sam152’s picture

Thanks for reviewing so fast.

sam152’s picture

StatusFileSize
new596 bytes

Tested this on my project and noticed a tiny issue with the params being the wrong way around. See attached.

Also, supporting a new version of the API is probably reason enough for a beta-2?

  • das-peter committed ade1ab8 on 7.x-2.x authored by Sam152
    Issue #2301419 by Sam152, joelpittet, kbentham, mollux: Support...
das-peter’s picture

Thanks for reviewing so fast.

Apparently to fast - I missed that switch too ;)
Thanks for the update - patched.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

Joanrufe’s picture

Hi, I was following this issue but I've got errors.

I has code from versión 7.x-2.x-dev ( from 2015-May-27) that have inside all the patches you wrote.

I have got this error: Fatal error: Call to a member function subscribe() on a non-object in /sites/all/modules/webform_mailchimp/webform_mailchimp.module on line 162.

line 162:
$q->lists->subscribe($mailchimp_list, array('email' => $email_address), $mergefields_replacements, 'html', $double_opt_in, TRUE);

Also, $q object doesn't have lists object inside.

Joanrufe’s picture

StatusFileSize
new323 bytes

There is another error when trying to access to a mailchimp component of a webform formulary.

Fatal error: Cannot use object of type stdClass as array in /home/..../sites/all/modules/webform_mailchimp/webform_mailchimp.inc on line 58

This can be fixed with the attached patch.

yeskmilo’s picture

@Joanrufe the patch that you attached in the previous comment does not work for me, Can you please check if this is correctly generated?

yeskmilo’s picture

Priority: Normal » Critical
Status: Closed (fixed) » Active
strategicweb’s picture

StatusFileSize
new353 bytes

Here is a fix for editing the mailchimp component on the webform edit components page

sijuwi’s picture

I also have this error on the current dev version:

line 162:
$q->lists->subscribe($mailchimp_list, array('email' => $email_address), $mergefields_replacements, 'html', $double_opt_in, TRUE);

jphelan’s picture

I got it working with the 4.x version of the Mailchimp module by replacing line 163
replace
$q->lists->subscribe($mailchimp_list, array('email' => $email_address), $mergefields_replacements, 'html', $double_opt_in, TRUE);
with
mailchimp_subscribe($mailchimp_list, $email_address, $mergefields_replacements, $groupfields_replacements, $double_opt_in);

youlikeit’s picture

Hi jphelan,
It worked for me but I get error message
Warning: Creating default object from empty value in mailchimp_update_local_cache() (line 584 of /data/sites/xxx/sites/all/modules/mailchimp/mailchimp.module).
Clearing cache does not solve the problem

jphelan’s picture

You are running 4.x and you downloaded v3 of the Mailchimp API using composer? If so have you tried refreshing lists from Mailchimp at /admin/config/services/mailchimp/lists?

andyg5000’s picture

Status: Active » Fixed

I think the issues addressed in 31+ are related to mailchimp-7.x-4.x. There's a patch in #2785563: WSOD, PHP Fatal error using Mailchimp 7.x-4.4 + Webform 7.x-4.13 + Webform Mailchimp 7.x-2.x-dev that fixes #35 in that issue and @jphelan's update in #39 fixes the undefined method error. I'm closing this back out as I believe mailchimp-7.x-3.x issues have been addressed. Let's post 4.x dialog to the other issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.