0

I have a User Post Submission form, and it has three issues, as well as one potential issue.

Here is the code that processes the form.

<?php if(isset($_POST['user_submission_form'])) {

    if(wp_verify_nonce($_POST['user_submission_form'], 'user_submission_form')) {

        $user_submitted_title = sanitize_text_field($_POST['user_submitted_title']);
        $user_submitted_progress = $_POST['user_submitted_progress'];
        $user_submitted_goals = $_POST['user_submitted_goals'];
        $user_submitted_categories = $_POST['user_submitted_categories'];
        $user_submitted_tags = sanitize_text_field($_POST['user_submitted_tags']);
        $user_submitted_video = sanitize_text_field($_POST['user_submitted_video']);
        $user_submitted_audio = sanitize_text_field($_POST['user_submitted_audio']);

        if(($user_submitted_title != '') && ($user_submitted_progress != '') && ($user_submitted_goals != '') && ($user_submitted_categories != '') && ($user_submitted_tags != '')) {

            $user_post = array(
                'comment_status' => 'open',
                'post_author'    => $user_ID,
                'post_category'  => array($user_submitted_categories),
                'post_content'   => '<h2>Project Progress</h2>' . $user_submitted_progress . '<h2>Project Goals</h2>' . $user_submitted_goals,
                'post_status'    => 'publish',
                'post_title'     => $user_submitted_title,
                'post_type'      => 'post',
                'tags_input'     => $user_submitted_tags
            );

            $user_post_id = wp_insert_post($user_post);
            add_post_meta($user_post_id, 'wpcf-video', $user_submitted_video);
            add_post_meta($user_post_id, 'wpcf-audio', $user_submitted_audio);

            global $post;
            if ( $_FILES ) {
                $files = $_FILES['upload_attachment'];
                foreach ($files['name'] as $key => $value) {
                    if ($files['name'][$key]) {
                        $file = array(
                            'name' => $files['name'][$key],
                            'type' => $files['type'][$key],
                            'tmp_name' => $files['tmp_name'][$key],
                            'error' => $files['error'][$key],
                            'size' => $files['size'][$key]
                        );
                        $_FILES = array("upload_attachment" => $file);
                        foreach ($_FILES as $file => $array) {
                            $newupload = insert_attachment($file,$user_post_id);
                        }
                    }
                }
            }

            $user_post_redirect = get_permalink($user_post_id);
            wp_redirect($user_post_redirect); exit;

        }

        else {
            //Notify the user that they must fill out all required fields
        }

    }

    else {
        print 'Sorry, your post did not verify.';
        exit;
    }

}?>

<?php get_header(); ?>

Here is the form (after the header)

<?php if (is_user_logged_in()) { ?>

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

        <input type="hidden" name="user_submission_form" value="<?php echo wp_create_nonce('user_submission_form'); ?>">

        <h2>Title</h2>
        <input type="text" id="user_submitted_title" name="user_submitted_title">

        <p>Please provide detailed information about the long-term goals of your project, as well as your current project progress. Feel free to format your text using boldness, italics, lists, and block quotes. Simply click on the formatting option you'd like to use and start typing. When you no longer need the format you have selected, hit enter to go to the next line, and click on the active format button to end formatting.</p>

        <h2>Project Progress</h2>
        <?php wp_editor( '', 'user_submitted_progress', $settings = array('media_buttons' => false, 'quicktags' => false, 'textarea_rows' => 15, 'editor_css' => '<style type="text/css">.wp_themeSkin .mceListBox .mceText {width: 81px;} .wp_themeSkin table.mceToolbar {margin: 5px;} td.mceToolbar > div {height: inherit;} tr.mceLast {display: none;} .wp_themeSkin .mceButton {margin: 1px 12px;}</style>', 'tinymce' => add_filter("mce_buttons", "base_extended_editor_mce_buttons", 0), add_filter("mce_buttons_2", "base_extended_editor_mce_buttons_2", 0)) ); ?>

        <h2>Project Goals</h2>
        <?php wp_editor( '', 'user_submitted_goals', $settings = array('media_buttons' => false, 'quicktags' => false, 'textarea_rows' => 15, 'tinymce' => add_filter("mce_buttons", "base_extended_editor_mce_buttons", 0), add_filter("mce_buttons_2", "base_extended_editor_mce_buttons_2", 0)) ); ?>

        <h2>Category</h2>
        <?php wp_dropdown_categories($args = array('orderby' => 'name', 'hide_empty' => 0, 'hierarchical' => 1, 'id' => 'user_submitted_categories', 'name' => 'user_submitted_categories')); ?>

        <h2>Tags</h2>
        <p>Separate tags with commas.</p>
        <input type="text" id="user_submitted_tags" name="user_submitted_tags">

        <h2>Video</h2>
        <p>Copy and paste links from Youtube and Vimeo in the field below</p>
        <textarea id="user_submitted_video" name="user_submitted_video"></textarea>

        <h2>Audio</h2>
        <p>Copy and paste links from Soundcloud in the field below</p>
        <textarea id="user_submitted_audio" name="user_submitted_audio"></textarea>

        <h2>Images</h2>
        <input type="file" name="upload_attachment[]" multiple="multiple">

        <button name="submit">Submit</button>

    </form>

<?php } else { ?>

    <?php echo 'Sorry, but you need to be logged in to see that. You can <a href="'; ?>
    <?php echo wp_login_url( get_permalink() ); ?>
    <?php echo '" title="Login">login here</a>'; ?>

<?php } ?>

And here is the function in functions.php that attaches the images to the post in the database

//Attach Image to Post in Database
function insert_attachment($file_handler,$user_post_id,$setthumb='false') {
    if ($_FILES[$file_handler]['error'] !== UPLOAD_ERR_OK) __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, $user_post_id);
    if ($setthumb) update_post_meta($user_post_id,'_thumbnail_id',$attach_id);
    return $attach_id;
}

When the post is successful, i get an error saying cannot modify headers, but the form does process and the content is posted to the database. When the users don't fill out all of the required fields, the page refreshes, and the form is completely empty, so they lose their progress on the form and have to start over. The part that says

//Notify the user that they must fill out all required fields

is where I want to put the event that occurs on validation failure. I'd like it to just be a simple alert popup or something that says Fill out all required fields. Nothing beyond that will be necessary. It also has an issue in that if you hit the submit button repeatedly, it will process the post as many times as you click the submit button, creating duplicate posts. How can I fix that?

My only remaining question is whether or not the image uploader can be exploited in this scenario.

1 Answer 1

1

When you get those "headers already sent" messages, it is usually one of several things:

  1. You are echoing something when you shouldn't be, which is any time before get_header on the front end. I can't remember exactly where the window is on the backend.

  2. You are doing something that is triggering a warning or notice that is printing content too soon. Things like if ( $_FILES ) {, while very common, will trigger notices if that variable is not set, and if those print to the screen you have echoed content whether you meant to or not. You should be using !empty($_FILES) or !isset($_FILES) to check the variable.

  3. You are attempting to redirect too late-- after the headers have been sent. Usually this means redirecting after get_header.

I see wp_header after your redirect so I expect that the problem is one of the first two possibilities.

As far as your visitors loosing form data, you have that $_POST data. Use it to repopulate the form on failure. This part is really just an HTML question but supply your inputs with value attributes.

<input type="text" id="user_submitted_tags" name="user_submitted_tags" value="<?php if (!empty($_POST['user_submitted_tags'])) echo esc_attr($_POST['user_submitted_tags'])">

Again, not really a WordPress question but to provide your notices, set a variable then echo it conditionally.

else {
    //Notify the user that they must fill out all required fields
    $notice = 'Fill stuff out';
}

Then in the form somewhere

if (!empty($notice)) {
  echo $notice;
}

Reference

http://codex.wordpress.org/Function_Reference/esc_attr

1
  • Apparently, I had a blank line before the first section of code that I pasted into this post. that's why the redirect wasn't working. All of your other advice worked, thank you. Now I just need to figure out a way to prevent multiple clicks. Maybe something that disables the submit button the first time it's clicked. Commented May 12, 2013 at 3:25

Your Answer

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

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