I’m taking multiple location values with each post, so it’s an array (always). My post meta form field is like so:
<select name="<?php echo $project_prefix; ?>offer_locations[]" id="<?php echo $project_prefix; ?>offer_locations" required multiple="multiple">
...
...
...
</select>
If the post already exists without any value for locations, the existing value will come null
, but as the field is mandatory, the new location value [on saving] will surely be an array, and we should add the postmeta value.
The conditionals I made with array_diff()
is working fine. I made a custom scenario and checked the code, and even in WordPress, I’ve checked the code (custom code block), as you can see couple of var_dump()
, echo
and exit()
inline. But…
<?php
function save_post_specifics_meta( $post_id ) {
global $project_prefix;
// verify nonce
if (!isset($_POST['post_specifics_nonce']) || !wp_verify_nonce($_POST['post_specifics_nonce'], basename(__FILE__)))
return $post_id;
// check autosave
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
// check permissions
if ( 'post' == $_POST['post_type'] && !current_user_can('edit_post', $post_id) )
return $post_id;
//Location meta data
$existing_locations = get_post_custom_values( "{$project_prefix}post_locations", $post_id );
$new_locations = $_POST["{$project_prefix}post_locations"]; //always an array
var_dump($existing_locations); //for debugging only
var_dump($new_locations); //for debugging only
if( is_array( $existing_locations ) ) {
$new_diff = array_diff( $new_locations, $existing_locations );
$existing_diff = array_diff( $existing_locations, $new_locations );
} else {
$new_diff = $new_locations;
$existing_diff = $existing_locations;
}
var_dump($new_diff); //for debugging only
var_dump($existing_diff); //for debugging only
if( $new_diff ) {
foreach( $new_diff as $new_location ) {
add_post_meta( $post_id, "{$project_prefix}post_locations", $new_location );
echo "New Multiple: ", $new_location, '<br>'; //for debugging only
}
}
if( $existing_locations && $existing_diff ) {
if( is_array( $existing_diff ) ) {
foreach ( $existing_diff as $existing_location ) {
delete_post_meta( $post_id, "{$project_prefix}post_locations", $existing_location );
echo "Delete Multiple: ", $existing_location, '<br>'; //for debugging only
}
} else {
delete_post_meta( $post_id, "{$project_prefix}post_locations", $existing_diff );
echo "Delete Single: ", $existing_diff, '<br>'; //for debugging only
}
}
exit(); //for debugging only
}
add_action( 'save_post', 'save_post_specifics_meta', 10 );
add_action( 'new_to_publish', 'save_post_specifics_meta', 10 );
On saving or updating post, location meta field is doing as expected. But if the data entry operator hit the Preview Changes button, the add_post_meta()
is triggering, even within the true conditional braces, and adding duplicate entries, I don’t know how!!! 😮
I then added true
to the last parameter (line#40) to make the value unique, so that I can stop duplicate entries. But adding true
stopped adding any new value to the meta_key
even on saving.
How can I stop adding meta value on Preview Changes hit?
1 Answer
Actually I’d love to have an answer from @ialocin, because he suggested me the way. But as the code is a bit long for comment field I’m posting it here as an answer. But I’d love to accept an answer more appropriate to the situation:
After @ialocin’s suggestion, I got that, the $post_id
wasn’t accurate for a Preview Changes hit, so the $existing_locations
wasn’t getting the correct db info. Now I changed the following line:
$existing_locations = get_post_custom_values( "{$project_prefix}post_locations", $post_id );
into the following conditional lines:
if( $_POST[ 'wp-preview' ] === 'dopreview' ) {
//if it's a preview hit, grab the actual post's data
$actual_post_id = wp_get_post_parent_id( $post_id );
$existing_locations = get_post_custom_values( "{$project_prefix}post_locations", $actual_post_id );
} else {
//else, go with the actual post
$existing_locations = get_post_custom_values( "{$project_prefix}post_locations", $post_id );
}
Everything is working as expected in localhost. Though sometimes, the Preview hit fails the preview_id
and preview_nonce
etc. and doesn’t show the preview, but when they’re set, the preview is, exactly what it should be.