File: D:/HostingSpaces/SBogers10/shop.komma.nl/app/Cart/ShoppingCart.php
<?php
namespace App\Cart;
use App\Discounts\DiscountableTrait;
use App\Products\AbstractProductable;
use App\Session\HasSessionTrait;
use App\Products\Product\Product;
use App\ShippingCosts\ShippingCostsService;
use App\Vat\VatService;
/**
* Represents a shopping cart
*
* Class ShoppingCartService
* @package App\Cart
*/
class ShoppingCart implements ShoppingCartInterface
{
use HasSessionTrait;
use DiscountableTrait;
use HasCouponCodesTrait {
addCouponCode as traitAddCouponCode;
removeCouponCode as traitRemoveCouponCode;
}
/** @var array The names of variables in this class to store and restore. */
protected $variablesForSession = [
'items',
'couponCodes',
'shippingCosts'
];
/** @var ShoppingCartItem[] $items */
private array $items = [];
private float $shippingCosts = 0;
private VatService $vatService;
private ShippingCostsService $shippingCostService;
public function __construct()
{
$this->items = [];
$this->discountPriceMutations = collect();
$this->discountQuantityMutations = collect();
$this->restoreFromSession();
}
/**
* Add a productable in the cart
*
* @param AbstractProductable $productable
* @param int $quantity
* @return ShoppingCartItem
*/
public function addProductable(AbstractProductable $productable, int $quantity = 1) : ?ShoppingCartItem
{
/** @var Product $product */
if(!$productable) return null;
//If item exists, update it's quantity...
/** @var ShoppingCartItem $shoppingCartItem */
$item = $this->getShoppingCartItemByProductableIdAndType($productable);
if($item) {
$item->setQuantity($item->getQuantity() + $quantity);
}
//Else add a new Shopping cart item
else {
/** @var ShoppingCartItem $shoppingCartItem */
$shoppingCartItem = (app(ShoppingCartItem::class));
$item = $shoppingCartItem->setProductable($productable)->setQuantity($quantity);
$this->items[] = $item;
}
$this->saveSession();
return $item;
}
/**
* Returns an existing shoppingCartItem by checking if it has a productable with a
* certain id or false if there was no shoppingcart item with a
* productable with the specified productable id
* @param $productable
* @return ShoppingCartItem|false
*/
private function getShoppingCartItemByProductableIdAndType(AbstractProductable $productable)
{
foreach($this->items as $item)
{
$itemProductable = $item->getProductable();
/** @var ShoppingCartItem $item */
if($itemProductable->id == $productable->id && get_class($productable) === get_class($itemProductable)) return $item;
}
return false;
}
/**
* Set the amount of items for a product
*
* @param int $itemId
* @param int $quantity
*
* @return ShoppingCartInterface
*/
public function setItemQuantity(int $itemId, int $quantity = 1): ShoppingCartInterface
{
$item = $this->getItemById($itemId);
if(!$item) return $this;
$item->setQuantity($quantity);
$this->saveSession();
return $this;
}
/**
* Deletes the ShoppingCartItem that has a product with the specified id
*
* @param int $itemId
*
* @return ShoppingCartInterface
*/
public function deleteItem(int $itemId): ShoppingCartInterface
{
foreach($this->items as $index => $item) {
if ($item->getId() == $itemId) {
unset($this->items[$index]);
}
}
$this->saveSession();
return $this;
}
/**
* Clears the shopping cart of all items
*
* @return ShoppingCartInterface
*/
public function clear(): ShoppingCartInterface
{
$this->items = [];
$this->saveSession();
return $this;
}
/**
* Returns the amount of items in the cart.
* @return int
*/
public function getItemsCount(): int
{
return array_reduce($this->getItems(), function (int $accumulator, ShoppingCartItem $item) {
return $accumulator + $item->getQuantity();
}, 0);
}
/**
* Get all shopping cart items
*
* @return array
*/
public function getItems(): array
{
return !empty($this->items) ? $this->items : [];
}
/**
* Get a shoppingCartItem by ID
*
* @param $itemId int
* @return ShoppingCartItem
*/
private function getItemById(int $itemId): ?ShoppingCartItem
{
$returnItem = null;
foreach($this->items as $index => $item) {
if ($item->getId() == $itemId) {
$returnItem = $item;
}
}
return $returnItem;
}
}