0

I have a JS file that triggers a PHP callback file. The PHP file is supposed to work on the Post that is currently opened (wp-admin/post.php). I do not want the JS file to pass the post id though since that could be tampered with.

Is there any way to repopulate the global $post or set up the callback appropriately?

JS trigger:

jQuery.ajax({
        type: 'POST',
        url: js_vars.ajaxurl,
        data: {
            action: 'my_action_key'
        }
    });

PHP Callback:

<?php
add_action('wp_ajax_sometest', function () {
    $post_id = get_the_ID();
    echo $post_id; // does not print id
});
1

It's possible to capture the $post_id using a combination of wp_get_referer() and url_to_postid() then reset the $post using setup_postdata.

That should work easy enough for the front-end. But on the admin side we'll need to pull the query with parse_url and grab the ID using parse_str. For good measure we should double check if we're editing a post by checking the action and also see if the ID is_numeric -- running intval before we use it to rule out any funny business.

PHP

// for logged-in users
add_action( 'wp_ajax_foobar', 'wpse20160117_wp_ajax_foobar' );

// let's skip the nopriv because we want to only target logged-in users
// add_action( 'wp_ajax_nopriv_foobar', 'wpse20160117_wp_ajax_foobar' );

function wpse20160117_wp_ajax_foobar() {

    $url     = wp_get_referer();

    $post_id = '';

    // works with front-end urls
    // $post_id = url_to_postid( $url );

    if ( empty( $post_id ) ) { // lets do it the hard way

        // strip the query
        $query = parse_url( $url, PHP_URL_QUERY );

        // parse the query args
        $args  = array();
        parse_str( $query, $args );

        // make sure we are editing a post and that post ID is an INT
        if ( isset( $args[ 'post' ] ) && is_numeric( $args[ 'post' ] ) && isset( $args[ 'action' ] ) && $args [ 'action' ] === 'edit' ) {

            if ( $id = intval( $args[ 'post' ] ) ) {

                // cool.. it worked
                $post_id = $id;
            }
        }
    }

    if ( ! $post_id ) {
        echo "No foobar for you!";
    } else {
        global $post;

        // make sure we have a post
        if ( $post = get_post( $post_id ) ) {

            // prep the post data
            setup_postdata( $post );

            // now we're ready!
            echo "Are you referring to $post_id? Title: " . get_the_title();

        } else {
            echo "No post for you!";
        }
    }
    die();
}

JS

jQuery.post(
    ajaxurl, 
    {
        'action': 'foobar',
        'data':   'baz'
    }, 
    function(response){
        alert('The server responded: ' + response);
    }
);
| improve this answer | |
  • This approach sounds really promising. url_to_postid only seems to work when given a frontend-permalink though - is there a similar method for the admin panel? (the url in my case would be e.g. http://localhost/wordpress/test/wp-admin/post.php?post=553&action=edit) – mschrimpf Jan 18 '16 at 10:06
  • Modified it slightly to only work with logged-in users and on the back-end. You can still uncomment the sections to work with the front-end. – jgraup Jan 18 '16 at 20:21
  • Is there any need to use nonces with this approach, i.e. is the wp_get_referer method safe? – mschrimpf Jan 21 '16 at 0:17
  • Yes, you should be passing nonces to tie the action to a specific logged In user for a short amount of time. – jgraup Jan 21 '16 at 0:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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