View source
<?php
module_load_include('inc', 'mailchimp_lists', 'includes/mailchimp_lists.field');
function mailchimp_lists_menu() {
$items = array();
$items['admin/config/services/mailchimp/lists'] = array(
'title' => t('Lists'),
'description' => t('Display Mailchimp Lists and configure Webhooks.'),
'page callback' => 'mailchimp_lists_overview_page',
'access callback' => 'mailchimp_apikey_ready_access',
'access arguments' => array(
'administer mailchimp',
),
'type' => MENU_LOCAL_TASK,
'file' => 'includes/mailchimp_lists.admin.inc',
'weight' => 10,
);
$items['admin/config/services/mailchimp/fields'] = array(
'title' => t('Fields'),
'description' => t('Display Mailchimp Subscription Fields and trigger merge variable updates.'),
'page callback' => 'mailchimp_lists_fields_overview_page',
'access callback' => 'mailchimp_apikey_ready_access',
'access arguments' => array(
'administer mailchimp',
),
'type' => MENU_LOCAL_TASK,
'file' => 'includes/mailchimp_lists.admin.inc',
'weight' => 10,
);
$items['admin/config/services/mailchimp/lists/%/webhook/%'] = array(
'title' => t('Enable/disable Webhooks'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_webhook_form',
5,
7,
),
'access callback' => 'mailchimp_apikey_ready_access',
'access arguments' => array(
'administer mailchimp',
),
'file' => 'includes/mailchimp_lists.admin.inc',
);
$items['admin/config/services/mailchimp/lists/update_mergevars/%/%/%'] = array(
'title' => t('Mass Update Merge Variables'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailchimp_lists_update_mergevars_form',
6,
7,
8,
),
'access callback' => 'mailchimp_apikey_ready_access',
'access arguments' => array(
'administer mailchimp',
),
'file' => 'includes/mailchimp_lists.admin.inc',
);
return $items;
}
function mailchimp_lists_entity_delete($entity, $type) {
$fields = field_info_fields();
foreach ($fields as $field) {
if ($field['type'] == 'mailchimp_lists_subscription' && isset($field['bundles'][$type])) {
$wrapper = entity_metadata_wrapper($type, $entity);
if (in_array($wrapper
->getBundle(), $field['bundles'][$type])) {
$instance = field_info_instance($type, $field['field_name'], $wrapper
->getBundle());
if ($instance['settings']['unsubscribe_on_delete']) {
mailchimp_lists_process_subscribe_form_choices(array(
'subscribe' => FALSE,
), $instance, $field, $entity);
}
}
}
}
}
function mailchimp_lists_load_email($instance, $entity, $log_errors = TRUE) {
if (isset($entity->original)) {
$email = mailchimp_lists_load_email($instance, $entity->original, $log_errors);
if ($email) {
return $email;
}
}
if (!isset($instance['settings']['mergefields']['EMAIL'])) {
if ($log_errors) {
watchdog('mailchimp_lists', 'Mailchimp Lists field "@field" on @entity -> @bundle has no EMAIL field configured, subscription actions cannot take place.', array(
'@field' => $instance['field_name'],
'@entity' => $instance['entity_type'],
'@bundle' => $instance['bundle'],
), WATCHDOG_NOTICE);
}
return FALSE;
}
list($id, $vid, $bundle) = entity_extract_ids($instance['entity_type'], $entity);
if (!isset($id) || $id === 0) {
return FALSE;
}
$tokens = array();
foreach ($instance['settings']['mergefields'] as $key => $token) {
$tokens[$key] = token_replace($token, array(
$instance['entity_type'] => $entity,
), array(
'clear' => TRUE,
));
}
$email = $tokens['EMAIL'];
if (valid_email_address($email)) {
return $email;
}
else {
return FALSE;
}
}
function mailchimp_lists_forms($form_id, $args) {
$forms = array();
if (strpos($form_id, 'mailchimp_lists_') === 0 && isset($args[3]['type']) && $args[3]['type'] == "mailchimp_lists_subscription") {
$forms['mailchimp_lists_' . $args[0]['field_name'] . '_form'] = array(
'callback' => 'mailchimp_lists_subscribe_form',
);
}
return $forms;
}
function mailchimp_lists_subscribe_form($form, &$form_state, $instance, $settings, $entity, $field) {
$use_interest_groups = $instance['settings']['show_interest_groups'] && $settings['show_interest_groups'];
$mc_list = mailchimp_get_list($field['settings']['mc_list_id'], $use_interest_groups);
$email = mailchimp_lists_load_email($instance, $entity);
if (!$email) {
return array();
}
$is_subscribed = mailchimp_is_subscribed($mc_list->id, $email);
$wrapper_key = 'mailchimp_' . $instance['field_name'];
$form_state['settings'] = array(
'wrapper_key' => $wrapper_key,
'instance' => $instance,
'field' => $field,
'entity' => $entity,
);
$form[$wrapper_key] = array(
'#type' => 'container',
'#tree' => TRUE,
'#description' => $instance['description'],
'#attributes' => array(
'class' => array(
'mailchimp-newsletter-wrapper',
'mailchimp-newsletter-' . $instance['field_name'],
),
),
);
$form[$wrapper_key]['subscribe'] = array(
'#type' => 'checkbox',
'#title' => t('Subscribe'),
'#disabled' => $instance['required'],
'#required' => $instance['required'],
'#default_value' => $instance['required'] || $is_subscribed,
);
if ($use_interest_groups) {
if (is_array($mc_list->intgroups)) {
$form[$wrapper_key]['interest_groups'] = array(
'#type' => 'fieldset',
'#title' => isset($settings['interest_groups_label']) ? $settings['interest_groups_label'] : t('Interest Groups'),
'#weight' => 100,
'#states' => array(
'invisible' => array(
':input[name="' . $wrapper_key . '[subscribe]"]' => array(
'checked' => FALSE,
),
),
),
);
$form[$wrapper_key]['interest_groups'] += mailchimp_interest_groups_form_elements($mc_list, $instance['default_value'][0]['interest_groups'], $email);
}
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function mailchimp_lists_subscribe_form_submit($form, &$form_state) {
mailchimp_lists_process_subscribe_form_choices($form_state['values'][$form_state['settings']['wrapper_key']], $form_state['settings']['instance'], $form_state['settings']['field'], $form_state['settings']['entity']);
}
function mailchimp_lists_process_subscribe_form_choices($choices, $instance, $field, $entity) {
$email = mailchimp_lists_load_email($instance, $entity);
if (!$email) {
return;
}
$function = FALSE;
$list_id = $field['settings']['mc_list_id'];
$subscribed = mailchimp_is_subscribed($list_id, $email);
if ($choices['subscribe'] != $subscribed) {
if ($choices['subscribe']) {
$function = 'add';
}
elseif (isset($field['settings']['unsubscribe_action'])) {
$function = $field['settings']['unsubscribe_action'];
}
else {
$function = 'remove';
}
}
elseif ($choices['subscribe']) {
$function = 'update';
}
if ($function) {
if ($function == 'remove') {
$mergevars = array();
}
else {
$mergevars = _mailchimp_lists_mergevars_populate($instance['settings']['mergefields'], $entity, $instance['entity_type'], $list_id);
}
$interest_groups = isset($choices['interest_groups']) ? $choices['interest_groups'] : array();
$interests = array();
foreach ($interest_groups as $interest_group) {
foreach ($interest_group as $interest_id => $interest_status) {
$interests[$interest_id] = $interest_status !== 0;
}
}
switch ($function) {
case 'add':
$ret = mailchimp_subscribe($list_id, $email, $mergevars, $interests, $field['settings']['double_opt_in']);
break;
case 'unsubscribe':
$ret = mailchimp_unsubscribe_member($list_id, $email, FALSE);
break;
case 'remove':
$ret = mailchimp_unsubscribe_member($list_id, $email, TRUE);
break;
case 'update':
if (_mailchimp_lists_subscription_has_changed($instance, $field, $entity, $email, $choices)) {
$ret = mailchimp_update_member($list_id, $email, $mergevars, $interests);
}
else {
$ret = TRUE;
}
break;
}
if (empty($ret) || isset($ret->success) && $ret->success === FALSE) {
drupal_set_message(t('There was a problem with your newsletter signup.'), 'warning');
}
}
}
function _mailchimp_lists_subscription_has_changed($instance, $field, $entity, $email, $choices) {
if (isset($entity->original)) {
$new_entity_wrapper = entity_metadata_wrapper($instance['entity_type'], $entity);
$old_entity_wrapper = entity_metadata_wrapper($instance['entity_type'], $entity->original);
if ($instance['settings']['show_interest_groups']) {
$old_settings = $old_entity_wrapper->{$field['field_name']}
->value();
$new_settings = $new_entity_wrapper->{$field['field_name']}
->value();
foreach ($new_settings['interest_groups'] as $id => $new_interests) {
if (!isset($old_settings['interest_groups'][$id])) {
return TRUE;
}
$old_interests = $old_settings['interest_groups'][$id];
if (!is_array($new_interests)) {
$new_interests = array(
$new_interests => $new_interests,
);
}
foreach ($new_interests as $index => $new_int) {
if ($old_interests[$index] !== $new_int) {
return TRUE;
}
}
}
}
$mergevars_new = mailchimp_mergevars_populate($instance['settings']['mergefields'], $entity, $instance['entity_type']);
$mergevars_old = mailchimp_mergevars_populate($instance['settings']['mergefields'], $entity->original, $instance['entity_type']);
if ($mergevars_new != $mergevars_old) {
return TRUE;
}
}
else {
$member_info = mailchimp_get_memberinfo($field['settings']['mc_list_id'], $email);
$interest_groups = isset($choices['interest_groups']) ? $choices['interest_groups'] : array();
foreach ($interest_groups as $interest_group) {
foreach ($interest_group as $interest_id => $interest_status) {
if ($interest_status !== 0 && empty($member_info->interests->{$interest_id})) {
return TRUE;
}
if ($interest_status === 0 && !empty($member_info->interests->{$interest_id})) {
return TRUE;
}
}
}
}
return FALSE;
}
function _mailchimp_lists_mergevars_populate($mergefields, $entity, $entity_type, $list_id = NULL) {
$mergevars = mailchimp_mergevars_populate($mergefields, $entity, $entity_type, $list_id);
drupal_alter('mailchimp_lists_mergevars', $mergevars, $entity, $entity_type, $list_id);
return $mergevars;
}
function mailchimp_lists_update_member_merge_values($entity_type, $bundle_name, $field) {
$instance = field_info_instance($entity_type, $field['field_name'], $bundle_name);
$mergefields = $instance['settings']['mergefields'];
$batch = array(
'operations' => array(
array(
'mailchimp_lists_update_member_batch',
array(
$entity_type,
$bundle_name,
$field,
$mergefields,
$field['settings']['mc_list_id'],
),
),
),
'finished' => 'mailchimp_lists_populate_member_batch_complete',
'title' => t('Processing Merge Variable Updates'),
'init_message' => t('Starting Mailchimp Merge Variable Update.'),
'progress_message' => t('Processed @current out of @total.'),
'error_message' => t('Mailchimp Merge Variable Update Failed.'),
);
batch_set($batch);
}
function mailchimp_lists_get_subscribers($field, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['results']['subscribers'] = array();
$context['sandbox']['progress'] = 0;
}
$batch_size = variable_get('mailchimp_batch_limit', 100);
$options = array(
'offset' => $context['sandbox']['progress'],
'count' => $batch_size,
);
$matches = mailchimp_get_members($field['settings']['mc_list_id'], 'subscribed', $options);
if (!empty($matches) && $matches->total_items > 0) {
if (!isset($context['sandbox']['max'])) {
$context['sandbox']['max'] = $matches->total_items;
}
foreach ($matches->members as $result) {
$context['results']['subscribers'][strtolower($result->email_address)] = $result;
}
$context['sandbox']['progress'] += count($matches->members);
$context['message'] = t('Check subscription status for contact %count of %total.', array(
'%count' => $context['sandbox']['progress'],
'%total' => $context['sandbox']['max'],
));
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
function mailchimp_lists_update_member_batch($entity_type, $bundle_name, $field, $mergefields, $list_id, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['entity_info'] = entity_get_info($entity_type);
$context['sandbox']['progress'] = 0;
$context['results']['errors'] = 0;
$context['results']['updates'] = 0;
$context['results']['no_entity'] = 0;
}
$batch_size = variable_get('mailchimp_batch_limit', 100);
$options = array(
'offset' => $context['sandbox']['progress'],
'count' => $batch_size,
);
$subscriber_emails = array();
$subscribers = array();
$update_queue = array();
$matches = mailchimp_get_members($field['settings']['mc_list_id'], 'subscribed', $options);
if (!empty($matches) && $matches->total_items > 0) {
if (!isset($context['sandbox']['max'])) {
$context['sandbox']['max'] = $matches->total_items;
}
foreach ($matches->members as $result) {
$subscribers[strtolower($result->email_address)] = $result;
$subscriber_emails[] = strtolower($result->email_address);
}
}
$entity_email_field_parts = explode(':', str_replace(array(
']',
'[',
), '', $mergefields['EMAIL']));
$entity_email_field_name = str_replace('-', '_', $entity_email_field_parts[1]);
$entity_email_field_info = field_info_field($entity_email_field_name);
if (!empty($entity_email_field_info)) {
$entity_email_field_column = 'value';
}
else {
$entity_email_property_column = $entity_email_field_parts[1];
}
if (empty($entity_email_field_column) && empty($entity_email_property_column)) {
watchdog('mailchimp_lists', 'Could not update merge variables. Unable to match token @email with a field or property of the @entity entity.', array(
'@email' => $mergefields['EMAIL'],
'@entity' => $entity_type,
), WATCHDOG_ERROR);
drupal_set_message(t('Unable to update merge variables. Please see your error log for details.'), 'error');
$context['finished'] = 1;
return;
}
foreach ($subscriber_emails as $subscriber_email) {
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', $entity_type);
if ($entity_type !== 'user') {
$query
->entityCondition('bundle', $bundle_name);
}
if (!empty($entity_email_field_column)) {
$query
->fieldCondition($entity_email_field_name, $entity_email_field_column, $subscriber_email, '=');
}
elseif (!empty($entity_email_property_column)) {
$query
->propertyCondition($entity_email_property_column, $subscriber_email, '=');
}
$query_results = $query
->execute();
if (isset($query_results[$entity_type])) {
$entity_id = array_keys($query_results[$entity_type])[0];
$entity = entity_load_single($entity_type, $entity_id);
}
if (!empty($entity)) {
$merge_vars = _mailchimp_lists_mergevars_populate($mergefields, $entity, $entity_type, $field['settings']['mc_list_id']);
if ($merge_vars['EMAIL'] && isset($subscribers[strtolower($merge_vars['EMAIL'])])) {
$update_queue[] = array(
'email' => $merge_vars['EMAIL'],
'email_type' => $subscribers[strtolower($merge_vars['EMAIL'])]->email_type,
'merge_vars' => $merge_vars,
);
}
}
else {
$context['results']['no_entity']++;
}
}
$batch_result = mailchimp_lists_execute_mergevar_batch_update($list_id, $update_queue);
$context['results']['errors'] += $batch_result->errored_operations;
$context['sandbox']['progress'] += count($subscriber_emails);
$context['results']['updates'] += count($subscriber_emails);
$context['message'] = t('Updating items %count - %next of %total.', array(
'%count' => $context['sandbox']['progress'],
'%next' => $context['sandbox']['progress'] + $batch_size,
'%total' => $context['sandbox']['max'],
));
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
function mailchimp_lists_execute_mergevar_batch_update($list_id, $batch) {
$result = mailchimp_batch_update_members($list_id, $batch, FALSE, TRUE, FALSE);
if ($result) {
$mc = mailchimp_get_api_object();
return $mc
->getBatchOperation($result->id);
}
}
function mailchimp_lists_populate_member_batch_complete($success, $results, $operations) {
if ($success) {
if ($results['errors']) {
drupal_set_message(t('Update errors occurred: merge variables updated on %count records, errors occurred on %errors records.', array(
'%count' => $results['updates'],
'%errors' => $results['errors'],
)), 'warning');
}
else {
drupal_set_message(t('Merge variables updated on %count records. %no_entity subscribers had no matching entity in Drupal.', array(
'%count' => $results['updates'],
'%no_entity' => $results['no_entity'],
)), 'status');
}
}
else {
drupal_set_message(t('Merge variable update failed.'), 'error');
}
}
function mailchimp_lists_mollom_form_list() {
$forms = array();
$forms['mailchimp_lists_subscribe_form'] = array(
'title' => t('Mailchimp Newsletter Subscription Fields'),
);
return $forms;
}
function mailchimp_lists_mollom_form_info($form_id) {
$form_info = array(
'bypass access' => array(
'administer mailchimp',
),
'mode' => MOLLOM_MODE_CAPTCHA,
);
return $form_info;
}
function mailchimp_lists_fieldmap_options($entity_type, $entity_bundle = NULL, $required = FALSE, $prefix = NULL, $tree = NULL) {
$options = array();
if (!$prefix) {
$options[''] = t('-- Select --');
}
$properties = entity_get_all_property_info($entity_type);
if (isset($entity_bundle)) {
$info = entity_get_property_info($entity_type);
$properties = $info['properties'];
if (isset($info['bundles'][$entity_bundle])) {
$properties += $info['bundles'][$entity_bundle]['properties'];
}
}
foreach ($properties as $key => $property) {
$key = str_replace('_', '-', $key);
$keypath = $prefix ? $prefix . ':' . $key : $entity_type . ':' . $key;
$type = isset($property['type']) ? entity_property_extract_innermost_type($property['type']) : 'text';
$is_entity = $type == 'entity' || (bool) entity_get_info($type);
$required_property = isset($property['required']) ? $property['required'] : FALSE;
$computed_property = isset($property['computed']) ? $property['computed'] : FALSE;
if ($is_entity) {
if (!$prefix) {
$bundle = isset($property['bundle']) ? $property['bundle'] : NULL;
$options[$property['label']] = mailchimp_lists_fieldmap_options($type, $bundle, $required, $keypath, $property['label']);
}
}
elseif (!$required || $required_property || $computed_property) {
if (isset($property['field']) && $property['field'] && !empty($property['property info'])) {
foreach ($property['property info'] as $sub_key => $sub_prop) {
$label = isset($tree) ? $tree . ' - ' . $property['label'] : $property['label'];
$token = '[' . $keypath . ']';
$options[$label][$token] = $sub_prop['label'];
}
}
else {
$token = '[' . $keypath . ']';
$options[$token] = $property['label'];
}
}
}
return $options;
}
function mailchimp_lists_action_info() {
$actions = array(
'mailchimp_lists_add_to_segment_action' => array(
'type' => 'entity',
'label' => t('Add to Mailchimp List Tag'),
'configurable' => FALSE,
'triggers' => array(
'any',
),
'vbo_configurable' => TRUE,
),
);
return $actions;
}
function mailchimp_lists_add_to_segment_action($entity, $context = array()) {
list($id, $vid, $bundle) = entity_extract_ids($context['entity_type'], $entity);
$list_id = $context['mc_list_id'];
$field_instance = field_info_instance($context['entity_type'], $context['mailchimp_field'], $bundle);
$email = mailchimp_lists_load_email($field_instance, $entity);
$queue_id = 'mailchimp_lists_action_' . $list_id . '_' . $context['segment_id'];
if ($email) {
mailchimp_segment_add_subscriber($list_id, $context['segment_id'], $email, TRUE, $queue_id);
}
if ($context['progress']['current'] == $context['progress']['total'] || !($context['progress']['current'] % 10000)) {
$batch_queue = DrupalQueue::get($queue_id);
$batch_queue
->createQueue();
$queue_count = $batch_queue
->numberOfItems();
if ($queue_count > 0) {
$count = 0;
$batch = array();
while ($count < $queue_count) {
if ($item = $batch_queue
->claimItem()) {
$batch[] = $item->data['item'];
$batch_queue
->deleteItem($item);
}
$count++;
}
mailchimp_segment_batch_add_subscribers($list_id, $context['segment_id'], $batch);
}
}
}
function mailchimp_lists_add_to_segment_action_form($context, &$form_state) {
$form = array();
$mailchimp_field_options = array();
$form_state['mc_list_ids'] = array();
foreach ($context['settings']['mailchimp_field'] as $field) {
if ($info = field_info_field($field)) {
$form_state['mc_list_ids'][$field] = $info['settings']['mc_list_id'];
$bundle = reset($info['bundles'][$context['entity_type']]);
$instance_info = field_info_instance($context['entity_type'], $field, $bundle);
$mailchimp_field_options[$field] = t("@label (@fieldname)", array(
'@label' => $instance_info['label'],
'@fieldname' => $field,
));
}
}
$form['mailchimp_field'] = array(
'#type' => 'select',
'#title' => t('Select a Mailchimp List'),
'#options' => $mailchimp_field_options,
'#required' => TRUE,
'#ajax' => array(
'callback' => 'mailchimp_lists_segment_action_callback',
'wrapper' => 'segment-wrapper',
),
);
if (empty($form_state['values']['mailchimp_field'])) {
$form['segment'] = array(
'#prefix' => '<div id="segment-wrapper">',
'#suffix' => '</div>',
);
}
else {
$segments = mailchimp_get_segments($form_state['mc_list_ids'][$form_state['values']['mailchimp_field']]);
$seg_options = array(
0 => '-- Create New Segment --',
);
foreach ($segments['static'] as $segment) {
$seg_options[$segment['id']] = $segment['name'];
}
$form['segment'] = array(
'#type' => 'select',
'#title' => "Select a tag to add subscribed entities to.",
'#description' => "Only records that have the appropriate list field on their bundle, and are already subscribed to the list, will be added.",
'#id' => 'segment-wrapper',
'#options' => $seg_options,
);
}
$form['new_segment'] = array(
'#type' => 'textfield',
'#title' => "Name for your new tag",
'#states' => array(
'required' => array(
':input[name="segment"]' => array(
'value' => 0,
),
),
'visible' => array(
':input[name="segment"]' => array(
'value' => 0,
),
),
'invisible' => array(
':input[name="mailchimp_field"]' => array(
'value' => '',
),
),
),
);
return $form;
}
function mailchimp_lists_add_to_segment_action_submit($form, &$form_state) {
$mc_list_id = $form_state['mc_list_ids'][$form_state['values']['mailchimp_field']];
if (!$form_state['values']['segment']) {
$segment = mailchimp_segment_create($mc_list_id, $form_state['values']['new_segment'], 'static');
$form_state['values']['segment'] = $segment['id'];
}
$values = array(
'mailchimp_field' => $form_state['values']['mailchimp_field'],
'mc_list_id' => $mc_list_id,
'segment_id' => $form_state['values']['segment'],
);
return $values;
}
function mailchimp_lists_segment_action_callback($form, $form_state) {
$ret = $form['segment'];
return $ret;
}
function mailchimp_lists_add_to_segment_action_views_bulk_operations_form($options, $entity_type, $dom_id) {
$field_options = array();
$fields = field_read_fields(array(
'type' => 'mailchimp_lists_subscription',
'entity_type' => $entity_type,
));
foreach ($fields as $field) {
$info = field_info_field($field['field_name']);
if (isset($info['bundles'][$entity_type])) {
$bundle = reset($info['bundles'][$entity_type]);
$instance_info = field_info_instance($entity_type, $field['field_name'], $bundle);
$field_options[$field['field_name']] = t("@label (@fieldname)", array(
'@label' => $instance_info['label'],
'@fieldname' => $field['field_name'],
));
}
}
$form['mailchimp_field'] = array(
'#type' => 'select',
'#title' => t('REQUIRED: Mailchimp List Field(s)'),
'#options' => $field_options,
'#multiple' => TRUE,
'#description' => t('Select the Mailchimp fields for which to allow tagging.'),
'#default_value' => isset($options['mailchimp_field']) ? $options['mailchimp_field'] : NULL,
'#states' => array(
'required' => array(
':input[name="options[vbo_operations][action::mailchimp_lists_add_to_segment_action][selected]"]' => array(
'checked' => TRUE,
),
),
),
);
return $form;
}