mirror of
https://github.com/kevin-DL/LaravelShoppingcart.git
synced 2026-01-21 14:55:02 +00:00
Merge branch 'master' into fix_cart_database_timestamps
This commit is contained in:
101
src/Cart.php
101
src/Cart.php
@@ -61,7 +61,7 @@ class Cart
|
||||
private $discount = 0;
|
||||
|
||||
/**
|
||||
* Defines the discount percentage.
|
||||
* Defines the tax rate.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
@@ -120,11 +120,12 @@ class Cart
|
||||
* @param mixed $name
|
||||
* @param int|float $qty
|
||||
* @param float $price
|
||||
* @param float $weight
|
||||
* @param array $options
|
||||
*
|
||||
* @return \Gloudemans\Shoppingcart\CartItem
|
||||
*/
|
||||
public function add($id, $name = null, $qty = null, $price = null, array $options = [])
|
||||
public function add($id, $name = null, $qty = null, $price = null, $weight = 0, array $options = [])
|
||||
{
|
||||
if ($this->isMulti($id)) {
|
||||
return array_map(function ($item) {
|
||||
@@ -132,7 +133,7 @@ class Cart
|
||||
}, $id);
|
||||
}
|
||||
|
||||
$cartItem = $this->createCartItem($id, $name, $qty, $price, $options);
|
||||
$cartItem = $this->createCartItem($id, $name, $qty, $price, $weight, $options);
|
||||
|
||||
return $this->addCartItem($cartItem);
|
||||
}
|
||||
@@ -140,13 +141,14 @@ class Cart
|
||||
/**
|
||||
* Add an item to the cart.
|
||||
*
|
||||
* @param \Gloudemans\Shoppingcart\CartItem $item Item to add to the Cart
|
||||
* @param bool $keepDiscount Keep the discount rate of the Item
|
||||
* @param bool $keepTax Keep the Tax rate of the Item
|
||||
* @param \Gloudemans\Shoppingcart\CartItem $item Item to add to the Cart
|
||||
* @param bool $keepDiscount Keep the discount rate of the Item
|
||||
* @param bool $keepTax Keep the Tax rate of the Item
|
||||
* @param bool $dispatchEvent
|
||||
*
|
||||
* @return \Gloudemans\Shoppingcart\CartItem The CartItem
|
||||
*/
|
||||
public function addCartItem($item, $keepDiscount = false, $keepTax = false)
|
||||
public function addCartItem($item, $keepDiscount = false, $keepTax = false, $dispatchEvent = true)
|
||||
{
|
||||
if (!$keepDiscount) {
|
||||
$item->setDiscountRate($this->discount);
|
||||
@@ -164,7 +166,9 @@ class Cart
|
||||
|
||||
$content->put($item->rowId, $item);
|
||||
|
||||
$this->events->dispatch('cart.added', $item);
|
||||
if ($dispatchEvent) {
|
||||
$this->events->dispatch('cart.added', $item);
|
||||
}
|
||||
|
||||
$this->session->put($this->instance, $content);
|
||||
|
||||
@@ -194,6 +198,8 @@ class Cart
|
||||
$content = $this->getContent();
|
||||
|
||||
if ($rowId !== $cartItem->rowId) {
|
||||
$itemOldIndex = $content->keys()->search($rowId);
|
||||
|
||||
$content->pull($rowId);
|
||||
|
||||
if ($content->has($cartItem->rowId)) {
|
||||
@@ -207,7 +213,13 @@ class Cart
|
||||
|
||||
return;
|
||||
} else {
|
||||
$content->put($cartItem->rowId, $cartItem);
|
||||
if (isset($itemOldIndex)) {
|
||||
$content = $content->slice(0, $itemOldIndex)
|
||||
->merge([$cartItem->rowId => $cartItem])
|
||||
->merge($content->slice($itemOldIndex));
|
||||
} else {
|
||||
$content->put($cartItem->rowId, $cartItem);
|
||||
}
|
||||
}
|
||||
|
||||
$this->events->dispatch('cart.updated', $cartItem);
|
||||
@@ -378,7 +390,7 @@ class Cart
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subtotal (total - tax) of the items in the cart.
|
||||
* Get the discount of the items in the cart.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
@@ -390,7 +402,7 @@ class Cart
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subtotal (total - tax) of the items in the cart as formatted string.
|
||||
* Get the discount of the items in the cart as formatted string.
|
||||
*
|
||||
* @param int $decimals
|
||||
* @param string $decimalPoint
|
||||
@@ -404,7 +416,7 @@ class Cart
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subtotal (total - tax) of the items in the cart.
|
||||
* Get the price of the items in the cart (not rounded).
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
@@ -416,7 +428,7 @@ class Cart
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subtotal (total - tax) of the items in the cart as formatted string.
|
||||
* Get the price of the items in the cart as formatted string.
|
||||
*
|
||||
* @param int $decimals
|
||||
* @param string $decimalPoint
|
||||
@@ -429,6 +441,32 @@ class Cart
|
||||
return $this->numberFormat($this->initialFloat(), $decimals, $decimalPoint, $thousandSeperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the price of the items in the cart (previously rounded).
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function priceTotalFloat()
|
||||
{
|
||||
return $this->getContent()->reduce(function ($initial, CartItem $cartItem) {
|
||||
return $initial + $cartItem->priceTotal;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the price of the items in the cart as formatted string.
|
||||
*
|
||||
* @param int $decimals
|
||||
* @param string $decimalPoint
|
||||
* @param string $thousandSeperator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function priceTotal($decimals = null, $decimalPoint = null, $thousandSeperator = null)
|
||||
{
|
||||
return $this->numberFormat($this->priceTotalFloat(), $decimals, $decimalPoint, $thousandSeperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total weight of the items in the cart.
|
||||
*
|
||||
@@ -643,8 +681,29 @@ class Cart
|
||||
$this->createdAt = Carbon::parse(data_get($stored, 'created_at'));
|
||||
$this->updatedAt = Carbon::parse(data_get($stored, 'updated_at'));
|
||||
|
||||
$this->getConnection()->table($this->getTableName())
|
||||
->where('identifier', $identifier)->delete();
|
||||
$this->getConnection()->table($this->getTableName())->where('identifier', $identifier)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase the cart with the given identifier.
|
||||
*
|
||||
* @param mixed $identifier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function erase($identifier)
|
||||
{
|
||||
if ($identifier instanceof InstanceIdentifier) {
|
||||
$identifier = $identifier->getInstanceIdentifier();
|
||||
}
|
||||
|
||||
if (!$this->storedCartWithIdentifierExists($identifier)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->getConnection()->table($this->getTableName())->where('identifier', $identifier)->delete();
|
||||
|
||||
$this->events->dispatch('cart.erased');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,10 +712,11 @@ class Cart
|
||||
* @param mixed $identifier Identifier of the Cart to merge with.
|
||||
* @param bool $keepDiscount Keep the discount of the CartItems.
|
||||
* @param bool $keepTax Keep the tax of the CartItems.
|
||||
* @param bool $dispatchAdd Flag to dispatch the add events.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function merge($identifier, $keepDiscount = false, $keepTax = false)
|
||||
public function merge($identifier, $keepDiscount = false, $keepTax = false, $dispatchAdd = true)
|
||||
{
|
||||
if (!$this->storedCartWithIdentifierExists($identifier)) {
|
||||
return false;
|
||||
@@ -668,9 +728,11 @@ class Cart
|
||||
$storedContent = unserialize($stored->content);
|
||||
|
||||
foreach ($storedContent as $cartItem) {
|
||||
$this->addCartItem($cartItem, $keepDiscount, $keepTax);
|
||||
$this->addCartItem($cartItem, $keepDiscount, $keepTax, $dispatchAdd);
|
||||
}
|
||||
|
||||
$this->events->dispatch('cart.merged');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -716,11 +778,12 @@ class Cart
|
||||
* @param mixed $name
|
||||
* @param int|float $qty
|
||||
* @param float $price
|
||||
* @param float $weight
|
||||
* @param array $options
|
||||
*
|
||||
* @return \Gloudemans\Shoppingcart\CartItem
|
||||
*/
|
||||
private function createCartItem($id, $name, $qty, $price, array $options)
|
||||
private function createCartItem($id, $name, $qty, $price, $weight, array $options)
|
||||
{
|
||||
if ($id instanceof Buyable) {
|
||||
$cartItem = CartItem::fromBuyable($id, $qty ?: []);
|
||||
@@ -730,7 +793,7 @@ class Cart
|
||||
$cartItem = CartItem::fromArray($id);
|
||||
$cartItem->setQuantity($id['qty']);
|
||||
} else {
|
||||
$cartItem = CartItem::fromAttributes($id, $name, $price, $options);
|
||||
$cartItem = CartItem::fromAttributes($id, $name, $price, $weight, $options);
|
||||
$cartItem->setQuantity($qty);
|
||||
}
|
||||
|
||||
|
||||
135
src/CartItem.php
135
src/CartItem.php
@@ -5,7 +5,20 @@ namespace Gloudemans\Shoppingcart;
|
||||
use Gloudemans\Shoppingcart\Contracts\Buyable;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
/**
|
||||
* @property-read mixed discount
|
||||
* @property-read float discountTotal
|
||||
* @property-read float priceTarget
|
||||
* @property-read float priceNet
|
||||
* @property-read float priceTotal
|
||||
* @property-read float subtotal
|
||||
* @property-read float taxTotal
|
||||
* @property-read float tax
|
||||
* @property-read float total
|
||||
* @property-read float priceTax
|
||||
*/
|
||||
class CartItem implements Arrayable, Jsonable
|
||||
{
|
||||
/**
|
||||
@@ -57,6 +70,13 @@ class CartItem implements Arrayable, Jsonable
|
||||
*/
|
||||
public $options;
|
||||
|
||||
/**
|
||||
* The tax rate for the cart item.
|
||||
*
|
||||
* @var int|float
|
||||
*/
|
||||
public $taxRate = 0;
|
||||
|
||||
/**
|
||||
* The FQN of the associated model.
|
||||
*
|
||||
@@ -64,13 +84,6 @@ class CartItem implements Arrayable, Jsonable
|
||||
*/
|
||||
private $associatedModel = null;
|
||||
|
||||
/**
|
||||
* The tax rate for the cart item.
|
||||
*
|
||||
* @var int|float
|
||||
*/
|
||||
private $taxRate = 0;
|
||||
|
||||
/**
|
||||
* The discount rate for the cart item.
|
||||
*
|
||||
@@ -84,6 +97,7 @@ class CartItem implements Arrayable, Jsonable
|
||||
* @param int|string $id
|
||||
* @param string $name
|
||||
* @param float $price
|
||||
* @param float $weight
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($id, $name, $price, $weight = 0, array $options = [])
|
||||
@@ -97,6 +111,9 @@ class CartItem implements Arrayable, Jsonable
|
||||
if (strlen($price) < 0 || !is_numeric($price)) {
|
||||
throw new \InvalidArgumentException('Please supply a valid price.');
|
||||
}
|
||||
if (strlen($weight) < 0 || !is_numeric($weight)) {
|
||||
throw new \InvalidArgumentException('Please supply a valid weight.');
|
||||
}
|
||||
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
@@ -248,6 +265,20 @@ class CartItem implements Arrayable, Jsonable
|
||||
return $this->numberFormat($this->discountTotal, $decimals, $decimalPoint, $thousandSeperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the formatted total price for this cart item.
|
||||
*
|
||||
* @param int $decimals
|
||||
* @param string $decimalPoint
|
||||
* @param string $thousandSeperator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function priceTotal($decimals = null, $decimalPoint = null, $thousandSeperator = null)
|
||||
{
|
||||
return $this->numberFormat($this->priceTotal, $decimals, $decimalPoint, $thousandSeperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the quantity for this cart item.
|
||||
*
|
||||
@@ -274,7 +305,6 @@ class CartItem implements Arrayable, Jsonable
|
||||
$this->id = $item->getBuyableIdentifier($this->options);
|
||||
$this->name = $item->getBuyableDescription($this->options);
|
||||
$this->price = $item->getBuyablePrice($this->options);
|
||||
$this->priceTax = $this->price + $this->tax;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,13 +316,12 @@ class CartItem implements Arrayable, Jsonable
|
||||
*/
|
||||
public function updateFromArray(array $attributes)
|
||||
{
|
||||
$this->id = array_get($attributes, 'id', $this->id);
|
||||
$this->qty = array_get($attributes, 'qty', $this->qty);
|
||||
$this->name = array_get($attributes, 'name', $this->name);
|
||||
$this->price = array_get($attributes, 'price', $this->price);
|
||||
$this->weight = array_get($attributes, 'weight', $this->weight);
|
||||
$this->priceTax = $this->price + $this->tax;
|
||||
$this->options = new CartItemOptions(array_get($attributes, 'options', $this->options));
|
||||
$this->id = Arr::get($attributes, 'id', $this->id);
|
||||
$this->qty = Arr::get($attributes, 'qty', $this->qty);
|
||||
$this->name = Arr::get($attributes, 'name', $this->name);
|
||||
$this->price = Arr::get($attributes, 'price', $this->price);
|
||||
$this->weight = Arr::get($attributes, 'weight', $this->weight);
|
||||
$this->options = new CartItemOptions(Arr::get($attributes, 'options', $this->options));
|
||||
|
||||
$this->rowId = $this->generateRowId($this->id, $this->options->all());
|
||||
}
|
||||
@@ -351,39 +380,69 @@ class CartItem implements Arrayable, Jsonable
|
||||
if (property_exists($this, $attribute)) {
|
||||
return $this->{$attribute};
|
||||
}
|
||||
$decimals = config('cart.format.decimals', 2);
|
||||
|
||||
switch ($attribute) {
|
||||
case 'discount':
|
||||
return $this->price * ($this->discountRate / 100);
|
||||
case 'priceTarget':
|
||||
return $this->price - $this->discount;
|
||||
case 'subtotal':
|
||||
return $this->priceTarget * $this->qty;
|
||||
case 'tax':
|
||||
return $this->priceTarget * ($this->taxRate / 100);
|
||||
case 'priceTax':
|
||||
return $this->priceTarget + $this->tax;
|
||||
case 'total':
|
||||
return $this->priceTax * $this->qty;
|
||||
case 'taxTotal':
|
||||
return $this->tax * $this->qty;
|
||||
case 'discountTotal':
|
||||
return $this->discount * $this->qty;
|
||||
case 'weightTotal':
|
||||
return $this->weight * $this->qty;
|
||||
|
||||
case 'model':
|
||||
if (isset($this->associatedModel)) {
|
||||
return with(new $this->associatedModel())->find($this->id);
|
||||
}
|
||||
|
||||
case 'modelFQCN':
|
||||
if (isset($this->associatedModel)) {
|
||||
return $this->associatedModel;
|
||||
}
|
||||
case 'weightTotal':
|
||||
return round($this->weight * $this->qty, $decimals);
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
if (config('cart.gross_price')) {
|
||||
switch ($attribute) {
|
||||
case 'priceNet':
|
||||
return round($this->price / (1 + ($this->taxRate / 100)), $decimals);
|
||||
case 'discount':
|
||||
return $this->priceNet * ($this->discountRate / 100);
|
||||
case 'tax':
|
||||
return round($this->priceTarget * ($this->taxRate / 100), $decimals);
|
||||
case 'priceTax':
|
||||
return round($this->priceTarget + $this->tax, $decimals);
|
||||
case 'discountTotal':
|
||||
return round($this->discount * $this->qty, $decimals);
|
||||
case 'priceTotal':
|
||||
return round($this->priceNet * $this->qty, $decimals);
|
||||
case 'subtotal':
|
||||
return round($this->priceTotal - $this->discountTotal, $decimals);
|
||||
case 'priceTarget':
|
||||
return round(($this->priceTotal - $this->discountTotal) / $this->qty, $decimals);
|
||||
case 'taxTotal':
|
||||
return round($this->subtotal * ($this->taxRate / 100), $decimals);
|
||||
case 'total':
|
||||
return round($this->subtotal + $this->taxTotal, $decimals);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch ($attribute) {
|
||||
case 'discount':
|
||||
return $this->price * ($this->discountRate / 100);
|
||||
case 'tax':
|
||||
return round($this->priceTarget * ($this->taxRate / 100), $decimals);
|
||||
case 'priceTax':
|
||||
return round($this->priceTarget + $this->tax, $decimals);
|
||||
case 'discountTotal':
|
||||
return round($this->discount * $this->qty, $decimals);
|
||||
case 'priceTotal':
|
||||
return round($this->price * $this->qty, $decimals);
|
||||
case 'subtotal':
|
||||
return round($this->priceTotal - $this->discountTotal, $decimals);
|
||||
case 'priceTarget':
|
||||
return round(($this->priceTotal - $this->discountTotal) / $this->qty, $decimals);
|
||||
case 'taxTotal':
|
||||
return round($this->subtotal * ($this->taxRate / 100), $decimals);
|
||||
case 'total':
|
||||
return round($this->subtotal + $this->taxTotal, $decimals);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +468,7 @@ class CartItem implements Arrayable, Jsonable
|
||||
*/
|
||||
public static function fromArray(array $attributes)
|
||||
{
|
||||
$options = array_get($attributes, 'options', []);
|
||||
$options = Arr::get($attributes, 'options', []);
|
||||
|
||||
return new self($attributes['id'], $attributes['name'], $attributes['price'], $attributes['weight'], $options);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Gross price as base price
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This default value is used to select the method to calculate prices and taxes
|
||||
| If true the item price is managed as a gross price, so taxes will be calculated by separation/exclusion
|
||||
|
|
||||
*/
|
||||
|
||||
'gross_price' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default tax rate
|
||||
|
||||
@@ -30,6 +30,6 @@ class ShoppingcartServiceProvider extends ServiceProvider
|
||||
|
||||
$this->publishes([
|
||||
realpath(__DIR__.'/Database/migrations') => $this->app->databasePath().'/migrations',
|
||||
]);
|
||||
], 'migrations');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user