first commit
This commit is contained in:
82
bundles/KupShop/ShoppingListBundle/Admin/ShoppingList.php
Normal file
82
bundles/KupShop/ShoppingListBundle/Admin/ShoppingList.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Admin;
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
|
||||
use Query\Operator;
|
||||
|
||||
class ShoppingList extends \Window
|
||||
{
|
||||
protected $tableName = 'shopping_list';
|
||||
|
||||
/** @var ShoppingListUtil */
|
||||
public $shoppingListUtil;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->shoppingListUtil = ServiceContainer::getService(ShoppingListUtil::class);
|
||||
}
|
||||
|
||||
public function get_vars()
|
||||
{
|
||||
$vars = parent::get_vars();
|
||||
if ($ID = $this->getID()) {
|
||||
$sl = $this->shoppingListUtil->getShoppingList($ID);
|
||||
$vars['items'] = $this->shoppingListUtil->fetchItems($ID, true)->getProducts();
|
||||
$vars['name'] = $sl->getName();
|
||||
$vars['id_user'] = $sl->getIdUser();
|
||||
$vars['note'] = $sl->getNote();
|
||||
$vars['date'] = $sl->getDate() ?: date('Y-m-d');
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
public function handleUpdate()
|
||||
{
|
||||
$SQL = parent::handleUpdate(); // TODO: Change the autogenerated stub
|
||||
$data = $this->getData();
|
||||
|
||||
$id = $this->getID();
|
||||
$acn = $this->getAction();
|
||||
if ($SQL && !empty($data)) {
|
||||
if ($acn == 'add') {
|
||||
$this->shoppingListUtil->updateHash($id, date('Y-m-d'));
|
||||
$this->processShoppingListItems($id, $data['items'], true);
|
||||
$this->returnOK('Nákupní seznam byl vytvořen');
|
||||
} elseif ($acn == 'edit') {
|
||||
$this->processShoppingListItems($id, $data['items']);
|
||||
$this->returnOK('Nákupní seznam byl upraven');
|
||||
}
|
||||
}
|
||||
|
||||
return $SQL;
|
||||
}
|
||||
|
||||
protected function processShoppingListItems($id_shopping_list, $items, $duplicate = false): void
|
||||
{
|
||||
if (is_iterable($items)) {
|
||||
foreach ($items as $id => $item) {
|
||||
if ($id == 0) {
|
||||
continue;
|
||||
}
|
||||
if ($id > 0 && isset($item['delete'])) {
|
||||
$this->shoppingListUtil->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->shoppingListUtil->addProductToShoppingList(
|
||||
(int) $id_shopping_list,
|
||||
(int) $item['id_product'],
|
||||
(int) $item['id_variation'] ?: null,
|
||||
floatval($item['pieces']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ShoppingList::class;
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
$txt_str['ShoppingList'] = [
|
||||
'toolbar_list' => 'Seznam nákupních seznamů',
|
||||
'toolbar_add' => 'Přidat seznam',
|
||||
|
||||
'noUserSelected' => 'Uživatel',
|
||||
'description' => 'Popis',
|
||||
'flapList' => 'Nákupní seznam',
|
||||
'name' => 'Název',
|
||||
|
||||
'submitAddNewItem' => 'Přidat další produkt',
|
||||
'editItems' => 'Uložit',
|
||||
|
||||
'titleEdit' => 'Úprava nákupního seznamu',
|
||||
];
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Admin\lists;
|
||||
|
||||
use KupShop\AdminBundle\AdminList\BaseList;
|
||||
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
|
||||
|
||||
class ShoppingListList extends BaseList
|
||||
{
|
||||
protected $tableDef = [
|
||||
'id' => 'id',
|
||||
'fields' => [
|
||||
'Uživatel' => ['field' => 'id_user', 'size' => 0.6, 'render' => 'renderCustomer'],
|
||||
'Název' => ['field' => 'name', 'size' => 2],
|
||||
'Datum' => ['field' => 'date', 'size' => 1.5, 'render' => 'renderDate'],
|
||||
'Poznámka' => ['field' => 'note', 'size' => 0.6],
|
||||
],
|
||||
];
|
||||
|
||||
public function getQuery()
|
||||
{
|
||||
return sqlQueryBuilder()
|
||||
->select('s.*, u.name as user_name, u.surname as user_surname, u.firm')
|
||||
->from('shopping_list', 's')
|
||||
->leftJoin('s', 'users', 'u', 'u.id = s.id_user');
|
||||
}
|
||||
|
||||
public function renderCustomer($values)
|
||||
{
|
||||
$userID = $values['id_user'];
|
||||
if (!$userID) {
|
||||
return $values['id_user'];
|
||||
}
|
||||
|
||||
$parts = [];
|
||||
|
||||
$name = $this->getListRowValue($values, 'user_name');
|
||||
$surname = $this->getListRowValue($values, 'user_surname');
|
||||
$company = $this->getListRowValue($values, 'firm');
|
||||
|
||||
if ($company) {
|
||||
$parts[] = $company;
|
||||
}
|
||||
|
||||
if ($name || $surname) {
|
||||
$parts[] = implode(' ', [$surname, $name]);
|
||||
}
|
||||
|
||||
return HTML::create('a')
|
||||
->attr('href', 'javascript:nw(\'users\', \''.$values['id_user'].'\')')
|
||||
->text(implode(', ', $parts));
|
||||
}
|
||||
}
|
||||
|
||||
return ShoppingListList::class;
|
||||
@@ -0,0 +1,3 @@
|
||||
<p>{ldelim}OD{rdelim} Vám posílá nákupní seznam: </p>
|
||||
|
||||
{ldelim}PRODUKTY_V_SEZNAMU{rdelim}
|
||||
@@ -0,0 +1,181 @@
|
||||
{extends "[shared]window.tpl"}
|
||||
|
||||
{block tabs}
|
||||
{windowTab id='flapList'}
|
||||
{/block}
|
||||
|
||||
{block tabsContent}
|
||||
<div id="flapList" class="tab-pane fade active in boxStatic">
|
||||
<input type="hidden" name="data[date]" value="{$date}"/>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-xs-12">
|
||||
<div class="wpj-form-group">
|
||||
<label for="data[name]">{'name'|translate}</label>
|
||||
<input type="text" id="data[name]" name="data[name]" class="form-control" value="{$name}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xs-12">
|
||||
<label for="data[id_user]">{'noUserSelected'|translate}</label>
|
||||
<select id="data[id_user]" name="data[id_user]" class="selecter" data-autocomplete="users" data-preload="users">
|
||||
{if !$id_user}
|
||||
<option value="">-- bez uživatele --</option>
|
||||
{else}
|
||||
<option value="{$id_user}">{$id_user}</option>
|
||||
{/if}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="wpj-form-group">
|
||||
<label for="data[note]">{'description'|translate}</label>
|
||||
<textarea id="data[note]" name="data[note]" class="form-control">{$note}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="items">
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<div class="wpj-form-group">
|
||||
<a href="#" data-form-add class="btn btn-success btn-block"><span
|
||||
class="bi bi-plus-lg m-r-1"></span> {'submitAddNewItem'|translate nofilter}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-panel wpj-panel-default m-b-1" data-form-new style="display:none">
|
||||
<div class="wpj-panel-body">
|
||||
{block 'autocomplete-html'}
|
||||
<div class="row wpj-form-group-flex">
|
||||
<div class="col-md-8 col-xs-12">
|
||||
<div class="wpj-form-group">
|
||||
<label for="data[product]">{'productItem'|translate:'orders'}</label>
|
||||
<input type="text" data-autocomplete-search="product" autocomplete="off" id="data[product]" name="data[product]"
|
||||
class="form-control autocomplete-control" placeholder="Vyhledat produkt"
|
||||
data-preload="product_variation"
|
||||
value="{if $body.data.id_product}{$body.data.id_product}{if $body.data.id_variation}-{$body.data.id_variation}{/if}{/if}">
|
||||
<input type="hidden" name="data[items][0][id_product]" value="{$body.data.id_product}">
|
||||
<input type="hidden" name="data[items][0][id_variation]" value="{$body.data.id_variation}">
|
||||
<script type="application/javascript">
|
||||
$('[data-autocomplete-search="product"]').adminVariationAutoComplete({
|
||||
allowSelectProduct: false,
|
||||
select: function (e, item) {
|
||||
let { product, variation } = item;
|
||||
|
||||
if (variation && typeof variation !== 'string' && variation.id) {
|
||||
variation = variation.id
|
||||
}
|
||||
|
||||
$('[name="data[items][0][id_product]"]').val(product.id);
|
||||
$('[name="data[items][0][id_variation]"]').val(variation);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-xs-10">
|
||||
<div class="wpj-form-group">
|
||||
<label for="data[items][0][pieces]">{'countPieces'|translate:'orders'}</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" id="data[items][0][pieces]" name="data[items][0][pieces]"
|
||||
size="5" maxlength="11"
|
||||
data-calculate='pieces' value="1">
|
||||
<span class="input-group-addon">{'piecesUnit'|translate:'orders'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1 col-xs-2 text-right">
|
||||
<div class="wpj-form-group">
|
||||
<a class="btn btn-danger" data-form-delete>
|
||||
<input class="hidden" type="checkbox" name="data[items][0][delete]">
|
||||
<span class="bi bi-trash"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-panel wpj-panel-default">
|
||||
<div class="wpj-panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-xs-7">
|
||||
<p><strong>{'productItem'|translate:'orders'}</strong></p>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<p><strong>{'pieces'|translate:'orders'}</strong></p>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<p><strong>{'piecePrice'|translate:'orders'} {$labelPricePreferred}</strong></p>
|
||||
</div>
|
||||
<div class="col-xs-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpj-list-group">
|
||||
{block "order-items"}
|
||||
{foreach $items as $item}
|
||||
<div class="wpj-list-group-item" data-form-item="{$item.id}">
|
||||
<input type="hidden" name="data[items][{$item.id}][id_product]" value="{$item.id}">
|
||||
<input type="hidden" name="data[items][{$item.id}][id_variation]" value="{$item.variationId}">
|
||||
<input type="hidden" name="data[items][{$item.id}][id]" value="{$item.id_slp}">
|
||||
<div class="row">
|
||||
<div class="col-xs-7">
|
||||
<strong>{$item.title}</strong>
|
||||
{if $item.variationId}
|
||||
<br><small class="variation-title">{$item.variationTitle}</small>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input class="form-control" type="number" name="data[items][{$item.id}][pieces]"
|
||||
value="{$item.pieces}">
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
{$item.price_array|format_price}
|
||||
</div>
|
||||
<div class="col-xs-1 text-right">
|
||||
<a class="btn btn-danger" data-form-delete>
|
||||
<input class="hidden" type="checkbox" name="data[items][{$item.id}][delete]">
|
||||
<span class="bi bi-trash"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/foreach}
|
||||
{/block}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
{block onready append}
|
||||
|
||||
initForm({
|
||||
selector: '#items',
|
||||
beforeAdd: function (original) {
|
||||
var $form = original();
|
||||
createAutocomplete($form);
|
||||
}
|
||||
});
|
||||
|
||||
function createAutocomplete($form) {
|
||||
$form.find('[data-autocomplete-search="product"]').adminVariationAutoComplete({
|
||||
select: function (e, item) {
|
||||
$form.find(":input[name*=id_product]").val(item.product.id);
|
||||
|
||||
if (item.variation) {
|
||||
$form.find(":input[name*=id_variation]").val(item.variation.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
{/block}
|
||||
</script>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\AdminRegister;
|
||||
|
||||
use KupShop\AdminBundle\AdminRegister\AdminRegister;
|
||||
use KupShop\AdminBundle\AdminRegister\IAdminRegisterDynamic;
|
||||
use KupShop\AdminBundle\AdminRegister\IAdminRegisterStatic;
|
||||
|
||||
class ShoppingListAdminRegister extends AdminRegister implements IAdminRegisterStatic, IAdminRegisterDynamic
|
||||
{
|
||||
public function getDynamicMenu(): array
|
||||
{
|
||||
return [
|
||||
static::createMenuItem('ordersMenu', [
|
||||
'name' => 'Shoppinglist',
|
||||
'left' => 's=menu.php&type=ShoppingList',
|
||||
'right' => 's=list.php&type=ShoppingList',
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPermissions(): array
|
||||
{
|
||||
return [
|
||||
static::createPermissions('Shoppinglist', [\Modules::SHOPPING_LIST], ['SHOPPINGLIST']),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Controller;
|
||||
|
||||
use KupShop\GraphQLBundle\EventListener\JsShopRefreshListener;
|
||||
use KupShop\KupShopBundle\Context\UserContext;
|
||||
use KupShop\KupShopBundle\Routing\TranslatedRoute;
|
||||
use KupShop\KupShopBundle\Util\Contexts;
|
||||
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
|
||||
use KupShop\ShoppingListBundle\View\ShoppingListCreateView;
|
||||
use KupShop\ShoppingListBundle\View\ShoppingListProductsView;
|
||||
use KupShop\ShoppingListBundle\View\ShoppingListSharedView;
|
||||
use KupShop\ShoppingListBundle\View\ShoppingListView;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ShoppingListController extends AbstractController
|
||||
{
|
||||
public function __construct(protected readonly ShoppingListUtil $shoppingListUtil)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#")
|
||||
*/
|
||||
public function shoppingListAction(Request $request, ShoppingListView $view)
|
||||
{
|
||||
if (!\User::getCurrentUser()) {
|
||||
addUserMessage(translate('need_log_in', 'shopping_list'), 'danger');
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_user_login_login', ['url' => urlencode($request->getUri())])
|
||||
);
|
||||
}
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/odebrat/{id}")
|
||||
*/
|
||||
public function removeAction($id)
|
||||
{
|
||||
if (!$this->shoppingListUtil->isUserOwner($id)) {
|
||||
throw new NotFoundHttpException(translate('delete_permissions', 'shopping_list'));
|
||||
}
|
||||
|
||||
$this->shoppingListUtil->deleteShoppingList($id);
|
||||
addUserMessage(translate('list_delete', 'shopping_list'), 'success');
|
||||
|
||||
return new RedirectResponse(path('kupshop_shoppinglist_shoppinglist_shoppinglist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/odebrat-produkt/{id}/")
|
||||
*/
|
||||
public function removeProductAction(Request $request, $id)
|
||||
{
|
||||
$idSl = $this->shoppingListUtil->getProductlistIdForProduct($id);
|
||||
if (!$this->shoppingListUtil->isUserOwner($idSl)) {
|
||||
throw new NotFoundHttpException(translate('delete_permissions', 'shopping_list'));
|
||||
}
|
||||
|
||||
$this->shoppingListUtil->removeProductFromList($id);
|
||||
addUserMessage(translate('list_product_delete', 'shopping_list'), 'success');
|
||||
|
||||
if (findModule(\Modules::JS_SHOP) && $this->shoppingListUtil->getShoppingListLabel($idSl) === 'favorites') {
|
||||
$request->getSession()->set(JsShopRefreshListener::SESSION_NAME, true);
|
||||
}
|
||||
|
||||
return new RedirectResponse($this->getNextUrl($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/vytvorit/")
|
||||
*
|
||||
* @return RedirectResponse|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function createShoppingList(Request $request, ShoppingListCreateView $view)
|
||||
{
|
||||
if ($request->request->get('newListName')) {
|
||||
$listId = $this->shoppingListUtil->createShoppingList($request->request->get('newListName'));
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_shoppinglist_shoppinglist_showshoppinglistproducts', ['listId' => $listId])
|
||||
);
|
||||
}
|
||||
|
||||
addUserMessage(translate('enter_name', 'shopping_list'), 'danger');
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/{listId}/", requirements={"listId":"[0-9]+"})
|
||||
*/
|
||||
public function showShoppingListProducts(ShoppingListProductsView $view, $listId, Request $request)
|
||||
{
|
||||
if (!$this->shoppingListUtil->isUserOwner($listId)) {
|
||||
throw new NotFoundHttpException(translate('not_permission', 'shopping_list'));
|
||||
}
|
||||
|
||||
$view->setIdList($listId);
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/{listId}/{hash}", requirements={"listId":"[0-9]+", "hash":".*"})
|
||||
*/
|
||||
public function showSharedShoppingListProducts(ShoppingListSharedView $view, $listId, $hash, Request $request)
|
||||
{
|
||||
if (!($this->shoppingListUtil->validHash($listId, $hash) || $this->shoppingListUtil->isUserOwner($listId))) {
|
||||
addUserMessage(translate('not_permission', 'shopping_list'), 'danger');
|
||||
throw new NotFoundHttpException('Shopping list not found');
|
||||
}
|
||||
|
||||
$view->setIdList($listId);
|
||||
|
||||
return $view->getResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/pridat/")
|
||||
*/
|
||||
public function addProductToShoppingList(Request $request)
|
||||
{
|
||||
$listId = $request->get('shoppingListId');
|
||||
if (!$listId && $request->get('newListName')) {
|
||||
$listId = $this->shoppingListUtil->createShoppingList($request->request->get('newListName'));
|
||||
} elseif (!$listId) {
|
||||
addUserMessage(translate('select_shopping_list', 'shopping_list'), 'danger');
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_shoppinglist_shoppinglist_shoppinglist')
|
||||
);
|
||||
}
|
||||
|
||||
if (!$this->shoppingListUtil->isUserOwner($listId)) {
|
||||
addUserMessage(translate('not_permission', 'shopping_list'), 'danger');
|
||||
|
||||
return new RedirectResponse(
|
||||
path('kupshop_shoppinglist_shoppinglist_shoppinglist')
|
||||
);
|
||||
}
|
||||
|
||||
$this->shoppingListUtil->addToShoppingList($listId, $request->get('products') ?? []);
|
||||
addUserMessage(translate('add_to_shopping_list', 'shopping_list'), 'success');
|
||||
|
||||
if ($request->get('addFromCart')) {
|
||||
addUserMessage(translate('copy_to_shopping_list', 'shopping_list'), 'success');
|
||||
|
||||
$this->shoppingListUtil->addItemsFromCart($listId);
|
||||
}
|
||||
|
||||
return new RedirectResponse($this->getNextUrl($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/do-kosiku/{listId}", requirements={"listId":"[0-9]+"})
|
||||
*/
|
||||
public function addEntireListToCart($listId, ShoppingListUtil $shoppingListUtil)
|
||||
{
|
||||
foreach ($this->shoppingListUtil->fetchItems($listId)->getProducts() as $item) {
|
||||
$cartItem = [
|
||||
'id_product' => $item->id,
|
||||
'id_variation' => $item->variationId ?? null,
|
||||
'pieces' => $item['pieces'],
|
||||
];
|
||||
$shoppingListUtil->addItemToCart($cartItem);
|
||||
}
|
||||
addUserMessage(translate('added_items_to_cart', 'shopping_list'), 'success');
|
||||
|
||||
return new RedirectResponse(path('kupshop_shoppinglist_shoppinglist_shoppinglist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @TranslatedRoute("/#shopping-list#/do-kosiku/")
|
||||
*/
|
||||
public function addShoppingListToCart(Request $request)
|
||||
{
|
||||
$slProducts = $request->get('products');
|
||||
|
||||
if ($request->get('updateCount') && is_iterable($slProducts)) {
|
||||
$this->shoppingListUtil->updateShoppingList($slProducts);
|
||||
addUserMessage(translate('update_shopping_list', 'shopping_list'), 'success');
|
||||
} elseif ($request->get('addProduct')) {
|
||||
$pieces = $slProducts[$request->get('addProduct')] ?? null;
|
||||
$this->shoppingListUtil->addItemsToCart([intval($request->get('addProduct')) => $pieces]);
|
||||
addUserMessage(translate('added_items_to_cart', 'shopping_list'), 'success');
|
||||
} elseif ($request->get('addAllProducts') && is_iterable($slProducts)) {
|
||||
$this->shoppingListUtil->addItemsToCart($slProducts);
|
||||
addUserMessage(translate('added_items_to_cart', 'shopping_list'), 'success');
|
||||
}
|
||||
|
||||
return new RedirectResponse($this->getNextUrl($request));
|
||||
}
|
||||
|
||||
#[TranslatedRoute(path: '/#shopping-list#/prejmenovat/{listId}')]
|
||||
public function renameShoppingList(Request $request, $listId)
|
||||
{
|
||||
if (!$this->shoppingListUtil->isUserOwner($listId)) {
|
||||
throw new NotFoundHttpException('Shopping list not found');
|
||||
}
|
||||
$name = $request->get('name');
|
||||
$from = $request->get('from');
|
||||
|
||||
if (!empty($name)) {
|
||||
$this->shoppingListUtil->renameShoppingList($listId, $name);
|
||||
}
|
||||
|
||||
if ($from == 'detail') {
|
||||
return new RedirectResponse(path('kupshop_shoppinglist_shoppinglist_showshoppinglistproducts', ['listId' => $listId]));
|
||||
} else {
|
||||
return new RedirectResponse(path('kupshop_shoppinglist_shoppinglist_shoppinglist'));
|
||||
}
|
||||
}
|
||||
|
||||
#[TranslatedRoute(path: '/#shopping-list#/sdilet/')]
|
||||
public function shareShoppingList(Request $request): RedirectResponse
|
||||
{
|
||||
$email = $request->get('email');
|
||||
$listId = $request->get('listId');
|
||||
|
||||
if (!$nameFrom = $request->get('nameFrom')) {
|
||||
$userContext = Contexts::get(UserContext::class);
|
||||
$user = $userContext->getActive();
|
||||
|
||||
$nameFrom = $user->name.' '.$user->surname ?? '';
|
||||
}
|
||||
|
||||
if (!$this->shoppingListUtil->isUserOwner($listId)) {
|
||||
throw new NotFoundHttpException('Shopping list not found');
|
||||
}
|
||||
|
||||
$this->shoppingListUtil->shareShoppingList($listId, $email, $nameFrom);
|
||||
|
||||
addUserMessage(translate('shopping_list_email_sent', 'shopping_list'), 'success');
|
||||
|
||||
return new RedirectResponse(path('kupshop_shoppinglist_shoppinglist_shoppinglist'));
|
||||
}
|
||||
|
||||
private function getNextUrl(Request $request)
|
||||
{
|
||||
if ($next = $request->query->get('NEXT')) {
|
||||
return $next;
|
||||
}
|
||||
|
||||
return $request->headers->get('referer', '/');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Email;
|
||||
|
||||
use KupShop\KupShopBundle\Email\BaseEmail;
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
class ShareShoppingListEmail extends BaseEmail
|
||||
{
|
||||
protected static $name = 'Sdílení nákupního seznamu';
|
||||
protected static $type = 'SHARE_SHOPPING_LIST';
|
||||
protected static $priority = -20;
|
||||
|
||||
protected $subject = 'Můj nákupní seznam';
|
||||
protected $template = 'email/email_share_shopping_list.tpl';
|
||||
|
||||
public ShoppingListUtil $shoppingListUtil;
|
||||
public int $listId;
|
||||
public string $from;
|
||||
|
||||
#[Required]
|
||||
final public function setShoppingListUtil(ShoppingListUtil $shoppingListUtil): void
|
||||
{
|
||||
$this->shoppingListUtil = $shoppingListUtil;
|
||||
}
|
||||
|
||||
public function setListId(int $listId): void
|
||||
{
|
||||
$this->listId = $listId;
|
||||
}
|
||||
|
||||
public function setFrom(string $from): void
|
||||
{
|
||||
$this->from = $from;
|
||||
}
|
||||
|
||||
public function testEmail(): array
|
||||
{
|
||||
$listId = sqlQueryBuilder()
|
||||
->select('id')
|
||||
->from('shopping_list')
|
||||
->setMaxResults(1)
|
||||
->execute()->fetchOne();
|
||||
|
||||
$shoppingList = $this->shoppingListUtil->getShoppingList($listId);
|
||||
$this->setListId($shoppingList->getId());
|
||||
$this->setFrom('Testovací Uživatel');
|
||||
|
||||
return parent::testEmail();
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
parent::__wakeup();
|
||||
|
||||
$this->shoppingListUtil = ServiceContainer::getService(ShoppingListUtil::class);
|
||||
}
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
return array_diff(parent::__sleep(), ['shoppingListUtil']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KupShop\ShoppingListBundle\EmailRegister;
|
||||
|
||||
use KupShop\KupShopBundle\Email\EmailInterface;
|
||||
use KupShop\KupShopBundle\EmailRegister\EmailRegisterInterface;
|
||||
use KupShop\ShoppingListBundle\Email\ShareShoppingListEmail;
|
||||
|
||||
class ShoppingListEmailRegister implements EmailRegisterInterface
|
||||
{
|
||||
public function applyPlaceholders(EmailInterface $email): void
|
||||
{
|
||||
if ($email instanceof ShareShoppingListEmail) {
|
||||
$email->addPlaceholder('PRODUKTY_V_SEZNAMU', function () use ($email) {
|
||||
$smarty = createSmarty(false, true);
|
||||
$smarty->assign('products', $email->shoppingListUtil->fetchItems($email->listId)->getProducts());
|
||||
|
||||
return $smarty->fetch('email/block.shopping-list-items.tpl');
|
||||
}, 'Produkty v nákupním seznamu');
|
||||
|
||||
$email->addPlaceholder('OD', function () use ($email) {
|
||||
return $email->from;
|
||||
}, 'Nákupní seznam uživatele');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Entity;
|
||||
|
||||
class ShoppingListEntity
|
||||
{
|
||||
private $id;
|
||||
private $id_user;
|
||||
private $name;
|
||||
private $date;
|
||||
private $note;
|
||||
public $hash;
|
||||
private $label;
|
||||
|
||||
public function __construct($id = null)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getId(): int
|
||||
{
|
||||
return (int) $this->id;
|
||||
}
|
||||
|
||||
public function getIdUser()
|
||||
{
|
||||
return $this->id_user;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getNote()
|
||||
{
|
||||
return $this->note;
|
||||
}
|
||||
|
||||
public function setIdUser($id_user): void
|
||||
{
|
||||
$this->id_user = $id_user;
|
||||
}
|
||||
|
||||
public function setName($name): void
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setNote($note): void
|
||||
{
|
||||
$this->note = $note;
|
||||
}
|
||||
|
||||
public function setId(?int $id): ShoppingListEntity
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDate($date): void
|
||||
{
|
||||
$this->date = $date;
|
||||
}
|
||||
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
public function getHash()
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function setHash($hash): void
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setLabel($label): void
|
||||
{
|
||||
$this->label = $label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
ProductSetsBundle:
|
||||
resource: "@ShoppingListBundle/Controller"
|
||||
type: annotation
|
||||
@@ -0,0 +1,7 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
KupShop\ShoppingListBundle\:
|
||||
resource: ../../{Controller,View,AdminRegister,Entity,Util,Email,EmailRegister}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty plugin.
|
||||
*/
|
||||
use KupShop\KupShopBundle\Context\UserContext;
|
||||
use KupShop\KupShopBundle\Util\Contexts;
|
||||
|
||||
/**
|
||||
* Type: function<br>
|
||||
* Name: get_shopping_lists<br>
|
||||
* Purpose: return array of shopping lists.
|
||||
*
|
||||
* @param array $params parameters
|
||||
* @param Smarty_Internal_Template $smarty template object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function smarty_function_get_shopping_lists($params, &$smarty)
|
||||
{
|
||||
$userContext = Contexts::get(UserContext::class);
|
||||
if ($userContext->getActiveId()) {
|
||||
$userId = (int) $userContext->getActiveId();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
$SQL = sqlQueryBuilder()
|
||||
->select('id, name')
|
||||
->from('shopping_list')
|
||||
->andWhere(\Query\Operator::equals(['id_user' => $userId]))
|
||||
->execute();
|
||||
|
||||
if (!empty($SQL)) {
|
||||
foreach ($SQL as $list) {
|
||||
$lists[] = ['id' => $list['id'], 'name' => $list['name']];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['assign']) && !empty($lists)) {
|
||||
$smarty->assign($params['assign'], $lists);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{foreach $products as $product}
|
||||
<a href="{url s='redir' type='product' id=$product.id absolute="1"}">{$product.title}</a><br />
|
||||
{/foreach}
|
||||
@@ -0,0 +1,76 @@
|
||||
{extends "focus/focus.base.tpl"}
|
||||
|
||||
{block "focus-title"}
|
||||
{if $onlyCreate}
|
||||
{t}Vytvořit nový seznam{/t}
|
||||
{else}
|
||||
{t}Přidat do seznamu{/t}
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block "focus-content"}
|
||||
{if $body.product.variations.variations|count and !$product.variationId}
|
||||
<div class="alert alert-danger">{t}Nejprve vyberte variantu produktu.{/t}</div>
|
||||
{elseif $onlyCreate}
|
||||
<form action="{path('kupshop_shoppinglist_shoppinglist_createshoppinglist')}" method="post" data-shopping-list-form>
|
||||
<div class="form-group">
|
||||
<input type="text" name="newListName" class="form-control" placeholder="{t}Název seznamu{/t}">
|
||||
</div>
|
||||
<button class="btn btn-primary btn-block" type="submit" disabled>{t}Vytvořit{/t}</button>
|
||||
</form>
|
||||
{else}
|
||||
<form action="{path('kupshop_shoppinglist_shoppinglist_addproducttoshoppinglist')}" method="post" data-shopping-list-form>
|
||||
{get_shopping_lists assign='shoppingLists'}
|
||||
{if $shoppingLists|count}
|
||||
<div class="form-group">
|
||||
<label>{t}Nákupní seznam{/t}</label>
|
||||
<select name="shoppingListId" class="form-control input-sm">
|
||||
<option value="">{t}Nevybráno{/t}</option>
|
||||
{foreach $shoppingLists as $value}
|
||||
<option value="{$value.id}">
|
||||
{$value.name}
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<p>{t}nebo{/t}</p>
|
||||
{/if}
|
||||
<div class="form-group">
|
||||
<input type="text" name="newListName" class="form-control input-sm" placeholder="{t}Vytvořit nový seznam{/t}">
|
||||
</div>
|
||||
{if $cart}
|
||||
<input type="hidden" name="addFromCart" value="1">
|
||||
{else}
|
||||
{if $product.variationId}
|
||||
<input type="hidden" name="products[{$product.id}][variationId]" value="{$product.variationId}">
|
||||
{/if}
|
||||
<input type="hidden" name="products[{$body.product.id|default:$product.id}][productId]"
|
||||
value="{$body.product.id|default:$product.id}">
|
||||
<input type="hidden" name="products[{$body.product.id|default:$product.id}][pieces]" value="1">
|
||||
{/if}
|
||||
<button class="btn btn-primary btn-block" type="submit" disabled>{t}Uložit{/t}</button>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
{if !($body.product.variations.variations|count and !$product.variationId)}
|
||||
<script>
|
||||
wpj.onReady.push(function () {
|
||||
const $selectList = $('[name="shoppingListId"]');
|
||||
const $newList = $('[name="newListName"]');
|
||||
const $submitBtn = $('[data-shopping-list-form] button[type="submit"]');
|
||||
|
||||
const toggleSubmitBtn = () => {
|
||||
const isEnabled = !!$selectList.val() || !!$newList.val();
|
||||
$submitBtn.attr('disabled', () => isEnabled ? null : 'disabled');
|
||||
};
|
||||
|
||||
toggleSubmitBtn();
|
||||
$newList.on('input', toggleSubmitBtn);
|
||||
|
||||
if ($selectList.length > 0) {
|
||||
$selectList.on('change', toggleSubmitBtn);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/if}
|
||||
{/block}
|
||||
@@ -0,0 +1,19 @@
|
||||
{extends "focus/focus.base.tpl"}
|
||||
|
||||
{block "focus-title"}
|
||||
{t}Přejmenovat{/t}
|
||||
{/block}
|
||||
|
||||
{block "focus-content"}
|
||||
<form method="post"
|
||||
action="{path("kupshop_shoppinglist_shoppinglist_renameshoppinglist", ['listId' => $body.listId, 'from' => $from|default: 'detail'])}">
|
||||
<div class="form-group">
|
||||
<label for="list-name">{t}Nový název nákupního seznamu{/t}</label>
|
||||
<input id="list-name" name="name" value="{$body.listName}" class="form-control" data-copy="val">
|
||||
</div>
|
||||
<div class="shopping-list-buttons">
|
||||
<button data-listid="{$listId}" class="btn btn-primary" data-focus="close">{t}Zrušit{/t}</button>
|
||||
<input type="submit" class="btn btn-ctr" value="{t}Přejmenovat{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
@@ -0,0 +1,26 @@
|
||||
{extends "focus/focus.base.tpl"}
|
||||
|
||||
{block "focus-title"}
|
||||
{t}Sdílet seznam{/t}
|
||||
{/block}
|
||||
|
||||
{block "focus-content"}
|
||||
<div class="form-group">
|
||||
<label>{t}Odkaz na seznam{/t} {$body.listName|default:"{t}bez názvu{/t}"}</label>
|
||||
<input name="share"
|
||||
value="{path('kupshop_shoppinglist_shoppinglist_showsharedshoppinglistproducts', ['listId'=>$body.listId, 'hash'=>$body.listHash], 0)}"
|
||||
class="form-control" readonly data-copy="val">
|
||||
<button class="btn btn-primary btn-block" data-copy="btn">{t}Zkopírovat odkaz{/t}</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<form action="{path('kupshop_shoppinglist_shoppinglist_shareshoppinglist')}">
|
||||
<input type="hidden" value="{$body.listId}" name="listId">
|
||||
<label>{t}Poslat e-mailem seznam{/t} {$body.listName|default:"{t}bez názvu{/t}"}</label>
|
||||
<div class="form-group"><input class="form-control" type="email" name="email" placeholder="{t}E-mail{/t}"></div>
|
||||
<div class="form-group"><input class="form-control" type="text" name="nameFrom" placeholder="{t}Jméno{/t}"></div>
|
||||
<input class="btn btn-primary" type="submit" value="{t}Odeslat e-mail{/t}">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/block}
|
||||
@@ -0,0 +1,15 @@
|
||||
{extends "account/account-wrapper.tpl"}
|
||||
|
||||
{block "title"}
|
||||
<h1>{$view->getTitle()}</h1>
|
||||
{/block}
|
||||
|
||||
{block "account-content"}
|
||||
<form method="post" action="{path('kupshop_shoppinglist_shoppinglist_createshoppinglist')}">
|
||||
<div class="form-group">
|
||||
<label for="newListName">{t}Název{/t}</label>
|
||||
<input type="text" name="newListName" id="newListName" class="form-control">
|
||||
</div>
|
||||
<button name="submit" type="submit" value="{t}Vytvořit{/t}" class="btn btn-search" >{t}Vytvořit{/t}</button>
|
||||
</form>
|
||||
{/block}
|
||||
@@ -0,0 +1,68 @@
|
||||
{extends "account/account-wrapper.tpl"}
|
||||
|
||||
{block "title"}
|
||||
<h1>{$view->getTitle()}</h1>
|
||||
{/block}
|
||||
|
||||
{block "account-content"}
|
||||
<table class="table table-shopping-lists">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t}Název{/t}</th>
|
||||
<th>{t}Počet položek{/t}</th>
|
||||
<th>{t}Datum vytvoření{/t}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $body.lists as $list}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{path('kupshop_shoppinglist_shoppinglist_showshoppinglistproducts', ['listId'=>$list.id])}">
|
||||
{$list.name|default:"{t}bez názvu{/t}"}
|
||||
</a>
|
||||
</td>
|
||||
<td>{$list.pocet}</td>
|
||||
<td>{$list.date|date_format:"%d. %m. %Y"}</td>
|
||||
|
||||
<td class="link">
|
||||
{*<a href="{path('kupshop_shoppinglist_shoppinglist_addentirelisttocart', ['listId'=>$list.id])}">
|
||||
<span class="fc icons_cart"></span>
|
||||
</a>*}
|
||||
<a data-wpj-focus="{path('kupshop_content_focus_focuslazy', ['template' => 'shopping-list-share', 'listId'=>$list.id, 'listHash'=>$list.hash, 'listName' => $list.name|default:"{t}bez názvu{/t}"])}" href="">
|
||||
<span class="fc icons_share"></span>
|
||||
</a>
|
||||
{if $list.label == 'favorites'}
|
||||
<a disabled style="pointer-events: none; opacity: .2;">
|
||||
{else}
|
||||
<a data-wpj-focus="{path("kupshop_content_focus_focuslazy", ['template' => 'shopping-list-rename','listId' => $list.id, 'listName' => $list.name|default:"{t}bez názvu{/t}"])}"
|
||||
href="" data-wpj-focus-remove-on-close="1">
|
||||
{/if}
|
||||
<span class="fc icons_edit"></span>
|
||||
</a>
|
||||
{if $list.label == 'favorites'}
|
||||
<a disabled style="pointer-events: none; opacity: .2;">
|
||||
{else}
|
||||
<a href="{path('kupshop_shoppinglist_shoppinglist_remove', ['id'=>$list.id])}"
|
||||
data-list-delete="{$list.name|default:"{t}bez názvu{/t}"}"
|
||||
data-info-message="{t}Opravdu chcete smazat seznam{/t}">
|
||||
{/if}
|
||||
<span class="fc icons_trash"></span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{foreachelse}
|
||||
<tr>
|
||||
<td colspan="4">{t}Prozatím nemáte žádné seznamy.{/t}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{$url = path('kupshop_shoppinglist_shoppinglist_createshoppinglist')}
|
||||
<button type="button" class="btn btn-primary" data-focus-opener="shopping-list">{t}Vytvořit nový seznam{/t}</button>
|
||||
{include "focus/focus.add-shopping-list.tpl" class="shopping-list" onlyCreate=true}
|
||||
{/block}
|
||||
|
||||
{block "js-entry" append}
|
||||
{encore_entry_script_tags entry='shopping_list'}
|
||||
{/block}
|
||||
@@ -0,0 +1,128 @@
|
||||
{$body.products = $body.products->getProducts()}
|
||||
<div class="shopping-list-links">
|
||||
{* <a href="" data-wpj-focus="{path('kupshop_content_focus_focuslazy', ['template' => 'product-delivery', 'productId' => $product.id, 'variationId' => $product.variationId])}">{t}Kdy zboží obdržím?{/t}</a>*}
|
||||
<a data-wpj-focus="{path('kupshop_content_focus_focuslazy', ['template' => 'shopping-list-share', 'listId'=>$body.listId, 'listHash'=>$body.hash, 'listName' => $view->getTitle()])}" href="">
|
||||
<span class="fc icons_share"></span> {t}Sdílet seznam{/t}</a>
|
||||
{if $view->isUserOwner($body.listId)}
|
||||
{if $view->getLabel() != 'favorites'}
|
||||
<a data-wpj-focus="{path("kupshop_content_focus_focuslazy", ['template' => 'shopping-list-rename','listId' => $body.listId, 'listName' => $view->getTitle()])}" href=""
|
||||
data-wpj-focus-remove-on-close="1">
|
||||
<span class="fc icons_file-txt"></span> {t}Přejmenovat seznam{/t}</a>
|
||||
<a href="{path('kupshop_shoppinglist_shoppinglist_remove', ['id'=>$body.listId])}"
|
||||
data-info-message="{t}Opravdu chcete smazat seznam{/t}"
|
||||
data-list-delete="{$view->getTitle()|default:"{t}bez názvu{/t}"}">
|
||||
<span class="fc icons_trash"></span> {t}Smazat seznam{/t}</a>
|
||||
{/if}
|
||||
{/if}
|
||||
<span>{$body.products|count} {t plural="položky" plural5="položek" count=$body.products|count}položka{/t}</span>
|
||||
</div>
|
||||
<form action="{path('kupshop_shoppinglist_shoppinglist_addshoppinglisttocart')}" method="post">
|
||||
<input type="hidden" value="{$body.listId}" name="listId">
|
||||
|
||||
<div class="shopping-list-products">
|
||||
{foreach $body.products as $product}
|
||||
<div class="product">
|
||||
<div class="image">
|
||||
<a href="{url s=product IDproduct=$product.id TITLE=$product.title}"
|
||||
title="{t}Zobrazit zboží{/t}">
|
||||
{$photo_type = 'product_catalog'}
|
||||
{if $cfg.Photo.types['product_cart']}
|
||||
{$photo_type = 'product_cart'}
|
||||
{/if}
|
||||
{$photo_dimensions = $cfg.Photo.types[$photo_type].size}
|
||||
|
||||
<img src="{get_photo photo=$product.image size=$photo_type}" alt="{$product.title}" class="img-responsive"
|
||||
width="{$photo_dimensions[0]}" height="{$photo_dimensions[1]}">
|
||||
</a>
|
||||
</div>
|
||||
<div class="title">
|
||||
<a href="{url s=product IDproduct=$product.id TITLE=$product.title}"
|
||||
title="{t}Zobrazit produkt{/t}">{$product.title}</a>
|
||||
{if $product.variationTitle}
|
||||
<span class="variation">{$product.variationTitle}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="availability">
|
||||
{block "availability"}
|
||||
{if $product.inStore > 0}
|
||||
{$inStore = $product.inStore|round:$product.unit.pieces_precision}
|
||||
{if $product.in_store_show_max && $inStore > $product.in_store_show_max}
|
||||
{$inStore = $product.in_store_show_max|round:$product.unit.pieces_precision}
|
||||
{/if}
|
||||
|
||||
{if $dbcfg.inStore_max_visible and $inStore > $dbcfg.inStore_max_visible}
|
||||
{$inStore = "> $inStore"}
|
||||
{/if}
|
||||
<span class="delivery delivery-0">{t}skladem{/t} {$inStore}
|
||||
{$product.unit.short_name|default:"{t}ks{/t}"}</span>
|
||||
{else}
|
||||
<span class="delivery delivery-{$product.deliveryTime}">{$product.deliveryTimeText}</span>
|
||||
{/if}
|
||||
{/block}
|
||||
</div>
|
||||
<div class="in-cart">
|
||||
{$product.in_cart|round:$product.unit.pieces_precision} {$product.unit.short_name|default:"{t}ks{/t}"} {t}v košíku{/t}
|
||||
</div>
|
||||
<div class="price">
|
||||
{$product.productPrice|format_price}
|
||||
</div>
|
||||
<div class="pieces" data-buy_count="wrapper">
|
||||
{$step = 1}
|
||||
|
||||
{ifmodule PRODUCTS__STEP}
|
||||
{if $item && $item.product}
|
||||
{$data = $item.product->getData()}
|
||||
{$step = $data.step|default:$step}
|
||||
{/if}
|
||||
{/ifmodule}
|
||||
|
||||
<input type="number" name="products[{$product.id_slp}]" value="{$product.pieces|round:$product.unit.pieces_precision}"
|
||||
class="form-control" min="{$step}" step="{$step}" data-buy_count="input">
|
||||
<div class="buy_count">
|
||||
<button type="button" class="fc plus plus_unit icons_caret_up" title="{t mnozstvi=$step}Přidat {mnozstvi} ks{/t}"
|
||||
data-cart="plus"></button>
|
||||
<button type="button" class="fc minus minus_unit icons_caret_down"
|
||||
title="{t mnozstvi=$step}Odebrat {mnozstvi} ks{/t}"
|
||||
data-cart="minus"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btns">
|
||||
{$addToCart = ""}
|
||||
{if $product.has_variations && !$product.variationId}
|
||||
{* nejde vlozit do kosiku - neni vybrana varianta *}
|
||||
{$addToCart = "disabled"}
|
||||
{ifmodule COMPONENTS}
|
||||
{* modal pro vyber varianty a pridani do kosiku *}
|
||||
{$addToCart = "data-wpj-modal=/_modal/submit-block-modal?id_product=`$product.id`"}
|
||||
{/ifmodule}
|
||||
{/if}
|
||||
<button type="submit" name="addProduct" class="btn-reset" title="{t}Vložit do košíku{/t}"
|
||||
value="{$product.id_slp}" {$addToCart}>
|
||||
<span class="fc icons_cart" {if $addToCart}style="color: #fc3884;"
|
||||
data-tooltip="{t}Vyberte variantu{/t}" title="{t}Vyberte variantu{/t}"{/if}></span>
|
||||
</button>
|
||||
{if $view->isUserOwner($body.listId)}
|
||||
<a href="{path('kupshop_shoppinglist_shoppinglist_removeproduct', ['id'=>$product.id_slp])}"
|
||||
title="{t}Odstranit z nákupního seznamu{/t}">
|
||||
<span class="fc icons_trash"></span>
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{foreachelse}
|
||||
<div class="alert alert-info">{t}Prozatím nemáte v seznamu žádné produkty.{/t}</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
{if $body.products|count}
|
||||
<div class="shopping-list-buttons">
|
||||
{if $view->isUserOwner($body.listId)}
|
||||
<button type="submit" name="updateCount" class="btn btn-primary" value="1">{t}Uložit počty ks v seznamu{/t}</button>
|
||||
{/if}
|
||||
{ifmodule COMPONENTS}
|
||||
{* Prozatím skrýt tlačítko Vložit vše do košíku *}
|
||||
{elsemodule}
|
||||
<button type="submit" name="addAllProducts" class="btn btn-ctr" value="1">{t}Vložit vše do košíku{/t}</button>
|
||||
{/ifmodule}
|
||||
</div>
|
||||
{/if}
|
||||
</form>
|
||||
@@ -0,0 +1,13 @@
|
||||
{extends "account/account-wrapper.tpl"}
|
||||
|
||||
{block "title"}
|
||||
<h1>{$view->getTitle()}</h1>
|
||||
{/block}
|
||||
|
||||
{block "account-content"}
|
||||
{include 'shoppingList/shopping-list-items.tpl'}
|
||||
{/block}
|
||||
|
||||
{block "js-entry" append}
|
||||
{encore_entry_script_tags entry='shopping_list'}
|
||||
{/block}
|
||||
@@ -0,0 +1,9 @@
|
||||
{extends "index.tpl"}
|
||||
|
||||
{block "content"}
|
||||
{include 'shoppingList/shopping-list-items.tpl'}
|
||||
{/block}
|
||||
|
||||
{block "js-entry" append}
|
||||
{encore_entry_script_tags entry='shopping_list'}
|
||||
{/block}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\Resources\upgrade;
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
|
||||
use Query\Operator;
|
||||
|
||||
class ShoppingListUpgrade extends \UpgradeNew
|
||||
{
|
||||
public function check_ProductsShoppingListTable()
|
||||
{
|
||||
return $this->checkTableExists('shopping_list');
|
||||
}
|
||||
|
||||
/** Create 'shopping_list' table */
|
||||
public function upgrade_ProductsShoppingListTable()
|
||||
{
|
||||
sqlQuery('create table shopping_list
|
||||
(
|
||||
id int auto_increment,
|
||||
id_user int(11) unsigned default 0 not null,
|
||||
name varchar(255) null,
|
||||
constraint shopping_list_pk
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create unique index shopping_list_id_uindex
|
||||
on shopping_list (id);
|
||||
');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ProductsShoppingListProductsTable()
|
||||
{
|
||||
return $this->checkTableExists('shopping_list_products');
|
||||
}
|
||||
|
||||
/** Create 'shopping_list' table */
|
||||
public function upgrade_ProductsShoppingListProductsTable()
|
||||
{
|
||||
sqlQuery('create table shopping_list_products
|
||||
(
|
||||
id int auto_increment null,
|
||||
id_shopping_list int null,
|
||||
id_product int not null,
|
||||
id_variation int default null null,
|
||||
pieces decimal(15, 4) default 0.0000 null,
|
||||
date_created datetime default current_timestamp null,
|
||||
constraint products_shoppig_list_products_pk
|
||||
primary key (id)
|
||||
);');
|
||||
sqlQuery('create unique index shopping_list_uniq_prod on shopping_list_products (id_shopping_list, id_product);');
|
||||
sqlQuery('create unique index shopping_list_uniq on shopping_list_products (id_shopping_list, id_product, id_variation);');
|
||||
sqlQuery('create unique index shopping_list_products_id_uindex on shopping_list_products (id);');
|
||||
sqlQuery('alter table shopping_list_products
|
||||
add constraint shopping_list_products_shopping_list_id_fk
|
||||
foreign key (id_shopping_list) references shopping_list (id) on update cascade on delete cascade;');
|
||||
sqlQuery('alter table shopping_list_products
|
||||
add constraint shopping_list_products_products_id_fk
|
||||
foreign key (id_product) references products (id) ON UPDATE CASCADE ON DELETE CASCADE;');
|
||||
sqlQuery('alter table shopping_list_products
|
||||
add constraint shopping_list_products_products_variations_id_fk
|
||||
foreign key (id_variation) references products_variations (id) ON UPDATE CASCADE ON DELETE CASCADE;');
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_shoppingListProductsCascade()
|
||||
{
|
||||
return $this->checkConstraintRule('shopping_list_products', 'shopping_list_products_products_variations_id_fk', 'CASCADE');
|
||||
}
|
||||
|
||||
/** change shopping_list_products_products_id_fk constraint to CASCADE */
|
||||
public function upgrade_shoppingListProductsCascade()
|
||||
{
|
||||
sqlQuery('ALTER TABLE shopping_list_products DROP CONSTRAINT shopping_list_products_products_id_fk');
|
||||
sqlQuery('ALTER TABLE shopping_list_products DROP CONSTRAINT shopping_list_products_products_variations_id_fk');
|
||||
sqlQuery('ALTER TABLE shopping_list_products
|
||||
ADD CONSTRAINT shopping_list_products_products_id_fk
|
||||
FOREIGN KEY (id_product) REFERENCES products (id)
|
||||
ON UPDATE CASCADE ON DELETE CASCADE');
|
||||
sqlQuery('ALTER TABLE shopping_list_products
|
||||
ADD CONSTRAINT shopping_list_products_products_variations_id_fk
|
||||
FOREIGN KEY (id_variation) REFERENCES products_variations (id)
|
||||
ON UPDATE CASCADE ON DELETE CASCADE');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ColumnDate()
|
||||
{
|
||||
return $this->checkColumnExists('shopping_list', 'date');
|
||||
}
|
||||
|
||||
/** Add index on Orders.status */
|
||||
public function upgrade_ColumnDate()
|
||||
{
|
||||
sqlQuery('alter table shopping_list add date date null;');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ColumnNote()
|
||||
{
|
||||
return $this->checkColumnExists('shopping_list', 'note');
|
||||
}
|
||||
|
||||
/** Add index on Orders.status */
|
||||
public function upgrade_ColumnNote()
|
||||
{
|
||||
sqlQuery('alter table shopping_list add note text null;');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ShoppingListHashColumn()
|
||||
{
|
||||
return $this->checkColumnExists('shopping_list', 'hash');
|
||||
}
|
||||
|
||||
/** Migrate shopping list hashes into database */
|
||||
public function upgrade_ShoppingListHashColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE shopping_list ADD COLUMN hash VARCHAR(60)');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ShoppingListDropIndexUniqProd()
|
||||
{
|
||||
return !$this->checkIndexNameExists('shopping_list_products', 'shopping_list_uniq_prod');
|
||||
}
|
||||
|
||||
/** Drop unique index id_shopping_list id_product */
|
||||
public function upgrade_ShoppingListDropIndexUniqProd()
|
||||
{
|
||||
sqlQuery('DROP INDEX shopping_list_uniq_prod ON shopping_list_products');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_ShoppingListLabelColumn()
|
||||
{
|
||||
return $this->checkColumnExists('shopping_list', 'label');
|
||||
}
|
||||
|
||||
/** Add label column to shopping_list table */
|
||||
public function upgrade_ShoppingListLabelColumn()
|
||||
{
|
||||
sqlQuery('ALTER TABLE shopping_list ADD COLUMN label VARCHAR(50) DEFAULT NULL');
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
|
||||
public function check_FavoritesShoppingList()
|
||||
{
|
||||
return findModule(\Modules::COMPONENTS) && !$this->checkTableExists('products_favorites');
|
||||
}
|
||||
|
||||
/** Migrate products favorites to shopping lists */
|
||||
public function upgrade_FavoritesShoppingList()
|
||||
{
|
||||
$shoppingListUtil = ServiceContainer::getService(ShoppingListUtil::class);
|
||||
$list_name = translate('title', 'category')['favorites'] ?? 'Favorites';
|
||||
$users = sqlQueryBuilder()->select('DISTINCT id_user')->from('products_favorites');
|
||||
foreach ($users->execute() as $user) {
|
||||
$id_user = $user['id_user'];
|
||||
$id_list = sqlQueryBuilder()->select('id')->from('shopping_list')
|
||||
->andWhere(Operator::equals(['id_user' => $id_user, 'label' => 'favorites']))
|
||||
->execute()->fetchOne();
|
||||
if (!$id_list) {
|
||||
$created = date('Y-m-d');
|
||||
sqlQueryBuilder()->insert('shopping_list')
|
||||
->directValues([
|
||||
'id_user' => $id_user,
|
||||
'date' => $created,
|
||||
'name' => $list_name,
|
||||
'label' => 'favorites',
|
||||
])->execute();
|
||||
|
||||
$id_list = intval(sqlInsertId());
|
||||
$shoppingListUtil->updateHash($id_list, $created);
|
||||
}
|
||||
|
||||
sqlQuery("INSERT IGNORE INTO shopping_list_products (id_shopping_list, id_product, pieces)
|
||||
SELECT {$id_list}, id_product, 1
|
||||
FROM products_favorites
|
||||
WHERE id_user = '{$id_user}'");
|
||||
sqlQuery("DELETE FROM products_favorites WHERE id_user = '{$id_user}'");
|
||||
}
|
||||
// delete products_favorites
|
||||
|
||||
$this->upgradeOK();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ShoppingListBundle extends Bundle
|
||||
{
|
||||
}
|
||||
395
bundles/KupShop/ShoppingListBundle/Util/ShoppingListUtil.php
Normal file
395
bundles/KupShop/ShoppingListBundle/Util/ShoppingListUtil.php
Normal file
@@ -0,0 +1,395 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Views\View;
|
||||
|
||||
class ShoppingListCreateView extends View
|
||||
{
|
||||
protected $template = 'shoppingList/create-list.tpl';
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return translate('title_create', 'shopping_list');
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Context\UserContext;
|
||||
use KupShop\KupShopBundle\Views\Traits\RequestTrait;
|
||||
use KupShop\KupShopBundle\Views\View;
|
||||
use KupShop\ShoppingListBundle\Entity\ShoppingListEntity;
|
||||
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
|
||||
|
||||
class ShoppingListProductsView extends View
|
||||
{
|
||||
use RequestTrait;
|
||||
|
||||
protected string $smartyFallback = 'account';
|
||||
protected string $entrypoint = 'account';
|
||||
protected $idList;
|
||||
|
||||
protected $template = 'shoppingList/shopping-list-products.tpl';
|
||||
|
||||
private $user;
|
||||
|
||||
public function __construct(public readonly ShoppingListUtil $shoppingListUtil, public ShoppingListEntity $shoppingListEntity, public UserContext $userContext)
|
||||
{
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->shoppingListEntity->getName() ?: translate('products_title', 'shopping_list');
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->shoppingListEntity->getLabel();
|
||||
}
|
||||
|
||||
public function getNote()
|
||||
{
|
||||
return $this->shoppingListEntity->getNote() ?: null;
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
$this->shoppingListEntity = $this->shoppingListUtil->getShoppingList($this->getIdList());
|
||||
$vars['products'] = $this->shoppingListUtil->fetchItems($this->getIdList());
|
||||
$vars['listId'] = $this->getIdList();
|
||||
$vars['hash'] = $this->shoppingListEntity->getHash();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
private function getUser()
|
||||
{
|
||||
if ($this->user) {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
return $this->user = $this->userContext->getActive();
|
||||
}
|
||||
|
||||
public function getIdList()
|
||||
{
|
||||
return $this->idList;
|
||||
}
|
||||
|
||||
public function setIdList($idList): void
|
||||
{
|
||||
$this->idList = $idList;
|
||||
}
|
||||
|
||||
public function getBreadcrumbs()
|
||||
{
|
||||
return getReturnNavigation(-1,
|
||||
'USER',
|
||||
[['link' => path('kupshop_shoppinglist_shoppinglist_shoppinglist'), 'text' => translate('title', 'shopping_list')],
|
||||
$this->getTitle(), ]);
|
||||
}
|
||||
|
||||
public function isUserOwner()
|
||||
{
|
||||
return $this->shoppingListUtil->isUserOwner($this->getIdList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Views\Traits\RequestTrait;
|
||||
|
||||
class ShoppingListSharedView extends ShoppingListProductsView
|
||||
{
|
||||
use RequestTrait;
|
||||
|
||||
protected $idList;
|
||||
|
||||
protected $template = 'shoppingList/shopping-list-shared-products.tpl';
|
||||
}
|
||||
59
bundles/KupShop/ShoppingListBundle/View/ShoppingListView.php
Normal file
59
bundles/KupShop/ShoppingListBundle/View/ShoppingListView.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace KupShop\ShoppingListBundle\View;
|
||||
|
||||
use KupShop\KupShopBundle\Views\View;
|
||||
|
||||
class ShoppingListView extends View
|
||||
{
|
||||
protected string $smartyFallback = 'account';
|
||||
protected string $entrypoint = 'account';
|
||||
protected $template = 'shoppingList/list.tpl';
|
||||
|
||||
private $user;
|
||||
|
||||
private $checkUserLog;
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return translate('title', 'shopping_list');
|
||||
}
|
||||
|
||||
public function getBodyVariables()
|
||||
{
|
||||
$vars = parent::getBodyVariables();
|
||||
$this->checkUserLog();
|
||||
$this->getUser();
|
||||
$vars['lists'] = $this->getUserShoppingLists();
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
private function getUserShoppingLists()
|
||||
{
|
||||
return $this->user->getShoppingLists();
|
||||
}
|
||||
|
||||
protected function checkUserLog()
|
||||
{
|
||||
if ($this->checkUserLog) {
|
||||
if (!$this->getUser()) {
|
||||
redirection('LOGIN');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getUser()
|
||||
{
|
||||
if ($this->user) {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
return $this->user = \User::getCurrentUser();
|
||||
}
|
||||
|
||||
public function getBreadcrumbs()
|
||||
{
|
||||
return getReturnNavigation(-1, 'USER', [$this->getTitle()]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user