BFWebAdmin BFWebAdmin - 3 months ago 10
PHP Question

jQuery AJAX post only finds first line of mult line textbox

I've got a POST form on WordPress that I'm using to pass data to MailChimp via its API.

In and of itself (i.e. not using jQuery), it works as expected. However, when instead of using the form's action to navigate to a new page I try to pass the data via an AJAX post action, it only finds the first row of the multi line text box.

FORM

<?php

// Template Name: MailChimp Form
get_header();

?>

<form id="mailchimp_actions" method="post" action="/ajax-curl-actions/">
<select name="action" id="action">
<option>Subscribe</option>
<option>Unsubscribe</option>
<option>Find</option>
</select>
<textarea name="import_data" id="import_data" placeholder="Email Address,First Name,Last Name"></textarea>
<input type="submit">
</form>

<?php get_footer(); ?>


PAGE THAT PROCESSES THE $_POST DATA

<?php

// Template: AJAX - cURL actions.

###############################################################################
# #
# Available options: #
# #
# Add New Subscriber - Create a new subscriber and add them to a list. #
# Subscribe - Add an existing email to the specified list. #
# Unsubscribe - Completely unsubscribe an email from all mailers. #
# Update - Change subscriber information. #
# #
###############################################################################

$subscribers = bfm_data_format($_POST);

$final_report = array('successes'=>0,'failures'=>array());

foreach($subscribers as $subscriber) :
$post_data = array('email' => $subscriber[0], 'fname' => $subscriber[1], 'lname' => $subscriber[2]);
$action = $_POST['action'];
if(!bfm_subscriber_exists($subscriber[0]) && $action=='Subscribe') $action = 'Add New Subscriber';
$report = bfm_curl_actions(bfm_list_id(),bfm_api_key(),$post_data,$action);
if($report['success']) :
$final_report['successes']++;
else:
$final_report['failures'][] = $report['error'];
endif;
endforeach;

?>


FUNCTIONS

// Format data

function bfm_data_format($data) {
$import_data = $data['import_data'];
$import_data_lines = explode("\n",$import_data);
$i=0;
foreach($import_data_lines as $import_data_line) :
$import_data_lines[$i] = explode(',',$import_data_line);
$i++;
endforeach;
return $import_data_lines;
}

// MailChimp data manipulation

function bfm_curl_actions($list_id,$api_key,$post_data,$action) {

$auth = base64_encode( 'user:'.$api_key );

$data = array(
'apikey' => $api_key,
'email_address' => $post_data['email'],
'merge_fields' => array(
'FNAME' => $post_data['fname'],
'LNAME' => $post_data['lname'],
)
);

if($action == 'Subscribe' || $action == 'Add New Subscriber') :
$data['status']='subscribed';
elseif($action == 'Unsubscribe'):
$data['status']='unsubscribed';
endif;

$member_id = md5($post_data['email']);

$json_data = json_encode($data);

$ch = curl_init();

$curlopt_url = "https://us7.api.mailchimp.com/3.0/lists/$list_id/members/";
if($action!='Add New Subscriber') $curlopt_url.=$member_id; // Member ID needs to be excluded if adding an entirely new person.
curl_setopt($ch, CURLOPT_URL, $curlopt_url);
if($action == 'Subscribe' || $action == 'Unsubscribe' || $action == 'Update') :
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
endif;
if($action == 'Find'):
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
endif;
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/3.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);

$result = curl_exec($ch);
$status = "undefined";
$msg = "";
$myArray = json_decode($result, true);

foreach($myArray as $key => $value)
{

if( $key == "status" )
{
$status=$value;
}
else if ($key == "title")
{
$msg=$value;
}

}

$email = $post_data['email'];

if($action == 'Subscribe' || $action == 'Add New Subscriber'):
if($status == "subscribed") :
$report = array ('success'=>true,'error'=>'');
else:
$report = array('success'=>false,'error'=>array('email'=>$email,'message'=>$msg));
endif;
endif;

return $report;

}


function bfm_subscriber_exists($email) {

$api_key = bfm_api_key();
$list_id = bfm_list_id();

$auth = base64_encode( 'user:'.$api_key );

$data = array(
'apikey' => $api_key,
'email_address' => $email,
);

$member_id = md5($email);

$json_data = json_encode($data);

$ch = curl_init();

$curlopt_url = "https://us7.api.mailchimp.com/3.0/lists/$list_id/members/$member_id";

curl_setopt($ch, CURLOPT_URL, $curlopt_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/3.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);

$result = json_decode(curl_exec($ch),true);

if ($result['status']=='404') return false;

return true;

die(' '); // Free up memory.

}


This, as is, works as expected. The second page imports the data from the first into MailChimp.

However, if I try to do the same via AJAX by using the following jQuery, it still imports into MailChimp, but only the first line of the multi line text box is included; all other lines are ignored.

$(document).on("submit","#mailchimp_actions",
function(event) {
event.preventDefault();
var bfm_action = $('#action').val();
var bfm_import = encodeURIComponent($('#import_data').val());
console.log(bfm_action);
console.log(bfm_import);
$.post("/ajax-curl-actions/",
{
import_data: bfm_import,
action: bfm_action,
},
function () {
alert("Successful import.");
}
);
}
);


What am I missing? How do I get it to recognise all the lines in the textbox?

Answer

It seems the problem is caused by double-escaping your variables: Once by you and then again by jQuery when you send the key-value pairs as an object.

If you send key-value pairs to any of jQuery's ajax methods, jQuery takes care of the escaping for you so you can remove encodeURIComponent:

$(document).on("submit","#mailchimp_actions", 
    function(event) {
        event.preventDefault();
        var bfm_action = $('#action').val();
        var bfm_import = $('#import_data').val();
                         ^^^^^^^^^^^^^^^^^^^^^^^ here
        console.log(bfm_action);
        console.log(bfm_import);
        ...
Comments