Form resubmit issue on page refresh – while on preview page in wordpress

I run wordpress as CMS. I have put together a simple multi-part form which works pretty well and allows to post from front-end. It is a two part form where the first part is where he submits data and second step where he gets a preview of data he just submitted. The submitted data creates a nice draft post in wp as expected.

Here is a first chunk of code within the form’s page template, which displays the form. In the lower part of the code you will note a PREVIEW SECTION (read the comments within code) which displays the data that was just submitted. All of this works really well, I have even been able to retrieve an image, after the submit.

Read More
     <?php
            global $wpdb;
            $this_page  =   $_SERVER['REQUEST_URI'];
            $page       =   $_POST['page'];
            if ( $page == NULL ) { ?> 

        <form method="POST" id="test_form" name="test_form" enctype="multipart/form-data" action="">

        <div>LOCATION : <input type="text" name="location" id="location"/></div>

        <div>DESCRIPTION : <textarea id="details" cols="80" rows="10 maxlength="600" name="details" rows="20"></textarea></div>

        <div>UPLOAD IMAGE : <input type="file" name="loc-image" id="loc-image" tabindex="25" /></div>


        <input type="hidden" value="1" name="page" />
        <input type="hidden" name="action" value="post_action" />
        <input type="submit" name="submit" id="submit" value="PROCEED"/>
        </form>

        <?php 
        } else if ( $page == 1 ) { ?> 

        <?php include_once('validate_first_step.php'); ?>
        <?php if (isset($_POST['submit']) && (!empty($error))) { ?>

                    <h3>Submission Failed.  Errors highlighted below.</h3><br/>
                    <a href="javascript:history.go(-1)">GO BACK</a><br/><br/>
                    <?php echo $error . '</br>';
                    } else { ?>


<?php echo 'h2>'.'YOUR SUBMISSION IS ACCEPTED. PREVIEW.'. '</h2>';?>

    <?php  //PREVIEW SECTION OF THE FORM BEGINS 
    $location=$_POST['location'];
    $description=$_POST['details'];
    ?>

    <?php
    echo 'Location : ' . $location . '</br>';
    echo 'Details  : ' . $description . '</br>'; 
    ?>
    <?php echo wp_get_attachment_image( $newupload,'medium' ); ?>

    <?php //PREVIEW ENDS
    }
    }
    ?>

This is how the form is processed. Actual code is pretty complex, I have just put here that was necessary to deliver the idea. Pretty standard stuff for inserting in wordpress.

if( 'POST' == $_SERVER['REQUEST_METHOD'] &&  !empty( $_POST['action'] ) && $_POST['action'] == "post_action") {


    // Do some minor form validation to make sure there is content
    if (isset($_POST['submit'])) {
            $error = "";

        if ($_POST['details'] != null) {
            $description = trim(strip_tags($_POST['details']));
        } else {
            $error .= 'Put description.</br>';
        }

        if ($_POST['location'] != null) {
            $location = trim(strip_tags($_POST['location']));
        } else {
            $error .= 'Put location.</br>';
        }

    }  



            if (empty($error)) {   
            $new_post = array(   //insert form inputs, set var and define array
            'post_title'    =>  $location, 
            'post_content'  =>  $description,
            'post_status'   =>  'draft',
            'post_author'   =>  '2',    
            'post_type' =>  'post'  
            // assigning tags and categories are no issue
            );

            $pid = wp_insert_post($new_post);


                    //attachment helper function    
                    function insert_attachment($file_handler,$post_id,$setthumb='false') {

                    if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK){ return __return_false(); 
                    } 
                    require_once(ABSPATH . "wp-admin" . '/includes/image.php');
                    require_once(ABSPATH . "wp-admin" . '/includes/file.php');
                    require_once(ABSPATH . "wp-admin" . '/includes/media.php');

                    $attach_id = media_handle_upload( $file_handler, $post_id );

                    //set post thumbnail
                    if ($setthumb) update_post_meta($post_id,'_thumbnail_id',$attach_id);
                    return $attach_id;
                    }


                    //INSERT OUR MEDIA ATTACHMENTS
                    if ($_FILES) {
                    foreach ($_FILES as $file => $array) {
                    $newupload = insert_attachment($file,$pid);
                    }
                    } 

        } //end of if empty error
    }

ISSUE: Here is the issue that I noticed while testing the form. After the form submit when I am in the PREVIEW SECTION, data is displayed correctly as expected BUT when I REFRESH the page the same data is submitted again into wordpress, creating a duplicate draft post.

THINGS TRIED : I am aware of a redirection solution and able to employ wp_redirect , but redirection is not what I am looking at as I need to show them the preview. I have spent a few hours looking for solution and alternatives and still doing it.

REQUEST : Please let me know how I can stop this from happening. I cannot expect people not to click refresh, they will basically do whatever they want. So instead of a javascript notification I would like to perform this using server-side php. As it may perform even if the javascript is disabled, as will the rest of my code. Basically I need a solution that simply ignores the refresh, after the submit. Please suggest me a code or a hint to right direction that can make this possible. Many thanks.


UPDATE : As suggested by @user2758004 I tried the comparision method and it worked. I have put the following code at top of the processor.

$location=$_POST['location'];

$args = array(
        'post__not_in'=> array($id),
        'post_type' => 'post',
        'post_status' => array('publish','pending','draft','future','private'),
        'meta_query' => array(
        'relation' => 'AND',

        array(
        'key' => 'location',
        'value' => $location,
        'compare' => '='
        ),
    )
);

Now within the processor I check if the meta_value of the meta_key ‘full_name’ already exists. In case it does, the form displays an error and simply stops the process. Hope it helps someone.

    $existingMeta = get_posts( $args );
        if(!empty($existingMeta)){ 
    $error .= 'Bummer, ' .$location. ' is already in database.</br>';
        return;

} 
        else { 
                  //check for rest of the errors
    } 

Related posts

Leave a Reply

2 comments

  1. There might be two ways:

    1. Before adding the form data into database, check for the user’s last submitted form data, compare them, if they are identical, then deny.

    2. Use jquery’s ajax post to submit the data to a specific handling script, then even if the user refreshes, the browser won’t show the “would you like to submit this again?” tip. (I am currently using this trick, and it works fine)

    PS.
    The first solution is easy to come up with, but it’s not perfect, when user accidentally refreshes the page, the ugly “would you like to submit this again?” still shows, I think it’s better to combine these two methods to add additional security.

  2. if (isset($_POST['submit'])) {
                $error = "";
    session_start(); // just to make sure you have an active session
    
            if ($_POST['details'] != null) {
                $_SESSION['description'] = trim(strip_tags($_POST['details']));
            } else {
                $error .= 'Put description.</br>';
            }
    
            if ($_POST['location'] != null) {
                 $_SESSION['location'] = trim(strip_tags($_POST['location']));
            } else {
                $error .= 'Put location.</br>';
            }
    
        }  
    

    We arent submitting data to database at first step. just saving it in session to be used in step 2

    <?php echo 'h2>'.'YOUR SUBMISSION IS ACCEPTED. PREVIEW.'. '</h2>';?>
    
        <?php  //PREVIEW SECTION OF THE FORM BEGINS 
        $location=$_SESSION['location'];
        $description=$_SESSION['description'];
        ?>
    
        <?php
        echo 'Location : ' . $location . '</br>';
        echo 'Details  : ' . $description . '</br>'; 
        ?>
        <?php echo wp_get_attachment_image( $newupload,'medium' ); ?>
    
        <?php //PREVIEW ENDS
        }
        }
        ?>
    

    On step 2 you can submit data to database