10

I wonder if anyone could advise me further on my problem. Part of my plugin stores log files for debugging purposes. I have successfully displayed them in a (div#log) in my admin page using jquery and wp_localise_script. I have a button to delete these logs but I am unsure how to process this. I have a feeling that ajax might come in handy here but not sure where to start.

Here is the relevant parts of my code:

admin_enqueue_scripts (action)

 $args = array(get_option('wow_tweets_log'));//log files fetched from wp_options table    
    wp_enqueue_script('wow_tweet');//registered earlier on with jQuery dependency
    wp_localize_script('wow_tweet', 'wow_vars', $args);

Admin Page

<tr><th scope="row"><strong>Debugging</strong></th><td>
    <div id="debug" class="button-primary">Debug</div><!--debug button shows logs-->
    <div id="hide_debug" class="button-secondary">Hide</div><!--debug button hides logs-->
    <div id="clear_log" class="button-secondary">Empty Log</div><!--Press to delete logs-->
</td></tr>
<tr><th scope="row"></th><td><div id="log"><!--Logs show here--></div></td></tr>

Javascript

jQuery(document).ready(function() { 

    var debug_show = jQuery('#log').hide();//hides log by default

    jQuery('#debug').click(function(){//on click shows logs files in div#log
        for (var i = 0, l = wow_vars.length; i < l; i++) {
            var data = wow_vars[i];
        }
        jQuery('#log').show().html(data);

    });
    jQuery('#hide_debug').click(function()
    {
        debug_show.hide();
    }); 
});

Action to clear log

 function clear_log(){
    delete_option('wow_tweets_log');//am stuck on how to invoke this

    /*die();  would go at the end if ajax used*/
 }
 add_action('clear_log','clear_log');

So far this script is working to show all the log files, now all I need is to delete them when clicking #clear_log. I know plugging a do_action on init will delete them as soon as the page loads, making my javascript useless so I guess the only option is ajax! Do I need to add another reference to wp_localize_script()? Any help would be appreciated.

4
  • Thanks guys for all of your input. I had never thought about using the nonce to delete the options. I haven't quite got it to work yet but I reckon it's down to something I have done so I will have a good bash at it taking everything you have said on board
    – Tracy
    Apr 24, 2013 at 9:59
  • @brasofilo Thanks for your kind comment. I believe being descriptive helps others to understand and be able to help you with your problem more.
    – Tracy
    Apr 24, 2013 at 10:09
  • Hey @Tracy, the nonce is just a one time check to make sure that the request is valid, i.e. came from your site and you meant to do it. If you want to edit your post with the code you have now I'm sure everyone would be happy to take a look. Apr 24, 2013 at 16:06
  • Sorry about that, had a blonde moment there! I have successfully completed what I was aiming to do. I used ajax on #debug.click() to load the logs then ajax again on #clear_log.click() to remove the logs. There is probably a better method out there (using 1 ajax call for example) but now it's working I can test these theories out. Thanks again for all of your insight!
    – Tracy
    Apr 25, 2013 at 13:05

1 Answer 1

7

Ajax in WordPress works by sending an HTTP post to /wp-admin/admin-ajax.php (by default) that then fires the corresponding hook. So, you attach some jquery to an event triggered by your delete button, which then posts to admin-ajax.php, which has an action, say, delete_my_options(), which actually runs the php to delete. Then, you have a function, called a callback, that runs on successful completion of the ajax request. You could use this to fade your #log div out for example.

In short, you have three steps, the action, the ajax and the callback. The action is triggered by a DOM event and attached to two hooks, wp_ajax_{action_name} and wp_ajax_nopriv_{action_name} (only if you want no logged in users to be able to do it). These fire when that action is posted to wp-admin/admin-ajax.php. The ajax is the php (usually) function hooked to them. The callback function is a javascript function that is fired when the ajax is successfully completed.

Step by step:

Step 1, in your js file

jQuery('#hide_debug').click(function()
{
    var data = {};
    data.action = 'clear_log_action';
    data.options_delete_nonce = ajax_object.options_delete_nonce;
    jQuery.post(ajax_object.ajax_url, data, clear_log_callback);

}); 

Step 2, in your functions.php or a plugin

Add this to the function that you enqueue your javascript from: (thanks @Milo)

wp_localize_script( 'my_js_file_name', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ,   'options_delete_nonce' => wp_create_nonce( 'options_delete_nonce' ), ) );

Then add this to your functions.php or plugin:

// Edit: removed the nopriv hook (Thanks @toscho)
add_action('wp_ajax_clear_log_action','clear_log_ajax'); // attach your data.action to wp_ajax and wp_ajax_nopriv and hook your php function
function clear_log_ajax() {
    $nonce = $_POST['options_delete_nonce'];
    // Edit: Added nonces and permissions check (Thanks @Otto)
    if( wp_verify_nonce( $nonce, 'options_delete_nonce' ) && current_user_can( 'manage_options' ) ) {
        delete_option('wow_tweets_log');
        die(); // make sure to put a die() or exit() at the end of your ajax
    }
}

Step 3, back in your js file

// output will be what is echoed from your ajax, if anything
function clear_log_callback(output) 
{
    jQuery('#log').hide();
}
6
  • 4
    the one thing I would change here is to use admin_url with wp_localize_script to output the admin-ajax.php URL, it's not '/wp-admin/admin-ajax.php' in many cases, depending on install specifics.
    – Milo
    Apr 22, 2013 at 21:41
  • 5
    I would leave out wp_ajax_nopriv_clear_log_action. Why should any visitor be allowed to clear the log? :)
    – fuxia
    Apr 22, 2013 at 22:38
  • 2
    Well, I wanted it to be a general example :) But, very valid points, edited out the nopriv and put in the ajaxurl set up. Apr 22, 2013 at 22:41
  • 5
    Additionally, you should add in a nonce to prevent CSRF attacks. Also, is_admin() isn't a valid check to see if the user is an admin, it checks to see if you're in the wp-admin path. So you should really check to see if current_user_can( 'manage_options' ).
    – Otto
    Apr 22, 2013 at 23:00
  • 4
    You just got great advice from three heavy weights, the Answer is an exemplary intro to Ajax, this code will be copy pasted numberless times, and I don't remember seeing a first Question so well written, kudos to @all :)
    – brasofilo
    Apr 22, 2013 at 23:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.