This commit is contained in:
Mike Jolley 2017-10-22 07:13:31 -07:00
parent 1881b590d5
commit 2255066c0f
1 changed files with 48 additions and 43 deletions

View File

@ -72,12 +72,13 @@ class WC_Discounts {
$item->key = $key;
$item->object = $cart_item;
$item->product = $cart_item['data'];
$item->quantity = $cart_item['quantity'];
$item->price = wc_add_number_precision_deep( $item->product->get_price() ) * $item->quantity;
$this->items[ $key ] = $item;
}
$item->price = wc_add_number_precision_deep( $item->product->get_price() );
uasort( $this->items, array( $this, 'sort_by_price' ) );
for ( $i = 0; $i < $cart_item['quantity']; $i ++ ) {
$this->items[ $key . ':' . $i ] = clone $item;
$this->items[ $key . ':' . $i ]->index = $i;
}
}
}
/**
@ -135,14 +136,22 @@ class WC_Discounts {
}
/**
* Get all discount totals.
* Get all discount totals for line items.
*
* @since 3.2.0
* @param bool $in_cents Should the totals be returned in cents, or without precision.
* @return array
*/
public function get_discounts( $in_cents = false ) {
$discounts = $this->discounts;
$discounts = array();
foreach ( $this->discounts as $coupon_code => $coupon_discounts ) {
foreach ( $coupon_discounts as $key => $discount ) {
$line_item_key = current( explode( ':', $key ) );
$discounts[ $coupon_code ][ $line_item_key ] = isset( $discounts[ $coupon_code ], $discounts[ $coupon_code ][ $line_item_key ] ) ? $discounts[ $coupon_code ][ $line_item_key ] + $discount : $discount;
}
}
return $in_cents ? $discounts : wc_remove_number_precision_deep( $discounts );
}
@ -154,16 +163,16 @@ class WC_Discounts {
* @return array
*/
public function get_discounts_by_item( $in_cents = false ) {
$discounts = $this->discounts;
$item_discount_totals = (array) array_shift( $discounts );
$discounts = array();
foreach ( $discounts as $item_discounts ) {
foreach ( $item_discounts as $item_key => $item_discount ) {
$item_discount_totals[ $item_key ] += $item_discount;
foreach ( $this->discounts as $coupon_code => $coupon_discounts ) {
foreach ( $coupon_discounts as $key => $discount ) {
$line_item_key = current( explode( ':', $key ) );
$discounts[ $line_item_key ] = isset( $discounts[ $line_item_key ] ) ? $discounts[ $line_item_key ] + $discount : $discount;
}
}
return $in_cents ? $item_discount_totals : wc_remove_number_precision_deep( $item_discount_totals );
return $in_cents ? $discounts : wc_remove_number_precision_deep( $discounts );
}
/**
@ -198,7 +207,7 @@ class WC_Discounts {
* @return int
*/
public function get_discounted_price_in_cents( $item ) {
return absint( $item->price - $this->get_discount( $item->key, true ) );
return absint( $item->price - $this->get_discount( $item->key . ':' . $item->index, true ) );
}
/**
@ -239,14 +248,14 @@ class WC_Discounts {
$this->apply_coupon_fixed_cart( $coupon, $items_to_apply );
break;
default :
foreach ( $items_to_apply as $item ) {
foreach ( $items_to_apply as $key => $item ) {
$discounted_price = $this->get_discounted_price_in_cents( $item );
$price_to_discount = wc_remove_number_precision( ( 'yes' === get_option( 'woocommerce_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : $item->price );
$discount = wc_add_number_precision( $coupon->get_discount_amount( $price_to_discount, $item->object ) ) * $item->quantity;
$discount = min( $discounted_price, $discount );
// Store code and discount amount per item.
$this->discounts[ $coupon->get_code() ][ $item->key ] += $discount;
$this->discounts[ $coupon->get_code() ][ $key ] += $discount;
}
break;
}
@ -263,12 +272,14 @@ class WC_Discounts {
* @return int
*/
protected function sort_by_price( $a, $b ) {
$price_1 = $a->price * $a->quantity;
$price_2 = $b->price * $b->quantity;
$price_1 = $this->get_discounted_price_in_cents( $a );
$price_2 = $this->get_discounted_price_in_cents( $b );
var_dump($price_1);var_dump($price_2);
if ( $price_1 === $price_2 ) {
return 0;
}
return ( $price_1 < $price_2 ) ? 1 : -1;
return ( $price_1 > $price_2 ) ? 1 : -1;
}
/**
@ -299,12 +310,15 @@ class WC_Discounts {
$limit_usage_qty = $coupon->get_limit_usage_to_x_items();
}
foreach ( $this->items as $item ) {
uasort( $this->items, array( $this, 'sort_by_price' ) );
foreach ( $this->items as $key => $item ) {
$item_to_apply = clone $item; // Clone the item so changes to this item do not affect the originals.
if ( 0 === $this->get_discounted_price_in_cents( $item_to_apply ) ) {
continue;
}
if ( ! $coupon->is_valid_for_product( $item_to_apply->product, $item_to_apply->object ) && ! $coupon->is_valid_for_cart() ) {
continue;
}
@ -312,20 +326,11 @@ class WC_Discounts {
if ( $limit_usage_qty && $applied_count >= $limit_usage_qty ) {
break;
}
if ( $limit_usage_qty && $item_to_apply->quantity > ( $limit_usage_qty - $applied_count ) ) {
$limit_to_qty = absint( $limit_usage_qty - $applied_count );
// Lower the qty and cost so the discount is applied less.
$item_to_apply->price = ( $item_to_apply->price / $item_to_apply->quantity ) * $limit_to_qty;
$item_to_apply->quantity = $limit_to_qty;
}
if ( 0 >= $item_to_apply->quantity ) {
continue;
}
$items_to_apply[] = $item_to_apply;
$applied_count += $item_to_apply->quantity;
echo $key . ' ';
$items_to_apply[ $key ] = $item_to_apply;
$applied_count = $applied_count + 1;
}
return $items_to_apply;
}
@ -344,7 +349,7 @@ class WC_Discounts {
// Because get_amount() could return an empty string, let's be sure to set our local variable to a known good value.
$coupon_amount = ( '' === $coupon->get_amount() ) ? 0 : $coupon->get_amount();
foreach ( $items_to_apply as $item ) {
foreach ( $items_to_apply as $key => $item ) {
// Find out how much price is available to discount for the item.
$discounted_price = $this->get_discounted_price_in_cents( $item );
@ -367,7 +372,7 @@ class WC_Discounts {
$total_discount += $discount;
// Store code and discount amount per item.
$this->discounts[ $coupon->get_code() ][ $item->key ] += $discount;
$this->discounts[ $coupon->get_code() ][ $key ] += $discount;
}
// Work out how much discount would have been given to the cart as a whole and compare to what was discounted on all line items.
@ -390,10 +395,10 @@ class WC_Discounts {
* @return int Total discounted.
*/
protected function apply_coupon_fixed_product( $coupon, $items_to_apply, $amount = null ) {
$total_discount = 0;
$amount = $amount ? $amount : wc_add_number_precision( $coupon->get_amount() );
$total_discount = 0;
$amount = $amount ? $amount: wc_add_number_precision( $coupon->get_amount() );
foreach ( $items_to_apply as $item ) {
foreach ( $items_to_apply as $key => $item ) {
// Find out how much price is available to discount for the item.
$discounted_price = $this->get_discounted_price_in_cents( $item );
@ -401,7 +406,7 @@ class WC_Discounts {
$price_to_discount = ( 'yes' === get_option( 'woocommerce_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : $item->price;
// Run coupon calculations.
$discount = $amount * $item->quantity;
$discount = $amount;
if ( is_a( $this->object, 'WC_Cart' ) && has_filter( 'woocommerce_coupon_get_discount_amount' ) ) {
// Send through the legacy filter, but not as cents.
@ -412,7 +417,7 @@ class WC_Discounts {
$total_discount += $discount;
// Store code and discount amount per item.
$this->discounts[ $coupon->get_code() ][ $item->key ] += $discount;
$this->discounts[ $coupon->get_code() ][ $key ] += $discount;
}
return $total_discount;
}
@ -469,8 +474,8 @@ class WC_Discounts {
*/
protected function apply_coupon_remainder( $coupon, $items_to_apply, $amount ) {
$total_discount = 0;
foreach ( $items_to_apply as $item ) {
return;
foreach ( $items_to_apply as $key => $item ) {
for ( $i = 0; $i < $item->quantity; $i ++ ) {
// Find out how much price is available to discount for the item.
$discounted_price = $this->get_discounted_price_in_cents( $item );
@ -485,7 +490,7 @@ class WC_Discounts {
$total_discount += $discount;
// Store code and discount amount per item.
$this->discounts[ $coupon->get_code() ][ $item->key ] += $discount;
$this->discounts[ $coupon->get_code() ][ $key ] += $discount;
if ( $total_discount >= $amount ) {
break 2;