ComlyW
ComlyW

Reputation: 77

Execute a shortcode when button is clicked

I am using a metabox in the Post creator to store extra content as described in this post

Now, I would like to execute the shortcode [extra] on the click of a button similar to this post, but I can't get it to work.

Here's my code so far:

jQuery

    jQuery(document).ready(function($) {
        $('#extra').on('click',function() {
            $.ajax({
                type: "POST", 
                url: my_ajaxurl, 
                data: {
                    action : 'process_shortcode_on_click_action'
                },
                success:function(data) {
                    console.log("Success");
                },
                error: function(errorThrown){
                    console.log("Error");
                }
            });
        })
    })

functions.php

    add_action( 'wp_enqueue_scripts', 'add_my_script' );
    function add_my_script() {
        wp_enqueue_script(
            'extra-script', // name your script so that you can attach other scripts and de-register, etc.
            get_template_directory_uri() . '/js/script.js', // this is the location of your script file
            array('jquery') // this array lists the scripts upon which your script depends
        );
        wp_localize_script( 'extra-script', 'my_ajaxurl', admin_url( 'admin-ajax.php' ) );
    }
    
    add_shortcode( 'extra',  't5_extra_content' );
    add_action( 'add_meta_boxes_post', 't5_register_extra_metabox' );
    add_action( 'save_post', 't5_save_shortcode_box', 10, 2);
    add_action( 'wp_ajax_process_shortcode_on_click_action', 'process_shortcode_on_click_ajax');
    add_action( 'wp_ajax_nopriv_process_shortcode_on_click_action', 'process_shortcode_on_click_ajax');
    
    function process_shortcode_on_click_ajax() {
        echo do_shortcode('[extra]');
        die;
    }
    
    function t5_extra_content( $attributes, $content = '' )
    {
        $args = shortcode_atts( array ( 'cap' => 'edit_posts' ), $attributes );
            if ( current_user_can( $args['cap'] ) )
            return wpautop(
            get_post_meta( get_the_ID(), '_t5_extra_box', TRUE )
                . $content
            );
    }
    
    function t5_register_extra_metabox()
    {
        add_meta_box(
            't5_extra',
            'My Point of View',
            't5_extra_metabox_callback',
            NULL, // screen
            'normal',
            'default'
        );
    }
    function t5_extra_metabox_callback( $post )
    {
        $nonce = wp_create_nonce( __FILE__ );
        echo "<input type='hidden' name='t5_extra_box_nonce' value='$nonce' />";
        $content = get_post_meta($post->ID, '_t5_extra_box', TRUE );
        wp_editor(
            $content,
            '_t5_extra_box',
            array (
                'textarea_rows' => 10,
                'media_buttons' => FALSE,
                'teeny'         => TRUE,
                'tinymce'       => TRUE
            )
        );
    }
    function t5_save_shortcode_box( $post_id )
    {
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE
            or ! isset ( $_POST['post_type'] )
            or 'post' !== $_POST['post_type']
            or ! current_user_can( 'edit_post', $post_id )
            or ! wp_verify_nonce( $_POST[ 't5_extra_box_nonce' ], __FILE__ )
        )
        {
            return;
        }
    
        if ( isset ( $_POST['_t5_extra_box'] ) )
            update_post_meta( $post_id, '_t5_extra_box', $_POST['_t5_extra_box'] );
        else
            delete_post_meta( $post_id, '_t5_extra_box' );
    }

I am seeing "Success" in the console, so I know that the jQuery is getting called correctly. I can't figure out how to get the do_shortcode('[extra]') to fire however. Any help is greatly appreciated.

Upvotes: 1

Views: 1807

Answers (1)

Phil F
Phil F

Reputation: 702

Your ajax call does not have coxtent of the global $post from the page the ajax request is coming from and thus get_the_ID() should be false and get_post_meta( get_the_ID(), '_t5_extra_box', TRUE ) will also be false. Furthermore, you're calling do_shortcode('[extra]') (no content) so $content inside your callback will be an empty string. So return wpautop(get_post_meta( get_the_ID(), '_t5_extra_box', TRUE).$content); becomes return wpautop(''); which is just an empty string. Based on your code I would expect your data response to always be an empty string.

To fix this I would add an extra ajax post data item along with the action that tells the callback what $post_id should be. That's the most primitive way. You may want to add a nonce or some other measure for security (but that may not be relevant for your original question).

UPDATE

I haven't tested this, and you may want to do it differently, but here is one option. Ultimately you just need a way to get the $post_id from the original request and pass it along to the ajax call. Since you're already passing the ajax url via wp_localize_script, I would just add another JavaScript variable there.

jQuery

jQuery(document).ready(function ($) {
    $('#extra').on('click', function () {
        $.ajax({
            type: "POST",
            url: my_ajaxurl,
            data: {
                action: 'process_shortcode_on_click_action',
                post_id: my_postid,
            },
            success: function (data) {
                console.log("Success");
            },
            error: function (errorThrown) {
                console.log("Error");
            }
        });
    })
})

functions.php

add_action('wp_enqueue_scripts', 'add_my_script');
function add_my_script () {
    wp_enqueue_script(
        'extra-script', // name your script so that you can attach other scripts and de-register, etc.
        get_template_directory_uri() . '/js/script.js', // this is the location of your script file
        array('jquery') // this array lists the scripts upon which your script depends
    );
    wp_localize_script('extra-script', 'my_ajaxurl', admin_url('admin-ajax.php'));
    wp_localize_script('extra-script', 'my_postid', get_the_ID());
}

add_action('wp_ajax_process_shortcode_on_click_action', 'process_shortcode_on_click_ajax');
add_action('wp_ajax_nopriv_process_shortcode_on_click_action', 'process_shortcode_on_click_ajax');
function process_shortcode_on_click_ajax ()
{
    $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);

    if (empty($post_id = $_POST['post_id']) || !is_numeric($post_id)) {
        wp_die('Post ID is Invalid', 400);
    }

    echo do_shortcode("[extra post_id='{$post_id}']");
    wp_die();
}

add_shortcode('extra', 't5_extra_content');
function t5_extra_content ($attributes, $content = '')
{
    $defaults = [
        'post_id' => get_the_ID(),
        'cap'     => 'edit_posts'
    ];

    $args = shortcode_atts($defaults, $attributes);

    if (!current_user_can($args['cap']) || empty($args['post_id'])) {
        return ''; // or some message on fail
    }

    return wpautop(get_post_meta($args['post_id'], '_t5_extra_box', TRUE) . $content);
}

Upvotes: 1

Related Questions