Is there a way to add a default shipping class to all products? I have one shipping class and need an automated way to add that class to all products when they are created vs. having to constantly add the shipping class.
Many solutions
There is two solutions :
First add the term dynamically before the cart totals (add to your functions.php)
add_action('woocommerce_before_calculate_totals' , 'add_shipping_terms_before_totals' , 10, 1);
function add_shipping_terms_before_totals(WC_Cart $wc_cart){
if( count($wc_cart->get_cart()) == 0 ){
return;
}
// Here you need to edit the slug_to_edit with your custom slug
$shipping_terms = get_term_by( 'slug', 'slug_to_edit', 'product_shipping_class' );
// If can't find the terms, return
if( empty($shipping_terms) ){
return;
}
foreach( $wc_cart->get_cart() as $item){
$product = new WC_Product( $item['product_id'] );
$product_shipping_class = $product->get_shipping_class();
if( !empty($product_shipping_class) ){
continue;
}
wp_set_post_terms( $product->id, array( $shipping_terms->term_id ), 'product_shipping_class' );
}
}
Or, you can add a function that you can manually trigger when you add a products :
if( isset($_GET['update_products']) && is_super_admin() ){
add_action( 'init', 'add_shipping_terms_on_all_products' );
}
function add_shipping_terms_on_all_products(){
global $wpdb;
// Here you need to edit the slug_to_edit with your custom slug
$shipping_terms = get_term_by( 'slug', 'slug_to_edit', 'product_shipping_class' );
// If can't find the terms, return
if( empty($shipping_terms) ){
return;
}
// Request all product
$products = $wpdb->get_results( "
SELECT p.ID as ID
FROM wp_posts AS p
WHERE p.post_status = 'publish'
AND p.post_type = 'product'
" );
foreach($products as $_product){
$product = new WC_Product($_product->ID);
$product_shipping_class = $product->get_shipping_class();
if( !empty($product_shipping_class) ){
continue;
}
wp_set_post_terms( $product->id, array( $shipping_terms->term_id ), 'product_shipping_class' );
}
}
Then you just have to trigger :
http://yoururl?update_products
as admin.
Don't forget to edit slug_to_edit with your shipping class slug
Related
I'm stuck on a task where I need to make WooCommerce automatically apply a shipping class to products uploaded by "Vendor Admins" user role (as set by WooCommerce Product Vendors). I tried to adapt a code snippet I fond here, but apparently this isn't for my usage case. I appreciate your help & comments!
`
if( isset($_GET['update_products']) && is_wc_product_vendors_admin_vendor() ){
add_action( 'init', 'add_shipping_terms_on_all_products' );
}
function add_shipping_terms_on_all_products(){
global $wpdb;
// Here you need to edit the slug_to_edit with your custom slug
$shipping_terms = get_term_by( 'slug', 'old-books', 'product_shipping_class' );
// If can't find the terms, return
if( empty($shipping_terms) ){
return;
}
// Request all product
$products = $wpdb->get_results( "
SELECT p.ID as ID
FROM wp_posts AS p
WHERE p.post_status = 'publish'
AND p.post_type = 'product'
" );
foreach($products as $_product){
$product = new WC_Product($_product->ID);
$product_shipping_class = $product->get_shipping_class();
if( !empty($product_shipping_class) ){
continue;
}
wp_set_post_terms( $product->id, array( $shipping_terms->term_id ), 'product_shipping_class' );
}
}
`
I tried to adapt the snippet and unfortunately nothing happened. I don't know how to proceed.
ACF is set up for post type on WooCommerce products. However, I am trying to add a custom column to WooCommerce orders list within Admin dashboard and add the products ACF field.
I have added the column to display after order_status, but I'm having problems getting the ACF field to display.
// ADD NEW COLUMN
add_filter( 'manage_edit-shop_order_columns', 'custom_shop_order_column', 20 );
function custom_shop_order_column($columns)
{
$reordered_columns = array();
foreach( $columns as $key => $column){
$reordered_columns[$key] = $column;
if( $key == 'order_status' ){
$reordered_columns['my-column'] = __( 'Location','theme_domain');
}
}
return $reordered_columns;
}
Here, adding ACF to new colum.
// ADD ACF FIELD TO COLUMN
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 20, 2 );
function custom_orders_list_column_content( $column, $post_id )
{
if ( 'Location' == $column_name ){
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
echo get_field( 'location', $product_id );
}
return true;
}
Still learning and not sure how to do this, any advice?
An order generally consists of several products, therefore you cannot use $product_id directly, but you have to loop through the order items.
So you get:
/**
* Add columns
*/
function filter_manage_edit_shop_order_columns( $columns ) {
$reordered_columns = array();
foreach ( $columns as $key => $column ) {
$reordered_columns[$key] = $column;
if ( $key == 'order_status' ) {
$reordered_columns['my-column'] = __( 'Location','theme_domain' );
}
}
return $reordered_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'filter_manage_edit_shop_order_columns', 10, 1 );
/**
* Populate columns
*/
function filter_manage_shop_order_posts_custom_column( $column, $post_id ) {
// Compare
if ( $column == 'my-column' ) {
// Get order
$order = wc_get_order( $post_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Get items
$items = $order->get_items();
// Loop through
foreach ( $items as $key => $item ) {
// Product ID
$product_id = $item->get_variation_id() > 0 ? $item->get_variation_id() : $item->get_product_id();
// Get field
$address = get_field( 'location', $product_id );
// Output
echo ($address) ? '<div>Address: ' . $address . '</div>' : '<div>Address: No address found!</div>';
}
}
}
}
add_filter( 'manage_shop_order_posts_custom_column', 'filter_manage_shop_order_posts_custom_column', 10, 2 );
We're building a clothing store. The products that will be uploaded could have label sizes from various countries, and as such we have two size taxonomies: product_size and product_size_uk.
I'm trying to set the uk size based upon the international size at the point the product is saved/updated, and running a switch to set a variable to the id of the uk size taxonomy and using
wp_set_object_terms. But this isn't working:
add_action( 'save_post', 'save_uk_size' );
function save_uk_size( $post_id ) {
if ( $post->post_type == 'product' ) {
$post = get_post($post_id);
$terms = wp_get_post_terms( $post->ID, 'product_size', array( 'fields' => 'all' ) );
if ( $terms ) {
$prod_size_int = $terms[0]->slug;
}
switch ($prod_size_int) {
...
case "FR-36":
$prod_size_uk = 805;
break;
case "FR-38":
$prod_size_uk = 806;
break;
...
}
wp_set_object_terms($post_id, $prod_size_uk, 'product_size_uk');
}
}
Can anyone steer me in the right direction? Thanks!
First you need to install Advanced Custom Fields plugin
Then for taxonomy product_size we create Taxonomy field (product_size_uk).
Now in the pages of taxonomy product_size in admin panel there is a field where we can choose which product_size_uk corresponds to this taxonomy.
3.Then we have to choose product_size_uk matching for all sizes.
And then this code
add_action( 'save_post_product', 'product_save_new_term' );
function product_save_new_term($post_id) {
remove_action( 'save_post_product', 'product_save_new_term' );
$terms = wp_get_object_terms( $post_id, 'product_size' );
$term_id = $terms[0]->term_id;
if($term_id != "") {
$key_for_field = 'product_size_' . $term_id;
$product_size_uk_value = get_field( 'product_size_uk', $key_for_field );
wp_set_object_terms($post_id, $product_size_uk_value, 'product_size_uk');
clean_post_cache( $post_id );
} else {
wp_delete_object_term_relationships( $post_id, 'product_size_uk' );
}
add_action( 'save_post_product', 'product_save_new_term' );
}
Or, if you don't want to have controls for size matching in the admin panel and it's easier for you to write everything in the code.
add_action( 'save_post_product', 'product_save_new_term' );
function product_save_new_term($post_id) {
$data_array = array(
"product_size_term_id" => "product_size_uk_term_id",
"product_size_term_id2" => "product_size_uk_term_id2",
"product_size_term_id3" => "product_size_uk_term_id3",
);
remove_action( 'save_post_product', 'product_save_new_term' );
$terms = wp_get_object_terms( $post_id, 'product_size' );
$term_id = $terms[0]->term_id;
if($term_id != "") {
$product_size_uk_value = $data_array[$term_id];
if($product_size_uk_value !="") {
wp_set_object_terms($post_id, $product_size_uk_value, 'product_size_uk');
}
clean_post_cache( $post_id );
} else {
wp_delete_object_term_relationships( $post_id, 'product_size_uk' );
}
add_action( 'save_post_product', 'product_save_new_term' );
}
I've added in a function for a custom field on the product general options:
// Add Custom Field to Product under General
function create_extra_fee_field() {
$args = array(
'id' => 'park_fee',
'label' => __( 'Natl Park Entrance Fee', 'tranq-lsx-child' ),
'class' => 'tranq-custom-field',
'desc_tip' => true,
'description' => __( 'This sets the Fee that will be added to the car.', 'tranq-lsx-child' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_general_product_data', 'create_extra_fee_field' );
// Save Custom Field Data
function save_extra_fee_field( $post_id ) {
$product = wc_get_product( $post_id );
$title = isset( $_POST['park_fee'] ) ? $_POST['park_fee'] : '';
$product->update_meta_data( 'park_fee', sanitize_text_field( $title ) );
$product->save();
}
add_action( 'woocommerce_process_product_meta', 'save_extra_fee_field' );
I would like to add this as an extra fee to the Cart Totals which multiplied based on the amount of Person/People that were selected from the Woocommerce Bookings.
Something like this:
// Calculate Extra Fee Based on Amount of People.
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
function add_custom_fees( WC_Cart $cart ){
$park_fee = get_post_meta($item['product_id'] , 'park_fee', true);
foreach( $cart->get_cart() as $item ){
$fees += $item[ 'park_fee' ] * 14706;
}
if( $fees != 0 ){
$cart->add_fee( 'Park Fee', $fees);
}
}
How do I go about in achieving this? Any Links to a walkthrough would be greatly appreciated.
I've added this and it seems to work:
// Add Custom Field to Cart Totals
function woo_add_cart_fee() {
global $woocommerce;
foreach( WC()->cart->get_cart() as $cart_item ){
// Get the WC_Product object (instance)
$product = $cart_item['data'];
$product_id = $product->get_id(); // get the product ID
$custom_field_value = get_post_meta( $product->get_id(), 'park_fee', true );
$person = array_sum( $cart_item['booking']['_persons'] );
}
$additional_fee_name = "Natl Park Entrance Fee";
$extra_fee = $custom_field_value * $person;
$addedFee = false;
// first check to make sure it isn’t already there
foreach ( $woocommerce->cart->get_fees() as $_fee )
{
if ($_fee->id == sanitize_title($additional_fee_name) )
{
$_fee->amount = (float) esc_attr( $extra_fee );
}
}
if (!$addedFee)
{
$woocommerce->cart->add_fee( __($additional_fee_name, "woocommerce"),
$extra_fee, $additional_fee_taxable );
}
}
add_action( "woocommerce_before_calculate_totals", "woo_add_cart_fee" );
I already found a snippet to sort the checkout cart alphabetically. This works perfect but as mentioned I try to sort and group my products by category.
Is there anyone who could tweak the following snippet so it sorts the products by category?
add_action( 'woocommerce_cart_loaded_from_session', 'bbloomer_sort_cart_items_alphabetically' );
function bbloomer_sort_cart_items_alphabetically() {
global $woocommerce;
// READ CART ITEMS
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$products_in_cart[ $key ] = $item['data']->get_title();
}
// SORT CART ITEMS
natsort( $products_in_cart );
// ASSIGN SORTED ITEMS TO CART
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $woocommerce->cart->cart_contents[ $cart_key ];
}
$woocommerce->cart->cart_contents = $cart_contents;
}
In order to grouped cart items by categories, add follows code snippet -
function woocommerce_before_cart_contents(){
global $woocommerce;
$cat_wisw_pros = array();
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
$cat_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
foreach ( $cat_ids as $id ) {
$cat_wisw_pros[$id][$cart_item_key] = $cart_item;
}
}
ksort( $cat_wisw_pros ); // Cat ID wise sort
$grouped_cart_items = array();
foreach ( $cat_wisw_pros as $cat_id => $cart_items ) {
foreach ( $cart_items as $cart_item_key => $cart_item ) {
if( !array_key_exists( $cart_item_key, $grouped_cart_items ) )
$grouped_cart_items[$cart_item_key] = $cart_item;
}
}
$woocommerce->cart->cart_contents = $grouped_cart_items;
}
add_action( 'woocommerce_before_cart_contents', 'woocommerce_before_cart_contents' );
You should be able to access the category ids with the method get_category_ids() as defined in the class WC_Product
$item['data']->get_category_ids()
but this gives you back an array, so you need to handle getting the id, e.g.
$ids = $item['data']->get_category_ids();
$id = $ids[ 0 ];
and transforming to a string, e.g.
$term_obj = get_term( $id, 'product_cat' );
$name = $term_obj->name;
you could then do
$products_in_cart[ $key ] = $name;
and by the same logic used in the code in your question sort by category.
There are several things to consider though, this does not handle items being in multiple categories, it just gets the first by using index 0. Additionally, this has no extra logic of sorting, if there are multiple products in the same category.
Please note, this is untested and merely an idea of an approach of how this could be handled.