Ajax function that retrieve an e-mail template and send it - php

I'm trying to create an ajax function that retrieve an e-mail template and send it. This is my code so far:
<?php
add_action('wp_ajax_nopriv_test_function', 'test_function');
add_action('wp_ajax_test_function', 'test_function');
function test_function() {
$content = Array(
"name"=>$_POST['name'],
"email"=>$_POST['email'],
);
ob_start();
include("../emails/email_template.php");
$message = ob_get_contents();
ob_end_clean();
$headers[] = 'Content-Type: text/html; charset=UTF-8';
wp_mail($_POST['email'], "[E-mail subject] This is a test", $message, $headers);
$result['feedback'] = "All OK!";
}
wp_send_json($result);
die();
}
?>
The ajax call works. I get the response.feedback properly, even knowing it's not "All OK!".
You can analyze email_template.php by clicking here. It's basically a resposive e-mail template that receives some PHP variables from $contents. See line 313.
Unfortunately, I'm getting this error:
PHP Fatal error: Unknown: Cannot use output buffering in output buffering display handlers in Unknown on line 0, referer: http://example.com/.
I've searched here and in other sources, but didn't found an proper answer. Am i missing something? Is this even possible?
Thanks in advance :)

Sorry for posting this as an answer but I don't have enough points to post a comment. I have been following this question for weeks as I am extremely curious as to the critical difference between the working code and the non-working code. I absolutely don't understand what is wrong with the original solution. For my curiosity can you add the following code before the call to ob_start()
error_log( 'before ob_start(): ' . print_r( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), true ) );
The error you are getting should only occur if ob_start() is called in an output buffering callback. I really don't see how this can happen in your given code but maybe the backtrace will show something.
I know several weeks have passed and maybe you have lost interest in this problem but hopefully you are like me and still would like to understand why. I have looked at this code many times and cannot see any problem and would really like to understand what is wrong.
Thanks in advance for any consideration.
UPDATE:
I tested your code using the following plugin:
<?php
/*
Plugin Name: Gruby's Problem
*/
add_action('wp_ajax_nopriv_test_function', 'test_function');
add_action('wp_ajax_test_function', 'test_function');
function test_function() {
$content = Array(
"name"=>$_POST['name'],
"email"=>$_POST['email'],
);
ob_start();
include("email_template.php");
$message = ob_get_contents();
ob_end_clean();
$headers[] = 'Content-Type: text/html; charset=UTF-8';
wp_mail($_POST['email'], "[E-mail subject] This is a test", $message, $headers);
$result['feedback'] = "All OK!";
wp_send_json($result);
die();
}
add_shortcode( 'send_gruby_ajax_test', function() {
?>
<button id="gruby_send_ajax_test">Send Gruby Ajax Test</button>
<script>
jQuery( 'button#gruby_send_ajax_test' ).click( function() {
jQuery.post( '<?php echo admin_url( 'admin-ajax.php' ); ?>', { action: 'test_function', name: 'Magenta', email: 'xxx#xxx.com' }, function( r ) {
console.log( r );
} );
} );
</script>
<?php
} );
?>
I had to fix 2 problems - removed an extraneous '}' after the line
$result['feedback'] = "All OK!";
and changed line 313 in email_template.php
Your order has shipped, <?php echo $content['nome'];?>!
to
Your order has shipped, <?php echo $content['name'];?>!
After these changes the code worked as expected. So your original code does work in my environment. I am still curious as to how you are getting your code to fail. Can you run my plugin and see if it causes the same error as before. To test the plugin you need to create a page with post content:
[send_gruby_ajax_test]
This will display a button which when clicked will send the AJAX request for the 'test_function'.

Changed my code to:
<?php
add_action('wp_ajax_nopriv_test_function', 'test_function');
add_action('wp_ajax_test_function', 'test_function');
function test_function() {
ob_start();
$content = Array(
"nome"=>$_POST['nome_registro'],
"email"=>$_POST['email_registro'],
);?>
<?php include(ABS_PATH_DEFINED_ELSEWHERE."my-plugin/inc/emails/email_template.php"); ?>
<?php
$message = ob_get_contents();
ob_end_clean();
$headers[] = 'Content-Type: text/html; charset=UTF-8';
wp_mail($_POST['email'], "[E-mail subject] This is a test", $message, $headers);
$result['feedback'] = "All OK!";
}
wp_send_json($result);
die();
}
?>
And worked like a charm :)
Anyone has an explanation of why the previous code didn't worked?

Related

WordPress - Export table as csv using jQuery/Ajax

Question:: I am developing a plugin. This plugins creates a custom table in WP database. How can I export the data from this table using Ajax?
Where I am?: I have created the hook and the handler. I can actually grab the data. Please see my code below.
add_action ( 'wp_ajax_nopriv_exportcsv', 'exprot_to_csv' );
add_action ( 'wp_ajax_exportcsv', 'exprot_to_csv' );
<script type="text/javascript">
jQuery("#export-csv").on("click",function(e){
jQuery.ajax({
type: "POST",
url: ajaxurl,
data: {"action":"exportcsv"},
success: function(response){alert(response);}
})
});</script>
function exprot_to_csv(){
global $wpdb;
$table_prefix = $wpdb->prefix;
$table = $table_prefix.'my_custom_table';
$result = $wpdb->get_results("SELECT * FROM ".$table."");
foreach ($result as $row) {
$output .="\n";
$output .='"'.$row->post_id.'",';
}
$output .="\n";
$file = "custom_table";
$filename = $file."_".date("Y-m-d_H-i",time());
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
echo $output;
exit;
}
In the alert box, I am getting comma separated post IDs as expected. But I am not sure how to move on from here. I mean how to handle this response and prompt the user to save/download the file.
Any help?
You are close...! I ran into same problem, tried a similar solution.
Check this question out:
Download file through an ajax call php
And THIS specific answer:
https://stackoverflow.com/a/11452917
Make sure to look at Dario's answer
Summary -
AJAX is not for streaming downloads.
The solution here is to make an iFrame
Load a PHP file into that iFrame using jQuery
Serve up your file with a File Transfer
'header('Content-Description: File Transfer');'
This works in WordPress. Use Admin-Ajax.
Cheers
Hopefully this will solve your problem.
In jQuery:
window.location = response->in success
Action ajax:
Please remove all headers
echo admin_url($filename);
die;

can not echo a function content inside file_get_contents

Suppose this code prints Youtube:
<?php ytio_empt(); ?>
I want a dynamic way to echo the content of the above function in the place of 'YouTube' in the following xml data:
$xmlData = file_get_contents( 'http://gdata.youtube.com/feeds/api/users/'. 'YouTube' );
I have tried:
$xmlData = file_get_contents( 'http://gdata.youtube.com/feeds/api/users/'. ytio_empt() );
But in vain, the file_get_contents() always fails to open stream.
P.S: Perhaps using HTML will work: to put <?php ytio_empt(); ?> in the place of ytio_empt() in $xmlData. I just don't know how to end PHP function and resume it later..
So as you posted your function in the comments:
function ytio_empt() {
if(empty(get_option('ytio_username'))) {
echo esc_attr( get_option('ytio_id') );
//^^^^
} else {
echo esc_attr( get_option('ytio_username') );
//^^^^
}
}
You will see you don't return the values you just print them! So in order to return them you simply have to change echo -> return.
And if you want to read more about return values see the manual: http://php.net/manual/en/functions.returning-values.php

How to use file_put_contents() for part of the php file

I'm using PHP and html in order to develop a simple mechanism that creates reports and send them by Email.
I use the function file_put_contents() and the function ob_get_contents() as a parameter in order to create an html file which I use to send by the mail.
I realized that if I use ob_get_contents() without using ob_start() it simply takes all the file and put it to an html file. This is not good for me since I want only parts of the file to be in the generated html. To be more clear my code looks something like this:
<html and php code I want to include in my html file>
.
.
<html and php code I don't want to include in my html file>
.
.
<html and php code I want to include in my html file>
.
.
<html and php code I don't want to include in my html file>
.
.
.
file_put_contents('report.html', ob_get_contents());
$message = file_get_contents('report.html');
mail($to, $subject, $message, $Headers);
So how do I choose only the parts I want to be included in report.html?
Thank you very much!
You are doing it unnecessarily difficult, you don't need external files to generate your report. Take a look at this:
<?php
$report = '';
// ...
// Code not included in your report
// ...
ob_start();
// ...
// HTML and PHP code you want in your report
// ...
$report .= ob_get_clean();
// ...
// Code not included in your report
// ...
ob_start();
// ...
// HTML and PHP code you want in your report
// ...
$report .= ob_get_clean();
// Mail it
mail($to, $subject, $report, $headers);
?>
EDIT: Regarding to OP's comment.
What you need is ob_get_flush() instead of ob_get_clean(). Both return the buffer contents as a string, but the first one dumps it to the script output while the second one empties the buffer instead.
May or May not Help
I always handle this the same way I load pages when using vanila PHP, with a snippet! The following is one I've kept around forever and used. It has 2 possible primary functions. One is to load a view (html page), the other is to get a page of html as a string for such things as inclusion in an email body.
For example:
// will load a page into the clients browser
// note the page location would indicate it will get the file "index.html" from "$_SERVER["DOCUMENT_ROOT"] . '/views/'"
loadView('/views/index.html');
// or, as would be more helpful to you
$msgHTML = loadView('/views/index.html', NULL, TRUE);
The TRUE param simply tells the function to only return a string and not echo anything to a client.
The NULL param you see there is for an array of data to be passed through. For instance, say you have an html page with a table you want populated for a database call. You would simply make your call, place your return in an array and then add to page.
$arr = array( 'key' => 'value' );
$msgHTML = loadView('/views/index.html', $arr, TRUE);
// then in the index.html
<div><?= $key; ?></div>
This makes it very easy to build anything HTML you need for an Email.
Snippet
if (!function_exists('loadView')) {
function loadView($file, $data=NULL, $get=FALSE) {
if (!empty($data)) extract($data);
ob_start();
if (is_file($file)) include($file);
$return = ob_get_clean();
if (!$get) echo($return);
return $return;
}
}
Thus you could do something like:
$htmlFirst = loadView('report.html', NULL, TRUE);
$msgFirst = 'Some message string here';
$htmlSecond = loadView('report2.html', NULL, TRUE);
$msgSecond = 'Some message string here';
$body = $htmlFirst . $msgFirst . $htmlSecond . $msgSecond;
mail($to, $subject, $body, $Headers);

Can't seem to write a valid .ics file?

I need your help. I'm writing a iCal .ics File-format with a php function.
If I open the .ics file with iCal it says the application says: "Calendar can’t read this calendar file. No events have been added to your calendar."
However if I validate the file with an online .ics validator it says everything should be fine except the line endings. The validator says this:
Your calendar is using an invalid newline format. Make sure to use
\r\n to end lines rather than just \n (RFC 2445 §4.1).
Congratulations; your calendar validated!
But I'm not sure if this is the "real" problem why my iCal can't read the file.
First off, I wonder how to change this line endings?
<?php
function wpse63611_events_feed_output(){
$filename = urlencode( 'My-Events-' . date('Y') . '.ics' );
// Start collecting output
ob_start();
header( 'Content-Description: File Transfer' );
header( 'Content-Disposition: attachment; filename=' . $filename );
header( 'Content-type: text/calendar' );
header( "Pragma: 0" );
header( "Expires: 0" );
?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php get_bloginfo('name'); ?>//NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo('name');?> - Events
<?php
if ( have_posts() ):
$now = new DateTime();
$datestamp =$now->format('Ymd\THis\Z');
while( have_posts() ): the_post();
global $post;
$uid = md5(uniqid(mt_rand(), true))."#mydomain.com";
$start = unixToiCal(get_event_date($post, true, true), 2.0);
$end = unixToiCal(get_event_end_date($post, true, true), 2.0);
$summary = wpse63611_esc_ical_text(get_the_title());
$description = apply_filters('the_excerpt_rss', get_the_content());
$description = wpse63611_esc_ical_text($description); ?>
BEGIN:VEVENT
UID:<?php echo $uid; ?>
<?php echo "\r\n"; ?>
DTSTAMP:<?php echo $datestamp; ?>
<?php echo "\r\n"; ?>
DTSTART:<?php echo $start; ?>
<?php echo "\r\n"; ?>
DTEND:<?php echo $end; ?>
<?php echo "\r\n"; ?>
SUMMARY:<?php echo $summary; ?>
<?php echo "\r\n"; ?>
DESCRIPTION:<?php echo $description; ?>
<?php echo "\r\n"; ?>
END:VEVENT
<?php endwhile; endif; ?>
END:VCALENDAR
<?php
// Collect output and echo
$eventsical = ob_get_contents();
ob_end_clean();
echo $eventsical;
exit();
}
function unixToiCal( $uStamp = 0, $tzone = 0.0 ) {
$uStampUTC = $uStamp + ($tzone * 3600);
$stamp = date("Ymd\THis\Z", $uStampUTC);
return $stamp;
}
function wpse63611_esc_ical_text( $text='' ) {
$text = str_replace("\\", "", $text);
$text = str_replace("\r", "\r\n ", $text);
$text = str_replace("\n", "\r\n ", $text);
return $text;
}
?>
Can you see any problem with this? What could cause the calendar not to work?
UPDATE
Well, I fixed the line endings and the calendar validates fine now. So no errors when validating it, but I still can't get it working in iCal. When I open it it still says the calendar file is not readable. Here is the actual file that is generated by my script … http://cl.ly/383D3M3q3P32
looking at your ical file brings 2 topics:
as mentionned above, all your lines need to be ended by \r\n (i.e. you need to ensure
BEGIN:VCALENDAR
VERSION:2.0
..
are also ended properly
2.you need to escape commas in text (see RFC5545 §3.3.11: https://www.rfc-editor.org/rfc/rfc5545#section-3.3.11 )
you can also run those through online icalendar validators see this post answer: https://stackoverflow.com/a/4812081/1167333
You have the wpse63611_esc_ical_text() function to normalize output but you only apply it to some output fragments. The funny thing is that such function expects Unix-style input ("\n") but the whole mechanism relies in saving your source code as Windows-style ("\r\n"). Additionally, you sometimes call the function twice on the same text.
I believe the root problem is the you don't really know what a line ending is. When you hit your keyboard's Enter key, you'll actually get a different character depending on whether your computer runs Windows or some kind of Unix (such as Linux or MacOS). On Windows, you'll actually get two characters, represented as "\r\n" in PHP. On Unix, you'll get one character, represented as "\n" in PHP. If your editor is good enough, it'll allow you to save the file with the line ending of your choice, no matter what your computer runs. Check the "Save as" dialogue for further info.
Since you aren't actually typing the ICS file, you need to ensure that PHP generates the appropriate characters. The simplest way is to type and save the source code as you please and then convert the complete output once:
$output = strtr($output, array(
"\r\n" => "\r\n",
"\r" => "\r\n",
"\n" => "\r\n",
));
You'll probably need to clean up your code first.

get html content with paging stored in cookies

I have a page where i need to go to www.site.com/search/all and then i can use www.site.com/page/2 3 4 ...etc. If i go directly to www.site.com/page/2 i don't have anything because it's no stored in cookies by the first url (www.site.com/search/all).
I want to run all pages and get the content, but i only can get content from the first page, that's given to me by (www.site.com/search/all).
i've made a $context and used session_start() to check if it works, but no success.
Theres my code:
<?php
require 'simple_html_dom.php';
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"));
$context = stream_context_create($opts);
session_write_close(); // unlock the file
$f=10;
for($i=1;$i<=$f;$i++) {
if($i==1) {
$html = file_get_html('http://www.site.com/search/all',false,$context);
session_start();
}
else {
$html = file_get_html('http://www.site.com/page/$i',false,$context);
}
echo $i;
echo $html;
?>
The $html result it's always from the first page, it wont go to the next, i think because of the cookies.

Categories