478 lines
12 KiB
PHP
Executable File
478 lines
12 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace mirzaev\arming_bot\controllers;
|
|
|
|
// Files of the project
|
|
use mirzaev\arming_bot\controllers\core,
|
|
mirzaev\arming_bot\models\cart as model,
|
|
mirzaev\arming_bot\models\product,
|
|
mirzaev\arming_bot\models\menu,
|
|
mirzaev\arming_bot\models\enumerations\language;
|
|
|
|
// Framework for PHP
|
|
use mirzaev\minimal\http\enumerations\content,
|
|
mirzaev\minimal\http\enumerations\status;
|
|
|
|
/**
|
|
* Controller of cart
|
|
*
|
|
* @package mirzaev\arming_bot\controllers
|
|
*
|
|
* @param model|null $cart Instance of the cart
|
|
* @param array $errors Registry of errors
|
|
*
|
|
* @method null index() HTML-document with shopping cart and delivery settings
|
|
* @method null product(int|string|null $identifier, ?string $type, int|string|null $amount) Change status of the product in the cart
|
|
* @method null summary() Information about products in the cart
|
|
*
|
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
*/
|
|
final class cart extends core
|
|
{
|
|
/**
|
|
* Cart
|
|
*
|
|
* @var model|null $cart Instance of the cart
|
|
*/
|
|
protected readonly ?model $cart;
|
|
|
|
/**
|
|
* Errors
|
|
*
|
|
* @var array $errors Registry of errors
|
|
*/
|
|
protected array $errors = [
|
|
'session' => [],
|
|
'account' => [],
|
|
'menu' => [],
|
|
'cart' => []
|
|
];
|
|
|
|
/**
|
|
* Index
|
|
*
|
|
* HTML-document with shopping cart and delivery settings
|
|
*
|
|
* @param null
|
|
*/
|
|
public function index(): null
|
|
{
|
|
if (isset($menu)) {
|
|
//
|
|
|
|
} else {
|
|
// Not received ... menu
|
|
|
|
// Search for filters and write to the buffer of global variables of view templater
|
|
$this->view->menu = menu::_read(
|
|
return: 'MERGE(d, { name: d.name.@language })',
|
|
sort: 'd.style.order ASC, d.created DESC, d._key DESC',
|
|
amount: 4,
|
|
parameters: ['language' => $this->language->name],
|
|
errors: $this->errors['menu']
|
|
);
|
|
}
|
|
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
// Initializing the cart data
|
|
$this->view->cart = [
|
|
'summary' => $this->cart?->summary(currency: $this->currency),
|
|
'products' => $this->cart?->products(language: $this->language, currency: $this->currency)
|
|
];
|
|
|
|
// Initializing types of avaiabld deliveries
|
|
$this->view->deliveries = [
|
|
'cdek' => [
|
|
'label' => 'CDEK'
|
|
]
|
|
];
|
|
|
|
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
|
// Request for JSON response
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->json([
|
|
'main' => '',
|
|
'errors' => $this->errors
|
|
])
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
} else if (str_contains($this->request->headers['accept'], content::any->value)) {
|
|
// Request for any response
|
|
|
|
// Render page
|
|
$page = $this->view->render('cart/page.html', [
|
|
'h2' => $this->language === language::ru ? 'Корзина' : 'Cart' // @see https://git.mirzaev.sexy/mirzaev/huesos/issues/1
|
|
]);
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->write($page)
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
|
|
// Deinitializing rendered page
|
|
unset($page);
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Product
|
|
*
|
|
* Change status of the product in the cart
|
|
*
|
|
* @param int|string|null $identifier Product identifier
|
|
* @param string|null $type Action type (toggle, write, delete, set)
|
|
* @param int|string|null $amount Amount of actions with the product (for write, delete and differently used by set)
|
|
*
|
|
* @return null
|
|
*
|
|
* @todo
|
|
* 1. Add a limit on adding products to the cart based on the number of products in stock
|
|
*/
|
|
public function product(
|
|
int|string|null $identifier = null,
|
|
?string $type = null,
|
|
int|string|null $amount = null
|
|
): null {
|
|
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
|
// Request for JSON response
|
|
|
|
// Declaring buffer with amount of the product in the cart
|
|
$cart = 0;
|
|
|
|
// Validating @todo add throwing errors
|
|
if (isset($identifier) && preg_match('/[\d]+/', urldecode($identifier), $matches)) $identifier = (int) $matches[0];
|
|
else unset($identifier);
|
|
|
|
if (isset($identifier)) {
|
|
// Received and validated identfier of the product
|
|
|
|
// Search for the product
|
|
$product = product::read(
|
|
filter: "d.identifier == @identifier && d.deleted != true && d.hidden != true",
|
|
sort: 'd.created DESC',
|
|
amount: 1,
|
|
parameters: ['identifier' => $identifier],
|
|
errors: $this->errors['cart']
|
|
);
|
|
|
|
if ($product instanceof product) {
|
|
// Initialized the product
|
|
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
if ($this->cart instanceof model) {
|
|
// Initialized the cart
|
|
|
|
// Initializing buffer with amount of the product in the cart
|
|
$cart = $this->cart->count(product: $product, limit: 100, errors: $this->errors['cart']) ?? 0;
|
|
|
|
if ($this->cart instanceof model) {
|
|
// Initialized the cart
|
|
|
|
// Validating @todo add throwing errors
|
|
if (isset($type) && preg_match('/[\w]+/', urldecode($type), $matches)) $type = $matches[0];
|
|
else unset($type);
|
|
|
|
if (isset($type)) {
|
|
// Received and validated type of action with the product
|
|
|
|
if ($type === 'toggle') {
|
|
// Write the product to the cart if is not in the cart and vice versa
|
|
|
|
if ($cart > 0) {
|
|
// The cart has the product
|
|
|
|
// Deleting the product from the cart
|
|
$this->cart->delete(product: $product, amount: $cart, errors: $this->errors['cart']);
|
|
|
|
// Reinitializing the buffer with amount of the product in the cart
|
|
$cart = 0;
|
|
} else {
|
|
// The cart has no the product
|
|
|
|
// Writing the product to the cart
|
|
$this->cart->write(product: $product, amount: 1, errors: $this->errors['cart']);
|
|
|
|
// Reinitializing the buffer with amount of the product in the cart
|
|
$cart = 1;
|
|
}
|
|
} else {
|
|
// Received not the "toggle" command
|
|
|
|
// Validating @todo add throwing errors
|
|
if (isset($amount) && preg_match('/[\d]+/', urldecode($amount), $matches)) $amount = (int) $matches[0];
|
|
else unset($amount);
|
|
|
|
if (isset($amount)) {
|
|
// Received and validated amount parameter for action with the product
|
|
|
|
if ($type === 'write') {
|
|
// Increase amount of the product in the cart
|
|
|
|
if ($cart + $amount < 101) {
|
|
// Validated amount to wrting
|
|
|
|
// Writing the product to the cart
|
|
$this->cart->write(product: $product, amount: $amount, errors: $this->errors['cart']);
|
|
|
|
// Reinitialize the buffer with amount of the product in the cart
|
|
$cart += $amount;
|
|
}
|
|
} else if ($type === 'delete') {
|
|
// Decrease amount of the product in the cart
|
|
|
|
if ($cart - $amount > -1) {
|
|
// Validated amount to deleting
|
|
|
|
// Deleting the product from the cart
|
|
$this->cart->delete(product: $product, amount: $amount, errors: $this->errors['cart']);
|
|
|
|
// Reinitialize the buffer with amount of the product in the cart
|
|
$cart -= $amount;
|
|
}
|
|
} else if ($type === 'set') {
|
|
// Set amount of the product in the cart
|
|
|
|
if ($amount > -1 && $amount < 101) {
|
|
// Validated amount to setting
|
|
|
|
if ($amount > $cart) {
|
|
// Requested amount more than actual amount of the product in the cart
|
|
|
|
// Writing the product to the cart
|
|
$this->cart->write(product: $product, amount: $amount - $cart, errors: $this->errors['cart']);
|
|
} else {
|
|
// Requested amount less than actual amount of the product in the cart
|
|
|
|
// Deleting the product from the cart
|
|
$this->cart->delete(product: $product, amount: $cart - $amount, errors: $this->errors['cart']);
|
|
}
|
|
|
|
// Reinitializing the buffer with amount of the product in the cart
|
|
$cart = $amount;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->json([
|
|
'amount' => $cart, // $cart does not store a real value, but is calculated without a repeated request to ArangoDB
|
|
'errors' => $this->errors
|
|
])
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
|
|
// Deinitializing buffer with amount of the product in the cart
|
|
unset($cart);
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Summary
|
|
*
|
|
* Information about products in the cart
|
|
*
|
|
* @return null
|
|
*/
|
|
public function summary(): null
|
|
{
|
|
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
|
// Request for JSON response
|
|
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
if ($this->cart instanceof model) {
|
|
// Initialized the cart
|
|
|
|
// Initializing summary data of the cart
|
|
$summary = $this->cart?->summary(currency: $this->currency, errors: $this->errors['cart']);
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->json([
|
|
'cost' => $summary['cost'] ?? 0,
|
|
'amount' => $summary['amount'] ?? 0,
|
|
'errors' => $this->errors
|
|
])
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
|
|
// Deinitializing summary data of the cart
|
|
unset($summary);
|
|
}
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Share
|
|
*
|
|
* Share the cart
|
|
*
|
|
* @return null
|
|
*/
|
|
public function share(): null
|
|
{
|
|
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
|
// Request for JSON response
|
|
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
if ($this->cart instanceof model) {
|
|
// Initialized the cart
|
|
|
|
if ($share = $this->cart->share ?? $this->cart->share()) {
|
|
// The cart is available for sharing
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->json([
|
|
'share' => $share,
|
|
'errors' => $this->errors
|
|
])
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
}
|
|
|
|
// Deinitializing unnecessary variables
|
|
unset($hash);
|
|
}
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Pay
|
|
*
|
|
* Pay for the cart
|
|
*
|
|
* @return null
|
|
*/
|
|
public function pay(): null
|
|
{
|
|
if (str_contains($this->request->headers['accept'], content::json->value)) {
|
|
// Request for JSON response
|
|
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
if ($this->cart instanceof model) {
|
|
// Initialized the cart
|
|
|
|
if ($share = $this->cart->share ?? $this->cart->share()) {
|
|
// The cart is available for sharing
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->json([
|
|
'share' => $share,
|
|
'errors' => $this->errors
|
|
])
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
}
|
|
|
|
// Deinitializing unnecessary variables
|
|
unset($hash);
|
|
}
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Robokassa
|
|
*
|
|
* HTML-document with robokassa iframe
|
|
*
|
|
* @param null
|
|
*
|
|
* @todo THIS MUST BE A PAYMENT OF ORDER IN THE FUTURE, NOT CART
|
|
*/
|
|
public function robokassa(): null
|
|
{
|
|
// Initializing the cart
|
|
$this->cart ??= $this->account?->cart() ?? $this->session?->cart();
|
|
|
|
// Initializing the cart data
|
|
$this->view->cart = $this->cart;
|
|
$this->view->summary = $this->cart?->summary(currency: $this->currency);
|
|
|
|
if (str_contains($this->request->headers['accept'], content::any->value)) {
|
|
// Request for any response
|
|
|
|
// Render page
|
|
$page = $this->view->render('iframes/robokassa.html');
|
|
|
|
// Sending response
|
|
$this->response
|
|
->start()
|
|
->clean()
|
|
->sse()
|
|
->write($page)
|
|
->validate($this->request)
|
|
?->body()
|
|
->end();
|
|
|
|
// Deinitializing rendered page
|
|
unset($page);
|
|
}
|
|
|
|
// Exit (success/fail)
|
|
return null;
|
|
}
|
|
}
|