public function __construct(\OrderItem $item)
 {
     $this->item = $item;
     $this->quantity = $item->Quantity;
     $originalprice = method_exists($item, "DiscountableAmount") ? $item->DiscountableAmount() : $item->UnitPrice();
     parent::__construct($originalprice);
 }
 /**
  * Work out the discount for a given order.
  *
  * @param Order $order
  * @return double - discount amount
  */
 public function calculate()
 {
     $total = 0;
     // clear any existing linked discounts
     $this->modifier->Discounts()->removeAll();
     // work out all item-level discounts, and load into infoitems
     $infoitems = $this->createPriceInfoList($this->order->Items());
     foreach ($this->getItemDiscounts() as $discount) {
         // item discounts will update info items
         $action = $discount->Type === "Percent" ? new \ItemPercentDiscount($infoitems, $discount) : new \ItemFixedDiscount($infoitems, $discount);
         $action->perform();
     }
     // select best item-level discounts
     foreach ($infoitems as $infoitem) {
         $bestadjustment = $infoitem->getBestAdjustment();
         if (!$bestadjustment) {
             continue;
         }
         $amount = $bestadjustment->getValue();
         // prevent discounting more than original price
         if ($amount > $infoitem->getOriginalTotal()) {
             $amount = $infoitem->getOriginalTotal();
         }
         $total += $amount;
         // remove any existing linked discounts
         $infoitem->getItem()->Discounts()->removeAll();
         $infoitem->getItem()->Discounts()->add($bestadjustment->getAdjuster(), array('DiscountAmount' => $amount));
         $this->logDiscountAmount("Item", $amount, $bestadjustment->getAdjuster());
     }
     // work out all cart-level discounts, and load into cartpriceinfo
     $cartpriceinfo = new PriceInfo($this->order->SubTotal());
     foreach ($this->getCartDiscounts() as $discount) {
         $action = new \SubtotalDiscountAction($this->getDiscountableAmount($discount), $discount);
         $action->reduceRemaining($this->discountSubtotal($discount));
         $adjust = new Adjustment($action->perform(), $discount);
         $cartpriceinfo->adjustPrice($adjust);
     }
     $cartremainder = $cartpriceinfo->getOriginalPrice() - $total;
     // keep remainder sane, i.e above 0
     $cartremainder = $cartremainder < 0 ? 0 : $cartremainder;
     // select best cart-level discount
     if ($bestadjustment = $cartpriceinfo->getBestAdjustment()) {
         $discount = $bestadjustment->getAdjuster();
         $amount = $bestadjustment->getValue();
         // don't let amount be greater than remainder
         $amount = $amount > $cartremainder ? $cartremainder : $amount;
         $total += $amount;
         $this->modifier->Discounts()->add($discount, array('DiscountAmount' => $amount));
         $this->logDiscountAmount("Cart", $amount, $discount);
     }
     if (class_exists('ShippingFrameworkModifier') && ($shipping = $this->order->getModifier("ShippingFrameworkModifier"))) {
         // work out all shipping-level discounts, and load into shippingpriceinfo
         $shippingpriceinfo = new PriceInfo($shipping->Amount);
         foreach ($this->getShippingDiscounts() as $discount) {
             $action = new \SubtotalDiscountAction($shipping->Amount, $discount);
             $action->reduceRemaining($this->discountSubtotal($discount));
             $shippingpriceinfo->adjustPrice(new Adjustment($action->perform(), $discount));
         }
         //select best shipping-level disount
         if ($bestadjustment = $shippingpriceinfo->getBestAdjustment()) {
             $discount = $bestadjustment->getAdjuster();
             $amount = $bestadjustment->getValue();
             //don't let amount be greater than remainder
             $total += $amount;
             $this->modifier->Discounts()->add($discount, array('DiscountAmount' => $amount));
             $this->logDiscountAmount("Shipping", $amount, $discount);
         }
     }
     return $total;
 }