You are here

mailchimp_campaign.module in Mailchimp 7.4

Module file for mailchimp_campaign.

File

modules/mailchimp_campaign/mailchimp_campaign.module
View source
<?php

/**
 * @file
 * Module file for mailchimp_campaign.
 */

/**
 * Implements hook_entity_info().
 */
function mailchimp_campaign_entity_info() {
  $return = array(
    'mailchimp_campaign' => array(
      'label' => t('Mailchimp Campaign'),
      'entity class' => 'MailChimpCampaign',
      'controller class' => 'MailChimpCampaignController',
      'base table' => 'mailchimp_campaigns',
      'fieldable' => FALSE,
      'exportable' => FALSE,
      'entity keys' => array(
        'id' => 'mc_campaign_id',
      ),
      'token type' => 'mailchimp_campaign',
      'module' => 'mailchimp_campaign',
      'label callback' => 'entity_class_label',
      'view modes' => array(
        'full' => array(
          'label' => t('Full Campaign'),
          'custom settings' => FALSE,
        ),
      ),
    ),
  );
  return $return;
}

/**
 * Implements hook_permission().
 */
function mailchimp_campaign_permission() {
  return array(
    'administer mailchimp campaigns' => array(
      'title' => t('Administer Mailchimp campaigns'),
      'description' => t('Create and send Mailchimp campaigns.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function mailchimp_campaign_menu() {
  $items['admin/config/services/mailchimp/campaigns'] = array(
    'title' => t('Campaigns'),
    'description' => t('Manage Mailchimp Campaigns.'),
    'page callback' => 'mailchimp_campaign_overview_page',
    'access callback' => 'mailchimp_apikey_ready_access',
    'access arguments' => array(
      'administer mailchimp campaigns',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
  );
  $items['admin/config/services/mailchimp/campaigns/add'] = array(
    'title' => t('Add a Campaign'),
    'description' => t('Add a new Mailchimp campaign.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_campaign_campaign_form',
    ),
    'access callback' => 'mailchimp_apikey_ready_access',
    'access arguments' => array(
      'administer mailchimp campaigns',
    ),
    'file' => 'includes/mailchimp_campaign.admin.inc',
    'type' => MENU_LOCAL_ACTION,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign'] = array(
    'title callback' => 'mailchimp_campaign_page_title',
    'title arguments' => array(
      5,
    ),
    'page callback' => 'mailchimp_campaign_view',
    'page arguments' => array(
      5,
    ),
    'access arguments' => array(
      'administer mailchimp campaigns',
    ),
    'load arguments' => array(
      5,
    ),
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/view'] = array(
    'title' => t('View'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/send'] = array(
    'title' => t('Send'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_campaign_send_form',
      5,
    ),
    'access callback' => 'mailchimp_campaign_access',
    'access arguments' => array(
      5,
      FALSE,
    ),
    'file' => 'includes/mailchimp_campaign.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/send-test'] = array(
    'title' => 'Send Test',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_campaign_send_test_form',
      5,
    ),
    'access callback' => 'mailchimp_campaign_access',
    'access arguments' => array(
      5,
      FALSE,
    ),
    'file' => 'includes/mailchimp_campaign.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/edit'] = array(
    'title' => t('Edit'),
    'description' => t('Edit a Mailchimp campaign.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_campaign_campaign_form',
      5,
    ),
    'access callback' => 'mailchimp_campaign_access',
    'access arguments' => array(
      5,
      FALSE,
    ),
    'file' => 'includes/mailchimp_campaign.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/delete'] = array(
    'title' => t('Delete'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mailchimp_campaign_delete_form',
      5,
    ),
    'access callback' => 'mailchimp_campaign_access',
    'access arguments' => array(
      5,
      FALSE,
    ),
    'file' => 'includes/mailchimp_campaign.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
  );
  $items['admin/config/services/mailchimp/campaigns/%mailchimp_campaign/stats'] = array(
    'title' => t('Stats'),
    'page callback' => 'mailchimp_campaign_stats_page',
    'page arguments' => array(
      5,
    ),
    'access callback' => 'mailchimp_campaign_access',
    'access arguments' => array(
      5,
      TRUE,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 4,
  );
  $items['admin/config/services/mailchimp/campaigns/entities'] = array(
    'page callback' => 'mailchimp_campaign_entities_autocomplete_callback',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Callback for campaign template entity search field.
 *
 * @param string $type
 *   The entity type to limit search to.
 * @param string $string
 *   The string to search entity titles for.
 *
 * @return array
 *   Entities with titles matching search string.
 */
function mailchimp_campaign_entities_autocomplete_callback($type, $string = '') {
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', $type)
    ->propertyCondition('title', $string, 'CONTAINS')
    ->range(0, 10);
  $entities = array();
  $result = $query
    ->execute();
  if (isset($result[$type])) {
    $entity_ids = array_keys($result[$type]);
    $entities_data = entity_load($type, $entity_ids);
    if (!empty($entities_data)) {
      foreach ($entities_data as $id => $entity) {
        $entities[$entity->title . ' [' . $id . ']'] = $entity->title;
      }
    }
  }
  drupal_json_output($entities);
}

/**
 * Title callback: Generate a title for a registration entity.
 *
 * Callback for hook_menu() within system_themes_page().
 *
 * @param MailChimpCampaign $campaign
 *   The Mailchimp campaign instance.
 *
 * @return string
 *   The entity title.
 */
function mailchimp_campaign_page_title(MailChimpCampaign $campaign) {
  return $campaign
    ->label();
}

/**
 * Access callback for campaigns.
 *
 * Provides access to features based on whether or not a campaign has been sent.
 *
 * @param MailChimpCampaign $campaign
 *   The Mailchimp campaign instance.
 * @param bool $sent
 *   Set to TRUE when a campaign has been sent.
 */
function mailchimp_campaign_access(MailChimpCampaign $campaign, $sent = TRUE) {
  $access = FALSE;

  // Only campaigns that haven't been sent can be changed.
  if (user_access('administer mailchimp campaigns') && ($campaign->mc_data->status === 'sent') === $sent) {
    $access = TRUE;
  }
  return $access;
}

/**
 * Page callback for showing a list of Mailchimp Campaign entities.
 */
function mailchimp_campaign_overview_page() {
  $campaigns = mailchimp_campaign_load_multiple();
  $templates = mailchimp_campaign_list_templates(FALSE, 0, 500);
  $rows = array();
  foreach ($campaigns as $campaign) {
    $actions = array();
    $actions[] = l(t('View Archive'), $campaign->mc_data->archive_url, array(
      'attributes' => array(
        'target' => '_blank',
      ),
    ));
    $actions[] = l(t('View'), 'admin/config/services/mailchimp/campaigns/' . $campaign->mc_campaign_id);
    if ($campaign->mc_data->status == 'save') {
      $actions[] = l(t('Send'), 'admin/config/services/mailchimp/campaigns/' . $campaign->mc_campaign_id . '/send');
    }
    else {
      $actions[] = t('Sent');
    }
    $campaign_template = NULL;
    foreach ($templates as $template_set) {
      foreach ($template_set as $template) {
        if ($template->id == $campaign->mc_data->settings->template_id) {
          $campaign_template = $template;
        }
      }
    }
    $rows[] = array(
      l($campaign
        ->label(), 'admin/config/services/mailchimp/campaigns/' . $campaign->mc_campaign_id),
      $campaign->mc_data->settings->subject_line,
      $campaign->mc_data->status,
      l($campaign->list->name, 'https://admin.mailchimp.com/lists/', array(
        'attributes' => array(
          'target' => '_blank',
        ),
      )),
      $campaign_template != NULL ? $campaign_template->name : '',
      format_date(strtotime($campaign->mc_data->create_time), 'custom', 'F j, Y - g:ia'),
      implode(' | ', $actions),
    );
  }
  return array(
    '#theme' => 'table',
    '#header' => array(
      t('Title'),
      t('Subject'),
      t('Status'),
      t('Mailchimp list'),
      t('Mailchimp template'),
      t('Created'),
      t('Actions'),
    ),
    '#rows' => $rows,
  );
}

/**
 * Implements hook_theme().
 */
function mailchimp_campaign_theme($existing, $type, $theme, $path) {
  return array(
    'mailchimp_campaign_node_campaigns_list' => array(
      'variables' => array(
        'node_campaigns' => array(),
      ),
    ),
    'mailchimp_campaign_mclinks' => array(
      'variables' => array(
        'data' => NULL,
      ),
    ),
    'mailchimp_campaign_actions' => array(
      'variables' => array(
        'campaign' => NULL,
      ),
    ),
  );
}

/**
 * Save a campaign in Mailchimp and as a Drupal entity.
 *
 * @param array $template
 *   Associative array of template content indexed by section IDs.
 * @param object $recipients
 *   List settings for the campaign.
 * @param object $settings
 *   The subject, from name, reply-to, etc settings for the campaign.
 * @param int $template_id
 *   The Mailchimp template ID.
 * @param string $campaign_id
 *   The ID of the campaign to save, if updating.
 *
 * @return string
 *   New or existing campaign ID.
 */
function mailchimp_campaign_save_campaign($template, $recipients, $settings, $template_id, $campaign_id = NULL) {

  // Allow alter of template and options used in campaign
  drupal_alter('mailchimp_campaign', $recipients, $template, $campaign_id);

  // Convert template to content by running through formatter.
  if (isset($template['html'])) {
    $content = mailchimp_campaign_render_template($template);
  }
  else {
    $content = array(
      'sections' => mailchimp_campaign_render_template($template),
    );
  }

  // Test for valid list segment, if selected.
  if (isset($recipients->segment_opts)) {
    if (mailchimp_test_list_segment($recipients->list_id, $recipients->segment_opts->saved_segment_id) === NULL) {
      return NULL;
    }
  }

  // Build content parameters.
  $content_parameters = array();
  if (!empty($template_id)) {

    // Use template sections as campaign content.
    $content_parameters['template'] = (object) array(
      'id' => (int) $template_id,
      'sections' => (object) $content['sections'],
    );
  }
  else {
    if (isset($content['html'])) {

      // Use HTML as campaign content.
      $content_parameters['html'] = $content['html'];
    }
  }

  /* @var \Mailchimp\MailchimpCampaigns $mc_campaigns */
  $mc_campaigns = mailchimp_get_api_object('MailchimpCampaigns');

  // Save campaign to Mailchimp. (Only regular campaigns are supported).
  $is_new = empty($campaign_id);
  if ($is_new) {
    try {
      if (!$mc_campaigns) {
        throw new MailchimpException('Cannot create campaign without Mailchimp API. Check API key has been entered.');
      }
      $result = $mc_campaigns
        ->addCampaign(\Mailchimp\MailchimpCampaigns::CAMPAIGN_TYPE_REGULAR, $recipients, $settings);
      if (!empty($result->id)) {
        $campaign_id = $result->id;
        $mc_campaigns
          ->setCampaignContent($campaign_id, $content_parameters);
      }
    } catch (Exception $e) {
      drupal_set_message($e
        ->getMessage(), 'error');
      watchdog('mailchimp_campaign', 'An error occurred while creating this campaign: %message', array(
        '%message' => $e
          ->getMessage(),
      ), WATCHDOG_ERROR);
      return NULL;
    }
  }
  else {

    // Update an existing campaign.
    try {
      if (!$mc_campaigns) {
        throw new MailchimpException('Cannot update campaign without Mailchimp API. Check API key has been entered.');
      }
      $result = $mc_campaigns
        ->updateCampaign($campaign_id, \Mailchimp\MailchimpCampaigns::CAMPAIGN_TYPE_REGULAR, $recipients, $settings);
      if (!empty($result->id)) {
        $mc_campaigns
          ->setCampaignContent($result->id, $content_parameters);
      }
    } catch (Exception $e) {
      drupal_set_message($e
        ->getMessage(), 'error');
      watchdog('mailchimp_campaign', 'An error occurred while updating this campaign: %message', array(
        '%message' => $e
          ->getMessage(),
      ), WATCHDOG_ERROR);
      return NULL;
    }
  }
  if (!empty($result->id)) {
    drupal_set_message(t('Campaign %name (%cid) was successfully saved.', array(
      '%name' => $settings->title,
      '%cid' => $campaign_id,
    )));

    // Save the campaign entity:
    $campaign = entity_create('mailchimp_campaign', array(
      'mc_campaign_id' => $campaign_id,
      'template' => $template,
      'is_new' => $is_new,
    ));
    mailchimp_campaign_save($campaign);

    // Clear cached data for this campaign.
    mailchimp_campaign_get_campaigns(array(
      $campaign_id,
    ), TRUE);
  }
  return $campaign_id;
}

/**
 * Send Mailchimp campaign.
 */
function mailchimp_campaign_send_campaign(MailChimpCampaign $campaign) {

  /* @var \Mailchimp\MailchimpCampaigns $mc_campaign */
  $mc_campaign = mailchimp_get_api_object('MailchimpCampaigns');

  // Send campaign.
  try {
    if (!$mc_campaign) {
      throw new MailchimpException('Cannot send campaign without Mailchimp API. Check API key has been entered.');
    }
    $mc_campaign
      ->send($campaign->mc_campaign_id);
    $campaign = $mc_campaign
      ->getCampaign($campaign->mc_campaign_id);
    if ($campaign->status == MAILCHIMP_STATUS_SENT) {

      // Log action, and notify the user.
      watchdog('mailchimp_campaign', 'Mailchimp campaign %name has been sent.', array(
        '%name' => $campaign
          ->label(),
      ));
      entity_get_controller('mailchimp_campaign')
        ->resetCache(array(
        $campaign
          ->identifier(),
      ));
      return TRUE;
    }
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred while sending to this campaign: %message', array(
      'message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
  }
  return FALSE;
}

/**
 * Send Mailchimp campaign.
 */
function mailchimp_campaign_send_test_campaign(MailChimpCampaign $campaign, $recipients = array()) {

  /* @var \Mailchimp\MailchimpCampaigns $mc_campaigns */
  $mc_campaigns = mailchimp_get_api_object('MailchimpCampaigns');
  try {
    if (!$mc_campaigns) {
      throw new MailchimpException('Cannot send campaign without Mailchimp API. Check API key has been entered.');
    }
    $mc_campaigns
      ->sendTest($campaign->mc_campaign_id, $recipients, \Mailchimp\MailchimpCampaigns::EMAIL_TYPE_HTML);

    // Log action, and notify the user.
    watchdog('mailchimp_campaign', 'Mailchimp test message for campaign %name has been sent to %recipients.', array(
      '%name' => $campaign
        ->label(),
      '%recipients' => implode(', ', $recipients),
    ), WATCHDOG_INFO);
    return TRUE;
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred while sending a test of this campaign: %message', array(
      '%message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
  }
  return FALSE;
}

/**
 * Delete a Mailchimp campaign and the local entity.
 */
function mailchimp_campaign_delete_campaign($cid) {

  /* @var \Mailchimp\MailchimpCampaigns $mc_campaigns */
  $mc_campaigns = mailchimp_get_api_object('MailchimpCampaigns');
  $result = NULL;

  // Delete campaign from Mailchimp.
  try {
    if (!$mc_campaigns) {
      throw new MailchimpException('Cannot delete campaign without Mailchimp API. Check API key has been entered.');
    }
    mailchimp_campaign_delete($cid);
    $mc_campaigns
      ->delete($cid);
    watchdog('mailchimp_campaign', 'Mailchimp campaign %cid was deleted.', array(
      '%cid' => $cid,
    ), WATCHDOG_INFO);
    return TRUE;
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred while deleting this campaign: %message', array(
      '%message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
    return FALSE;
  }
  return FALSE;
}

/**
 * Return all available user templates.
 *
 * @param bool $reset
 *   True if templates should not be loaded from cache.
 * @param int $offset
 *   The number of templates to skip.
 * @param int $count
 *   The number of templates to return.
 * @param string $type
 *   The template type to limit results to.
 * @param int $folder_id
 *   The template folder ID to limit results to.
 *
 * @return mixed
 *   Array listing existing Mailchimp templates by type.
 */
function mailchimp_campaign_list_templates($reset = FALSE, $offset = 0, $count = 10, $type = NULL, $folder_id = NULL) {
  $cache_key = 'templates-' . $offset . '-' . $count . '-' . $type . '-' . $folder_id;
  $cache = $reset ? NULL : cache_get($cache_key, 'cache_mailchimp');
  $all_templates = array();

  // Return cached templates:
  if ($cache) {
    $all_templates = $cache->data;
  }
  else {

    /* @var \Mailchimp\MailchimpTemplates $mc_templates */
    if ($mc_templates = mailchimp_get_api_object('MailchimpTemplates')) {
      $template_params = array(
        'offset' => $offset,
        'count' => $count,
      );
      if ($type != NULL) {
        $template_params['type'] = $type;
      }
      if ($folder_id != NULL) {
        $template_params['folder_id'] = $folder_id;
      }
      $response = $mc_templates
        ->getTemplates($template_params);
      if ($response->total_items > 0) {
        foreach ($response->templates as $template) {
          $all_templates[$template->type][$template->id] = $template;
        }
      }
    }
    cache_set($cache_key, $all_templates, 'cache_mailchimp', CACHE_TEMPORARY);
  }
  return $all_templates;
}

/**
 * Return full details for a Mailchimp Template.
 *
 * @param string $template_id
 *   The ID of the template.
 * @param bool $reset
 *   True if templates should not be loaded from cache.
 *
 * @return mixed
 *   An array with all configuration and content for a Mailchimp Template.
 */
function mailchimp_campaign_get_template($template_id, $reset = FALSE) {
  $template = NULL;
  if (!empty($template_id)) {
    $cache = $reset ? NULL : cache_get('mc_template_' . $template_id, 'cache_mailchimp');
    if ($cache) {
      $template = $cache->data;
    }
    else {
      if ($mc_templates = mailchimp_get_api_object('MailchimpTemplates')) {
        $template = $mc_templates
          ->getTemplate($template_id);
        if (!empty($template)) {
          $template->info = $mc_templates
            ->getTemplateContent($template_id);
          cache_set('mc_template_' . $template_id, $template, 'cache_mailchimp', CACHE_TEMPORARY);
        }
      }
    }
  }
  return $template;
}

/**
 * Change the relative URLs to absolute ones in the message.
 */
function mailchimp_campaign_convert_url($text) {
  global $base_url;
  $matches = array();
  preg_match_all('/<(a|img).*?(href|src)="(.*?)"/', $text, $matches);
  foreach ($matches[3] as $key => $url) {
    if ($url[0] == '/') {
      $new_url = $base_url . $url;
      $new_match = str_replace($url, $new_url, $matches[0][$key]);
      $text = str_replace($matches[0][$key], $new_match, $text);
    }
  }
  return $text;
}

/**
 * Implements hook_filter_info().
 */
function mailchimp_campaign_filter_info() {
  $filters['mailchimp_campaign'] = array(
    'title' => t('Mailchimp Campaign filter'),
    'description' => t('Add content and covert URLs for sending as Mailchimp campaigns.'),
    'process callback' => 'mailchimp_campaign_filter_campaign_process',
    'tips callback' => 'mailchimp_campaign_filter_tips',
  );
  return $filters;
}

/**
 * Tips callback for mailchimp_campaign_filter_info().
 *
 * @param object $filter
 *   The filter object containing settings for the given format.
 * @param object $format
 *   The text format object assigned to the text to be filtered.
 * @param bool $long
 *   Set to TRUE to return a long tip, FALSE for short.
 *
 * @return string
 *   Translated text to display as a tip.
 */
function mailchimp_campaign_filter_tips($filter, $format, $long) {
  $tip = t('Converts content tokens in the format %pattern into the appropriate rendered content and makes all paths absolute. Use the "Insert Site Content" widget below to generate tokens.', array(
    '%pattern' => '[mailchimp_campaign|entity_type=node|entity_id=1|view_mode=teaser]',
  ));
  return $tip;
}

/**
 * Process callback for mailchimp_campaign_filter_info().
 *
 * @string $text
 *   The text string to be filtered.
 * @object object $filter
 *   The filter object containing settings for the given format.
 * @string $format
 *   The text format object assigned to the text to be filtered.
 * @string $langcode
 *   The language code of the text to be filtered.
 * @bool $cache
 *   A Boolean indicating whether the filtered text is going to be cached in
 *   {cache_filter}.
 * @int $cache_id
 *   The ID of the filtered text in {cache_filter}, if $cache is TRUE.
 *
 * @return string
 *   The filtered text.
 */
function mailchimp_campaign_filter_campaign_process($text, $filter, $format, $langcode, $cache, $cache_id) {

  // Replace node macros with entity content:
  $pattern = '/\\[mailchimp_campaign\\|entity_type=(\\w+)\\|entity_id=(\\d+)\\|view_mode=(\\w+)\\]/s';
  $text = preg_replace_callback($pattern, 'mailchimp_campaign_process_callback', $text);

  // Convert URL to absolute:
  $text = mailchimp_campaign_convert_url($text);
  return $text;
}

/**
 * Callback for preg_replace in mailchimp_campaign_filter_campaign_process().
 */
function mailchimp_campaign_process_callback($matches = array()) {
  $content = '';
  $entity_type = $entity_id = $view_mode = '';
  foreach ($matches as $key => $match) {
    switch ($key) {
      case 1:
        $entity_type = $match;
        break;
      case 2:
        $entity_id = $match;
        break;
      case 3:
        $view_mode = $match;
        break;
    }
  }
  $entities = entity_load($entity_type, array(
    $entity_id,
  ));
  if (!empty($entities)) {

    // Prevent session information from being rendered.
    drupal_save_session(FALSE);

    // Force the current user to anonymous to prevent access bypass.
    $original_user = $GLOBALS['user'];
    $GLOBALS['user'] = drupal_anonymous_user();

    // Render the entity.
    $render_array = entity_view($entity_type, $entities, $view_mode, NULL, TRUE);

    // Remove contextual links.
    _mailchimp_campaign_recursive_unset($render_array[$entity_type][$entity_id], '#contextual_links');
    $content = render($render_array);

    // Restore the user.
    $GLOBALS['user'] = $original_user;
    drupal_save_session(TRUE);
  }
  return $content;
}

/**
 * Helper function to recursively unset a given key from an array.
 *
 * Used here by mailchimp_campaign_process_callback() to remove all contextual
 * links, even from nested entity objects.
 *
 * @param array $array Array that needs keys removed.
 * @param string $unwanted_key Key that needs to be removed.
 */
function _mailchimp_campaign_recursive_unset(&$array, $unwanted_key) {

  // Remove key from top level of array.
  if (isset($array[$unwanted_key])) {
    unset($array[$unwanted_key]);
  }

  // Recurse through any remaining keys that may themselves be arrays.
  foreach ($array as &$value) {
    if (is_array($value)) {
      _mailchimp_campaign_recursive_unset($value, $unwanted_key);
    }
  }
}

/**
 * Page callback for a campaign's statistics.
 *
 * @param MailChimpCampaign $campaign
 *   The Mailchimp campaign instance.
 *
 * @return array
 *   A renderable array for the campaign stats page.
 */
function mailchimp_campaign_stats_page(MailChimpCampaign $campaign) {

  /* @var \Mailchimp\MailchimpReports $mc_reports */
  $mc_reports = mailchimp_get_api_object('MailchimpReports');
  $result = NULL;
  try {
    if (!$mc_reports) {
      throw new MailchimpException('Cannot get campaign stats without Mailchimp API. Check API key has been entered.');
    }
    $result = $mc_reports
      ->getCampaignSummary($campaign->mc_campaign_id);
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred getting report data from Mailchimp: %message', array(
      '%message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
    return NULL;
  }

  // Tabular summary:
  $rows = array(
    array(
      t('Emails sent'),
      $result->emails_sent,
    ),
    array(
      t('Abuse reports'),
      $result->abuse_reports,
    ),
    array(
      t('Unsubscribed'),
      $result->unsubscribed,
    ),
  );
  $stat_groups = array(
    'bounces',
    'forwards',
    'opens',
    'clicks',
    'facebook_likes',
    'list_stats',
  );
  foreach ($stat_groups as $group) {
    $rows[] = array(
      'data' => array(
        array(
          'data' => '<strong>' . drupal_ucfirst(str_replace('_', ' ', $group)) . '</strong>',
          'colspan' => 2,
        ),
      ),
    );
    foreach ($result->{$group} as $key => $stat) {
      $rows[] = array(
        $key,
        drupal_ucfirst(str_replace('_', ' ', $stat)),
      );
    }
  }

  // Time series chart data:
  $settings = array();
  foreach ($result->timeseries as $series) {
    $settings['mailchimp_campaign']['stats'][] = array(
      'timestamp' => $series->timestamp,
      'emails_sent' => $series->emails_sent,
      'unique_opens' => $series->unique_opens,
      'recipients_click' => $series->recipients_clicks,
    );
  }
  $render = array(
    '#attached' => array(
      'js' => array(
        array(
          'data' => 'https://www.google.com/jsapi',
          'type' => 'external',
        ),
        drupal_get_path('module', 'mailchimp_campaign') . '/js/mailchimp_campaign.js',
        array(
          'data' => $settings,
          'type' => 'setting',
        ),
      ),
    ),
    'charts' => array(
      '#prefix' => '<h2>' . t('Hourly stats for the first 24 hours of the campaign') . '</h2>',
      '#markup' => '<div id="mailchimp-campaign-chart"></div>',
    ),
    'overview' => array(
      '#prefix' => '<h2>' . t('Other campaign metrics') . '</h2>',
      '#theme' => 'table',
      '#rows' => $rows,
      '#header' => array(
        t('Key'),
        t('Value'),
      ),
    ),
  );
  return $render;
}

/**
 * Convert an array of templates into rendered content.
 *
 * @param array $template
 *   Array keyed by the section name with a value of the template.
 *
 * @return array
 *   Array of template content indexed by section ID.
 */
function mailchimp_campaign_render_template($template) {
  $content = array();
  foreach ($template as $key => $part) {
    if (isset($part['format'])) {
      $content[$key] = check_markup($part['value'], $part['format']);
    }
  }
  return $content;
}

/**
 * Get Mailchimp campaigns.
 *
 * @param array $campaign_ids
 *   Array of Mailchimp campaign IDs.
 * @param bool $reset
 *   Set to TRUE if campaigns should not be loaded from cache.
 *
 * @return array
 *   Associative array of Mailchimp campaigns indexed by campaign ID.
 */
function mailchimp_campaign_get_campaigns($campaign_ids, $reset = FALSE) {
  $campaigns = array();
  $cached_campaigns = cache_get('campaigns', 'cache_mailchimp');
  foreach ($campaign_ids as $id) {
    if (!isset($cached_campaigns->data[$id]) || $cached_campaigns->data[$id]->status == MAILCHIMP_STATUS_SENDING || $reset) {
      $to_refresh[] = $id;
    }
    else {
      $campaigns[$id] = $cached_campaigns->data[$id];
    }
  }
  if (!empty($to_refresh)) {

    /* @var \Mailchimp\MailchimpCampaigns $mc_campaigns */
    $mc_campaigns = mailchimp_get_api_object('MailchimpCampaigns');
    try {
      if (!$mc_campaigns) {
        throw new MailchimpException('Cannot get list without Mailchimp API. Check API key has been entered.');
      }
      foreach ($to_refresh as $campaign_id) {
        try {
          $response = $mc_campaigns
            ->getCampaign($campaign_id);
        } catch (Exception $e) {
          $message = t('An error occurred while getting campaign %campaign_id. Would you like to <a href="@administer-page">delete it</a>?', array(
            '%campaign_id' => $campaign_id,
            '@administer-page' => url('admin/config/services/mailchimp/campaigns/' . $campaign_id . '/delete'),
          ));
          drupal_set_message($message, 'error');
          watchdog('mailchimp_campaign', 'An error occurred while getting campaign %campaign_id:  %message', array(
            '%campaign_id' => $campaign_id,
            '%message' => $e
              ->getMessage(),
          ), WATCHDOG_ERROR);
        }
        if (!empty($response->id)) {
          $campaigns[$response->id] = $response;
        }
      }
    } catch (Exception $e) {
      drupal_set_message($e
        ->getMessage(), 'error');
      watchdog('mailchimp_campaign', 'An error occurred while getting campaigns: %message', array(
        '%message' => $e
          ->getMessage(),
      ), WATCHDOG_ERROR);
      return NULL;
    }
    cache_set('campaigns', $campaigns, 'cache_mailchimp');
  }
  return $campaigns;
}

/**
 * Gets an array of list segments for a given list ID.
 *
 * @param int $list_id
 *   The list ID.
 * @param string $type
 *   The segment type to get. "static" or "saved"
 *
 * @return array
 *   Array of Mailchimp list segments.
 */
function mailchimp_campaign_get_list_segments($list_id, $type) {

  /* @var \Mailchimp\MailchimpLists $mc_lists */
  $mc_lists = mailchimp_get_api_object('MailchimpLists');
  try {
    if (!$mc_lists) {
      throw new MailchimpException('Cannot get list segments without Mailchimp API. Check API key has been entered.');
    }
    $parameters = array(
      'type' => $type,
      'count' => 500,
    );
    $response = $mc_lists
      ->getSegments($list_id, $parameters);
    return $response->segments;
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred getting list segments for list ID %list_id: %message', array(
      '%list_id' => $list_id,
      '%message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
    return NULL;
  }
}

/**
 * Tests a list segment, returning the number of subscribers in the segment.
 *
 * @param string $list_id
 *   The list ID.
 * @param string $list_segment_id
 *   The list segment ID.
 *
 * @return int
 *   The number of subscribers contained in the segment.
 */
function mailchimp_test_list_segment($list_id, $list_segment_id) {

  /* @var \Mailchimp\MailchimpLists $mc_lists */
  $mc_lists = mailchimp_get_api_object('MailchimpLists');
  try {
    if (!$mc_lists) {
      throw new MailchimpException('Cannot get campaign list segment without Mailchimp API. Check API key has been entered.');
    }
    $result = $mc_lists
      ->getSegmentMembers($list_id, $list_segment_id, array(
      'count' => 500,
    ));
    return $result->total_items;
  } catch (Exception $e) {
    drupal_set_message($e
      ->getMessage(), 'error');
    watchdog('mailchimp_campaign', 'An error occurred testing a list segment: %message', array(
      '%message' => $e
        ->getMessage(),
    ), WATCHDOG_ERROR);
    return NULL;
  }
}

/**
 * Saves a campaign.
 */
function mailchimp_campaign_save(MailChimpCampaign $campaign) {
  $campaign->updated = REQUEST_TIME;

  // Set the creation timestamp if not set.
  if (!isset($campaign->created) || empty($campaign->created)) {
    $campaign->created = REQUEST_TIME;
  }
  return $campaign
    ->save();
}

/**
 * Load a campaign by ID.
 */
function mailchimp_campaign_load($cid, $reset = FALSE) {
  $campaign = mailchimp_campaign_load_multiple(array(
    $cid,
  ), array(), $reset);
  return $campaign ? $campaign[$cid] : FALSE;
}

/**
 * Loads multiple campaigns.
 */
function mailchimp_campaign_load_multiple($campaign_ids = array(), $conditions = array(), $reset = FALSE) {
  if (empty($campaign_ids)) {
    $campaign_ids = FALSE;
  }
  $campaigns = entity_load('mailchimp_campaign', $campaign_ids, $conditions, $reset);
  return $campaigns;
}

/**
 * Delete a campaign.
 */
function mailchimp_campaign_delete($cid) {
  return mailchimp_campaign_delete_multiple(array(
    $cid,
  ));
}

/**
 * Delete multiple campaigns.
 */
function mailchimp_campaign_delete_multiple($campaign_ids) {
  return entity_get_controller('mailchimp_campaign')
    ->delete($campaign_ids);
}

/**
 * Display a campaign.
 *
 * @param object $campaign
 *   A fully loaded campaign object.
 *
 * @return array
 *   Renderable elements.
 */
function mailchimp_campaign_view($campaign) {
  return $campaign
    ->view();
}

Functions

Namesort descending Description
mailchimp_campaign_access Access callback for campaigns.
mailchimp_campaign_convert_url Change the relative URLs to absolute ones in the message.
mailchimp_campaign_delete Delete a campaign.
mailchimp_campaign_delete_campaign Delete a Mailchimp campaign and the local entity.
mailchimp_campaign_delete_multiple Delete multiple campaigns.
mailchimp_campaign_entities_autocomplete_callback Callback for campaign template entity search field.
mailchimp_campaign_entity_info Implements hook_entity_info().
mailchimp_campaign_filter_campaign_process Process callback for mailchimp_campaign_filter_info().
mailchimp_campaign_filter_info Implements hook_filter_info().
mailchimp_campaign_filter_tips Tips callback for mailchimp_campaign_filter_info().
mailchimp_campaign_get_campaigns Get Mailchimp campaigns.
mailchimp_campaign_get_list_segments Gets an array of list segments for a given list ID.
mailchimp_campaign_get_template Return full details for a Mailchimp Template.
mailchimp_campaign_list_templates Return all available user templates.
mailchimp_campaign_load Load a campaign by ID.
mailchimp_campaign_load_multiple Loads multiple campaigns.
mailchimp_campaign_menu Implements hook_menu().
mailchimp_campaign_overview_page Page callback for showing a list of Mailchimp Campaign entities.
mailchimp_campaign_page_title Title callback: Generate a title for a registration entity.
mailchimp_campaign_permission Implements hook_permission().
mailchimp_campaign_process_callback Callback for preg_replace in mailchimp_campaign_filter_campaign_process().
mailchimp_campaign_render_template Convert an array of templates into rendered content.
mailchimp_campaign_save Saves a campaign.
mailchimp_campaign_save_campaign Save a campaign in Mailchimp and as a Drupal entity.
mailchimp_campaign_send_campaign Send Mailchimp campaign.
mailchimp_campaign_send_test_campaign Send Mailchimp campaign.
mailchimp_campaign_stats_page Page callback for a campaign's statistics.
mailchimp_campaign_theme Implements hook_theme().
mailchimp_campaign_view Display a campaign.
mailchimp_test_list_segment Tests a list segment, returning the number of subscribers in the segment.
_mailchimp_campaign_recursive_unset Helper function to recursively unset a given key from an array.