0

This great answer by David Gard allowed me to have a metabox sticky (checkbox) for posts that could only be set (checked) on one posts in the loop at a time. If post A has that meta box checked, then B, C ... Z can't have it checked. In order to be able to check the box in another post, the user must first uncheck the box in post A, after which he or she is able to check the box in other boxes. This works great in itself. However, I am running into problems when using other meta boxes (text input fields). Every post has three metaboxes: sticky mentioned above, and two input text fields review and source (others might be added later on).

Let's say that post A has sticky checked, the values of review and source don't matter, they can be empty even. Saving this post works fine, and I can change the values of all three meta boxes as I please without any errors or faulty behaviour. However, when I edit source or review of any other post and then save that post, all of a sudden sticky is unset in post A. I don't see how these things can be related. Here is the code for the three meta boxes:

/*
 * STICKY POSTS
 *
*/

function add_sticky_metabox(){
    add_meta_box(
        'sticky_post_metabox', 'Sticky Post', 'output_sticky_metabox', 'post'
    );
}
add_action('add_meta_boxes', 'add_sticky_metabox');

// Make a post sticky
function output_sticky_metabox($post){

    /** Grab the current 'my_sticky_post' option value */
    $sp = intval(get_option('sticky_post'));

    /** Check to see if the 'my_sticky_post' option should be disabled or checked for the current Post */
    $checked = checked($sp, $post->ID, false);
    if($sp > 0) :
        $disabled = (!disabled($sp, $post->ID, false)) ? 'disabled="true"' : '';
    else :
        $disabled = '';
    endif;

    /** Add a nonce field */
    wp_nonce_field('sticky_post_metabox', 'sticky_post_metabox_nonce');

    /** Add a hidden field to check against in case it is unchecked before save */
    $value = ($checked) ? '1' : '0';
    echo '<input type="hidden" name="was_checked" value="' . $value . '" />';

    /** Output the checkbox and label */
    echo '<label for="sticky_post">';
    echo '<input type="checkbox" id="sticky_post" name="sticky_post" value="' . $post->ID . '" ' . $checked . $disabled . '>';
    echo 'Make highlight?</label>';

    /** Let the user know which Post is currently sticky */
    switch($sp) :

        case 0:
            $message = 'There\'s no highlight.';
            break;
        case $post->ID:
            $message = 'This post is the highlight!';
            break;
        default:
            $message = '<a href="' . get_edit_post_link($sp) . '" title="' . the_title_attribute('before=Bewerk bericht \'&after=\'&echo=0') . '">' . get_the_title($sp) . '</a> is currently lit';;

    endswitch;
    echo '<p><em>' . $message .'</em></p>';

}


function save_sticky_metabox($post_id){
    /*
     * We need to verify this came from our screen and with proper authorization,
     * because the save_post action can be triggered at other times.
     */

    /** Ensure that a nonce is set */
    if(!isset($_POST['sticky_post_metabox_nonce'])) :
        return;
    endif;

    /** Ensure that the nonce is valid */
    if(!wp_verify_nonce( $_POST['sticky_post_metabox_nonce'], 'sticky_post_metabox')) :
        return;
    endif;

    /** Ensure that an AUTOSAVE is not taking place */
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) :
        return;
    endif;

    /** Ensure that the user has permission to update this option */
    if(!current_user_can('edit_post', $post_id)) :
        return;
    endif;

    /**
     * Everything is valid, now the option can be updated
     */

    /** Check to see if the 'my_sticky_post' option was checked */
    if(isset($_POST['sticky_post'])) : // It was...

        update_option('sticky_post', $_POST['sticky_post']);  // Update the option

    else : // It was not...

        /** Check to see if the option was checked prior to the options being updated */
        if(isset($_POST['was_checked'])) : // It was...

            update_option('sticky_post', 0); // Set the option to '0'

        endif;

    endif;

}
add_action('save_post', 'save_sticky_metabox');


/*
 * Source
 *
*/

function add_source_metabox(){
    add_meta_box(
        'source_post_metabox', 'Bron', 'output_source_metabox', 'post'
    );
}
add_action('add_meta_boxes', 'add_source_metabox');

function output_source_metabox($post){
    wp_nonce_field('source_post_metabox', 'source_post_metabox_nonce');
    $post_source = $post->post_source;

    echo '<label for="source_post">';
    echo '<input type="text" id="source_post" name="source_post" value="'.$post_source.'" style="width: 80%;max-width: 720px;">';
    echo ' Add a source to your post.</label>';
    echo '<p>E.g. <em>http://tweakers.net/nieuws/101372/ing-belgie-wil-betalingsgedrag-van-klanten-meer-gebruiken-voor-dienstverlening.html</em></p>';

}
function save_source_metabox($post_id){
    /*
     * We need to verify this came from our screen and with proper authorization,
     * because the save_post action can be triggered at other times.
     */

    /** Ensure that a nonce is set */
    if(!isset($_POST['source_post_metabox_nonce'])) :
        return;
    endif;

    /** Ensure that the nonce is valid */
    if(!wp_verify_nonce( $_POST['source_post_metabox_nonce'], 'source_post_metabox')) :
        return;
    endif;

    /** Ensure that an AUTOSAVE is not taking place */
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) :
        return;
    endif;

    /** Ensure that the user has permission to update this option */
    if(!current_user_can('edit_post', $post_id)) :
        return;
    endif;

    // Update and save the field so it can be used in our template
    if ( isset( $_POST['source_post'] ) ) {
        $data = sanitize_text_field( $_POST['source_post'] );
        update_post_meta( $post_id, 'post_source', $data );
    }

}
add_action('save_post', 'save_source_metabox');


/*
 * Reviews name field
 *
*/

function add_review_metabox(){
    add_meta_box(
        'review_post_metabox', 'Review', 'output_review_metabox', 'post'
    );
}
add_action('add_meta_boxes', 'add_review_metabox');

function output_review_metabox($post){
    wp_nonce_field('review_post_metabox', 'review_post_metabox_nonce');
    $post_review = $post->post_review;

    echo '<label for="review_post">';
    echo '<input type="text" id="review_post" name="review_post" value="'.$post_review.'" style="width: 80%;max-width: 720px;">';
    echo ' Add the name of the reviewed product.</label>';
    echo '<p>E.g. <em>Lumia 930</em></p>';

}
function save_review_metabox($post_id){
    /*
     * We need to verify this came from our screen and with proper authorization,
     * because the save_post action can be triggered at other times.
     */

    /** Ensure that a nonce is set */
    if(!isset($_POST['review_post_metabox_nonce'])) :
        return;
    endif;

    /** Ensure that the nonce is valid */
    if(!wp_verify_nonce( $_POST['review_post_metabox_nonce'], 'review_post_metabox')) :
        return;
    endif;

    /** Ensure that an AUTOSAVE is not taking place */
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) :
        return;
    endif;

    /** Ensure that the user has permission to update this option */
    if(!current_user_can('edit_post', $post_id)) :
        return;
    endif;

    // Update and save the field so it can be used in our template
    if ( isset( $_POST['review_post'] ) ) {
        $data = sanitize_text_field( $_POST['review_post'] );
        update_post_meta( $post_id, 'post_review', $data );
    }

}
add_action('save_post', 'save_review_metabox');

So when saving one post, this influences the value of the sticky of others. But I don't see how or why this happens. Any thoughts?

1

The problem here is a slight error in the origianl code.

Near the bottom of the save_sticky_metabox() callback, change the line -

if(isset($_POST['was_checked'])) :

To this -

if($_POST['was_checked'] != 0) :

The was_checked value is derived from a hidden field, not a checkbox, so regardless of the value it will always be set. Therefore we need to check if that value is not equal to 0, as opposed to just checking if it was set.

A few tips for you also -

  1. You should alwasy escape quote and apostraphe characters in strings -
    • Correct - 'There\'s no highlight.'
    • Incorrect - 'There's no highlight.' (this will cause a PHP error)
  2. As you are creating 2x postmeta fields, consider starting the metakey with an _ ('_post_source' and '_post_review'). Doing this means that the postmeta will be "hidden" and will not appear in the Custom Fields metabox on the edit posts page.
  3. If you wish, you can add all 3 metaboxes via one callback, rather than one for each (but that's personal preference, nothing wrong with doing it your way) -

Just in case you want to do that -

function add_post_metaboxs(){

    add_meta_box('sticky_post_metabox', 'Sticky Post', 'output_sticky_metabox', 'post');
    add_meta_box('source_post_metabox', 'Bron', 'output_source_metabox', 'post');
    add_meta_box('review_post_metabox', 'Review', 'output_review_metabox', 'post');

}
  • Ah yes, something I should've been able to figure out by myself. Thanks for the tips as well! 1 was caused because I quickly translated my actual file which is in Dutch, I must have overlooked to escape the characters here. Thanks for number 2. I had seen those fields starting with _ in plugins but I never knew what they were. 3: a coincidence that you should mention it. I posted a topic on CodeReview this morning for just that: making the code more compact. – Bram Vanroy Mar 2 '15 at 15:16
  • If you want you can always check it out here. – Bram Vanroy Mar 2 '15 at 15:17
  • A happy coincidence then. You can also, if you wish, get away with just one ``save_post'` callback - I'll post an answer to that in your question on Code Review. – David Gard Mar 2 '15 at 15:19

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.