Skip to content

Commit

Permalink
[ADD] sCart.
Browse files Browse the repository at this point in the history
  • Loading branch information
Seiger committed Dec 13, 2024
1 parent 667886d commit f588a79
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 96 deletions.
2 changes: 2 additions & 0 deletions lang/en/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@
"product_link_rule_help" => "Choose a rule for forming a link to the product.",
"product_link_rule_root" => "from the root of the site",
"product_name" => "Product Name",
"product_title_is_out_of_stock" => "Product :title is out of stock.",
"product_with_id_not_found" => "Product with ID :id not found.",
"products" => "Products",
"products_help" => "List of all store products.",
"products_icon" => "fa fa-store-alt",
Expand Down
2 changes: 2 additions & 0 deletions lang/ru/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@
"product_link_rule_help" => "Выберите правило для формирования ссылки на товар.",
"product_link_rule_root" => "от корня сайта",
"product_name" => "Название товара",
"product_title_is_out_of_stock" => "Продукт :title недостаточное количество на складе.",
"product_with_id_not_found" => "Товар с ID :id не найден.",
"products" => "Товари",
"products_help" => "Перечень всех товаров магазина.",
"products_icon" => "fa fa-store-alt",
Expand Down
2 changes: 2 additions & 0 deletions lang/uk/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@
"product_link_rule_help" => "Оберіть правило для формування посилання на товар.",
"product_link_rule_root" => "від корня сайту",
"product_name" => "Назва товару",
"product_title_is_out_of_stock" => "Продукт :title недостатня кількість на складі.",
"product_with_id_not_found" => "Товар із ID :id не знайдено.",
"products" => "Товари",
"products_help" => "Перелік всіх товарів магазину.",
"products_icon" => "fa fa-store-alt",
Expand Down
8 changes: 4 additions & 4 deletions src/Http/routes.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

use Illuminate\Support\Facades\Route;
//use Seiger\sMultisite\Controllers\sCommerceController;
use Seiger\sCommerce\Facades\sCart;

/*Route::middleware('mgr')->prefix('scommerce/')->name('sCommerce.')->group(function () {
Route::get('/', [sCommerce::class, 'index'])->name('index');
});*/
Route::middleware('web')->prefix('scommerce/')->name('sCommerce.')->group(function () {
Route::post('add-to-cart', fn() => tap(sCart::addProduct(), fn($result) => response()->json($result, $result['success'] === true ? 200 : 404)))->name('addToCart');
});
30 changes: 19 additions & 11 deletions src/Models/sProduct.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,23 @@ class sProduct extends Model
*
* @var array
*/
protected $appends = ['title', 'category', 'link', 'coverSrc', 'price', 'specialPrice'];
protected $appends = [
'title',
'category',
'link',
'coverSrc',
'price',
'specialPrice'
];

/**
* Get the attributes that should be cast.
*
* @var array
*/
protected $casts = [
'quantity' => 'integer',
];

/**
* Availability constants
Expand Down Expand Up @@ -429,11 +445,7 @@ public function getCoverSrcAttribute(): string
*/
public function getPriceAttribute(): string
{
if (!isset($_SESSION['currency'])) {
$_SESSION['currency'] = sCommerce::config('basic.main_currency', 'USD');
}

return $this->priceTo($_SESSION['currency']);
return $this->priceTo(sCommerce::currentCurrency());
}

/**
Expand Down Expand Up @@ -469,11 +481,7 @@ public function priceToNumber($currency): float
*/
public function getSpecialPriceAttribute(): string
{
if (!isset($_SESSION['currency'])) {
$_SESSION['currency'] = sCommerce::config('basic.main_currency', 'USD');
}

return $this->specialPriceTo($_SESSION['currency']);
return $this->specialPriceTo(sCommerce::currentCurrency());
}

/**
Expand Down
213 changes: 147 additions & 66 deletions src/sCart.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php namespace Seiger\sCommerce;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Seiger\sCommerce\Facades\sCommerce;
use Seiger\sCommerce\Models\sAttribute;
use Seiger\sCommerce\Models\sProduct;

Expand All @@ -13,18 +15,6 @@ public function __construct()
$this->cartData = $this->loadCartData();
}

/**
* Load cart data from the session or database.
*
* @return array The cart data.
*/
protected function loadCartData(): array
{
// Load cart data from the session or database
// Implementation needed based on your storage method
return session('cart', []);
}

/**
* Get a list of items in the cart with their IDs and quantities.
*
Expand All @@ -34,11 +24,14 @@ public function getItems(): array
{
$items = [];

foreach ($this->cartData as $productId => $quantity) {
$items[] = [
'product_id' => $productId,
'quantity' => $quantity
];
foreach ($this->cartData as $productId => $optionId) {
foreach ($optionId as $quantity) {
$items[] = [
'productId' => $productId,
//'optionId' => $optionId,
'quantity' => $quantity
];
}
}

return $items;
Expand All @@ -57,77 +50,81 @@ public function getDetailedItems(): array
{
$items = [];

foreach ($this->cartData as $productId => $attributes) {
// Retrieve product details from the database
foreach ($this->cartData as $productId => $optionId) {
$product = sProduct::find($productId);

// If product is not found, skip this item
if (!$product) {
continue;
}

// Get attributes for the product in the cart
$productAttributes = $this->getProductAttributes($productId, $attributes);

$items[] = [
'product_id' => $productId,
'product' => $product,
'quantity' => $attributes['quantity'] ?? 1, // Default to 1 if quantity is not set
'attributes' => $productAttributes
'quantity' => $attributes['quantity'] ?? 1,
];
}

return $items;
}

/**
* Retrieve attributes for a given product ID from the cart data.
*
* @param int $productId The ID of the product.
* @param array $attributes The attributes associated with the product in the cart.
* @return array An array of attributes and their values for the product.
*/
private function getProductAttributes(int $productId, array $attributes): array
{
$productAttributes = [];

foreach ($attributes['attributes'] ?? [] as $attributeId => $value) {
$attribute = sAttribute::find($attributeId);

// Add attribute to the array if it exists
if ($attribute) {
$productAttributes[] = [
'attribute_id' => $attributeId,
'attribute' => $attribute,
'value' => $value
];
}
}

return $productAttributes;
}

/**
* Add a product to the cart.
*
* @param int $productId The ID of the product to add.
* @param array $attributes The attributes associated with the product.
* @param int $optionId The ID option associated with the product.
* @param int $quantity The quantity of the product to add.
* @return void
*/
public function addProduct(int $productId, array $attributes = [], int $quantity = 1): void
public function addProduct(int $productId = 0, int $optionId = 0, int $quantity = 1): array
{
if (!isset($this->cartData[$productId])) {
$this->cartData[$productId] = [
'quantity' => 0,
'attributes' => []
if ($productId === 0) {
$productId = request()->integer('productId');
$optionId = request()->integer('optionId');
$quantity = max(request()->integer('quantity'), 1);
}

$product = $this->getProductDetails($productId);

if (!$product) {
Log::warning('sCart - ' . __('sCommerce::global.product_with_id_not_found', ['id' => $productId]));

return [
'success' => false,
'message' => __('sCommerce::global.product_with_id_not_found', ['id' => $productId]),
];
}

$this->cartData[$productId]['quantity'] += $quantity;
$this->cartData[$productId]['attributes'] = array_merge($this->cartData[$productId]['attributes'], $attributes);
if (!isset($this->cartData[$productId][$optionId])) {
$this->cartData[$productId][$optionId] = 0;
}

if (sCommerce::config('product.quantity_on', 0)) {
if ($product->quantity < 0) {
Log::alert('sCart - ' . __('sCommerce::global.product_title_is_out_of_stock', ['title' => $product->title]));

return [
'success' => false,
'message' => __('sCommerce::global.product_title_is_out_of_stock', ['title' => $product->title]),
];
} else {
$quantity = min($quantity, $product->quantity);
}
}

$this->cartData[$productId][$optionId] = ($quantity == 1 ? 1 : $quantity);
$this->saveCartData();

$totalCartSum = $this->getTotalCartSum();

return [
'success' => true,
'message' => "Product with ID {$productId} added to Cart.",
'productId' => $productId,
'product' => $this->getProductFields($product),
'quantity' => $this->cartData[$productId][$optionId],
'totalCartSum' => $totalCartSum,
'totalCartSumFormatted' => sCommerce::convertPrice($totalCartSum),
];
}

/**
Expand Down Expand Up @@ -158,21 +155,38 @@ public function updateQuantity(int $productId, int $quantity): void
}

/**
* Get the total number of items in the cart.
* Get the total sum of items in the cart in current Currency.
*
* @return int The total number of items in the cart.
* @return float The total sum of items in the cart.
*/
public function getTotalItems(): int
public function getTotalCartSum(): float
{
$total = 0;
$productIds = array_keys($this->cartData);
$products = sCommerce::getProducts($productIds);

foreach ($this->cartData as $item) {
$total += $item['quantity'];
foreach ($products as $product) {
foreach ($this->cartData[$product->id] as $optionId => $quantity) {
$price = $product->price_special > 0 ? $product->price_special : $product->price_regular;
$price = sCommerce::convertPriceNumber($price, $product->currency, sCommerce::currentCurrency());
$total += $price * $quantity;
}
}

return $total;
}

/**
* Load cart data from the session or database.
*
* @return array The cart data.
*/
protected function loadCartData(): array
{
//return session('sCart', []);
return $_SESSION['sCart'] ?? [];
}

/**
* Save the cart data to the session or database.
*
Expand All @@ -182,6 +196,73 @@ protected function saveCartData(): void
{
// Save cart data to the session or database
// Implementation needed based on your storage method
session(['cart' => $this->cartData]);
//session(['sCart' => $this->cartData]);
$_SESSION['sCart'] = $this->cartData;
}

/**
* Get details of a product by its ID.
*
* This method retrieves detailed information about a product from the database.
*
* @param int $productId The ID of the product.
* @throws \UnexpectedValueException If the returned object is not a product.
*/
private function getProductDetails(int $productId): ?sProduct
{
$fields = ['id', 'title', 'link', 'coverSrc', 'category', 'sku', 'quantity', 'price', 'specialPrice'];
$product = sCommerce::getProduct($productId);
return $product && $product->id ? $product : null;
}

/**
* Get details of a product by its ID with selected fields.
*
* This method retrieves detailed information about a product from the database.
*
* @param object $product The product.
* @throws \UnexpectedValueException If the returned object is not a product.
*/
private function getProductFields(object $product): ?array
{
$fields = [
'id',
'title',
'link',
'coverSrc',
'category',
'sku',
'quantity',
'price',
'specialPrice'
];
return $product->only($fields);
}

/**
* Retrieve attributes for a given product ID from the cart data.
*
* @param int $productId The ID of the product.
* @param array $attributes The attributes associated with the product in the cart.
* @return array An array of attributes and their values for the product.
*/
private function getProductAttributes(int $productId, array $attributes): array
{
$productAttributes = [];

foreach ($attributes['attributes'] ?? [] as $attributeId => $value) {
$attribute = sAttribute::find($attributeId);

// Add attribute to the array if it exists
if ($attribute) {
$productAttributes[] = [
'attribute_id' => $attributeId,
'attribute' => $attribute,
'value' => $value
];
}
}

return $productAttributes;
}
}
Loading

0 comments on commit f588a79

Please sign in to comment.