WooCommerce drop-down postcode / Zip with (space) or ( _ ) or ( - )? - php

I am building my website. I have a WooCommerce plugin installed and the country I live in it doesn't have postcode or zip. So to calculate the shipping I use districts. I am adding all districts as a dropdown in the cart page in (calculate shipping) area and checkout page. below the code for checkout page
function custom_override_default_postcode_field( $address_fields ) {
// Your postcodes array
$postcode_array = array(
'ALMOHAMMDIAH' => "ALMOHAMMDIAH",
'ALNAEEM' => "ALNAEEM",
'ALZAHRRA' => "ALZAHRRA"
);
$address_fields['postcode']['type'] = 'select';
$address_fields['postcode']['options'] = $postcode_array;
return $address_fields;
}
and adding the district in cart page in (calculate shipping) area code below
'woocommerce_shipping_calculator_enable_postcode', true ) ) : ?>
<p class="form-row form-row-wide" id="calc_shipping_postcode_field">
<?php
// HERE <===== define your array of cities
$postcodes = array('ALMOHAMMDIAH','ALNAEEM','ALZAHRRA');
$current_postcode = esc_attr( WC()->customer->get_shipping_postcode() );
?>
<select name="calc_shipping_postcode" id="calc_shipping_postcode">
<option value=""><?php _e( 'Select a District…', 'woocommerce' ); ?></option>
<?php foreach( $postcodes as $postcode ):
echo '<option value="'.$postcode.'" '.selected( $current_postcode, $postcode ).'>'.$postcode.'</option>';
endforeach; ?>
</select>
</p>
then I change the postcode / ZIP to districts by this core below
function my_text_strings( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Postcode / ZIP' :
$translated_text = __( 'District', 'woocommerce' );
break;
}
return $translated_text;
}
add_filter( 'gettext', 'my_text_strings', 20, 3 );
All the code above I found them online and changed some text and they are working.
The problem now is that the postcode in WooCommerce backend forces me to use all caps. Some districts must have spaces and I need to do that but I can't figure it out. How can I make the postcode in the backend accept spaces or at least - or _ ?
like ( AL MOHAMMDIAH or AL-MOHAMMDIAH ) instead of (ALMOHAMMDIAH)
btw the codes above I caps all districts so the calculation works. If I added space, _ or - it brock and nothing shows.

There is no easy fix. It would require editing core files and it should never be done if possible. ALL postcode data is sent through the 'cleaning' process, which removes all unwanted data in normal use cases (also made uppercase). There are no filters to stop it.
Now to a solution. There is no simple solution. The best way would be to make a small plugin, which would add field district and remove postcode, but only for your country. Then apply shipping logic to get prices etc. An alternative is to just ignore spaces and live without them, or replace the district names with something else.

What I did to make this work is I changed the state/Country field to be districts and hide the ZIP code. its working fine so far the only downside is the district name comes after the city. I guess its no big deal in the country where I live in
/* district added as state/Country for shipping purposes */
add_filter('woocommerce_states', 'add_custom_states_to_country');
add_filter('woocommerce_countries_allowed_country_states', 'add_custom_states_to_country');
function add_custom_states_to_country( $states ) {
$states['SA'] = array(
'JOR' => __('Abruq-Ar-Rughamah', 'woocommerce'),
'JAL' => __('Al-Adel', 'woocommerce'),
'JAJ' => __('Al-Ajaweed', 'woocommerce'),
'JAD' => __('Al-Ajwad', 'woocommerce'),
'JAW' => __('Al-Amwaj', 'woocommerce'),
'JAS' => __('Al-Andalus', 'woocommerce'),
'JAH' => __('Al-Asalah', 'woocommerce'),
'JZZ' => __('Al-Aziziyah', 'woocommerce'),
'JBH' => __('Al-Baghdadiyah', 'woocommerce'),
);
return $states;
}
and changed the text to districts
add_filter( 'woocommerce_default_address_fields' , 'bbloomer_override_postcode_validation' );
function bbloomer_override_postcode_validation( $address_fields ) {
unset($address_fields['company']); /* remove company */
unset($address_fields['postcode']); /* remove zip */
/*$address_fields['postcode']['required'] = false;*/ /* postcode req */
$address_fields['state']['required'] = true; /* state required */
$address_fields['state']['label'] = __('District'); /* state name to dist */
return $address_fields;
}
I hope this is useful for someone somewhere.

Related

Display last WooCommerce note to customer in My Account Order Page

This is my current recent order
I wish to add another column "Tracking Number" and it will show woocommerce "note to customer" inside.
result is like : Display last WooCommerce admin order note in customers order history
The difference is without clicking view order and my customer can get to known their tracking number.
But I totally no idea how this work because not familiar with php..
hope to make this done and learn something.
Thanks!
the result will
You Need to create a new column in My order page first
function order_note_in_column( $columns ) {
$new_columns = array();
foreach ( $columns as $key => $name ) {
$new_columns[ $key ] = $name;
// Your Column Name : Change Tracking Number with the Column Heading you Want
if ( 'order-status' === $key ) {
$new_columns['track-number'] = __( 'Tracking Number', 'textdomain' );
}
}
return $new_columns;
}
add_filter( 'woocommerce_my_account_my_orders_columns', 'order_note_in_column' );
Once you create a new column now the second step is to display Data in the column.keep type as internal to show private note, In this way customer notes will not be displayed at frontend
function order_note_value_in_column( $order ) {
//Get Notes by order ID & Here keep type as internal to show private note. In this way customer notes will not be displayed at frontend
$note = wc_get_order_notes([
'order_id' => $order->get_id(),
'type' => 'internal',
]);
// Displaying the latest Note. If no tracking number entered then order status will be displayed in column
print_r($note[0]->content);
}
add_action( 'woocommerce_my_account_my_orders_column_track-number', 'order_note_value_in_column' );
code goes in functions.php tested & works

Get custom Fields from registration to Woocommerce Checkout

Hi i am using a plugin to allow employers to register and post jobs. In the registration I have created custom fields they are also in the admin and in the Profile (VAT IDs they I need for billing). I can automaticaly fill and save them also update in the Profile or admin back-end. But I have to include them in the billing fields (not so important where maybe after company name) where they are generated into the invoice. I am not a programmer I only know html and css little bit. I am trying now for 12 hours and no chance to get it there.
I would also like to make them not-editable from user profile.
This are my fields saved in the child-theme functions.php I have done this with the help from Plugin author but he will not help me more because of no support. Plugin guide
add_action('iwj_employer_form_after_general',function ($job){
$post_id = $job ? $job->get_id() : '';
?>
<?php
iwj_field_text( '_ico_company', 'IČO spoločnosti*', true, $post_id, null, 'true', '', __( '' ) );
?>
<?php
});
add_action('iwj_admin_employer_form_after_general',function ($post_id){
?>
<?php
iwj_field_text( '_ico_company', 'IČO spoločnosti*', true, $post_id, null, 'true', '', __( '' ) );
?>
<?php
});
add_action('save_post', function($post_id){
if($post_id && get_post_type($post_id) == 'iwj_employer'){
$custom_field_value = sanitize_text_field($_POST['_ico_company']);
update_post_meta($post_id, '_ico_company', $custom_field_value);
}
}, 99);
add_action('iwj_register_process', function($uid){
$user = IWJ_User::get_user($uid);
$post_id = 0;
if($user->is_employer()){
$emp = $user->get_employer();
$post_id = $emp->get_id();
}
if($post_id){
//Add you custom field name process here
update_post_meta($post_id, '_ico_company', sanitize_text_field($_POST['_ico_company']));
}
});
I would be mega happy if someone could help me out with this :)
This will help you to have the fields in the checkout. I added a mock function get_vat_field, because I don't know yet how you are going to get the VAT field in the checkout.
Generally, it adds an additional field to the checkout, and when the checkout is completed, it adds it to the order. Which then is displayed in the order meta of the order. You can find that in the order itself in the admin panel (order edit page).
Simply add this to your functions.php of your child theme.
// Our hooked in function – $fields is passed via the filter!
function add_vat_to_checkout_fields( $fields ) {
$fields['billing']['vat'] = array(
'type' => 'text',
'label' => __('VAT', 'woocommerce'),
'placeholder' => _x('VAT', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide hidden'),
'clear' => true,
'value' => get_vat_field('') // this is the function that gets the field from the user account or job post.
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('VAT').':</strong> ' . get_post_meta( $order->get_id(), 'vat', true ) . '</p>';
}

Woocommerce sending array index as value on order submission

I have been trying to add a custom 'select' field to a woocommerce checkout. The select options are comprised of entries in an array, which in turn is comprised of titles and dates from a query of custom post types.
This all works fine, I can add new custom posts and the title and dates are concatenated, added to the array and in turn added to the select drop-down at the checkout, however when I submit the form and complete the order the index of the chosen select field value is added to the meta data, not the value.
I have added images in here to show you what I mean. e.g. if I select the third option from the dropdown 'Tain Farmers Market' which is array index 2 that's what is saved for the order meta instead of the value at that index entry.
The screenshot includes the results of the var dump showing the array contents as well as the select field below it.
image of how the array appears in var dump
the order meta showing in the admin screen, displaying the index not the value
Here is my code covering this section, any pointers would be really handy. I feel there is probably some simple solution to get the value at the chosen index when the order is processed?
/**
* Add custom Pickup Field field to the checkout page
*/
add_filter( 'woocommerce_after_order_notes', 'hiwoo_add_checkout_fields' );
function hiwoo_add_checkout_fields( $checkout ) {
$args = array(
'post_type' => 'pickup-point',
'posts_per_page' => -1,
'post_status' => 'publish'
);
// Custom query to pull in the pickup points.
$query = new WP_Query( $args );
$pickup_comb_option = [];
while ($query->have_posts()) {
$query->the_post();
$postid = $post->ID;
$pickuptitle = get_the_title($post);
$pickupdate = get_post_meta(get_the_id($post), 'available_date', true);
$pickupoption = $pickuptitle . ' - ' . $pickupdate;
array_push($pickup_comb_option, $pickupoption);
}
var_dump($pickup_comb_option);
// Restore original post data.
wp_reset_postdata();
echo '<div id="custom_checkout_field"><h2>' . __('Order Pickup Location/Date') . '</h2>';
woocommerce_form_field( 'pickup_point_options', array(
'type' => 'select',
'class' => array(
'my-field-class form-row-wide'
) ,
'label' => __('Select Pickup Location/Date') ,
'placeholder' => __('Pickup Point') ,
'options' => $pickup_comb_option,
),
$checkout->get_value( 'pickup_point_options' ));
echo '</div>';
} /* Close custom field function */
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['pickup_point_options'] )
wc_add_notice( __( 'Please select a pickup location from the list.' ), 'error' );
}
/**
* Update the order meta with field value
*/
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['pickup_point_options'] ) ) {
update_post_meta( $order_id, 'Pickup Location/Date', sanitize_text_field( $_POST['pickup_point_options'] ) );
}
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Pickup Location/Date').':</strong> ' . get_post_meta( $order->id, 'Pickup Location/Date', true ) . '</p>';
}
The html produced on the checkout page for the select field is:
array(3) {
[0]=>
string(32) "Tain Farmers Market - 2019-12-25"
[1]=>
string(30) "Hi Create Offices - 2019-10-25"
[2]=>
string(27) "Dornoch Stores - 2019-09-26"
}
<select name="pickup_point_options" id="pickup_point_options" class="select " data-placeholder="Pickup Point">
<option value="0">Tain Farmers Market - 2019-12-25</option>
<option value="1">Hi Create Offices - 2019-10-25</option>
<option value="2">Dornoch Stores - 2019-09-26</option>
</select>
According to your HTML I assume the value being saved in your example is "2" instead of "Tainy Farmers Market", right? If so, that is technically correct, as the value of a <select> being submitted on a form submit is always the value in the option's value attribute (<option value="2">) and not the text in between (<option value="2">Some text</option>)
To have it saving the text in between it has to be set inside the value-attribute. Therefor you need to change the option's array from numeric to associative, like so:
$pickup_comb_option = [];
while ($query->have_posts()) {
$query->the_post();
// ...
// change this line
array_push($pickup_comb_option, $pickupoption);
// to:
$pickup_comb_option[$pickupoption] = $pickupoption;
}
To verify this worked check for the generated HTML, it should look something like this:
<select>
<option value="Tain Farmers Market">Tain Farmers Market</option>
</select>
#edit
I should mention this approach has some downsides:
You should ensure that the string in $pickupoption is not used multiple times. It's also necessary that the string is valid for use as an array key (not NULL, not empty). Since the value is being written inside a html-attribute (value="$arrKey") you may also want to check how Woocommerce handle's such things as doublequotes inside the string. Just to avoid possible bugs beforehand.
An alternative approach could be to save an id instead of a string.

Get list of CITIES from Shipping rates based on city

So, I was following this example on How to change the city field to a dropdown by Jeroen in my Billing/Shipping section of my site.
/**
* Change the checkout city field to a dropdown field.
*/
function city_to_dropdown( $fields ) {
$city_args = wp_parse_args( array(
'type' => 'select',
'options' => array(
'amsterdam' => 'Amsterdam',
'rotterdam' => 'Rotterdam',
'den-haag' => 'Den Haag',
'utrecht' => 'Utrecht',
'leiden' => 'Leiden',
'groningen' => 'Groningen',
),
), $fields['shipping']['shipping_city'] );
$fields['shipping']['shipping_city'] = $city_args;
$fields['billing']['billing_city'] = $city_args; // Also change for billing field
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'city_to_dropdown' );
Everything works as expected, but here is what I want to do different.
I want to be able to query all the list of cities from the from shipping rates based on city and display them in the dropdown code above.
So then I wouldn’t have to add the cities manually in multiple places. My list of cities will always be the cities added in using the shipping rates based on city functionality.
What do I need to do to be able to remove the manually entered cities and have something similar to the following :
‘options’ => get_list_cities_from_shipping_rate(),
Question :
What filters or hooks in woocommerce do I have to call to be able to return the list of cities in my function get_list_cities_from_shipping_rate() ?
I'm new to writing these custom codes in wordpress. Any help pointers on how to get this started would be appreciated.
Thank you in advance
Try this:
function get_list_cities_from_shipping_rate( $rate_id ) {
$cities = '';
$key = '_wafs_shipping_method_conditions';
$conditions = get_post_meta( $rate_id, $key, true );
foreach ( (array) $conditions as $group ) {
foreach ( (array) $group as $cond ) {
if ( ! isset( $cond['condition'] ) ) {
continue;
}
if (
'city' === $cond['condition'] &&
'==' === $cond['operator']
) {
$cities .= $cities ? ', ' : '';
$cities .= $cond['value'];
}
}
}
$cities = preg_split( '/, */', $cities );
return array_unique( array_filter( $cities ) );
}
Things to note:
On the WooCommerce → Settings → Advanced Free Shipping page, the $rate_id is the one after the post= as in http://example.com/wp-admin/post.php?post=123&action=edit. Hover on the Free shipping rates table rows and you'd see the Edit URL having that post query.
You must use the city's name and not its slug. E.g. Den Haag instead of den-haag. See the image you provided.

Drop down of auto values country/state/city WooCommerce storefront

I am looking for a drop down of country/state/city. I am getting country state auto populated, but cities are not going through well. By default, I am able to get the countries.
// State-Country additions
/**
* Code goes in functions.php or a custom plugin.
*/
add_filter('woocommerce_states', 'SA_woocommerce_states');
function SA_woocommerce_states($states) {
$states['ZA'] = array(
'EC' => __('Eastern Cape', 'woocommerce'),
);
return $states;
}
// Change "city" checkout billing and shipping fields to a dropdown
add_filter('woocommerce_checkout_fields', 'override_checkout_city_fields');
function override_checkout_city_fields($fields) {
// Define here in the array your desired cities (Here an example of cities)
$option_cities = array(
'' => __('Select your city'),
'a' => 'a',
);
$fields['billing']['billing_city']['type'] = 'select';
$fields['billing']['billing_city']['options'] = $option_cities;
$fields['shipping']['shipping_city']['type'] = 'select';
$fields['shipping']['shipping_city']['options'] = $option_cities;
return $fields;
}
With your actual code you are replacing all existing states of "South Africa" (ZA) by one state. So you are getting something like:
To add this state you should need to change your code a little bit this way:
add_filter('woocommerce_states', 'sa_woocommerce_states');
add_filter('woocommerce_countries_allowed_country_states', 'sa_woocommerce_states');
function SA_woocommerce_states( $states ) {
$states['ZA']['EC'] = __('Eastern Cape', 'woocommerce');
return $states;
}
The code goes in the function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works. You will get that instead this time:
Now to get the cities auto populated you should use this:
add_filter( 'woocommerce_default_address_fields', 'override_checkout_city_fields', 10, 1 );
function override_checkout_city_fields($fields) {
// Define here in the array your desired cities (Here an example of cities)
$option_cities = array(
'' => __( 'Select your city' ),
'a' => 'a',
);
$fields['city']['type'] = 'select';
$fields['city']['options'] = $option_cities;
return $fields;
}
The code goes in the function.php file of your active child theme (or theme) or also in any plugin file.
It was tested ad worked…
But you will not get cities by states as this is a real development and too broad for Stack Overflow

Categories