Question

I have a radio control in the theme customizer. The code for that control is like below:

$wp_customize->add_setting( 'post_layout', array(
  'capability' => 'edit_theme_options',
  'default' => 'cover',
  'sanitize_callback' => 'sanitize_text_field',
) );

$wp_customize->add_control( 'post_layout', array(
  'type' => 'radio',
  'section' => 'post_options',
  'label' => __( 'Post Layout', 'mytheme' ),
  'choices' => array(
    'cover' => __( 'Cover', 'mytheme' ),
    'thumbnail' => __( 'Thumbnail', 'mytheme' ),
    'default' => __( 'Default', 'mytheme' ),
  ),
) );

And the complete code responsible to render the post meta-box is:

<?php
/**
 * Add the meta box
 *
 * @return void
 */
function mytheme_add_custom_box() {
  add_meta_box(
    'mytheme_sectionid',
    __( 'Post Options', 'mytheme' ),
    'mytheme_build_custom_box',
    'post',
    'side',
    'low'
  );
}
add_action( 'add_meta_boxes', 'mytheme_add_custom_box' );

/**
 * Prints the box content.
 * 
 * @param WP_Post $post The object for the current post/page.
 * @return void
 */
function mytheme_build_custom_box( $post ) {

  // Add an nonce field so we can check for it later.
  wp_nonce_field( 'mytheme_build_custom_box', 'mytheme_build_custom_box_nonce' );

  /*
   * Use get_post_meta() to retrieve an existing value
   * from the database and use the value for the form.
   */
  $value = get_post_meta( $post->ID, '_my_meta_value_key', true );

  $loxxo_post_header_layout = get_theme_mod( 'loxxo_post_header', 'cover' );
?>


  <p><?php __( 'Select a style', 'mytheme' ); ?></p>
  <input type="radio" id="mytheme_post_layout-cover" name="mytheme_post_layout" value="cover" <?php checked( $value, 'cover' ) ?> /><label for="mytheme_post_layout-cover"><?php _e( 'Cover/Fullscreen', 'mytheme' ); ?></label>
  <br>
  <input type="radio" id="mytheme_post_layout-thumbnail" name="mytheme_post_layout" value="thumbnail" <?php checked( $value, 'thumbnail' ) ?> /><label for="mytheme_post_layout-thumbnail"><?php _e( 'Regular', 'mytheme' ) ?></label>
  <br>
  <input type="radio" id="mytheme_post_layout-default" name="mytheme_post_layout" value="default" <?php checked( $value, 'default' ) ?> /><label for="mytheme_post_layout-default"><?php _e( 'Default', 'mytheme' ) ?></label>
<?php

}

/**
 * When the post is saved, saves our custom data.
 *
 * @param int $post_id The ID of the post being saved.
 * @return void
 */
function mytheme_save_postdata( $post_id ) {

  /*
   * We need to verify this came from the our screen and with proper authorization,
   * because save_post can be triggered at other times.
   */

  // Check if our nonce is set.
  if ( ! isset( $_POST['mytheme_build_custom_box_nonce'] ) )
    return $post_id;

  $nonce = $_POST['mytheme_build_custom_box_nonce'];

  // Verify that the nonce is valid.
  if ( ! wp_verify_nonce( $nonce, 'mytheme_build_custom_box' ) )
      return $post_id;

  // If this is an autosave, our form has not been submitted, so we don't want to do anything.
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
      return $post_id;

  // Check the user's permissions.
  if ( 'page' == $_POST['post_type'] ) {

    if ( ! current_user_can( 'edit_page', $post_id ) )
        return $post_id;

  } else {

    if ( ! current_user_can( 'edit_post', $post_id ) )
        return $post_id;
  }

  // Sanitize user input.
  $mydata = sanitize_text_field( $_POST['mytheme_post_layout'] );

  // Update the meta field in the database.
  update_post_meta( $post_id, '_my_meta_value_key', $mydata );
}
add_action( 'save_post', 'mytheme_save_postdata' );

Above is a bit lengthy code, sorry about that. The options are rendering correctly, and everything looks fine in the customizer and the meta-box.

The problem is, that I'm confused about making the default value of the meta-box radio options go hand-in-hand with the customizer's. Any clues and ideas will be appreciated.

Was it helpful?

Solution

Before to handle the defaut value, there is a lot of changes that you can do for the hook "save_post" and the first one is to no more use it.
You add the metabox only on post type post, then you can use the hook save_post_post to only doing the treatment for this custom post :
https://developer.wordpress.org/reference/hooks/save_post_post-post_type/

After that, you don't need to test the capability edit_post because the backend page "edit.php" does the test before to save. And you don't need to test DOING_AUTOSAVE because in the autosave case, the metabox values are not send. And then you just have to test the nonce.

Finally, to set a default value in the metabox, you can do it when $update === FALSE which is called when you click on the link "create a new post".

and then try this code :

add_action("save_post_post", function ($post_ID, $post, $update) {


    if (!$update) {

        // default values here

        $mydata = get_theme_mod( 'post_layout', 'cover' );
        update_post_meta( $post_ID, '_my_meta_value_key', $mydata );

        return;

    }


    if ( ! isset( $_POST['mytheme_build_custom_box_nonce'] ) ) {
        return;
    }

    // check the nonce
    check_admin_referer(
          "mytheme_build_custom_box"
        , "mytheme_build_custom_box_nonce"
    );


    // save the values

    // Sanitize user input.
    $mydata = sanitize_text_field( $_POST['mytheme_post_layout'] );

    // Update the meta field in the database.
    update_post_meta( $post_ID, '_my_meta_value_key', $mydata );


}, 10, 3);

OTHER TIPS

You're getting the saved value here:

$value = get_post_meta( $post->ID, '_my_meta_value_key', true );

All you need to do is check if the value contains anything. If it doesn't, set the value to the option from the customiser:

$value = get_post_meta( $post->ID, '_my_meta_value_key', true );

if ( ! $value ) {
    $value = get_theme_mod( 'loxxo_post_header', 'cover' );
}

Which can be accomplished in one line of code with the ternary operator (?:):

$value = get_post_meta( $post->ID, '_my_meta_value_key', true ) ?: get_theme_mod( 'loxxo_post_header', 'cover' );
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top