We have a website for orders that are then delivered. Now the thing is we want to utilize the details from the My Account Address Billing as the address to ship to, on checkout we want this populated from what's there but not allow the user to make any changes on that check out page Billing form.
This code:
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();;
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
if($key == 'billing_address_1' || $key == 'billing_address_2'){
$key_value = get_user_meta($user_id, $key, true);
if( strlen($key_value)>0){
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
Only makes the Address part not be changed however everything else from first name, last name, cellphone, etc is able to be modified.
We need all those fields to be locked just as that code as locked the Address field to read-only.
You can remove if($key == 'billing_address_1' || $key == 'billing_address_2'){ this line all fields. check beloe code.
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
$key_value = get_user_meta($user_id, $key, true);
if( $key_value != '' ){
if( $key == 'billing_country' || $key == 'billing_state' || $key == 'billing_suburb' ){
$checkout_fields['billing'][$key]['custom_attributes'] = array('disabled'=>'disabled');
}else{
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
For billing_country, billing_state and billing_suburb, you have to pass value in hidden because the select dropdown disabled the option value is not passed when you click place order and in order to solve this issue we can add hidden fields with our value.
add_action('woocommerce_after_order_notes', 'billing_countryand_state_hidden_field');
function billing_countryand_state_hidden_field($checkout){
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
echo '<input type="hidden" class="input-hidden" name="billing_country" value="'.get_user_meta($user_id, 'billing_country', true).'">';
echo '<input type="hidden" class="input-hidden" name="billing_state" value="'.get_user_meta($user_id, 'billing_state', true).'">';
echo '<input type="hidden" class="input-hidden" name="billing_suburb" value="'.get_user_meta($user_id, 'billing_suburb', true).'">';
}
Tested and works
Related
Currently I have billing address set to read only using the following code but I need to add customer first & last name to the read only too. I'm placing this in my theme functions.php file
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();;
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
if($key == 'billing_address_1' || $key == 'billing_address_2'){
$key_value = get_user_meta($user_id, $key, true);
if( strlen($key_value)>0){
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
Add this code in function.php file
add_filter('woocommerce_billing_fields', 'my_woocommerce_billing_fields');
function my_woocommerce_billing_fields($fields)
{
$fields['billing_first_name']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_last_name']['custom_attributes'] = array('readonly'=>'readonly');
return $fields;
}
I would like to prevent (make these fields readonly, for example) users from changing their billing information on the WooCommerce checkout form.
I'm currently using this code snippet:
add_filter('woocommerce_billing_fields', 'mycustom_woocommerce_billing_fields', 10, 1 );
function mycustom_woocommerce_billing_fields($fields)
{
$fields['billing_first_name']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_last_name']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_email']['custom_attributes'] = array('readonly'=>'readonly');
$fields['billing_phone']['custom_attributes'] = array('readonly'=>'readonly');
return $fields;
}
But the problem is: If the user has not filled in any of these fields in the registration, he is unable to insert his data in the checkout form because these fields are not editable.
My question is:
If the fields are not empty, how to make them readonly (or disabled)
Someone who can help me with this?
The answer of 7uc1f3r certainly works getting the user data… But since WooCommerce 3, you can use WC_Checkout get_value() dedicated method as follow:
add_filter( 'woocommerce_billing_fields', 'filter_wc_billing_fields', 10, 1 );
function filter_wc_billing_fields( $fields ) {
// On checkout and if user is logged in
if ( is_checkout() && is_user_logged_in() ) {
// Define your key fields below
$keys_fields = ['billing_first_name', 'billing_last_name', 'billing_email', 'billing_phone'];
// Loop through your specific defined fields
foreach ( $keys_fields as $key ) {
// Check that a value exist for the current field
if( ( $value = WC()->checkout->get_value($key) ) && ! empty( $value ) ) {
// Make it readonly if a value exist
$fields[$key]['custom_attributes'] = ['readonly'=>'readonly'];
}
}
}
return $fields;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
If you want this code to be also active in My account > Addresses > edit…, you will just have to remove is_checkout() && from the first IF statement.
I believe this is what you are looking for, comment with explanation added in code
function mycustom_woocommerce_billing_fields( $fields ) {
// Get current user
$user = wp_get_current_user();
// User id
$user_id = $user->ID;
// User id is found
if ( $user_id > 0 ) {
// Fields
$read_only_fields = array ( 'billing_first_name', 'billing_last_name', 'billing_email', 'billing_phone' );
// Loop
foreach ( $fields as $key => $field ) {
if( in_array( $key, $read_only_fields ) ) {
// Get key value
$key_value = get_user_meta($user_id, $key, true);
if( strlen( $key_value ) > 0 ) {
$fields[$key]['custom_attributes'] = array(
'readonly'=>'readonly'
);
}
}
}
}
return $fields;
}
add_filter('woocommerce_billing_fields', 'mycustom_woocommerce_billing_fields', 10, 1 );
I need to check the value of the billing_state equals to "xyz" on validation. and display the value in the "woocommerce_review_order_before_submit".
add_action( 'woocommerce_review_order_before_submit', 'messageonstate' );
function messageonstate() {
echo $fields['billing']['billing_state']['value'];
echo $_POST['_billing_state'];
echo"====+++++";
foreach( $checkout_fields as $key_field => $field_value ){
if( $input == $key_field && ! empty( $field_value ) ){
echo $value = $field_value;
}
}
}
The required code to for the display in review order before submit area is:
add_action( 'woocommerce_review_order_before_submit', 'review_order_before_submit_state_message' );
function review_order_before_submit_state_message() {
// HERE set your state code
$state_code = 'CA';
if( $selected_state_code = WC()->customer->get_billing_state() ){
$country_code = WC()->customer->get_billing_country();
$state_name = WC()->countries->get_states($country_code)[$state_code];
if( WC()->customer->get_billing_state() === $state_code ){
$message = "The billing state <strong>".$state_name."<strong> matches";
echo '<ul class="woocommerce-info">'.$message.'</ul>';
} else {
$message = "The billing state <strong>".$state_name."<strong> don't matches";
echo '<ul class="woocommerce-alert">'.$message.'</ul>';
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Note: Fields validation in Woocommerce to avoid checkout is handled differently.
I want country dropdown on woocommerce as readonly.
I already set the default country to australia but I want them to be readonly.
The answer of Kashalo is correct… You can also use one of this multiple other ways:
1) For Checkout Billing country only:
add_filter('woocommerce_checkout_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
// Make billing country field read only
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
2) For Checkout and My account Billing country only:
add_filter('woocommerce_billing_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
// Make billing country field read only
$fields['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
3 For Checkout billing and shipping country:
add_filter('woocommerce_checkout_fields', 'readdonly_country_select_field');
function readdonly_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
WC()->customer->set_shipping_country('AU');
// Make billing and shipping country field read only
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
$fields['shipping']['shipping_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
4) For Checkout and My account billing and shipping country:
add_filter('woocommerce_default_address_fields', 'readdonly_country_select_field');
function readdonly_country_select_field( $fields ) {
// Set billing and shipping country to AU
WC()->customer->set_billing_country('AU');
WC()->customer->set_shipping_country('AU');
// Make country field read only
$fields['country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
you can use woocommerce_form_field_args to add disabled attribute to the quntry select field.
add the following code to your functions.php and you will get the desired result.
add_action('woocommerce_form_field_args', 'disable_country_dropdown', 10, 3);
function disable_country_dropdown($args, $key, $value)
{
if ($key == 'billing_country') {
$args['custom_attributes'] = [
'disabled' => 'disabled',
];
}
return $args;
}
the issue when we puted the select drowpdown disabled the option value is not passed when you click place order and in order to solve this issue we can add hidden field with our desired value as follow:
add_action('woocommerce_after_order_notes', 'billing_country_hidden_field');
function billing_country_hidden_field($checkout)
{
echo '<input type="hidden" class="input-hidden" name="billing_country" value="PL">';
}
just change the value="PL" to your country code value and everything will work as expected.
OutPut :
Code is tested with StorrFront Theme.
/*CHECKOUT BILLING ADDRESS READ ONLY*/
add_action('woocommerce_checkout_fields','customization_readonly_billing_fields',10,1);
function customization_readonly_billing_fields($checkout_fields){
$current_user = wp_get_current_user();;
$user_id = $current_user->ID;
foreach ( $checkout_fields['billing'] as $key => $field ){
if($key == 'billing_company' || $key == 'billing_address_1' || $key == 'billing_address_2' || $key == 'billing_city' || $key == 'billing_postcode' || $key == 'billing_phone' || $key == 'invoice_email' || $key == 'purchase_order' || $key == 'ship_to_first_name' || $key == 'ship_to_last_name'){
$key_value = get_user_meta($user_id, $key, true);
if( strlen($key_value)>0){
$checkout_fields['billing'][$key]['custom_attributes'] = array('readonly'=>'readonly');
}
}
}
return $checkout_fields;
}
if ( is_user_logged_in() ) {
// your code for logged in user
add_filter('woocommerce_checkout_fields', 'readdonly_billing_country_select_field');
function readdonly_billing_country_select_field( $fields ) {
$fields['billing']['billing_country']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
add_filter('woocommerce_checkout_fields', 'readdonly_billing_state_select_field');
function readdonly_billing_state_select_field( $fields ) {
$fields['billing']['billing_state']['custom_attributes'] = array( 'disabled' => 'disabled' );
return $fields;
}
} else {
// your code for logged out user
}
I'm wondering if someone could help me. I'm trying to save the value of only the checked checkboxes in a wordpress metabox to the database as an array. So far, I've been able to save each of them as individual columns but I'd like to compile them into only one array, and when the checkbox is unclick, I'd like to update_post_meta to remove just the unclicked one. For some reason, it all keeps getting overridden.
The code I'm using that keeps saving them individually:
function save_location_meta($post_id) {
global $location_meta_fields;
// verify nonce
if (!isset($_POST['location_meta_box_nonce']) || !wp_verify_nonce($_POST['location_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;
}
// loop through fields and save the data
foreach ($location_meta_fields as $field) {
$old = get_post_meta($post_id, $field['id'], true);
$new = $_POST[$field['id']];
if($new == '' && !$old && array_key_exists('default',$field)){
$new = $field['default'];
}
if ($new != '' && $new != $old) {
update_post_meta($post_id, $field['id'], $new);
} elseif ($new == '' && $old != '') {
$post_users = get_weekly_stats( $post_id, $field['id'], $old );
$uid_key = array_search( $field['id'], $post_users);
unset( $post_users[$uid_key] );
update_post_meta( $post_id, "_test_one", $uid_key );
update_post_meta( $post_id, "test", $post_users );
delete_post_meta($post_id, $field['id'], $old);
}
} // end foreach
}
add_action('save_post', 'save_location_meta');
The metabox callback that displays the checkboxes:
function one_callback( $post ) {
global $location_meta_fields, $post;
// Use nonce for verification
echo '<input type="hidden" name="location_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';
// Begin the field table and loop
echo '<table class="form-table">';
foreach ($location_meta_fields as $field) {
// get value of this field if it exists for this post
$meta = get_post_meta($post->ID, $field['id'], true);
// begin a table row with
echo '<tr>
<td>';
echo '<input type="checkbox" name="'.$field['id'].'" id="'.$field['id'].'" ',$meta ? ' checked="checked"' : '','/>
<label for="'.$field['id'].'">'.$field['label'].'</label>';
echo '</td></tr>';
} // end foreach
echo '</table>'; // end table
}
My question: How do I save the checked values in one array as opposed to one for each checked value?
You need to write the names of the inputs with "[]", then PHP will treat the saved values as array.
function one_callback( $post ) {
global $location_meta_fields, $post;
// Use nonce for verification
echo '<input type="hidden" name="location_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';
// Begin the field table and loop
echo '<table class="form-table">';
foreach ($location_meta_fields as $field) {
// get value of this field if it exists for this post
$meta = get_post_meta($post->ID, $field['id'], true); ?>
<tr>
<td>
<input type="checkbox" name="fields[]" value="<?php echo $field['id']; ?>" id="<?php echo $field['id']; ?>" <?php checked($meta); ?>/>
<label for="<?php echo $field['id']; ?>"><?php echo $field['label']; ?></label>';
</td>
</tr>
<?php } // end foreach
echo '</table>'; // end table
}
So if you want for example to access the first value that was checked, you can do it like this $_POST['fields'][0].
Then in your function save_location_meta(), you don't need to loop over the fields, you can just save them as array to the DB like this:
update_post_meta($post_id, 'my-fields', $_POST['fields']);