Заранее оговорюсь, что не претендую на красивое решение, зато работает :)
Итак, принцип работы следующий:
— создание отдельной категории для товаров-подарков, где цена равно 0 (проверка по родителю категории будет);
— отключение аякса и перезагрузка страницы с корзиной (большой) для корректной работы плагина;
— изменение родного скрипта
— вывод украшательств в карточку товара
1. Изменение скрипта ms2
Сначала идем в системные настройки и меняем путь к скриптами минишопа. Ключ — ms2_frontend_js, значение (например) web/default_new.js
Теперь или копируем и изменяем default.js
(строка status: function (status) ),
вместо
if (status['total_count'] < 1)
пишемif(window.location.pathname == "/cart.html")
Где прописываем свой путь к большой корзине. assets/components/minishop2/js/web/default_new.js
2. Создаем подарочные товары
Тут ничего сложного. Просто в каком-то месте (например — рядом с каталогом общим) создаем категории товаров Подарки и не публикуем ее. Внутри создаем обычные товары, но с ценой равной 0. Проверяем, чтобы эти товары не мешались где-нибудь в вызовах на страницах.Например указываете parents = -5 (где 5 — id категории подарков).
В корзине заказов, под списком товаров и анимашками делаем вызов подарков.
{set $preset_limitpresent = $.session['preset_limitpresent']}
{if $preset_limitpresent > 0}
<section class="container" id="resset">
<h3>Выберите подарок</h3>
<div class="row">
</div>
</div>
{/if}
3. Создаем плагин
Отлавливаем событие изменения корзины и отдельно добавление в корзину.Я специально не вызываю
$count = $cart->status()['total_count'];
так как в этом случае подсчет будет не правильным, ведь система не разделит подарки и основные товары и в строку прогресса будет идти не то что нужно (а общая сумма).Готовый код с комментариями ниже.
<?php
switch ($modx->event->name) {
case 'msOnChangeInCart': case 'msOnRemoveFromCart': case 'msOnAddToCart' : case 'msOnEmptyCart':
$tmp = $cart->get(); //Получаем список товаров
// ниже функция для округления до 5 в большую сторону. Нужно для отлавливания колиества подарков на 5 единиц.
function roundClosest($num){
$helpVar = round($num/5);
$helpVar2 = $helpVar * 5;
if($num - $helpVar2 > 0.1){
$res = ($helpVar + 1) * 5;
}
else{
$res = $helpVar * 5;
}
return $res;
};
// а здесь мы будем склонение от количества правильное ловить
function declOfNum($num, $titles) {
$cases = array(2, 0, 1, 1, 1, 2);
return $num . " " . $titles[($num % 100 > 4 && $num % 100 < 20) ? 2 : $cases[min($num % 10, 5);
};
// эта часть нужна, если подарки будут даваться только за конкретные категории товаров (3 и 4). В ином случае можно почистить эти моменты.
$pdoRes = $modx->runSnippet('pdoResources', array( 'parents' => '3,4', 'limit' => 0, 'templates' => '4', 'tpl' => '@INLINE {$id},', 'tplLast' => '{$id}'));
$rows = explode(",",$pdoRes);
// назначаем начальные значения счетчиков и идем по массиву корзины
$count_category = 0;
$count_category_present = 0;
foreach ($tmp as &$tm) {
if ($product = $modx->getObject('msProduct', $tm['id'])) {
$parent = $product->get('parent');
// выделяем подарочную категорию
if ($parent == "5") {
$count_category_present = $count_category_present + $tm['count'];
}
else {
// и исключаем все остальные категории. Условие if внутри можно убрать, если акция на все товары магазина, а не на определенные
if (in_array($parent, $rows)) {
$count_category = $count_category + $tm['count'];
}
}
}
}
// и понеслась магия
$limit_category = $count_category / 5;
$limit_category = floor($limit_category); // получили лимит доступных товаров
$textlimit = declOfNum($limit_category, array('подарок', 'подарка', 'подарков'));
if ($count_category_present >= $limit_category) { // если подарков больше, чем нужно
$stopvount = 0;
foreach ($tmp as &$tm) {
if ($producttwo = $modx->getObject('msProduct', $tm['id'])) {
if ($producttwo->get('parent') == "5") {
$stopvount = $stopvount + $tm['count'];
if ($stopvount > $limit_category) {
$tm['count'] = 0;
}
}
}
}
}
$count = $count_category;
$more = roundClosest($count);
$more = $more - $count;
$limitpresent = floor($count / 5);
if ($more > 0) {
$ost = $limitpresent + 1;
$textmore = declOfNum($more, array('товар', 'товара', 'товаров'));
$textmoret = declOfNum($ost, array('подарка', 'подарков', 'подарков'));
$more = 'Вам осталось '.$textmore.' до '.$textmoret;
}
else {
$textmoret = declOfNum($limitpresent, array('подарка', 'подарков', 'подарков'));
$more = 'Вы собрали нужное количество товаров для '.$textmoret.'.';
}
if ($count > 0 && $count < 6) {
$width = $count * 20;
// заполняем шкалу
$_SESSION['preset_width'] = $width;
}
elseif ($count > 5) {
// заполняем шкалу
$_SESSION['preset_width'] = '100';
}
else {
$_SESSION['preset_width'] = '0';
}
$_SESSION['preset_more'] = $more;
$_SESSION['preset_limitpresent'] = $limitpresent;
$cart->set($tmp); //Записываем данные в корзину
break;
//////////////////////////////////////////////////////////
case 'msOnBeforeAddToCart' :
// и почти все то же самое на событие добавления
$tmp = $cart->get();
if ($product->get('parent') == "5"){
function declOfNum($num, $titles) {
$cases = array(2, 0, 1, 1, 1, 2);
return $num . " " . $titles[($num % 100 > 4 && $num % 100 < 20) ? 2 : $cases[min($num % 10, 5);
};
$pdoRes = $modx->runSnippet('pdoResources', array( 'parents' => '3,4', 'limit' => 0, 'templates' => '4', 'tpl' => '@INLINE {$id},', 'tplLast' => '{$id}'));
$rows = explode(",",$pdoRes);
$count_category = 0;
$count_category_present = 0;
foreach ($tmp as &$tm) {
if ($productcart = $modx->getObject('msProduct', $tm['id'])) {
$parent = $productcart->get('parent');
if ($parent == "5") {
$count_category_present = $count_category_present + $tm['count'];
}
else {
if (in_array($parent, $rows)) {
$count_category = $count_category + $tm['count'];
}
}
}
}
$limit_category = $count_category / 5;
$limit_category = floor($limit_category);
$textlimit = declOfNum($limit_category, array('товар', 'товара', 'товаров'));
if ($limit_category <= $count_category_present) {
$modx->event->output('Вы можете добавить только '.$textlimit); //прерывает добавление
}
}
$cart->set($tmp);
break;
}
4. Добавить красоту в корзину
Верстка в корзине, где происходит «магия»
<section class="progress">
{set $width = $.session['preset_width']}
<h3 class="progress__title">Доберите продукты до пяти и выберите подарок!</h3>
<div class="progress__box">
<div class="progressbar ui-progressbar ui-corner-all ui-widget ui-widget-content">
<div class="ui-progressbar-value ui-corner-left ui-widget-header" style="width:{$width}%;height: 100%;"></div>
</div>
</div>
<div class="progress__text">
{$.session['preset_more']}
</div>
</section>
Выглядит все так:
Вараника 27.02.2021 16:01 #
Вараника 19.03.2021 20:14 #
igor781 08.04.2021 22:47 #
а ну еще с точки зрения разумности у меня не .html, а / в конце, да и я где-то слышал, что нужно так писать массив [] и вот еще желательно переносить элементы массива, а не писать в одной строке, Для подарка и подарков, посоветовали компонент, вроде есть, точно не помню как называется (declOfNum ни о чем не говорит), еще говорят если pdoTools установлен, то не нужно getObject делать
Вараника 09.04.2021 11:55 #
Вараника 17.05.2021 15:29 #
Удалить товары равные 0.
Выявилось через месяцы. За вдохновение спасибо Сергею Федорову.