I will try to explain this, I have a button where I can upload and select a video to add to a post. And I have a input field which I can put in a duration (in seconds). I have made a function which pulls the length of the video from the database, and this length I want to put in the database under slide_duration. And if a video isn't selected I want it to work as it usually do, you can put in a custom value (in seconds) or you can leave this input empty (which makes it revert to the standard value).
The related PHP looks like this:
if ( isset( $_POST['slide_duration'] ) && is_numeric( $_POST['slide_duration'] ) && $_POST['slide_duration'] >= 1 ) {
$slide_duration = intval($_POST['slide_duration']);
update_post_meta( $post_id, 'slide_duration', $slide_duration );
}
else {
delete_post_meta( $post_id, 'slide_duration' );
}
This is how it looked before I touched it. It deletes slide_duration if no value is entered, this is how I need to keep it, to make it revert to the default value if nothing is put there.
I now added this part after the above code:
if ( isset( $_POST['background-video'] ) ) {
update_post_meta( $post_id, 'slide_duration', $video_meta['length'] );
}
This will update the slide_duration in the database when a video is selected. But I cannot manually set the time in the input field, it always reverts to 0 when saving/updating the post. If I put the code above the original, I can put in whatever value I want in the input, but selecting a video won't update slide_duration any longer.
For more context, this is how the input looks:
<?php
$slide_duration = isset( $theme_stored_meta['slide_duration'] ) ? intval($theme_stored_meta['slide_duration'][0]) : '';
?>
<input type="number" name="slide_duration" value="<?=$slide_duration?>" min="1" step="1" style="width: 70px;" /> <?=__('seconds', 'theme')?>
Hope I have explained well enough and provided enough of the code to get a clear picture of this.
EDIT: Tried this too:
if ( isset( $_POST['slide_duration'] ) && is_numeric( $_POST['slide_duration'] ) && $_POST['slide_duration'] >= 1 ) {
$slide_duration = intval($_POST['slide_duration']);
update_post_meta( $post_id, 'slide_duration', $slide_duration );
}
elseif ( isset( $_POST['slide_duration'] ) ) {
update_post_meta( $post_id, 'slide_duration', $video_meta['length'] );
}
if ( is_null( $_POST['slide_duration'] ) ) {
delete_post_meta( $post_id, 'slide_duration' );
}
Got it working finally!
I don't really know what did it, but this is working:
if ( $_POST['slide_duration'] == NULL ) {
delete_post_meta( $post_id, 'slide_duration' );
}
if ( isset( $_POST['slide_duration'] ) && is_numeric( $_POST['slide_duration'] ) && $_POST['slide_duration'] >= 1 ) {
update_post_meta( $post_id, 'slide_duration', (int) $_POST['slide_duration'] );
}
if( isset( $_POST[ 'background-video' ] ) && $video_meta['length'] >= 1 ) {
update_post_meta( $post_id, 'slide_duration', $video_meta['length'] );
}
Thank you very much Sally CJ
Related
I'm trying to add or update two post meta on saving a post. Add if it's a new post and update if existing, but this function creates four in the database instead of two meta.
add_action( 'save_post', 'add_rewards');
global $WCFM, $WCFMmp;
function add_rewards ($product_id){
if($product_id){
$post_type = get_post_type($product_id);
if($post_type == 'product'){
$product = wc_get_product( $product_id );
$reg_price = $product->get_regular_price();
$sal_price = $product->get_sale_price();
$pric = $product->get_price();
add_post_meta($product_id,'main_reward', $reg_price);
add_post_meta($product_id,'sub_reward', $sal_price);
}
}
}
As it explains in the save_post manual, you should use save_post_{$post->post_type} which minimizes the save_post calls on other post types. It's also a good idea to check for autosave.
Also, if you use update_post_meta instead of add_post_meta you'll end up with only one instance of each. As it explains in the manual for that function, it says:
If the meta field for the post does not exist, it will be added and its ID returned.
Can be used in place of add_post_meta().
add_action( 'save_post_product', 'so71077799_add_rewards', 99, 1 );
function so71077799_add_rewards( $product_id ) {
// Check to see if we are autosaving, if so, exit.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( isset( $_POST['_regular_price'] ) ) {
update_post_meta( $product_id, 'main_reward', number_format( floatval( $_POST['_regular_price'] ), '2' ) );
}
if ( isset( $_POST['_sale_price'] ) ) {
update_post_meta( $product_id, 'sub_reward', number_format( floatval( $_POST['_sale_price'] ), '2' ) );
}
}
I have a problem with updating my custom meta box in wordpress for a custom post news. I have made a meta box checkbox so I could decide if the post is featured or not. If the checkbox is checked then isFeatured = 1. Until this part it works, the problem is when after sometime I wan't to edit the post and deselect the checkbox. After updating the post the checkbox is checked all the time.
The database: meta_key | meta_value ---- > news_details | a:1:{s:10:"isFeatured";s:1:"1";}
This is how my code looks:
function add_news_details_meta_box() {
add_meta_box(
'news_details_meta_box', // $id
'Checkbox', // $title
'show_news_details_meta_box', // $callback
'news', // $screen
'normal', // $context
'high' // $priority
);
}
add_action( 'add_meta_boxes', 'add_news_details_meta_box' );
function show_news_details_meta_box() {
global $post;
$meta = get_post_meta( $post->ID, 'news_details', true ); ?>
<input type="hidden" name="news_details_meta_box_nonce" value="<?php echo wp_create_nonce( basename(__FILE__) ); ?>">
<p>
<label for="news_details[isFeatured]">Is this post featured?
<input type="checkbox" name="news_details[isFeatured]" value="1" <?php if (is_array($meta) && $meta['isFeatured'] === '1' ) { echo 'checked';} else { echo 'Unchecked';}?>>
</label>
</p>
<?php
}
function save_news_details_meta( $post_id ) {
// verify nonce
if ( !wp_verify_nonce( $_POST['news_details_meta_box_nonce'], basename(__FILE__) ) ) {
return $post_id;
}
// check autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// check permissions
if ( 'page' === $_POST['post_type'] ) {
if ( !current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
} elseif ( !current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
$old = get_post_meta( $post_id, 'news_details', true );
$new = $_POST['news_details'];
if ( $new && $new !== $old ) {
update_post_meta( $post_id, 'news_details', $new );
} elseif ( '' === $new && $old ) {
delete_post_meta( $post_id, 'news_details', $old );
}
}
add_action( 'save_post', 'save_news_details_meta' );
Could you explain to me what's wrong with updating the checkbox after sometime?
I think you should check the if condition. The way I got your description, the $meta['isFeatured'] === '1' always becomes true. You set the value to 1 in the input tag. So on save the value of 1 gets saved to the field I guess. On next load you are checking with an if, if the $meta['isFeatured'] is 1, so this is always true.
You could check if the checkbox in the form is checked with:
isset($_POST['name_of_your_checkbox_input'])
If it is set, you save the value of 1. If not, you stay at the pre defined value of 0.
What worked for me in this case was changing } elseif ( '' === $new && $old ) { to } else ( '' === $new && $old ) {
I have a custom metabox that I created and have been using on my website for a while, but there's a bit of an issue with how it saves. It tends to be rather volatile, meaning that when backing-up with xml or bulk-editing, it will always lose the data.
The following is the code that I use for the checkbox and to save it
function member_page_featured_meta() {
add_meta_box( 'member_page_meta', __( 'Page Template (if default, select none)', 'member_page_textdomain' ), 'member_page_meta_callback', 'page', 'side', 'low' );
}
add_action( 'add_meta_boxes', 'member_page_featured_meta' );
/**
* Outputs the content of the meta box
*/
function member_page_meta_callback( $post ) {
$values = get_post_meta( $post->ID );
$check = isset( $values['member_box_check'] ) ? esc_attr( $values['member_box_check'][0] ) : '';
wp_nonce_field( basename( __FILE__ ), 'member_page_nonce' );
$member_page_stored_meta = get_post_meta( $post->ID );
?>
<p>
<div class="member_page-row-content">
<label for="featured-checkbox">
<input type="checkbox" name="featured-checkbox" id="featured-checkbox" value="yes" <?php if ( isset ( $member_page_stored_meta['featured-checkbox'] ) ) checked( $member_page_stored_meta['featured-checkbox'][0], 'yes' ); ?> />
<?php _e( 'Member Page', 'member_page_textdomain' )?>
</label><br />
<label for="list-checkbox">
<input type="checkbox" name="list-checkbox" id="list-checkbox" value="yes" <?php if ( isset ( $member_page_stored_meta['list-checkbox'] ) ) checked( $member_page_stored_meta['list-checkbox'][0], 'yes' ); ?> />
<?php _e( 'Home List', 'member_page_textdomain' )?>
</label><br />
</div>
</p>
<?php
}
/**
* Saves the custom meta input
*/
function member_page_meta_save( $post_id ) {
// Checks save status - overcome autosave, etc.
$is_autosave = wp_is_post_autosave( $post_id );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = ( isset( $_POST[ 'member_page_nonce' ] ) && wp_verify_nonce( $_POST[ 'member_page_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';
// Exits script depending on save status
if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
return;
}
// Checks for input and saves - save checked as yes and unchecked at no
//This line of code is my hack (just keeps the boxes from saving pretty much)
//if (!empty($_POST['featured-checkbox']) && !empty($_POST['list-checkbox'])) {
if( isset( $_POST[ 'featured-checkbox' ] ) ) {
update_post_meta( $post_id, 'featured-checkbox', 'yes' );
} else {
update_post_meta( $post_id, 'featured-checkbox', 'no' );
};
if( isset( $_POST[ 'list-checkbox' ] ) ) {
update_post_meta( $post_id, 'list-checkbox', 'yes' );
} else {
update_post_meta( $post_id, 'list-checkbox', 'no' );
};
// (bracket ending the first if statement) }
}
add_action( 'save_post', 'member_page_meta_save' );
Is there any way to prevent this issue from happening or is it just something that has to be dealt with when saving check-boxes?
I've sorted out a bit of a hack that is working for now, but whenever I need to make changes to the check-boxes (which is fairly often by the nature of how they're used), I have to comment out a few lines of code, make the change, then un-comment the lines of code and it's a bit unconventional.
I mostly need to make it work when backing-up and restoring (on my backup/production website).
The save_post action is triggered when a post is created or updated, so quick edits and regular edits and the import of posts will trigger it too.
It is actually your script which clears the post meta when doing a quick edit or import, because the POST array does not contain the previously saved values of the checkboxes.
To solve this, you might want to know the "type of saving" currently happening, and only update the post meta when you are on the post edit screen in the admin area. A way of doing this is to check the action parameter of the POST array like the following, because the action parameter only has the value editpost when saving from a post edit screen:
if (filter_input(INPUT_POST, 'action') != 'editpost') {
return;
}
Putting this code at the beginning of the function hooked to the save_post action (member_page_meta_save in your case) will let the rest of the function run only when saving from the post edit screen.
I'm using a plugin on Woocommerce that adds a new metabox with editable quantity number fields onto the admin back-end.
My theme allows for front-end product posting and so I want to add bring some of these fields to the front-end.
I have managed to add the fields in my template file by using :
<?php
$min = get_post_meta( $post->ID, '_wpbo_minimum', true );
$max = get_post_meta( $post->ID, '_wpbo_maximum', true );
?>
<label for="_wpbo_minimum">Minimum Quantity</label>
<input type="number" name="_wpbo_minimum" value="<?php echo $min; ?>" />
<label for="_wpbo_maximum">Maximum Quantity</label>
<input type="number" name="_wpbo_maximum" value="<?php echo $max; ?>" />
Both fields are showing on my front-end product edit form and getting their values from the backend if these were previously filled in.
But now I am struggling with updating and saving the fields with updated values
from front-end or saving new values from front-end if these values were not previously filled in.
I spent hours finding some tutorial on this, I think I should be concentrating on the following code :
update_post_meta($post->ID, '_wpbo_minimum', $_POST['_wpbo_minimum']);
update_post_meta($post->ID, '_wpbo_maximum', $_POST['_wpbo_maximum']);
But I can't figure out if this is correct and where should this code be placed in order to save or update my fields.
I tried placing a function into my functions.php file that looks like this :
/* Update Minimum Qty field */
add_action('save_post', 'save_min_qty');
function save_min_qty($post_id)
{
if(get_post_type($post_id) != "VA_LISTING_PTYPE")
return;
$min = get_post_meta( $post->ID, '_wpbo_minimum', true );
if ( isset( $_POST['_wpbo_minimum'] )) {
$min = $_POST['_wpbo_minimum'];
}
if( isset( $_POST['_wpbo_minimum'] )) {
if ( $min != 0 ) {
$min = wpbo_validate_number( $min );
}
update_post_meta(
$post_id,
'_wpbo_minimum',
strip_tags( $min )
);
}
But this just doesn't seem to be the winner.
Would you be please able to point me to the right direction ?
Below is the code from the actual original plugin that creates metabox in the back-end, I am not sure if it's any relevant to what I need to do in front-end and what part of this and where should I be using it :
<?php
if ( ! class_exists( 'IPQ_Quantity_Meta_Boxes' ) ) :
class IPQ_Quantity_Meta_Boxes {
public function __construct() {
add_action( 'save_post', array( $this, 'save_quantity_meta_data' ) );
}
/* Handle Saving Meta Box Data */
public function save_quantity_meta_data( $post_id ) {
// Validate Post Type
if ( ! isset( $_POST['post_type'] ) or $_POST['post_type'] !== 'product' ) {
return;
}
// Validate User
if ( !current_user_can( 'edit_post', $post_id ) ) {
return;
}
// Verify Nonce
if ( ! isset( $_POST["_wpbo_product_rule_nonce"] ) or ! wp_verify_nonce( $_POST["_wpbo_product_rule_nonce"], plugin_basename( __FILE__ ) ) ) {
return;
}
// Update Rule Meta Values
if ( isset( $_POST['_wpbo_minimum'] )) {
$min = $_POST['_wpbo_minimum'];
}
if( isset( $_POST['_wpbo_minimum'] )) {
if ( $min != 0 ) {
$min = wpbo_validate_number( $min );
}
update_post_meta(
$post_id,
'_wpbo_minimum',
strip_tags( $min )
);
}
/* Make sure Max > Min */
if( isset( $_POST['_wpbo_maximum'] )) {
$max = $_POST['_wpbo_maximum'];
if ( isset( $min ) and $max < $min and $max != 0 ) {
$max = $min;
}
update_post_meta(
$post_id,
'_wpbo_maximum',
strip_tags( wpbo_validate_number( $max ) )
);
}
}
}
endif;
Everything is correct except that you are checking for the wrong post_type - it should be "product" not "VA_LISTING_PTYPE". Your function hooked to save_post is returning early because the post type is not correct.
Incorrect
if(get_post_type($post_id) != "VA_LISTING_PTYPE")
return;
Correct
if (get_post_type($post_id) != "product"){
// bail early if we aren't updating a WooCommerce Product
return;
}
You can see the same check in the plugin you are extending here:
https://github.com/wpbackoffice/woocommerce-incremental-product-quantities/blob/master/includes/class-ipq-product-meta-box.php#L222
I am creating a metabox that loops through all the posts of another CPT: 'product'. The metabox lists all the published products in that CPT, puts them in a table row along with an input box. Each input box has a unique ID based off of the CPT product id.
Most of this code I have added based on other posts, but I am having a problem saving the data. I know that it has to do with my value="", my nonce, and $meta_value, but I am not sure where to go next. Below is the code I have so far:
<?php
add_action('admin_init', 'my_theme_on_admin_init');
function my_theme_on_admin_init() {
add_meta_box('my_metabox',
__('Daily Inventory Levels', 'textdomain'),
'my_metabox_render',
'location_inventory', 'normal', 'high'
);
}
function my_metabox_render($post) {
// using an underscore, prevents the meta variable
// from showing up in the custom fields section
global $woocommerce, $post;
$productsList = new WP_Query( 'post_type=product&post_status=publish');
?>
<div class="inside">
<table class="form-table">
<input type="hidden" name="inventory_noncename" id="inventory_noncename" value="<?php wp_create_nonce( 'inventory-nonce' ); ?>" />
<?php
while ( $productsList->have_posts() ) {
$productsList->the_post();
?>
<tr><td><label for="location_inventory_product-<?php the_ID(); ?>"><?php the_title(); ?></label></td><td><input id="location_inventory_product-<?php the_ID(); ?>" name="location_inventory_product-<?php the_ID(); ?>" cols="40" rows="5" value="<?php echo $meta_key; ?>" /></td></tr>
<?php }
wp_reset_postdata();
?>
</table>
</div>
<?php
}
/*update on save*/
add_action('save_post', 'save_postdata_dynamic_inventory_metabox' );
function save_postdata_dynamic_inventory_metabox( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return;
}
// Check permissions
if ( 'location_inventory' == $_POST['post_type'] ) {
if ( !current_user_can( 'edit_page', $post_id )) {
return $post_id;
}
}
elseif ( !current_user_can( 'edit_post', $post_id )) {
return $post_id;
}
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if (isset($_POST['inventory_noncename'])){
if ( !wp_verify_nonce( $_POST['inventory_noncename'], 'inventory-nonce' ) )
return;
} else {
return;
}
// Get the posted data and sanitize it for use as an HTML class.
$new_meta_value = ( isset( $_POST['location_inventory_product-'.the_ID().''] ) ? sanitize_html_class( $_POST['location_inventory_product-'.the_ID().''] ) : '' );
// Get the meta key.
$meta_key = 'location_inventory_product-'.the_ID().'';
// Get the meta value of the custom field key.
$meta_value = get_post_meta( $post_id, $meta_key, true );
// If a new meta value was added and there was no previous value, add it.
if ( $new_meta_value && '' == $meta_value )
add_post_meta( $post_id, $meta_key, $new_meta_value, true );
// If the new meta value does not match the old value, update it.
elseif ( $new_meta_value && $new_meta_value != $meta_value )
update_post_meta( $post_id, $meta_key, $new_meta_value );
// If there is no new meta value but an old value exists, delete it.
elseif ( '' == $new_meta_value && $meta_value )
delete_post_meta( $post_id, $meta_key, $meta_value );
} // ends function save_postdata_dynamic_reviews_metabox
Some observations:
1) The hook save_post takes 2 arguments:
add_action( 'save_post', 'save_postdata_dynamic_inventory_metabox', 10, 2 );
function save_postdata_dynamic_inventory_metabox( $post_id, $post_object ) { }
2) I don't think checking for permissions is necessary (at least, never seen it). Just in case, this is an example of the post_object use:
if ( 'location_inventory' == $post_object->post_type )
3) Short this check:
if ( !isset($_POST['inventory_noncename']) || !wp_verify_nonce( $_POST['inventory_noncename'], 'inventory-nonce' ) )
return;
4) The use of the_ID() inside the function save_postdata_dynamic_inventory_metabox is wrong. This is only available inside a Loop and you already have $post_id at hand.
5) Finally, and the most important, the way you're handling the $meta_key is wrong. For one, it's not defined inside the function my_metabox_render. Check this Answer for a working example.
Research in this search query to find more examples.