Hi we are trying to sort the Woo Cart by Main product category and list under the products in that category. Like below:
Wheel Parts
spokes 12
Tyre's
Frame
Y Frame
X Frame
Z Frame
Seat
Seat 1
Seat 2
We have managed to get to display by cat order but it is not ordering them into Main Cat -> Sub Cat
We have the below code and trying to order cart array by cat and sub cat
add_action( 'woocommerce_cart_loaded_from_session', function() {
global $woocommerce;
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$terms = wp_get_post_terms($item['data']->id, 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->name;
}
natsort( $products_in_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;
}, 100 );
Any one have any ideas please?
Your code was correct but you had just natsort which returning 1 is causing the issue. You also need to sort categories by menu order. Please check the below code working perfectly.
add_action( 'woocommerce_cart_loaded_from_session', function() {
global $woocommerce;
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$terms = wp_get_post_terms($item['data']->id, 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->term_id;
}
// $categories = get_terms( 'product_cat', 'orderby=menu_order&hide_empty=1' );
asort($products_in_cart);
$cat_array = array();
foreach ($products_in_cart as $key => $value) {
$cat_array[$key] =get_term_by('id', $value, 'product_cat');
}
$mai_cat = [];
$i=0;
foreach ($cat_array as $parent_key => $parent_value) {
if($parent_value->parent == 0)
{
$mai_cat[$parent_key] = $parent_value->term_id;
foreach ($cat_array as $parent_key_sub => $parent_value_sub) {
if($parent_value_sub->parent == $parent_value->term_id)
{
$mai_cat[$parent_key_sub] = $parent_value_sub->term_id;
}
}
}
}
$cart_contents = array();
foreach ( $mai_cat as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $woocommerce->cart->cart_contents[ $cart_key ];
}
$woocommerce->cart->cart_contents = $cart_contents;
}, 100 );
Tested and works well
Related
When a coupon is applied (belonging to a certain type) I change the product discount price to the regular price via:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_object) {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$coupon = False;
if ($coupons = WC()->cart->get_applied_coupons() == False )
$coupon = False;
else {
foreach ( WC()->cart->get_applied_coupons() as $code ) {
$coupons1 = new WC_Coupon( $code );
if ($coupons1->type == 'percent_product' || $coupons1->type == 'percent')
$coupon = True;
}
}
if ($coupon == True)
foreach ( $cart_object->get_cart() as $cart_item )
{
$price = $cart_item['data']->regular_price;
$cart_item['data']->set_price( $price );
}
}
But if I have a category excluded, the code freaks out because it changes the price from sale to regular in the cart and does not add a discount.
How to work around this so that the excluded category does not change to the regular price?
To exclude certain categories you can use has_term() when loop through the cart items
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$excluded_categories = array( 63, 15, 'categorie-1' );
// Initialize
$coupon_flag = false;
// Loop through applied coupons
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'percent_product' ) ) ) {
$coupon_flag = true;
break;
}
}
// True
if ( $coupon_flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get product ID in
$product_id = $cart_item['product_id'];
// NOT contains the definite term
if ( ! has_term( $excluded_categories, 'product_cat', $product_id ) ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Set new price
$cart_item['data']->set_price( $regular_price );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
I need help. I want to sort prodyct in my cart page by category like this:
Category1
Product1
Product2
Product3
Category2
Product1
Product2
Product3
Category3
Product1
Product2
Product3
I found this code but it is working strange. For some products it is sorting OK, but for other - no. Could you help me?
add_action( 'woocommerce_cart_loaded_from_session', function() {
global $woocommerce;
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$terms = wp_get_post_terms($item['data']->id, 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->name;
}
ksort( $products_in_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;
}, 100 );```
You also need to set new cart session and you can also utilize $cart property passed into action:
( Although I have not tested this idea please try )
add_action( 'woocommerce_cart_loaded_from_session', function($cart) {
$products_in_cart = array();
foreach ( $cart->get_cart() as $key => $item ) {
$terms = wp_get_post_terms($item['data']->get_id(), 'product_cat' );
$products_in_cart[ $key ] = $terms[0]->name;
}
asort( $products_in_cart );
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $cart->cart_contents[ $cart_key ];
}
$cart->set_cart_contents($cart_contents);
$cart->set_session();
}, 100, 1 );
I'm trying to fetch bookings based on time availability in wocommerce bookings by passing the time selection in below format:
2019-08-26 08:00 - 2019-08-26 11:00
$available_blocks = $booking_form->product->get_available_blocks( array(
'blocks' => $blocks_in_range,
'from' => $from,
'to' => $to));
foreach ( $available_blocks as $check ) {
if ( true === $booking_form->product->check_availability_rules_against_date( $check, '' )){
//Custom Added to fetch only blocks in selected range
if( $from >= reset($available_blocks) && $to <= end($available_blocks)){
$matches[] = $post_id;
break; // check passed
}
}
}
But, it's only working when I pass time in Hour only format(10:00 AM), When I add minute(10:30 AM) it is not returning any available bookings.
Full function for reference.
/**
* Get all available booking products
*
* #param string $start_date_raw YYYY-MM-DD format
* #param string $end_date_raw YYYY-MM-DD format
* #param int $quantity Number of people to book
* #param string $behavior Whether to return exact matches
* #return array Available post IDs
*/
function get_available_bookings( $start_date_raw, $end_date_raw, $quantity = 1, $behavior = 'default' ) {
$matches = array();
// Separate dates from times
$start_date = explode( ' ', $start_date_raw );
$end_date = explode( ' ', $end_date_raw );
// If time wasn't passed, define defaults.
if ( ! isset( $start_date[1] ) ) {
$start_date[1] = '00:00';
}
$start = explode( '-', $start_date[0] );
$args = array(
'wc_bookings_field_resource' => 0,
'wc_bookings_field_persons' => $quantity,
'wc_bookings_field_duration' => 1,
'wc_bookings_field_start_date_year' => $start[0],
'wc_bookings_field_start_date_month' => $start[1],
'wc_bookings_field_start_date_day' => $start[2],
);
// Loop through all posts
foreach ( $this->product_ids as $post_id ) {
if ( 'product' == get_post_type( $post_id ) ) {
$product = wc_get_product( $post_id );
if ( is_wc_booking_product( $product ) ) {
// Grab the duration unit
$unit = $product->is_type( 'accommodation-booking' ) ? 'night' : $product->get_duration_unit();
// Support time
if ( in_array( $unit, array( 'minute', 'hour' ) ) ) {
if ( ! empty( $start_date[1] ) ) {
$args['wc_bookings_field_start_date_time'] = $start_date[1];
}
}
if ( 'exact' === $behavior ) {
$duration = $this->calculate_duration( $start_date_raw, $end_date_raw, $product->get_duration(), $unit );
$args['wc_bookings_field_duration'] = $duration;
}
$booking_form = new WC_Booking_Form( $product );
$posted_data = $booking_form->get_posted_data( $args );
// All slots are available (exact match)
if ( true === $booking_form->is_bookable( $posted_data ) ) {
$matches[] = $post_id;
}
// Any slot between the given dates are available
elseif ( 'exact' !== $behavior ) {
$from = strtotime( $start_date_raw );
$to = strtotime( $end_date_raw );
$blocks_in_range = $booking_form->product->get_blocks_in_range( $from, $to );
// Arguments changed in WC Bookings 1.11.1
$available_blocks = $booking_form->product->get_available_blocks( array(
'blocks' => $blocks_in_range,
'from' => $from,
'to' => $to
) );
foreach ( $available_blocks as $check ) {
if ( true === $booking_form->product->check_availability_rules_against_date( $check, '' )){
$matches[] = $post_id;
break; // check passed
}
}
}
}
}
}
return $matches;
}
Im tryng to mod this function to make an update more powerful.
What im tryng to do is to mod this function:
add_action( 'wp_loaded', 'cron_revise_changed_listings' );
function cron_revise_changed_listings() {
global $wpdb;
if ( !isset( $_REQUEST['wplister_revise_all'] ) ) {
return;
}
$limit = isset( $_REQUEST['revise_limit'] ) ? intval( $_REQUEST['revise_limit'] ) : 10;
$listings = $wpdb->get_results("
SELECT id, account_id
FROM {$wpdb->prefix}ebay_auctions
WHERE status = 'changed'
ORDER BY id DESC
LIMIT {$limit}", ARRAY_A );
if ( empty( $listings ) ) {
die( json_encode( array( 'revised' => 0 ) ) );
}
$lm = new ListingsModel();
$revised = 0;
$last_account_id = false;
foreach ( $listings as $listing ) {
if ( $last_account_id != $listing['account_id'] ) {
$last_account_id = $listing['account_id'];
WPLE()->initEC( $listing['account_id'] );
}
$lm->reviseItem( $listing['id'], WPLE()->EC->session );
$revised++;
}
WPLE()->EC->closeEbay();
die( json_encode( array( 'revised' => $revised ) ) );
}
What i need to obtain is to repeat cycle for each, but with a step of 10 items per time so for revise 100 items it need only to do 10 cicles and not 100...someone have any ideas?
I added some custom fields (dates) in my admin columns. I try to make them sortable but in order to do that I need to convert them from string to date. My naive and simple code obviously doesn't work... Can someone point out my error(s) ?
add_action( 'pre_get_posts', 'orderby_date' );
function orderby_date( $query ) {
$orderby = $query->get( 'orderby');
if( 'start' == $orderby ) {
$query->set('meta_key','class_start');
$query->set('orderby',"STR_TO_DATE(meta_value,'%m/%d/%Y')");
}
}
This is what you are looking for:
add_filter( 'posts_clauses', 'manage_wp_posts_be_qe_posts_clauses', 1, 2 );
function manage_wp_posts_be_qe_posts_clauses( $pieces, $query ) {
global $wpdb;
if ( $query->is_main_query() && ( $orderby = $query->get( 'orderby' ) ) ) {
$order = strtoupper( $query->get( 'order' ) );
if ( ! in_array( $order, array( 'ASC', 'DESC' ) ) )
$order = 'ASC';
switch( $orderby ) {
case 'class_start':
$pieces[ 'join' ] .= " LEFT JOIN $wpdb->postmeta wp_rd ON wp_rd.post_id = {$wpdb->posts}.ID AND wp_rd.meta_key = 'class_start'";
$pieces[ 'orderby' ] = "STR_TO_DATE( wp_rd.meta_value,'%m/%d/%Y' ) $order, " . $pieces[ 'orderby' ];
break;
}
}
return $pieces;
}
You can read more about it here: http://wpdreamer.com/2014/04/how-to-make-your-wordpress-admin-columns-sortable/