Skip to content

Instantly share code, notes, and snippets.

@cvstudios
Created May 28, 2018 19:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cvstudios/2cae789bcf0063343aa4c980e3a1b5cf to your computer and use it in GitHub Desktop.
Save cvstudios/2cae789bcf0063343aa4c980e3a1b5cf to your computer and use it in GitHub Desktop.
application/x-httpd-php mailchimp.php ( PHP script text )
<?php
/*
Plugin Name: MailChimp
Plugin URI: http://www.mailchimp.com/plugins/mailchimp-wordpress-plugin/
Description: The MailChimp plugin allows you to quickly and easily add a signup form for your MailChimp list.
Version: 1.5.7
Author: MailChimp
Author URI: https://mailchimp.com/
*/
/* Copyright 2008-2012 MailChimp.com (email : api@mailchimp.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Version constant for easy CSS refreshes
define('MCSF_VER', '1.5.7');
// What's our permission (capability) threshold
define('MCSF_CAP_THRESHOLD', 'manage_options');
// Define our location constants, both MCSF_DIR and MCSF_URL
mailchimpSF_where_am_i();
// Get our MailChimp API class in scope
if (!class_exists('MailChimp_API')) {
$path = plugin_dir_path(__FILE__);
require_once($path . 'lib/mailchimp/mailchimp.php');
}
// includes the widget code so it can be easily called either normally or via ajax
include_once('mailchimp_widget.php');
// includes the backwards compatibility functions
include_once('mailchimp_compat.php');
/**
* Do the following plugin setup steps here
*
* Internationalization
* Resource (JS & CSS) enqueuing
*
* @return void
*/
function mailchimpSF_plugin_init() {
// Internationalize the plugin
$textdomain = 'mailchimp_i18n';
$locale = apply_filters( 'plugin_locale', get_locale(), $textdomain);
load_textdomain('mailchimp_i18n', MCSF_LANG_DIR.$textdomain.'-'.$locale.'.mo');
// Remove Sopresto check. If user does not have API key, make them authenticate.
if (get_option('mc_list_id') && get_option('mc_merge_field_migrate') != true && mailchimpSF_get_api() !== false) {
mailchimpSF_update_merge_fields(get_option('mc_list_id'));
}
// Bring in our appropriate JS and CSS resources
mailchimpSF_load_resources();
}
add_action( 'init', 'mailchimpSF_plugin_init' );
/**
* Add the settings link to the MailChimp plugin row
*
* @param array $links - Links for the plugin
* @return array - Links
*/
function mailchimpSD_plugin_action_links($links) {
$settings_page = add_query_arg(array('page' => 'mailchimpSF_options'), admin_url('options-general.php'));
$settings_link = '<a href="'.esc_url($settings_page).'">'.__('Settings', 'mailchimp_i18n' ).'</a>';
array_unshift($links, $settings_link);
return $links;
}
add_filter('plugin_action_links_'.plugin_basename(__FILE__), 'mailchimpSD_plugin_action_links', 10, 1);
/**
* Loads the appropriate JS and CSS resources depending on
* settings and context (admin or not)
*
* @return void
*/
function mailchimpSF_load_resources() {
// JS
if (get_option('mc_use_javascript') == 'on') {
if (!is_admin()) {
wp_enqueue_script('jquery_scrollto', MCSF_URL.'/js/scrollTo.js', array('jquery'), MCSF_VER);
wp_enqueue_script('mailchimpSF_main_js', MCSF_URL.'/js/mailchimp.js', array('jquery', 'jquery-form'), MCSF_VER);
// some javascript to get ajax version submitting to the proper location
global $wp_scripts;
$wp_scripts->localize('mailchimpSF_main_js', 'mailchimpSF', array(
'ajax_url' => trailingslashit(home_url()),
));
}
}
if (get_option('mc_use_datepicker') == 'on' && !is_admin()) {
// Datepicker theme
wp_enqueue_style('flick', MCSF_URL.'/css/flick/flick.css'
);
// Datepicker JS
wp_enqueue_script('datepicker', MCSF_URL.'/js/datepicker.js', array('jquery','jquery-ui-core'));
}
if(get_option('mc_nuke_all_styles') != true) {
wp_enqueue_style('mailchimpSF_main_css', home_url('?mcsf_action=main_css&ver='.MCSF_VER, 'relative'));
wp_enqueue_style('mailchimpSF_ie_css', MCSF_URL.'css/ie.css');
global $wp_styles;
$wp_styles->add_data( 'mailchimpSF_ie_css', 'conditional', 'IE' );
}
}
/**
* Loads resources for the MailChimp admin page
*
* @return void
*/
function mc_admin_page_load_resources() {
wp_enqueue_style('mailchimpSF_admin_css', MCSF_URL.'css/admin.css');
}
add_action('load-settings_page_mailchimpSF_options', 'mc_admin_page_load_resources');
/**
* Loads jQuery Datepicker for the date-pick class
**/
function mc_datepicker_load() {
require_once(MCSF_DIR . '/views/datepicker.php');
}
if (get_option('mc_use_datepicker') == 'on' && !is_admin()) {
add_action('wp_head', 'mc_datepicker_load');
}
/**
* Handles requests that as light-weight a load as possible.
* typically, JS or CSS
**/
function mailchimpSF_early_request_handler() {
if (isset($_GET['mcsf_action'])) {
switch ($_GET['mcsf_action']) {
case 'main_css':
header("Content-type: text/css");
mailchimpSF_main_css();
exit;
}
}
}
add_action('init', 'mailchimpSF_early_request_handler', 0);
/**
* Outputs the front-end CSS. This checks several options, so it
* was best to put it in a Request-handled script, as opposed to
* a static file.
*/
function mailchimpSF_main_css() {
require_once(MCSF_DIR . '/views/css/frontend.php');
}
/**
* Add our settings page to the admin menu
*
* @return void
*/
function mailchimpSF_add_pages(){
// Add settings page for users who can edit plugins
add_options_page( __( 'MailChimp Setup', 'mailchimp_i18n' ), __( 'MailChimp Setup', 'mailchimp_i18n' ), MCSF_CAP_THRESHOLD, 'mailchimpSF_options', 'mailchimpSF_setup_page');
}
add_action('admin_menu', 'mailchimpSF_add_pages');
function mailchimpSF_request_handler() {
if (isset($_POST['mcsf_action'])) {
switch ($_POST['mcsf_action']) {
case 'login':
$key = trim($_POST['mailchimpSF_api_key']);
try {
$api = new MailChimp_API($key);
} catch (Exception $e) {
$msg = "<strong class='mc_error_msg'>" . $e->getMessage() . "</strong>";
mailchimpSF_global_msg($msg);
break;
}
$key = mailchimpSF_verify_key($api);
if(is_wp_error($key)) {
$msg = "<strong class='mc_error_msg'>" . $key->get_error_message() . "</strong>";
mailchimpSF_global_msg($msg);
}
break;
case 'logout':
// Check capability & Verify nonce
if (!current_user_can(MCSF_CAP_THRESHOLD) || !wp_verify_nonce($_POST['_mcsf_nonce_action'], 'mc_logout')) {
wp_die('Cheatin&rsquo; huh?');
}
// erase auth information
$options = array('mc_api_key', 'mc_sopresto_user', 'mc_sopresto_public_key', 'mc_sopresto_secret_key');
mailchimpSF_delete_options($options);
break;
case 'change_form_settings':
if (!current_user_can(MCSF_CAP_THRESHOLD) || !wp_verify_nonce($_POST['_mcsf_nonce_action'], 'update_general_form_settings')) {
wp_die('Cheatin&rsquo; huh?');
}
// Update the form settings
mailchimpSF_save_general_form_settings();
break;
case 'mc_submit_signup_form':
// Validate nonce
if (!wp_verify_nonce($_POST['_mc_submit_signup_form_nonce'], 'mc_submit_signup_form')) {
wp_die('Cheatin&rsquo; huh?');
}
// Attempt the signup
mailchimpSF_signup_submit();
// Do a different action for html vs. js
switch ($_POST['mc_submit_type']) {
case 'html':
/* This gets set elsewhere! */
break;
case 'js':
if (!headers_sent()){ //just in case...
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT', true, 200);
}
echo mailchimpSF_global_msg(); // Don't esc_html this, b/c we've already escaped it
exit;
}
}
}
}
add_action('init', 'mailchimpSF_request_handler');
function mailchimpSF_migrate_sopresto() {
$sopresto = get_option('mc_sopresto_secret_key');
if(!$sopresto) {
return;
}
// Talk to Sopresto, make exchange, delete old sopresto things.
$body = array(
'public_key' => get_option('mc_sopresto_public_key'),
'hash' => sha1(get_option('mc_sopresto_public_key').get_option('mc_sopresto_secret_key'))
);
$url = 'https://sopresto.socialize-this.com/mailchimp/exchange';
$args = array(
'method' => 'POST',
'timeout' => 500,
'redirection' => 5,
'httpversion' => '1.0',
'user-agent' => 'MailChimp WordPress Plugin/' . get_bloginfo( 'url' ),
'body' => $body
);
//post to sopresto
$key = wp_remote_post($url, $args);
if(!is_wp_error($key) && $key['response']['code'] == 200) {
$key = json_decode($key['body']);
try {
$api = new MailChimp_API($key->response);
} catch (Exception $e) {
$msg = "<strong class='mc_error_msg'>" . $e->getMessage() . "</strong>";
mailchimpSF_global_msg($msg);
return;
}
$verify = mailchimpSF_verify_key($api);
//something went wrong with the key that we had
if(is_wp_error($verify)) {
return;
}
delete_option('mc_sopresto_public_key');
delete_option('mc_sopresto_secret_key');
delete_option('mc_sopresto_user');
return;
}
// Nothing to do here.
return;
}
function mailchimpSF_update_merge_fields($list_id)
{
mailchimpSF_get_merge_vars(get_option('mc_list_id'), true);
mailchimpSF_get_interest_categories(get_option('mc_list_id'), true);
update_option('mc_merge_field_migrate', true);
}
function mailchimpSF_auth_nonce_key($salt = null) {
if (is_null($salt)) {
$salt = mailchimpSF_auth_nonce_salt();
}
return 'social_authentication' . md5( AUTH_KEY . $salt );
}
function mailchimpSF_auth_nonce_salt() {
return md5(microtime().$_SERVER['SERVER_ADDR']);
}
/**
* Creates new MailChimp API v3 object
*
* @return MailChimp_API | false
*/
function mailchimpSF_get_api($force = false) {
$key = get_option('mc_api_key');
if($key) {
return new MailChimp_API($key);
}
return false;
}
/**
* Checks to see if we're storing a password, if so, we need
* to upgrade to the API key
*
* @return bool
**/
function mailchimpSF_needs_upgrade() {
$igs = get_option('mc_interest_groups');
if ($igs !== false // we have an option
&& (
empty($igs) || // it can be an empty array (no interest groups)
(is_array($igs) && isset($igs[0]['id'])) // OR it should be a populated array that's well-formed
)) {
return false; // no need to upgrade
}
else {
return true; // yeah, let's do it
}
}
/**
* Deletes all mailchimp options
**/
function mailchimpSF_delete_setup() {
$options = array('mc_user_id', 'mc_sopresto_user', 'mc_sopresto_public_key', 'mc_sopresto_secret_key', 'mc_rewards', 'mc_use_javascript', 'mc_use_datepicker', 'mc_use_unsub_link', 'mc_list_id', 'mc_list_name', 'mc_interest_groups', 'mc_merge_vars');
$igs = get_option('mc_interest_groups');
if (is_array($igs)) {
foreach ($igs as $ig) {
$opt = 'mc_show_interest_groups_'.$ig['id'];
$options[] = $opt;
}
}
$mv = get_option('mc_merge_vars');
if (is_array($mv)){
foreach($mv as $var){
$opt = 'mc_mv_'.$var['tag'];
$options[] = $opt;
}
}
mailchimpSF_delete_options($options);
}
/**
* Gets or sets a global message based on parameter passed to it
*
* @return string/bool depending on get/set
**/
function mailchimpSF_global_msg($msg = null) {
global $mcsf_msgs;
// Make sure we're formed properly
if (!is_array($mcsf_msgs)) {
$mcsf_msgs = array();
}
// See if we're getting
if (is_null($msg)) {
return implode('', $mcsf_msgs);
}
// Must be setting
$mcsf_msgs[] = $msg;
return true;
}
/**
* Sets the default options for the option form
**/
function mailchimpSF_set_form_defaults($list_name = '') {
update_option('mc_header_content',__( 'Sign up for', 'mailchimp_i18n' ).' '.$list_name);
update_option('mc_submit_text',__( 'Subscribe', 'mailchimp_i18n' ));
update_option('mc_use_datepicker', 'on');
update_option('mc_custom_style','off');
update_option('mc_use_javascript','on');
update_option('mc_double_optin', true);
update_option('mc_use_unsub_link','off');
update_option('mc_header_border_width','1');
update_option('mc_header_border_color','E3E3E3');
update_option('mc_header_background','FFFFFF');
update_option('mc_header_text_color','CC6600');
update_option('mc_form_border_width','1');
update_option('mc_form_border_color','E0E0E0');
update_option('mc_form_background','FFFFFF');
update_option('mc_form_text_color','3F3F3f');
}
/**
* Saves the General Form settings on the options page
*
* @return void
**/
function mailchimpSF_save_general_form_settings() {
// IF NOT DEV MODE
if (isset($_POST['mc_rewards'])){
update_option('mc_rewards', 'on');
$msg = '<p class="success_msg">'.__('Monkey Rewards turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
} else if (get_option('mc_rewards')!='off') {
update_option('mc_rewards', 'off');
$msg = '<p class="success_msg">'.__('Monkey Rewards turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
if (isset($_POST['mc_use_javascript'])){
update_option('mc_use_javascript', 'on');
$msg = '<p class="success_msg">'.__('Fancy Javascript submission turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
} else if (get_option('mc_use_javascript')!='off') {
update_option('mc_use_javascript', 'off');
$msg = '<p class="success_msg">'.__('Fancy Javascript submission turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
if (isset($_POST['mc_use_datepicker'])){
update_option('mc_use_datepicker', 'on');
$msg = '<p class="success_msg">'.__('Datepicker turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
} else if (get_option('mc_use_datepicker')!='off') {
update_option('mc_use_datepicker', 'off');
$msg = '<p class="success_msg">'.__('Datepicker turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
/*Enable double optin toggle*/
if(isset($_POST['mc_double_optin'])) {
update_option('mc_double_optin', true);
$msg = '<p class="success_msg">'.__('Double opt-in turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
} else if (get_option('mc_double_optin') != false) {
update_option('mc_double_optin', false);
$msg = '<p class="success_msg">'.__('Double opt-in turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
/* NUKE the CSS! */
if(isset($_POST['mc_nuke_all_styles'])) {
update_option('mc_nuke_all_styles', true);
$msg = '<p class="success_msg">'.__('MailChimp CSS turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}elseif (get_option('mc_nuke_all_styles') !== false) {
update_option('mc_nuke_all_styles', false);
$msg = '<p class="success_msg">'.__('MailChimp CSS turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
/* Update existing */
if (isset($_POST['mc_update_existing'])) {
update_option('mc_update_existing', true);
$msg = '<p class="success_msg">' . __('Update existing subscribers turned On!') . '</p>';
mailchimpSF_global_msg($msg);
} elseif (get_option('mc_update_existing') ==! false) {
update_option('mc_update_existing', false);
$msg = '<p class="success_msg">' . __('Update existing subscribers turned Off!') . '</p>';
mailchimpSF_global_msg($msg);
}
if (isset($_POST['mc_use_unsub_link'])){
update_option('mc_use_unsub_link', 'on');
$msg = '<p class="success_msg">'.__('Unsubscribe link turned On!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
elseif (get_option('mc_use_unsub_link')!='off') {
update_option('mc_use_unsub_link', 'off');
$msg = '<p class="success_msg">'.__('Unsubscribe link turned Off!', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
$content = stripslashes($_POST['mc_header_content']);
$content = str_replace("\r\n","<br/>", $content);
update_option('mc_header_content', $content );
$content = stripslashes($_POST['mc_subheader_content']);
$content = str_replace("\r\n","<br/>", $content);
update_option('mc_subheader_content', $content );
$submit_text = stripslashes($_POST['mc_submit_text']);
$submit_text = str_replace("\r\n","", $submit_text);
update_option('mc_submit_text', $submit_text);
// Set Custom Style option
update_option('mc_custom_style', isset($_POST['mc_custom_style']) ? 'on' : 'off');
//we told them not to put these things we are replacing in, but let's just make sure they are listening...
if(isset($_POST['mc_form_border_width'])) {
update_option('mc_form_border_width',str_replace('px', '', $_POST['mc_form_border_width']) );
}
if(isset($_POST['mc_form_border_color'])) {
update_option('mc_form_border_color', str_replace('#', '', $_POST['mc_form_border_color']));
}
if(isset($_POST['mc_form_background'])){
update_option('mc_form_background',str_replace('#', '', $_POST['mc_form_background']));
}
if(isset($_POST['mc_form_text_color'])) {
update_option('mc_form_text_color', str_replace('#', '', $_POST['mc_form_text_color']));
}
// IF NOT DEV MODE
$igs = get_option('mc_interest_groups');
if (is_array($igs)) {
foreach($igs as $var){
$opt = 'mc_show_interest_groups_'.$var['id'];
if (isset($_POST[$opt])){
update_option($opt,'on');
} else {
update_option($opt,'off');
}
}
}
$mv = get_option('mc_merge_vars');
if (is_array($mv)) {
foreach($mv as $var){
$opt = 'mc_mv_'.$var['tag'];
if (isset($_POST[$opt]) || $var['required']=='Y'){
update_option($opt,'on');
} else {
update_option($opt,'off');
}
}
}
$msg = '<p class="success_msg">'.esc_html(__('Successfully Updated your List Subscribe Form Settings!', 'mailchimp_i18n')).'</p>';
mailchimpSF_global_msg($msg);
}
/**
* Sees if the user changed the list, and updates options accordingly
**/
function mailchimpSF_change_list_if_necessary() {
// Simple permission check before going through all this
if (!current_user_can(MCSF_CAP_THRESHOLD)) { return; }
$api = mailchimpSF_get_api();
if (!$api) { return; }
//we *could* support paging, but few users have that many lists (and shouldn't)
$lists = $api->get('lists',100, array('fields' => 'lists.id,lists.name,lists.email_type_option'));
$lists = $lists['lists'];
if (is_array($lists) && !empty($lists) && isset($_POST['mc_list_id'])) {
/* If our incoming list ID (the one chosen in the select dropdown)
is in our array of lists, the set it to be the active list */
foreach($lists as $key => $list) {
if ($list['id'] == $_POST['mc_list_id']) {
$list_id = $_POST['mc_list_id'];
$list_name = $list['name'];
$list_key = $key;
}
}
$orig_list = get_option('mc_list_id');
if ($list_id != '') {
update_option('mc_list_id', $list_id);
update_option('mc_list_name', $list_name);
update_option('mc_email_type_option', $lists[$list_key]['email_type_option']);
// See if the user changed the list
$new_list = false;
if ($orig_list != $list_id){
// The user changed the list, Reset the Form Defaults
mailchimpSF_set_form_defaults($list_name);
$new_list = true;
}
// email_type_option
// Grab the merge vars and interest groups
$mv = mailchimpSF_get_merge_vars($list_id, $new_list);
$igs = mailchimpSF_get_interest_categories($list_id, $new_list);
$igs_text = ' ';
if (is_array($igs)) {
$igs_text .= sprintf(__('and %s Sets of Interest Groups', 'mailchimp_i18n'), count($igs));
}
$msg = '<p class="success_msg">'.
sprintf(
__('<b>Success!</b> Loaded and saved the info for %d Merge Variables', 'mailchimp_i18n').$igs_text,
count($mv)
).' '.
__('from your list').' "'.$list_name.'"<br/><br/>'.
__('Now you should either Turn On the MailChimp Widget or change your options below, then turn it on.', 'mailchimp_i18n').'</p>';
mailchimpSF_global_msg($msg);
}
}
}
function mailchimpSF_get_merge_vars($list_id, $new_list) {
$api = mailchimpSF_get_api();
$mv = $api->get('lists/' . $list_id . '/merge-fields', 80);
//if we get an error back from the api, exit this process.
if(is_wp_error($mv)) {
return;
}
$mv['merge_fields'] = mailchimpSF_add_email_field($mv['merge_fields']);
update_option('mc_merge_vars', $mv['merge_fields']);
foreach($mv['merge_fields'] as $var){
$opt = 'mc_mv_'.$var['tag'];
//turn them all on by default
if ($new_list) {
update_option($opt, 'on' );
}
}
return $mv['merge_fields'];
}
function mailchimpSF_add_email_field($merge) {
$email = array(
'tag' => 'EMAIL',
'name' => __('Email Address', 'mailchimp_i18n'),
'type' => 'email',
'required' => true,
'public' => true,
'display_order' => 1,
'default_value' => null
);
array_unshift($merge, $email);
return $merge;
}
function mailchimpSF_get_interest_categories($list_id, $new_list) {
$api = mailchimpSF_get_api();
$igs = $api->get('lists/' . $list_id . '/interest-categories', 60);
//if we get an error back from the api, exis
if(is_wp_error($igs)) {
return;
}
if (is_array($igs)) {
$key = 0;
foreach($igs['categories'] as $ig) {
$groups = $api->get('lists/' . $list_id . '/interest-categories/' . $ig['id'] . '/interests', 60);
$igs['categories'][$key]['groups'] = $groups['interests'];
$opt = 'mc_show_interest_groups_'.$ig['id'];
//turn them all on by default
if ($new_list) {
update_option($opt, 'on' );
}
$key++;
}
}
update_option('mc_interest_groups', $igs['categories']);
return $igs['categories'];
}
/**
* Outputs the Settings/Options page
*/
function mailchimpSF_setup_page() {
$path = plugin_dir_path(__FILE__);
wp_enqueue_script('showMe', MCSF_URL.'js/hidecss.js', array('jquery'), MCSF_VER);
require_once($path.'/views/setup_page.php');
}//mailchimpSF_setup_page()
function mailchimpSF_register_widgets() {
if (mailchimpSF_get_api()) {
register_widget('mailchimpSF_Widget');
}
}
add_action('widgets_init', 'mailchimpSF_register_widgets');
function mailchimpSF_shortcode($atts){
ob_start();
mailchimpSF_signup_form();
return ob_get_clean();
}
add_shortcode('mailchimpsf_form', 'mailchimpSF_shortcode');
/**
* Attempts to signup a user, per the $_POST args.
*
* This sets a global message, that is then used in the widget
* output to retrieve and display that message.
*
* @return bool
*/
function mailchimpSF_signup_submit() {
$mv = get_option('mc_merge_vars', array());
$mv_tag_keys = array();
$igs = get_option('mc_interest_groups', array());
$listId = get_option('mc_list_id');
$email = isset($_POST['mc_mv_EMAIL']) ? strip_tags(stripslashes($_POST['mc_mv_EMAIL'])) : '';
$merge = $errs = $html_errs = array(); // Set up some vars
$merge = mailchimpSF_merge_submit($mv);
//Catch errors and fail early.
if(is_wp_error($merge)) {
$msg = "<strong class='mc_error_msg'>" . $merge->get_error_message() . "</strong>";
mailchimpSF_global_msg($msg);
return false;
}
// Head back to the beginning of the merge vars array
reset($mv);
// Ensure we have an array
$igs = !is_array($igs) ? array() : $igs;
$igs = mailchimpSF_groups_submit($igs);
// Clear out empty merge vars
$merge = mailchimpSF_merge_remove_empty($merge);
if (isset($_POST['email_type']) && in_array($_POST['email_type'], array('text', 'html', 'mobile'))) {
$email_type = $_POST['email_type'];
}
else {
$email_type = 'html';
}
$api = mailchimpSF_get_api();
if (!$api) {
$url = mailchimpSF_signup_form_url();
$error = '<strong class="mc_error_msg">'. __('We encountered a problem adding ' . $email . ' to the list. Please <a href="' . $url . '">sign up here.</a>') . '</strong>';
mailchimpSF_global_msg($error);
return false;
}
$url = 'lists/'. $listId . '/members/' . md5(strtolower($email));
$status = mailchimpSF_check_status($url);
// If update existing is turned off and the subscriber exists, error out.
if (get_option('mc_update_existing') == false && $status === 'subscribed') {
$msg = 'This email address is already subscribed to the list.';
$error = new WP_Error('mailchimp-update-existing', $msg);
mailchimpSF_global_msg('<strong class="mc_error_msg">' . $msg . '</strong>');
return false;
}
$body = mailchimpSF_subscribe_body($merge, $igs, $email_type, $email, $status, get_option('mc_double_optin'));
$retval = $api->post($url, $body, 'PUT');
// If we have errors, then show them
if(is_wp_error($retval)) {
$msg = "<strong class='mc_error_msg'>" . $retval->get_error_message() . "</strong>";
mailchimpSF_global_msg($msg);
return false;
}
if($retval['status'] == 'subscribed') {
$esc = __("Success, you've been signed up.", 'mailchimp_i18n');
$msg = "<strong class='mc_success_msg'>{$esc}</strong>";
} else {
$esc = __("Success, you've been signed up! Please look for our confirmation email.", 'mailchimp_i18n');
$msg = "<strong class='mc_success_msg'>{$esc}</strong>";
}
// Set our global message
mailchimpSF_global_msg($msg);
return true;
}
/*
Cleans up merge fields and interests to make them
API 3.0-friendly.
*/
function mailchimpSF_subscribe_body($merge, $igs, $email_type, $email, $status, $double_optin)
{
$body = new stdClass();
$body->email_address = $email;
$body->email_type = $email_type;
$body->merge_fields = $merge;
if (!empty($igs)) {
$body->interests = $igs;
}
if($status !== 'subscribed') {
// single opt-in that covers new subscribers
if (!$status && $double_optin == false) {
$body->status = 'subscribed';
} else {
// anyone else
$body->status = 'pending';
}
}
return $body;
}
function mailchimpSF_check_status($endpoint) {
$endpoint .= '?fields=status';
$api = mailchimpSF_get_api();
$subscriber = $api->get($endpoint, null);
if(is_wp_error($subscriber)) {
return false;
}
return $subscriber['status'];
}
function mailchimpSF_merge_submit($mv) {
// Loop through our Merge Vars, and if they're empty, but required, then print an error, and mark as failed
$merge = new stdClass();
foreach($mv as $var) {
// We also want to create an array where the keys are the tags for easier validation later
$tag = $var['tag'];
$mv_tag_keys[$tag] = $var;
$opt = 'mc_mv_' . $tag;
$opt_val = isset($_POST[$opt]) ? stripslashes_deep($_POST[$opt]) : '';
// Handle phone number logic
if ($var['type'] === 'phone' && $var['options']['phone_format'] === 'US') {
$opt_val = mailchimpSF_merge_validate_phone($opt_val, $var);
if(is_wp_error($opt_val)) {
return $opt_val;
}
}
// Handle address logic
else if (is_array($opt_val) && $var['type'] == 'address') {
$validate = mailchimpSF_merge_validate_address($opt_val, $var);
if(is_wp_error($validate)) {
return $validate;
}
if($validate) {
$merge->$tag = $validate;
}
continue;
}
else if (is_array($opt_val)) {
$keys = array_keys($opt_val);
$val = new stdClass();
foreach($keys as $key) {
$val->$key = $opt_val[$key];
}
$opt_val = $val;
}
if ($var['required'] == 'Y' && trim($opt_val) == '') {
$message = sprintf(__("You must fill in %s.", 'mailchimp_i18n'), esc_html($var['name']));
$error = new WP_Error('missing_required_field', $message);
return $error;
}
else {
if ($tag != 'EMAIL') {
$merge->$tag = $opt_val;
}
}
}
return $merge;
}
function mailchimpSF_merge_validate_phone($opt_val, $var) {
// This filters out all 'falsey' elements
$opt_val = array_filter($opt_val);
// If they weren't all empty
if (!$opt_val) {
return;
}
$opt_val = implode('-', $opt_val);
if (strlen($opt_val) < 12) {
$opt_val = '';
}
if (!preg_match('/[0-9]{0,3}-[0-9]{0,3}-[0-9]{0,4}/A', $opt_val)) {
$message = sprintf(__("%s must consist of only numbers", 'mailchimp_i18n'), esc_html($var['name']));
$error = new WP_Error('mc_phone_validation', $message);
return $error;
}
return $opt_val;
}
function mailchimpSF_merge_validate_address($opt_val, $var) {
if ($var['required'] == 'Y') {
if (empty($opt_val['addr1']) || empty($opt_val['city'])) {
$message = sprintf(__("You must fill in %s.", 'mailchimp_i18n'), esc_html($var['name']));
$error = new WP_Error('invalid_address_merge', $message);
return $error;
}
} else {
if (empty($opt_val['addr1']) || empty($opt_val['city'])) {
return false;
}
}
$merge = new stdClass();
$merge->addr1 = $opt_val['addr1'];
$merge->addr2 = $opt_val['addr2'];
$merge->city = $opt_val['city'];
$merge->state = $opt_val['state'];
$merge->zip = $opt_val['zip'];
$merge->country = $opt_val['country'];
return $merge;
}
function mailchimpSF_merge_remove_empty($merge)
{
foreach ($merge as $k => $v) {
if (is_object($v) && empty($v)) {
unset($merge->$k);
} elseif ((is_string($v) && trim($v) === '') || is_null($v)) {
unset($merge->$k);
}
}
// If we have an empty $merge, then assign empty string.
if (count($merge) == 0 || $merge == '') {
$merge = '';
}
return $merge;
}
function mailchimpSF_groups_submit($igs) {
$groups = mailchimpSF_set_all_groups_to_false();
if(empty($igs)) {
return new StdClass();
}
//get groups and ids
//set all to false
foreach ($igs as $ig) {
$ig_id = $ig['id'];
if (get_option('mc_show_interest_groups_'.$ig_id) == 'on' && $ig['type'] !== 'hidden') {
switch ($ig['type']) {
case 'dropdown':
case 'radio':
// there can only be one value submitted for radio/dropdowns, so use that at the group id.
if (isset($_POST['group'][$ig_id]) && !empty($_POST['group'][$ig_id])) {
$value = $_POST['group'][$ig_id];
$groups->$value = true;
}
break;
case 'checkboxes':
if (isset($_POST['group'][$ig_id])) {
foreach ($_POST['group'][$ig_id] as $id => $value) {
$groups->$id = true;
}
}
break;
default:
// Nothing
break;
}
}
}
return $groups;
}
function mailchimpSF_set_all_groups_to_false() {
$toreturn = new StdClass();
foreach (get_option('mc_interest_groups') as $grouping) {
if($grouping['type'] !== 'hidden') {
foreach ($grouping['groups'] as $group) {
$id = $group['id'];
$toreturn->$id = false;
}
}
}
return $toreturn;
}
function mailchimpSF_verify_key($api) {
$user = $api->get('');
if (is_wp_error($user)) {
return $user;
}
//Might as well set this data if we have it already.
$valid_roles = array('owner', 'admin', 'manager');
if(in_array($user['role'], $valid_roles)) {
update_option('mc_api_key', $api->key);
update_option('mc_user', $user);
update_option('mc_datacenter', $api->datacenter);
} else {
$msg = __('API Key must belong to "Owner", "Admin", or "Manager."', 'mailchimp_i18n');
return new WP_Error('mc-invalid-role', $msg);
}
return;
}
function mailchimpSF_update_profile_url($email) {
$dc = get_option('mc_datacenter');
$eid = base64_encode($email);
$user = get_option('mc_user');
$list_id = get_option('mc_list_id');
$url = 'http://' . $dc . '.list-manage.com/subscribe/send-email?u=' . $user['account_id'] . '&id=' . $list_id . '&e=' . $eid;
return $url;
}
function mailchimpSF_signup_form_url() {
$dc = get_option('mc_datacenter');
$user = get_option('mc_user');
$list_id = get_option('mc_list_id');
$url = 'http://' . $dc . '.list-manage.com/subscribe?u=' . $user['account_id'] . '&id=' . $list_id;
return $url;
}
function mailchimpSF_delete_options($options = array()) {
foreach($options as $option) {
delete_option($option);
}
}
/**********************
* Utility Functions *
**********************/
/**
* Utility function to allow placement of plugin in plugins, mu-plugins, child or parent theme's plugins folders
*
* This function must be ran _very early_ in the load process, as it sets up important constants for the rest of the plugin
*/
function mailchimpSF_where_am_i() {
$locations = array(
'plugins' => array(
'dir' => plugin_dir_path(__FILE__),
'url' => plugins_url()
),
'mu_plugins' => array(
'dir' => plugin_dir_path(__FILE__),
'url' => plugins_url(),
),
'template' => array(
'dir' => trailingslashit(get_template_directory()).'plugins/',
'url' => trailingslashit(get_template_directory_uri()).'plugins/',
),
'stylesheet' => array(
'dir' => trailingslashit(get_stylesheet_directory()).'plugins/',
'url' => trailingslashit(get_stylesheet_directory_uri()).'plugins/',
),
);
// Set defaults
$mscf_dirbase = trailingslashit(basename(dirname(__FILE__))); // Typically wp-mailchimp/ or mailchimp/
$mscf_dir = trailingslashit(plugin_dir_path(__FILE__));
$mscf_url = trailingslashit(plugins_url(null, __FILE__));
// Try our hands at finding the real location
foreach ($locations as $key => $loc) {
$dir = trailingslashit($loc['dir']).$mscf_dirbase;
$url = trailingslashit($loc['url']).$mscf_dirbase;
if (is_file($dir.basename(__FILE__))) {
$mscf_dir = $dir;
$mscf_url = $url;
break;
}
}
// Define our complete filesystem path
define('MCSF_DIR', $mscf_dir);
/* Lang location needs to be relative *from* ABSPATH,
so strip it out of our language dir location */
define('MCSF_LANG_DIR', trailingslashit(MCSF_DIR).'po/');
// Define our complete URL to the plugin folder
define('MCSF_URL', $mscf_url);
}
/**
* MODIFIED VERSION of wp_verify_nonce from WP Core. Core was not overridden to prevent problems when replacing
* something universally.
*
* Verify that correct nonce was used with time limit.
*
* The user is given an amount of time to use the token, so therefore, since the
* UID and $action remain the same, the independent variable is the time.
*
* @param string $nonce Nonce that was used in the form to verify
* @param string|int $action Should give context to what is taking place and be the same when nonce was created.
* @return bool Whether the nonce check passed or failed.
*/
function mailchimpSF_verify_nonce($nonce, $action = -1) {
$user = wp_get_current_user();
$uid = (int) $user->ID;
if ( ! $uid ) {
$uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
}
if ( empty( $nonce ) ) {
return false;
}
$token = 'MAILCHIMP';
$i = wp_nonce_tick();
// Nonce generated 0-12 hours ago
$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 1;
}
// Nonce generated 12-24 hours ago
$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
if ( hash_equals( $expected, $nonce ) ) {
return 2;
}
// Invalid nonce
return false;
}
/**
* MODIFIED VERSION of wp_create_nonce from WP Core. Core was not overridden to prevent problems when replacing
* something universally.
*
* Creates a cryptographic token tied to a specific action, user, and window of time.
*
* @param string $action Scalar value to add context to the nonce.
* @return string The token.
*/
function mailchimpSF_create_nonce($action = -1) {
$user = wp_get_current_user();
$uid = (int) $user->ID;
if ( ! $uid ) {
/** This filter is documented in wp-includes/pluggable.php */
$uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
}
$token = 'MAILCHIMP';
$i = wp_nonce_tick();
return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
}
@cvstudios
Copy link
Author

Code errors in mailchimp.php add an extra slash to the following file paths (noticed when running a link checker):

.../wp-content/plugins/mailchimp//js/scrollTo.js?ver=1.5.7
.../wp-content/plugins/mailchimp//js/mailchimp.js?ver=1.5.7
.../wp-content/plugins/mailchimp//css/flick/flick.css?ver=4.9.6
.../wp-content/plugins/mailchimp//js/datepicker.js?ver=4.9.6

Error Line 102:
MCSF_URL.'/js/scrollTo.js'
correct to:
MCSF_URL.'js/scrollTo.js'

Error Line 103:
MCSF_URL.'/js/mailchimp.js'
correct to:
MCSF_URL.'js/mailchimp.js'

Error Line 114:
MCSF_URL.'/css/flick/flick.css'
correct to:
MCSF_URL.'css/flick/flick.css'

Error Line 117:
MCSF_URL.'/js/datepicker.js'
correct to:
MCSF_URL.'js/datepicker.js'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment