1

I have a custom post type labelled 'web_design' and I want my 'web_design' posts to have the following custom fields:
1. 'client' - Client Name
2. 'exlink' - External Link
3. 'datefin' - Date Finished

I managed to put a Custom Metabox (titled 'Work Information') in my 'Web Design' Post Admin UI with the necessary inputs. Here is the entire code.

<?php
//3. Adding Custom Meta Box for Custom Fields
//a. add custom meta box
function work_meta_box( $post ){
    //variables
    $id = 'work_info';
    $title = 'Work Information';
    $callback = create_work_meta;
    $screen = 'web_design';
    $context = 'side';
    $priority = 'high';
    add_meta_box( $id, $title, $callback, $screen, $context, $priority );
}
add_action( 'add_meta_boxes_web_design', 'work_meta_box' );

//b. callback function for 'work_info' custom meta box (see $callback variable)
function create_work_meta( $post ){
    wp_nonce_field( basename( __FILE__ ), 'work_meta_box_nonce' );
    //custom fields
    $client = get_post_meta( $post->ID, 'client', true );
    $exlink =  get_post_meta( $post->ID, 'exlink', true );
    $datefin = get_post_meta( $post->ID, 'datefin', true );

    echo '<div>
        <p>
            <label for=\'client\'>Client:</label>
            <br />
            <input type=\'text\' name=\'client\' value=\'' . $client .'\' />
        </p>
        <p>
            <label for=\'exlink\'>External Link:</label>
            <br />
            <input type=\'url\' name=\'exlink\' value=\''. $exlink . '\' />
        </p>
        <p>
            <label for=\'datefin\'>Date Finished:</label>
            <br />
            <input type=\'date\' name=\'datefin\' value=\''. $datefin . '\' required />
        </p>
    </div>';
}

//c. saves data after submitting/updating custom post
function save_work_meta( $post_id ){
    //1. verifies meta box nonce (to prevent CSRF attacks)
    if( !isset( $_POST['work_meta_box_nonce'] ) || !wp_verify_nonce( $_POST['work_meta_box_nonce'] ) ){
        return;
    }
    //2. if autosaves
    if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
        return;
    }
    //3. if user's not admin
    if( !current_user_can( 'edit_post', $post_id ) ){
        return;
    } elseif ( !current_user_can ( 'edit_page', $post_id) ){
        return;
    }
    //4. checks all custom field values (see 'create_work_meta()' function)
    if( isset( $_REQUEST['client'] ) ){
        update_post_meta( $post_id, 'client', sanitize_text_field( $_POST['client'] ) );
    }
    if( isset( $_REQUEST['exlink'] ) ){
        update_post_meta( $post_id, 'exlink', sanitize_text_field( $_POST['exlink'] ) );
    }
    if( isset( $_REQUEST['datefin'] ) ){
        update_post_meta( $post_id, 'datefin', sanitize_text_field( $_POST['datefin'] ) );
    }
}
add_action( 'save_post_web_design', 'save_work_meta', 10, 2 );
?>

Here is additional code for creating the 'web_design' post type. The settings I used might be a clue to how this will work.

// H. Creating Custom Posts
// 1. 'Web Design' Posts (label: 'web_design')
function web_design_init(){
    //a. array set for '$labels' variable
    $labels = array(
        'name' => __( 'Web Design' ),
        'add_new' => __( 'Add New Sample' ),
        'add_new_item' => __( 'Web Design Sample'),
        'edit_item' => __( 'Edit Sample' ),
        'new_item' => __( 'New Sample' ),
        'search_items' => __( 'Search Sample' ),
        'not_found' => __( 'No Samples Found' ),
        'not_found_in_trash' => __( 'No Samples to Recover' )
    );

    //b. array set for '$supports' variable
    $supports = array(
        'title',
        'editor',
        'thumbnail',
        'post-formats'
    );

    //c. array set for '$args' variable
    $args = array(
        'labels' => $labels, //a.
        'description' => 'For web design works in portfolio.',
        'public' => true,
        'capability_type' => 'post', // <---- I want the 'web_design' posts to have the same capabilities as a default post item.
        'menu_position' => 5,
        'menu_icon' => 'dashicons-images-alt',
        'hierarchal' => false,
        'has_archive' => true,
        'supports' => $supports, //b.
        'taxonomies' => array('post_tag')
    );
    //registers 'web_design' post type
    register_post_type( 'web_design', $args );
}
add_action( 'init', 'web_design_init' );
  • don't use nonce in meta boxes it is not needed and just leads to trouble – Mark Kaplun Jul 14 '16 at 9:27
  • if you use it correctly, it doesnt lead to trouble ;) – websupporter Jul 14 '16 at 12:35
  • @websupporter, incorrect use of nonce is always trouble waiting to happen – Mark Kaplun Jul 14 '16 at 13:21
  • @MarkKaplun, I am not quite sure. wp_insert_post() and wp_update_post() are running the edit_post action but do not validate the nonce themselves. Lets assume another "unsafe" plugin is using these functions inproperly and so on... Better to go with the nonce I think, but maybe I've overlooked something. – websupporter Jul 14 '16 at 19:42
  • @websupporter, and they should not validate as they are APIs, the validation need to be done before the API is called. With the nonce check the API call will most likely fail for those item which might or might not be the desired result, but it is confusing and unexpected. Post submission handling checks the whole page nonce before doing anything, and that is just enough – Mark Kaplun Jul 14 '16 at 19:56
0

You do not verify the nonce correctly. Try this, it should work:

//1. verifies meta box nonce (to prevent CSRF attacks)
if( !isset( $_POST['work_meta_box_nonce'] ) || !wp_verify_nonce( $_POST['work_meta_box_nonce'], basename( __FILE__ ) ) ){
        return;
}

For more info on wp_verify_nonce see here.

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.