396 lines
14 KiB
PHP
396 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\ShoppingListBundle\Util;
|
|
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\GraphQLBundle\EventListener\JsShopRefreshListener;
|
|
use KupShop\KupShopBundle\Config;
|
|
use KupShop\KupShopBundle\Context\UserContext;
|
|
use KupShop\OrderingBundle\Cart;
|
|
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
|
|
use KupShop\ShoppingListBundle\Email\ShareShoppingListEmail;
|
|
use KupShop\ShoppingListBundle\Entity\ShoppingListEntity;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
class ShoppingListUtil
|
|
{
|
|
#[Required]
|
|
public ShoppingListEntity $shoppingListEntity;
|
|
#[Required]
|
|
public PurchaseUtil $purchaseUtil;
|
|
#[Required]
|
|
public Cart $cart;
|
|
#[Required]
|
|
public UserContext $userContext;
|
|
|
|
#[Required]
|
|
public SessionInterface $session;
|
|
|
|
#[Required]
|
|
public ShareShoppingListEmail $shareShoppingListEmail;
|
|
|
|
public function getShoppingList(?int $id): ShoppingListEntity
|
|
{
|
|
$sl = $this->shoppingListEntity;
|
|
$list = sqlQueryBuilder()->select('*')
|
|
->from('shopping_list')
|
|
->where(
|
|
Operator::equals(
|
|
['id' => $id]
|
|
)
|
|
)
|
|
->execute()->fetch();
|
|
if (!$list) {
|
|
return $sl;
|
|
}
|
|
$sl->setId($list['id']);
|
|
$sl->setIdUser($list['id_user']);
|
|
$sl->setName($list['name']);
|
|
$sl->setNote($list['note']);
|
|
$sl->setDate($list['date']);
|
|
$sl->setHash($list['hash']);
|
|
$sl->setLabel($list['label']);
|
|
|
|
return $sl;
|
|
}
|
|
|
|
public function processShoppingListItems($id_shopping_list, $items, $duplicate = false)
|
|
{
|
|
if (is_iterable($items)) {
|
|
foreach ($items as $id => $item) {
|
|
if ($id == 0) {
|
|
continue;
|
|
}
|
|
if ($id > 0 && isset($item['delete'])) {
|
|
$this->removeProductFromList($item['id']);
|
|
} elseif ($id > 0 && !$duplicate) {
|
|
sqlQueryBuilder()->update('shopping_list_products')
|
|
->set('pieces', $item['pieces'])
|
|
->where(Operator::equals(['id' => $item['id']]))->execute();
|
|
} elseif (!empty($item['id_product'])) {
|
|
$this->addProductToShoppingList(
|
|
(int) $id_shopping_list,
|
|
(int) $item['id_product'],
|
|
(int) $item['id_variation'] ?: null,
|
|
floatval($item['pieces']));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function renameShoppingList($id_shopping_list, $new_name): void
|
|
{
|
|
sqlQueryBuilder()->update('shopping_list')->directValues(['name' => $new_name])->andWhere(Operator::equals(['id' => $id_shopping_list]))->execute();
|
|
}
|
|
|
|
public function validHash(int $slId, string $hash): bool
|
|
{
|
|
return (bool) sqlQueryBuilder()->select('count(id)')
|
|
->from('shopping_list')
|
|
->where(Operator::equals([
|
|
'id' => $slId,
|
|
'hash' => $hash,
|
|
]))
|
|
->execute()->fetchOne();
|
|
}
|
|
|
|
public function createShoppingList(string $name, ?string $label = null): int
|
|
{
|
|
$created = date('Y-m-d');
|
|
sqlQueryBuilder()->insert('shopping_list')
|
|
->directValues([
|
|
'id_user' => $this->userContext->getActiveId(),
|
|
'date' => $created,
|
|
'name' => $name,
|
|
'label' => $label,
|
|
])->execute();
|
|
|
|
$insertedId = intval(sqlInsertId());
|
|
|
|
$this->updateHash($insertedId, $created);
|
|
|
|
return $insertedId;
|
|
}
|
|
|
|
public function updateHash(int $id, string $created): void
|
|
{
|
|
sqlQueryBuilder()
|
|
->update('shopping_list')->set('hash', ':hash')
|
|
->setParameter('hash', $this->createHash($id, $created))
|
|
->where(\Query\Operator::equals(['id' => $id]))
|
|
->execute();
|
|
}
|
|
|
|
public function createHash(int $id, string $created)
|
|
{
|
|
return urlencode(
|
|
sha1(
|
|
getShopUniqueName()
|
|
.join('', [
|
|
$id,
|
|
$created,
|
|
])
|
|
)
|
|
);
|
|
}
|
|
|
|
public function fetchItems(int $idSL, $fromAdmin = false): \ProductList
|
|
{
|
|
$productList = new \ProductList(findModule(\Modules::PRODUCTS_VARIATIONS));
|
|
if (!$fromAdmin) {
|
|
$productList->applyDefaultFilterParams();
|
|
}
|
|
|
|
$productList->andSpec(function (QueryBuilder $qb) use ($idSL) {
|
|
$qb->join('p', 'shopping_list_products', 'slp', 'slp.id_product = p.id')
|
|
->andWhere('id_shopping_list=:id_shopping_list')
|
|
->addParameters(['id_shopping_list' => $idSL]);
|
|
|
|
if (findModule(\Modules::PRODUCTS_VARIATIONS)) {
|
|
$qb->andWhere('slp.id_variation IS NULL OR slp.id_variation = pv.id');
|
|
$qb->addSelect('slp.id_variation');
|
|
$qb->addSelect(\Query\Product::getInStoreField(false, $qb).' AS in_store_product');
|
|
$qb->groupBy('p.id, slp.id_variation');
|
|
}
|
|
|
|
$qb->addSelect('slp.id as id_slp, slp.pieces as slp_pieces');
|
|
if ($in_store_show_max = findModule(\Modules::PRODUCTS, \Modules::SUB_SHOW_MAX)) {
|
|
$qb->addSelect("COALESCE(p.in_store_show_max, {$in_store_show_max}) AS in_store_show_max");
|
|
}
|
|
});
|
|
|
|
$productList->addResultModifiers(function (ProductCollection $products, $dataAll) use ($fromAdmin) {
|
|
if (!$fromAdmin && ($products->count() > 0)) {
|
|
$this->countItemsInCart($products);
|
|
}
|
|
foreach ($dataAll as $key => $data) {
|
|
$products[$key]['id_slp'] = $data['id_slp'];
|
|
$products[$key]['pieces'] = $data['slp_pieces'];
|
|
if (isset($data['in_store_show_max'])) {
|
|
$products[$key]['in_store_show_max'] = $data['in_store_show_max'];
|
|
}
|
|
if (($data['has_variations'] ?? false) && empty($data['id_variation'])) {
|
|
// kdyz produkt ma varianty, ale v nakupnim seznamu je bez vybrane varianty:
|
|
// inStore a deliveryTimeText jsou od varianty (matched_id_variation), protoze productList ma variationsAsResult=true,
|
|
// potrebujeme upravit inStore a deliveryTimeText, aby byly od produktu
|
|
$products[$key]['inStore'] = $data['in_store_product'];
|
|
unset($products[$key]['in_store_suppliers']);
|
|
$products[$key]->prepareDeliveryText();
|
|
}
|
|
}
|
|
});
|
|
$cfg = Config::get();
|
|
$mainSize = 'product_cart';
|
|
if (empty($cfg['Photo']['types']['product_cart'])) {
|
|
$mainSize = 'product_catalog';
|
|
}
|
|
$productList->fetchImages($mainSize, fallbackToProductPhoto: true);
|
|
|
|
return $productList;
|
|
}
|
|
|
|
private function countItemsInCart(&$products)
|
|
{
|
|
$products->forAll(function ($key, &$product) {
|
|
$product['in_cart'] = 0;
|
|
|
|
return true;
|
|
});
|
|
if (is_null($this->cart->only_virtual_products)) {
|
|
// not yet initialized, but purchaseState could be set somehow...
|
|
$this->cart->invalidatePurchaseState();
|
|
}
|
|
foreach ($this->purchaseUtil->getPurchaseState()->getProducts() as $cartItems) {
|
|
$key = $cartItems->getIdProduct();
|
|
if (isset($products[$key])) {
|
|
$products[$key]['in_cart'] += $cartItems->getPieces();
|
|
}
|
|
if ($idVariation = $cartItems->getIdVariation()) {
|
|
$key .= '/'.$idVariation;
|
|
if (isset($products[$key])) {
|
|
$products[$key]['in_cart'] += $cartItems->getPieces();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function removeProductFromList(int $id)
|
|
{
|
|
return sqlQueryBuilder()->delete('shopping_list_products')
|
|
->where(Operator::equals(['id' => $id]))
|
|
->execute();
|
|
}
|
|
|
|
public function getProductlistIdForProduct(int $idSlProduct)
|
|
{
|
|
return sqlQueryBuilder()->select('id_shopping_list')
|
|
->from('shopping_list_products')
|
|
->where(Operator::equals(['id' => $idSlProduct]))->execute()->fetchOne();
|
|
}
|
|
|
|
public function getShoppingListLabel(int $id)
|
|
{
|
|
return sqlQueryBuilder()->select('label')
|
|
->from('shopping_list')
|
|
->where(Operator::equals(['id' => $id]))->execute()->fetchOne();
|
|
}
|
|
|
|
public function deleteShoppingList(int $id)
|
|
{
|
|
return sqlQueryBuilder()->delete('shopping_list')
|
|
->where(Operator::equals(['id' => $id]))
|
|
->execute();
|
|
}
|
|
|
|
public function isUserOwner(int $idList): bool
|
|
{
|
|
if ($userId = $this->userContext->getActiveId()) {
|
|
if (sqlQueryBuilder()->select('count(id)')
|
|
->from('shopping_list')->where(
|
|
Operator::equals(['id_user' => $userId, 'id' => $idList])
|
|
)->execute()->fetchOne()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function addProductToShoppingList(int $listId, int $productId, ?int $variationId = null, float $pieces = 1): bool
|
|
{
|
|
if ($existId = sqlQueryBuilder()->select('id')
|
|
->from('shopping_list_products')
|
|
->where(
|
|
Operator::equalsNullable(
|
|
['id_shopping_list' => $listId, 'id_product' => $productId, 'id_variation' => $variationId]
|
|
)
|
|
)
|
|
->execute()->fetchOne()) {
|
|
return (bool) sqlQueryBuilder()->update('shopping_list_products')
|
|
->set('pieces', 'pieces+'.$pieces)
|
|
->where(Operator::equals(['id' => $existId]))->execute();
|
|
}
|
|
|
|
return (bool) sqlQueryBuilder()->insert('shopping_list_products')
|
|
->directValues([
|
|
'id_shopping_list' => $listId,
|
|
'id_product' => $productId,
|
|
'id_variation' => $variationId,
|
|
'pieces' => $pieces,
|
|
]
|
|
)->execute();
|
|
}
|
|
|
|
public function addItemsToCart(array $products)
|
|
{
|
|
foreach ($products as $id => $pieces) {
|
|
$product = $this->getShoppingListItem(intval($id));
|
|
if ($product) {
|
|
$item = ['id_product' => $product['id_product'], 'id_variation' => $product['id_variation'], 'pieces' => $pieces];
|
|
$this->addItemToCart($item);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function updateShoppingList(array $products)
|
|
{
|
|
foreach ($products as $id => $pieces) {
|
|
sqlQueryBuilder()->update('shopping_list_products')
|
|
->set('pieces', $pieces)
|
|
->where(Operator::equals(['id' => $id]))->execute();
|
|
}
|
|
}
|
|
|
|
private function getShoppingListItem(int $id)
|
|
{
|
|
return sqlQueryBuilder()->select('id_product, id_variation')
|
|
->from('shopping_list_products')
|
|
->where(Operator::equals(['id' => $id]))
|
|
->execute()->fetch();
|
|
}
|
|
|
|
public function addToShoppingList(int $listId, array $products): void
|
|
{
|
|
foreach ($products as $product) {
|
|
$this->addProductToShoppingList(
|
|
$listId,
|
|
intval($product['productId']),
|
|
!empty($product['variationId']) ? intval($product['variationId']) : null,
|
|
floatval($product['pieces'] ?? 1)
|
|
);
|
|
}
|
|
}
|
|
|
|
public function addItemsFromCart($idList): void
|
|
{
|
|
foreach ($this->purchaseUtil->getPurchaseState()->getProducts() as $product) {
|
|
if ($product->getIdProduct()) {
|
|
$this->addProductToShoppingList((int) $idList, $product->getIdProduct(), $product->getIdVariation(), (float) $product->getPieces());
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getHash($id)
|
|
{
|
|
return urlencode(
|
|
sha1(
|
|
getShopUniqueName()
|
|
.join('', [
|
|
$id,
|
|
date('Y-m-d'),
|
|
])
|
|
)
|
|
);
|
|
}
|
|
|
|
public function addItemToCart($item): void
|
|
{
|
|
$id = $this->cart->addItem($item);
|
|
if ($id <= 0) {
|
|
addUserMessage(translate('error', 'order')['invalid_variation'], 'error');
|
|
|
|
return;
|
|
}
|
|
|
|
if (findModule(\Modules::JS_SHOP)) {
|
|
$this->session->set(JsShopRefreshListener::SESSION_NAME, true);
|
|
}
|
|
}
|
|
|
|
public function getFavoritesShoppingList(): ?array
|
|
{
|
|
$id_user = $this->userContext->getActiveId();
|
|
if (!$id_user) {
|
|
return null;
|
|
}
|
|
|
|
$list = sqlQueryBuilder()->select('*')->from('shopping_list')
|
|
->andWhere(Operator::equals(['id_user' => $id_user, 'label' => 'favorites']))
|
|
->execute()->fetchAssociative();
|
|
|
|
return $list ?: null;
|
|
}
|
|
|
|
public function createFavoritesShoppingList(): int
|
|
{
|
|
return $this->createShoppingList(translate('title', 'category')['favorites'] ?? 'Favorites', 'favorites');
|
|
}
|
|
|
|
public function shareShoppingList(int $listId, string $emailTo, string $from): void
|
|
{
|
|
$this->shareShoppingListEmail->setListId($listId);
|
|
$this->shareShoppingListEmail->setFrom($from);
|
|
|
|
$email = $this->shareShoppingListEmail->getEmail();
|
|
|
|
$email['to'] = $emailTo;
|
|
|
|
$this->shareShoppingListEmail->sendEmail($email);
|
|
}
|
|
}
|