Mandatory custom radio button choice on Woocommerce checkout - wordpress

I've got this custom code working to add a couple of radio buttons into the checkout:
add_action( 'woocommerce_review_order_before_payment', 'display_extra_fields_after_billing_address' , 10, 1 );
function display_extra_fields_after_billing_address () { ?>
<h3 class="delivery-options-heading">Delivery Options <sup>*</sup></h3>
<div class="delivery-options">
<p><input type="radio" name="delivery_option" value="Have the courier leave a card." required /> Have the courier leave a card.</p>
<p><input type="radio" name="delivery_option" value="Leave the consignment without a signature." required /> Leave the consignment without a signature.</p>
</div>
<?php
}
add_action( 'woocommerce_checkout_update_order_meta', 'add_delivery_option_to_order' , 10, 1);
function add_delivery_option_to_order ( $order_id ) {
if ( isset( $_POST ['delivery_option'] ) && '' != $_POST ['delivery_option'] ) {
add_post_meta( $order_id, '_delivery_option', sanitize_text_field( $_POST ['delivery_option'] ) );
}
}
add_filter( 'woocommerce_email_order_meta_fields', 'add_delivery_option_to_emails' , 10, 3 );
function add_delivery_option_to_emails ( $fields, $sent_to_admin, $order ) {
if( version_compare( get_option( 'woocommerce_version' ), '3.0.0', ">=" ) ) {
$order_id = $order->get_id();
} else {
$order_id = $order->id;
}
$delivery_option = get_post_meta( $order_id, '_delivery_option', true );
if ( '' != $delivery_option ) {
$fields[ 'Delivery Date' ] = array(
'label' => __( 'Delivery Option', 'delivery_option' ),
'value' => $delivery_option,
);
}
return $fields;
}
Every part of this works fine except for the required attributes on the radio buttons, letting the user checkout without making a choice, which is not ideal. For some reason the required attributes are being ignored.
How can I force the user to select one of the radio buttons before checking out?

Please add this validation hook along with your code that will validate your option on checkout
function action_woocommerce_after_checkout_validation( $data, $errors ) {
if( !isset( $data['delivery_option'] ) || empty( $data['delivery_option'] ) ) :
$errors->add( 'required-field', __( 'No delivery option has been selected. Please choose delivery option.', 'woocommerce' ) );
endif; //Endif
}
// add the action
add_action( 'woocommerce_after_checkout_validation', 'action_woocommerce_after_checkout_validation', 10, 2 );

This was the solution, slightly different to what Krunal Prajapati suggested. The only difference is the second line:
function action_woocommerce_after_checkout_validation( $data, $errors ) {
if ( empty( $_POST['delivery_option'] ) ) :
$errors->add( 'required-field', __( 'No delivery option has been selected. Please choose delivery option.', 'woocommerce' ) );
endif; //Endif
}
// add the action
add_action( 'woocommerce_after_checkout_validation', 'action_woocommerce_after_checkout_validation', 10, 2 );

Related

Verifying Userprofile "Uniqueness" of Meta Value at the time of creation for wordpress user custom field meta-key "association_id"

I have a custom user profile field "association_id". I can see the field the underlying wordpess db table (usermeta) with the 'meta_key' as "association_id" and the 'meta_value' whatever that I maintain for each user.
add_action( 'show_user_profile', 'rudr_profile_fields' );
add_action( 'edit_user_profile', 'rudr_profile_fields' );
function rudr_profile_fields( $user )
{
// let's get custom field values
$association_id = get_user_meta( $user->ID, 'association_id', true );
?>
<h3>Association Information</h3>
<table class="form-table">
<tr>
<th><label for="association_id">Association_ID</label></th>
<td>
<input type="text" name="association_id" id="association_id" value="<?php echo esc_attr( $association_id ) ?>" class="regular-text" />
<span class="description"><?php _e("Please enter your Association ID (For eg. if RCIC, your license number)."); ?></span>
</td>
</tr>
</table>
<?php
}
//avoid self to edit //
//add_action( 'personal_options_update', 'rudr_save_profile_fields' ); //
add_action( 'edit_user_profile_update', 'rudr_save_profile_fields' );
function rudr_save_profile_fields( $user_id ) {
if( ! isset( $_POST[ '_wpnonce' ] ) || ! wp_verify_nonce( $_POST[ '_wpnonce' ], 'update-user_' . $user_id ) ) {
return;
}
if( ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
/* HOLDING SPACE FOR ENHANCED SNIPPED */
//include in the list view of users
add_filter( 'manage_users_columns', 'column_register_association_id' );
add_filter( 'manage_users_custom_column', 'column_display_association_id', 10, 3 );
function column_register_association_id( $columns )
{
$columns['association_id'] = 'association_id';
return $columns;
}
function column_display_association_id( $value, $column_name, $user_id )
{
$user_info = get_user_meta( $user_id, 'association_id', true );
if($column_name == 'association_id') return $user_info;
return $value;
}
//Sort association_id column
function association_id_register_sortable( $columns ) {
$columns['association_id'] = 'association_id';
return $columns;
}
add_filter( 'manage_users_sortable_columns', 'association_id_register_sortable' );
function association_id_orderby( $vars ) {
if ( isset( $vars['orderby'] ) && 'association_id' == $vars['orderby'] ) {
$vars = array_merge( $vars, array(
'meta_key' => 'association_id',
'orderby' => 'meta_value'
) );
}
return $vars;
}
add_filter( 'request', 'association_id_orderby' );
The preceding works fine and creates a meta key for storing meta value in the metadata wp table.
I want this custom user profile field value that I enter in the user admin page to be unique, verifying with the underlying wordpress database table. So I enhanced the code at the time of creation with the additional lines below. I tried these two snippets in the wordpress child theme, but it throws a critical error. I am on PHP version 8.
I tried two options below at the placeholder location in the above code, replacing the line below.
/* HOLDING SPACE FOR ENHANCED SNIPPED */
Option 1 that I tried.
$checkMeta=$wpdb->get_results("SELECT user_id FROM $wpdb->usermeta WHERE meta_key='association_id' AND meta_value=".$association_id,ARRAY_A);
if (empty($checkMeta)) {
update_user_meta( $user_id, 'association_id', sanitize_text_field( $_POST[ 'association_id' ] ) );
}
Option 2 that I tried.
$mysqli = new mysqli(SERVER, DBUSER, DBPASS, DATABASE); $result = $mysqli->query("SELECT user_id FROM usermeta WHERE meta_key='association_id' && meta_value=$association_id "); if($result->num_rows == 0) { // row not found, do stuff update_user_meta( $user_id, 'association_id', sanitize_text_field( $_POST[ 'association_id' ] ) ); } else { // row found, do stuff echo ' This ID is already used.'; } $mysqli->close();
Both failed to activate when I tried to create or change the 'association_field' value, throwing critical errors and aborting.

Dokan action to update order status

I need help with dokan actions on Orders page. Currently here i have two actions, to mark order complete or processing. What I want is to create action to mark order cancelled and on-hold.
I have accessed file that contains these two actions and they are in file Ajax.php:
add_action( 'wp_ajax_dokan-mark-order-complete', array( $this, 'complete_order' ) );
add_action( 'wp_ajax_dokan-mark-order-processing', array( $this, 'process_order' ) );
Is there a way to define similar action:
add_action( 'wp_ajax_dokan-mark-order-cancelled', array( $this, 'cancel_order' ) );
?
I already made a custom action that mark the order as shipped(custom status):
first you can add the below to include/Ajax.php > in the __construct function.
add_action( 'wp_ajax_dokan-mark-order-shipped', array( $this, 'ship_order' ) );
Then you have to include the custom function (in the same file):
public function ship_order() {
if ( ! is_admin() ) {
die();
}
if ( ! current_user_can( 'dokandar' ) || 'on' != dokan_get_option( 'order_status_change', 'dokan_selling', 'on' ) ) {
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'dokan-lite' ) );
}
if ( ! check_admin_referer( 'dokan-mark-order-shipped' ) ) {
wp_die( esc_html__( 'You have taken too long. Please go back and retry.', 'dokan-lite' ) );
}
$order_id = ! empty( $_GET['order_id'] ) ? intval( $_GET['order_id'] ) : 0;
if ( ! $order_id ) {
die();
}
if ( ! dokan_is_seller_has_order( dokan_get_current_user_id(), $order_id ) ) {
wp_die( esc_html__( 'You do not have permission to change this order', 'dokan-lite' ) );
}
$order = dokan()->order->get( $order_id );
$order->update_status( 'wc-completed' );
wp_safe_redirect( wp_get_referer() );
die();
}
then make sure that you modify the URL :
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=dokan-mark-order-shipped&order_id=' . dokan_get_prop( $order, 'id' ) ), 'dokan-mark-order-shipped' ),
Please let me know if you need any help

Custom Field created in add_meta_boxes reappearing itself again in the default Custom Metabox

I succeed in creating a metabox with custom field inside, and I restrict it to appear in a custom post type.
//define metabox
function product_info_en() {
add_meta_box( 'english_info', 'English Info', 'english_product_name_callback', array('product'), 'normal', 'high' );
}
//add to hook
add_action( 'add_meta_boxes', 'product_info_en' );
The code to display it in the product page:
// display in add product admin page
function english_product_name_callback( $post ) {
//ob_start();
$content = esc_attr( get_post_meta( get_the_ID(), 'product_desc_en', true ) );
//here goes the custom field
echo '<fieldset><div><label><b>English Product Name:</b></label><br/>';
echo '<input id="product_name_en" type="text" name="product_name_en" style="width:100%; margin:10px 0px"';
echo ' value="';
echo esc_attr( get_post_meta( get_the_ID(), 'product_desc_en', true ) );
echo '"></div></fieldset>';
//here goes the wp_editor
echo '<fieldset><div><label><b>English Product Content Info:</b></label><div><br/>';
echo '<div>';
wp_editor($content, 'product_desc_en', array(
'wpautop' => true,
'media_buttons' => true,
'textarea_rows' => 10
)
);
echo '</div></fieldset>';
}
Here goes the code that do the saving job:
//save
function enginfo_save_meta_box( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( $parent_id = wp_is_post_revision( $post_id ) ) {
$post_id = $parent_id;
}
$fields = [
'product_name_en',
];
foreach ( $fields as $field ) {
if ( array_key_exists( $field, $_POST ) ) {
update_post_meta( $post_id, $field, sanitize_text_field( $_POST[$field] ) );
}
}
update_post_meta( $post_id,'product_desc_en', wp_kses_post( $_POST['product_desc_en'] ) );
}
add_action( 'save_post', 'enginfo_save_meta_box' );
However, the custom created field that supposed to be going only into the newly created metabox, will always show up in the default "custom field". And this happens to all post type.
As shown below, What could possibly be the issue here?
To hide and not show your custom fields there in default box, please prefix your custom fields with underscore _ , so product_desc_en will become _product_des_en
I mean the names of your custom fields should be prefixed with underscore and WordPress default custom metabox will ignore them and not show in WordPress default GUI, but you can use and display them in your own custom metaboxes by calling with there new Underscore prefixed names.

Add input field to every item in cart

I am trying to add a new field on my cart.php file.
I actually want to insert a URL field, so user can set a URL for each order item.
I tried to use a code from another post here but I can't get it to work.
The first and the second functions are working but when it comes to the third one, 'woocommerce_get_item_data' the $cart_item['url'] doesn't contain anything even if I add something in the field and I press Update Cart.
$cart_totals[ $cart_item_key ]['url'] from the first function is outputting the right value when the page load.
I don't know what to do now, thanks for any help.
Here is the code
Add the field
cart/cart.php
<td class="product-url">
<?php
$html = sprintf( '<div class="url"><input type="text" name="cart[%s][url]" value="%s" size="4" title="Url" class="input-text url text" /></div>', $cart_item_key, esc_attr( $values['url'] ) );
echo $html;
?>
</td>
functions.php
// get from session your URL variable and add it to item
add_filter('woocommerce_get_cart_item_from_session', 'cart_item_from_session', 99, 3);
function cart_item_from_session( $data, $values, $key ) {
$data['url'] = isset( $values['url'] ) ? $values['url'] : '';
return $data;
}
// this one does the same as woocommerce_update_cart_action() in plugins\woocommerce\woocommerce-functions.php
// but with your URL variable
// this might not be the best way but it works
add_action( 'init', 'update_cart_action', 9);
function update_cart_action() {
global $woocommerce;
if ( ( ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) ) {
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
if ( isset( $cart_totals[ $cart_item_key ]['url'] ) ) {
$woocommerce->cart->cart_contents[ $cart_item_key ]['url'] = $cart_totals[ $cart_item_key ]['url'];
}
}
}
}
}
// this is in Order summary. It show Url variable under product name. Same place where Variations are shown.
add_filter( 'woocommerce_get_item_data', 'item_data', 10, 2 );
function item_data( $data, $cart_item ) {
if ( isset( $cart_item['url'] ) ) {
$data['url'] = array('name' => 'Url', 'value' => $cart_item['url']);
}
return $data;
}
// this adds Url as meta in Order for item
add_action ('woocommerce_add_order_item_meta', 'add_item_meta', 10, 2);
function add_item_meta( $item_id, $values ) {
woocommerce_add_order_item_meta( $item_id, 'Url', $values['url'] );
}
Add a textarea field to a WooCommerce cart item
First, we just need to add the textarea field. We use the woocommerce_after_cart_item_name hook so our textarea will appear after the product name.
<?php
/**
* Add a text field to each cart item
*/
function prefix_after_cart_item_name( $cart_item, $cart_item_key ) {
$notes = isset( $cart_item['notes'] ) ? $cart_item['notes'] : '';
printf(
'<div><textarea class="%s" id="cart_notes_%s" data-cart-id="%s">%s</textarea></div>',
'prefix-cart-notes',
$cart_item_key,
$cart_item_key,
$notes
);
}
add_action( 'woocommerce_after_cart_item_name', 'prefix_after_cart_item_name', 10, 2 );
/**
* Enqueue our JS file
*/
function prefix_enqueue_scripts() {
wp_register_script( 'prefix-script', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'update-cart-item-ajax.js', array( 'jquery-blockui' ), time(), true );
wp_localize_script(
'prefix-script',
'prefix_vars',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
)
);
wp_enqueue_script( 'prefix-script' );
}
add_action( 'wp_enqueue_scripts', 'prefix_enqueue_scripts' );
´´´
At the moment, the user will be able to enter text into the field but the text won’t save. We are going to use some AJAX to save the text.
The code above not only adds the textarea to the cart item, it also enqueues a JavaScript file ready for our AJAX.
It’s assumed that you’re using the code on this page to create a new plugin. If so, you should create a new JS file with the code below and place the file in the root directory of your plugin.
However, if you’ve added the PHP above to your theme functions.php or as a snippet on your site, you’ll need to change the location of the JS file by updating line 21 of the snippet above to identify the location of the JS file.
´´´
(function($){
$(document).ready(function(){
$('.prefix-cart-notes').on('change keyup paste',function(){
$('.cart_totals').block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
var cart_id = $(this).data('cart-id');
$.ajax(
{
type: 'POST',
url: prefix_vars.ajaxurl,
data: {
action: 'prefix_update_cart_notes',
security: $('#woocommerce-cart-nonce').val(),
notes: $('#cart_notes_' + cart_id).val(),
cart_id: cart_id
},
success: function( response ) {
$('.cart_totals').unblock();
}
}
)
});
});
})(jQuery);
´´´
Now, when the user types anything, the contents of the text field get sent back to the server ready to be saved as meta data to the cart item.
´´´
<?php
/**
* Update cart item notes
*/
function prefix_update_cart_notes() {
// Do a nonce check
if( ! isset( $_POST['security'] ) || ! wp_verify_nonce( $_POST['security'], 'woocommerce-cart' ) ) {
wp_send_json( array( 'nonce_fail' => 1 ) );
exit;
}
// Save the notes to the cart meta
$cart = WC()->cart->cart_contents;
$cart_id = $_POST['cart_id'];
$notes = $_POST['notes'];
$cart_item = $cart[$cart_id];
$cart_item['notes'] = $notes;
WC()->cart->cart_contents[$cart_id] = $cart_item;
WC()->cart->set_session();
wp_send_json( array( 'success' => 1 ) );
exit;
}
add_action( 'wp_ajax_prefix_update_cart_notes', 'prefix_update_cart_notes' );
function prefix_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
foreach( $item as $cart_item_key=>$cart_item ) {
if( isset( $cart_item['notes'] ) ) {
$item->add_meta_data( 'notes', $cart_item['notes'], true );
}
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'prefix_checkout_create_order_line_item', 10, 4 );
´´´
The prefix_update_cart_notes function does a security check using the WooCommerce cart nonce then saves the content of the textarea as meta data in the cart item. You can check out this article for more information about updating cart meta for items that have already been added to the cart.
Add the custom text to the order meta
Finally, we want to pass our meta data to the order so that we can use it after the customer has checked out. The prefix_checkout_create_order_line_item function takes care of that, iterating through each item and saving notes when it finds them.
https://pluginrepublic.com/how-to-add-an-input-field-to-woocommerce-cart-items/

how to add a meta box to wordpress pages

i want to make this code for pages
add_action( 'add_meta_boxes', 'meta_box_video' );
function meta_box_video()
{
add_meta_box( 'video-meta-box-id', 'Video Embed', 'meta_box_callback', 'post', 'normal', 'high' );
}
function meta_box_callback( $post )
{
$values = get_post_custom( $post->ID );
$selected = isset( $values['meta_box_video_embed'] ) ? $values['meta_box_video_embed'][0] : '';
wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );
?>
<p>
<label for="meta_box_video_embed"><p>Video Embed</p></label>
<textarea name="meta_box_video_embed" id="meta_box_video_embed" cols="62" rows="5" ><?php echo $selected; ?></textarea>
</p>
<p>Leave it Empty ( if you want to use an image thumbnail ) .</p>
<?php
}
add_action( 'save_post', 'meta_box_video_save' );
function meta_box_video_save( $post_id )
{
// Bail if we're doing an auto save
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// if our nonce isn't there, or we can't verify it, bail
if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
// if our current user can't edit this post, bail
if( !current_user_can( 'edit_post' ) ) return;
// now we can actually save the data
$allowed = array(
'a' => array( // on allow a tags
'href' => array() // and those anchords can only have href attribute
)
);
// Probably a good idea to make sure your data is set
if( isset( $_POST['meta_box_video_embed'] ) )
update_post_meta( $post_id, 'meta_box_video_embed', $_POST['meta_box_video_embed'] );
}
This:
function meta_box_video()
{
add_meta_box( 'video-meta-box-id', 'Video Embed', 'meta_box_callback', 'post', 'normal', 'high' );
}
Should specify page not post.
function meta_box_video()
{ // --- Parameters: ---
add_meta_box( 'video-meta-box-id', // ID attribute of metabox
'Video Embed', // Title of metabox visible to user
'meta_box_callback', // Function that prints box in wp-admin
'page', // Show box for posts, pages, custom, etc.
'normal', // Where on the page to show the box
'high' ); // Priority of box in display order
}
Take a look at the Codex for add_meta_box(). The examples are very helpful. The portion you are interested in is under "Parameter". The fourth parameter allows you to specify whether you want the metabox on pages, posts, etc.

Resources