Перейти к содержимому


Highest Reputation Content


#34996 Добавить товар в избранное

Написано zcz на 01 November 2016 - 11:16 AM

Спонсор stasikons

Модуль позволяет реализовать на сайте блок "избранное".
Работает все на ajax, для зарегистрированных заноситься в базу, для посетителей в сессию.
Сразу скажу, что код в шаблонах написан под 3.1.3 версию, но переделать, думаю, труда не составит.
Все ajax и js (jquery) написаны универсально + есть закомментированные строки под старую и новую версию шаблона

Если в шаблоне не установлен jquery, то его необходимо будет поставить!

Установка:

!ВКЛЮЧАЕМ ПРИНУДИТЕЛЬНУЮ ОЧИСТКУ КЕША В АДМИНКЕ!

Заливаем файлы в свои директории.

Открываем index.php в корне (да он должен быть открытым.)
Находим строку

if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file" ))) {

Заменяем на

if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file", "favourites" ))) {

в файле core/config/tables.inc.php в самый низ перед закрывающим тегом ?> вставляем

if(!defined('FAVORITES_TABLE')) {
define('FAVORITES_TABLE', 'ПРЕФИКС_favourites');
}

Открываем файл core/functions/product_functions.php
Находим функцию prdSearchProductByTemplate

в ней, в самом низу, перед $result[] = $row; вставляем

//вставка для избранных товаров
if ( isset($_SESSION["log"]) ) {
$select = mysql_query("SELECT customerID FROM ".CUSTOMERS_TABLE." WHERE `Login` = '".$_SESSION["log"]."' ");
$rows = mysql_fetch_array($select);
$favorit = mysql_query("SELECT productsID FROM ".FAVORITES_TABLE." WHERE customerID = '".$rows[0]."'");
$r = mysql_fetch_array($favorit);
$prd = explode(",", $r[0]);
foreach ($prd as $v) {
if($v == $row['productID']) {
$row["inF"] = 1;
}
}
}
else {
$prd = explode(",", $_SESSION['f_prod']);
foreach ($prd as $v) {
if($v == $row['productID']) {
$row["inF"] = 1;
}
}
}
//END вставка для избранных товаров

открываем core/tpl/user/ВАШ_ШАБЛОН/product_detailed.tpl.html

в нужном месте вставляем кусок кода для кнопки "в избранное"

{*Добавить в избранное*}
<span id="favour_{$product_info.productID}">
{if $in_favorite eq 1}
<a href="#" onclick="doFavoriteDel('pID={$product_info.productID}'); return false" class="btn btn-default">Удалить из избранного</a>
{else}
<a href="#" onclick="doFavorite('pID={$product_info.productID}'); return false" class="btn btn-default">В избранное</a>
{/if}
</span>
{*END добавить в избранное*}

в файле core/tpl/user/ВАШ_ШАБЛОН/product_brief.tpl.html в нужном месте вставляем

{*Добавить в избранное*}
<span id="favour_{$product_info.productID}">
{if $product_info.inF eq 1}
<a href="#" onclick="doFavoriteDel('pID={$product_info.productID}'); return false" class="btn btn-default btn-xs">Удалить из избранного</a>
{else}
<a href="#" onclick="doFavorite('pID={$product_info.productID}'); return false" class="btn btn-default btn-xs">В избранное</a>
{/if}			  
</span>
{*END добавить в избранное*}

в core/tpl/user/ВАШ_ШАБЛОН/index.tpl.html перед закрывающим тегом </body> добавляем


{* добавление в избранное *}
<script src="data/{$smarty.const.TPL}/favourites.js"></script>
{* END добавление в избранное *}

в htaccess необходимо в самый низ добавить строки

#Избранные товары
RewriteRule ^favourites\.html$ index.php?favourites=yes [L]
#END избранные товары

После всех изменений переходим на страницу http://ВАШ_САЙТ/favourites.html

Должен сработать первый запуск модуля и вылезти окошко об успешной установке.

Устанавливаем блок из "управления блоками" (добавить блок из файла) или вставляем вручную в нужном месте шаблона.
Если все шаги были выполнены верно, то можно наслаждаться новым модулем.

Прикрепленный файл  Добавить в избранное.rar   7.47К   25 Количество загрузок:
Прикрепленный файл  favourites_js_3_1_2.rar   902байт   8 Количество загрузок: - JS для shopcms 3.1.1 и 3.1.2
  • 7


#34208 Ускоряем работу клиентской части ShopCMS при большом количестве товаров и кат...

Написано badisoft на 20 January 2016 - 03:37 PM

Ускоряем работу клиентской части ShopCMS
с большим количеством каталогов (порядка тысячи и более),
большим количеством товаров (десятки тысяч и более)
и большим количеством зарегистрированных клиентов (порядка нескольких тысяч и более).

Количество категорий и товаров можно посмотреть в "Админка->Отчеты->Системные данные".
Количество зарегистрированных клиентов в "Админка->Списки->Покупатели",
там умножить число строк (обычно это 20) на число страниц.


Программная часть (скорость выполнения PHP-кода)
================================================

При тысяче (и более) категорий основное время PHP-вычислений занимает построение иерархического списка категорий, который мы видим в блоке "Развернутый каталог" и на странице "Расширенный поиск".
При каждой перезагрузке страницы таблица категорий заново получается SQL-запросом из базы и на нее напускается рекурсивная функция построения списка, которая (при тысяче категорий/подкатегорий) работает долго.
Но зачем каждый раз заново строить список категорий в клиентской части, если изменяется этот список только в админке? Куда правильнее сохранить этот список готовым в файл и брать его каждый раз оттуда, меняя этот файл только из админки.
Примерно так и сделано.
В клиентской части: если файлов с таблицей категорий и построенным списком нет, то все происходит штатным путем (медленно), а таблица категорий и построенный список сохраняются в файлы. Т.е. на следующей странице они будут взяты уже из файлов (быстро).
В админской части: если произошли изменения в таблице категорий, то файлы удаляются и - см.выше.
Можно прямо в админке их и создать заново, но особого смысла я не вижу. Просто у первого клиента после изменений в категориях медленнее загрузится первая страница.
Второй список категорий (для "не развернутого" каталога) не трогался, т.к. строится линейно и быстро.


1. в файле category_functions.php

1.1. в функции catGetCategoryCListMin

вместо


return _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);


вставляем


# BEGIN кэшируем в файл клиентский список категорий
#return _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);
if (file_exists("core/temp/catcache.txt") && ($cache = file_get_contents("core/temp/catcache.txt")) && $cats = unserialize($cache)) return $cats;
else
{
$cats = _recursiveGetCategoryCList( 1, 0, null, 'NUM', false, false);
file_put_contents("core/temp/catcache.txt",serialize($cats));
return $cats;
}
# END кэшируем в файл клиентский список категорий


1.2. в функции update_psCount в начало вставляем


# BEGIN кэшируем в файл клиентский список категорий
if (file_exists("core/temp/catcache.txt")) unlink("core/temp/catcache.txt");
if (file_exists("core/temp/categories.txt")) unlink("core/temp/categories.txt");
# END кэшируем в файл клиентский список категорий



2. в файле index.php

2.1. перед


$q = db_query("select categoryID, name, products_count, products_count_admin, parent, picture, subcount FROM ".CATEGORIES_TABLE." ORDER BY sort_order, name");


вставляем


# BEGIN кэшируем в файл клиентский список категорий
if (file_exists("core/temp/categories.txt") && ($cache = file_get_contents("core/temp/categories.txt")) && $categories = unserialize($cache))
{
foreach ($categories as $row)
{
$fc[(int)$row["categoryID"]] = $row;
$mc[(int)$row["categoryID"]] = (int)$row["parent"];
}
}
else
{
$categories = array();
# END кэшируем в файл клиентский список категорий


2.2. после


$mc[(int)$row["categoryID"]] = (int)$row["parent"];


вставляем


# BEGIN кэшируем в файл клиентский список категорий
$categories[] = $row;
}
file_put_contents("core/temp/categories.txt",serialize($categories));
# END кэшируем в файл клиентский список категорий




SQL-часть (скорость выполнения запросов)
========================================

У таблиц категорий, товаров и клиентов довольно небольшой список используемых вариантов сортировки и полей для поиска.
Достаточно добавить несколько индексов, чтобы на удивление сильно увеличить скорость выполнения некоторых тормозных запросов.

создаем файл addon.php с содержимым


<?php
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX date_added(date_added)"); // home.php - новинки
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX items_sold(items_sold)"); // home.php - популярные

db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX sort_order_name(sort_order,name)"); // стандартная сортировка товара
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX price(Price)"); // сортировка по цене товара
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX enabled(enabled)"); // включенные-отключенные товары
db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD INDEX name(name)"); // сортировка по названию товара

db_query("ALTER TABLE ".CATEGORIES_TABLE." ADD INDEX sort_order_name(sort_order,name)"); // стандартная сортировка категорий

db_query("ALTER TABLE ".CUSTOMERS_TABLE." ADD INDEX login(Login)"); // для WHERE Login=

unlink("core/includes/admin/addon.php");
?>


Кладем его в core/includes/admin/ и заходим в админку либо перезагружаем страницу, если уже в админке.
Файл добавит индексы и должен удалиться сам, но лучше проверить (мне попадались сайты, где удаление файлов в этом каталоге было запрещено).


В общем случае я искал тормозные запросы следующим образом:

В файле mysql.php в функции db_query

строку


$res["resource"] = mysql_query($s);


заменил на


if (isset($_GET['speedtest'])) global $relaccess;list($usec, $sec) = explode(" ", microtime());$start = (float)$usec + (float)$sec;
$res["resource"] = mysql_query($s);
if (isset($_GET['speedtest'])) if (in_array(100, $relaccess)) {list($usec1, $sec1) = explode(" ", microtime());$f=fopen('sql.txt','a');fwrite($f,round((float)$usec1+(float)$sec1-$start,5)."/".$s."\n");fclose($f);}


При этом если находишься под админом и добавляешь в url строку с GET-переменной speedtest=1 (например, http://badisoft.ru/?speedtest=1), то в корне сайта создастся (либо будет дополняться, если уже есть) файл sql.txt примерно с таким содержимым:

0.00021/select code, currency_value, where2show, currency_iso_3, Name, roundval from emph_currency_types where CID=3
0.0002/select CID, Name, code, currency_value, where2show, roundval, currency_iso_3 from emph_currency_types order by sort_order
0.01132/select categoryID, name, products_count, products_count_admin, parent, picture, subcount FROM emph_categories ORDER BY sort_order, name
0.00056/select bid, title, content, bposition, which, sort, html, url, admin, pages, dpages, categories, products FROM emph_blocks WHERE active=1 ORDER BY sort ASC
0.00021/select count(*) from emph_categories where categoryID=1
0.0002/select categoryID, parent, name FROM emph_categories WHERE categoryID=1
0.00051/select categoryID, parent, name, products_count from emph_categories where parent=1  order by sort_order, name
0.00023/select last_update from emph_dump where type=1
0.00022/select today from emph_counter WHERE tbid=1
0.05832/replace into emph_online values ('97ca250a247dba98302e15d5f127644a', '1453217907')
0.0584/UPDATE emph_counter SET todayp=todayp+0, todayv=todayv+1, allp=allp+0, allv=allv+1, allieb=allieb+0, allmozb=allmozb+1, allopb=allopb+0, allozb=allozb+0, allrusl=allrusl+1, allenl=allenl+0, allozl=allozl+0, allwins=allwins+1, alllins=alllins+0, allmacs=allmacs+0, allozs=allozs+0 WHERE tbid=1
0.00096/select count(*) from emph_online WHERE time > 1453217307
0.00023/select todayp, todayv, allp, allv from emph_counter WHERE tbid=1
0.00019/select poll_id, poll_title, poll_ans, all_poll FROM emph_survey WHERE active=1
[тут кусок лога вырезан для краткости]
0.00024/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'
0.00025/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'
0.00701/select customerID from emph_customers where Login='admin'
0.00021/select itemID, Quantity FROM emph_shopping_carts WHERE customerID=1
0.0003/select orderID, customerID, order_time, customer_ip,  shipping_type, payment_type, customers_comment,  statusID, shipping_cost, order_discount, order_amount,  currency_code, currency_value, customer_firstname, customer_lastname,  customer_email, shipping_firstname, shipping_lastname,  shipping_country, shipping_state, shipping_city,  shipping_address, billing_firstname, billing_lastname, billing_country,  billing_state, billing_city, billing_address,  cc_number, cc_holdername, cc_expires, cc_cvv, affiliateID, shippingServiceInfo, currency_round  from emph_orders where orderID=0
0.00018/select AID, uri, update_date, title, textToPrePublication, bid from emph_articles order by ordering,update_date DESC,AID DESC
0.00025/select settings_value from emph_settings where settings_constant_name='CONF_DATE_FORMAT'

Что мы видим? Видим кучу запросов по 0.000xx секунд и четыре явно медленных запроса 0.01132, 0.05832, 0.0584, 0.00701.
Первый решается индексом этой таблицы (категорий) по sort_order+name.
Второй и третий - это запросы малюсеньких таблиц (в третьм таблица вообще в одну запись), но с изменением содержимого таблиц, тут был не лучшим образом настроен SQL-сервер.
Четвертый решается индексом этой таблицы (клиентов) по Login.

Вот таким не особенно сложным способом скорость работы сайта была улучшена с

Обработка данных: 0.350 сек
Работа с БД: 0.260 сек
Общее время работы: 0.665 сек

до

Обработка данных: 0.041 сек
Работа с БД: 0.011 сек
Общее время работы: 0.056 сек

PS. В процессе улучшений случился также и переезд на другое железо, но, как ни странно, особого прироста производительности это не дало. Хотя "стало в два раза быстрее" - это тоже хорошо.
Наибольший прирост общей скорости работы дали:
1. кэширование на диск списка категорий.
2. настройка MySQL-сервера. Исходно ооочень медленно, на порядок-два хуже SELECT-ов выполнялись запросы, меняющие содержимое таблиц - UPDATE, REPLACE, INSERТ. Что-то связанное с кэшированием изменений и сбросом их на диск. Делал не я. Я в настройках MySQL-сервера ничего не понимаю. Видимо, какая-то специфика развернутого сервера, т.к. у меня все MySQL-сервера стоят с настройками практически по дефолту, но такой разницы между SELECT-ом и UPDATE-ом нет.
3. создание индексов по часто используемым полям у объемных таблиц (категории, товары, клиенты).


PPS. Обязательно надо мониторить в админке раздел "Статистика ошибок" и следить, чтобы там не было записей.
Особенно если в лог валятся не только ошибки, но и warning по несоответствию типа данных, чего даже в штатном shopCMS "из коробки" довольно много.
При появлении error или warning происходит:
1. вставка сообщения в таблицу (INSERT)
2. подсчет записей в таблице (SELECT)
3. усечение таблицы, если записей больше пятидесяти (DELETE)
т.е. при периодическом warning, который никак не влияет на работоспособность сайта мы получим три лишних SQL-запроса по каждому warning, причем два из них могут оказаться не быстрыми.

Некоторый (довольно небольшой) прирост даст убивание сбора статистики по клиентам (файл counter.php, но осторожно, там еще и ежесуточная чистка таблицы сессий).
Просто станет на пять SQL-запросов меньше.
Статистика там все равно довольно бессмысленная (браузеры - IE/FF/Opera/Other, ОС - Win/Lin/Mac/Other, Языки - Ru/En/Other).
Новых браузеров нет, новых ОС нет.
Статистика Яндекса или Гугля (а обычно у сайта есть обе) покажут то же самое намного лучше и развесистей.
  • 7


#25878 Слайдер баннеров для ShopCMS

Написано zcz на 18 March 2013 - 01:43 PM

Давно ничего не писал, т.к. времени в обрез.
Представляю вашему вниманию новый модуль для организации слайдера.

О модуле:
Данный модуль позволяет создать на сайте слайдер изображения, с возможностью выставления ссылки для определенной картинки и описательного текста.

Модуль писался под заказ.

Прикрепленный файл  slider_by_zcz.rar   1.92МБ   129 Количество загрузок:

пример работы: shotshop.ru
  • 7


#18727 Модуль "Быстрый заказ" by vsupport.club

Написано R.Sergey на 16 April 2012 - 01:24 AM

С чего все началось )))) заказчик заказал установку модуля "Быстрый заказ" .... )) но это не модуль а убожество какое-то, поэтому решил сегодня написать свой, человеческий.
Получилось вроде неплохо, хотя еще есть кое-что что не мешало бы доделать.

Прикрепленный файл  screen.png   615.3К   67 Количество загрузок:

Ну и собственно демонстрация

http://www.youtube.com/watch?v=O_og9Kjl_Yk

Скачать модуль "Быстрый заказ" by vsupport.club
  • 7


#35004 Авторизация/регистрация через соц.сети (uLogin)

Написано zcz на 03 November 2016 - 08:22 PM

Модуль авторизации/регистрации через соц.сети с помощью uLogin для ShopCMS 3.1.*

ВСЕ ГОВОРИМ СПАСИБО stasikons

Собственно и говорить не о чем.
Модуль дает возможность регистрироваться и авторизовываться через соц.сети с помощью сервиса uLogin. ru

Усановка:

Заливаем файлы по своим папкам.

!ВКЛЮЧАЕМ ПРИНУДИТЕЛЬНУЮ ОЧИСТКУ КЕША!

Открываем index.php и находим строчку

if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file" ))) {

в конце, после
"get_file"
вставляем
, "ulogin"

открываем core/includes/admin/modules.php

перед строкой

array("id"=>"yandex", "name"=>"Яндекс.Маркет" )

ставим

//uLogin
array("id"=>"ulogin", "name"=>"Настройки uLogin"),
//END uLogin

открываем core/tpl/admin/menu.tpl.html и перед строкой

<table class="adn topj"><tr><td><img src="data/admin/drs.gif" alt=""></td><td width="100%"><a href="{$smarty.const.ADMIN_FILE}?dpt=modules&amp;sub=yandex">{$smarty.const.ADMIN_STRING_YANDEX}</a></td></tr></table>

вставляем

{*uLogin*}
<table class="adn topj"><tr><td><img src="data/admin/drs.gif" alt=""></td><td width="100%"><a href="{$smarty.const.ADMIN_FILE}?dpt=modules&amp;sub=ulogin">uLogin</a></td></tr></table>
{*END uLogin*}

На удивление, но работа с файлами закончена.
Теперь необходимо зарегистрироваться (если еще не сделали этого) в системе uLogin.ru
Что вам необходимо от этой системы - регистрация, подтверждение сайта и получение уникального ID для работы модуля.
Это я расписывать не буду - там все интуитивно понятно.
После подтверждения сайта и получения уникального ID (выглядит он примерно так 123ba45b), заходим в админку и кликаем по ссылке модуля для его установки и настройки.

Появляться на сайте uLogin, в принципе, нет никакой нужды, т.к. вся настройка модуля (кнопки, язык, доп.поля, и внешний вид) происходит уже у вас в админке.

Наслаждайтесь!

Прикрепленный файл  uLogin.rar   53.37К   14 Количество загрузок:

При регистрации берутся логин, имя, фамилия, емейл. Если каких-то из данных не хватает в соц.сети, то uLogin сам предлагает их заполнить.
доп.поля город и страна подключаются в админке (если не включены, то не записываются в базу)
т.е. после регистрации, клиент получает полный доступ ко всем функциям сайта и в дальнейшем может проходить авторизацию как через соц.сеть, так и по логину и паролю.
  • 6


#32686 Нет на складе

Написано namer на 22 March 2015 - 07:08 PM

Полностью переписал модуль.
Теперь он позволяет переключаться между выводом всех товаров, товаров в наличие, отсутствующих на складе и товаров под заказ.
Прикрепленный файл  qcc_hg87ih.jpg   100.62К   39 Количество загрузок:
Прикрепленный файл  display_product_control.zip   13.53К   13 Количество загрузок:
  • 6


#31845 Штатные ошибки ShopCMS, из коробки :).

Написано badisoft на 09 November 2014 - 03:57 PM

Решил собрать в кучу и худо-бедно причесать найденные в ShopCMS штатные ошибки и странности:

================================================
Штатная ошибка. Из-за нее незарегистрированный пользователь не сможет скачать купленный им электронный товар.

В файле core/includes/processor/get_file.php
строку:


$q = db_query("select order_time from ".ORDERS_TABLE." where orderID=".orderID);


нужно заменить на:


$q = db_query("select order_time from ".ORDERS_TABLE." where orderID=".$orderID);


P.S. Чтобы незарегистрированный пользователь мог получить ссылку на электронный товар, нужно в общих настройках админ-панели поставить галочку напротив пункта E-mail отчеты для покупателей

=====================

Нашел ошибку в catalog_extra.php (штатную). Перепутаны таблицы, это вызывает ошибку SQL при удалении варианта характеристики.
Исправление:


#db_query("delete from ".CATEGORY_PRODUCT_OPTIONS_TABLE." where variantID=".$variantid);
db_query("delete from ".CATEGORY_PRODUCT_OPTION_VARIANTS." where variantID=".$variantid);


=============================

Штатная ошибка: При импорте из CSV варианты характеристик, содержащие символы '"<>& двоятся, т.е. создаются столько раз, сколько товаров с таким вариантом характеристики.

Исправление: в функции optOptionValueExists строку


" where optionID=".(int)$optionID." and option_value='".xEscSQL(trim($value_name))."';");


заменяем на


#" where optionID=".(int)$optionID." and option_value='".xEscSQL(trim($value_name))."';");
" where optionID=".(int)$optionID." and option_value='".xToText(trim($value_name))."';");



=============================

Есть в discount_functions.php функция _calculateGeneralPriceDiscount, возвращающая размер скидки в зависимости от суммы заказа. Выглядит она вот так:


function _calculateGeneralPriceDiscount( $orderPrice, $log )
{
$customerID = (int)regGetIdByLogin($log);
$q = db_query("select discount_id, price_range, percent_discount from ".
ORDER_PRICE_DISCOUNT_TABLE." order by price_range " );
$data = array();
while( $row = db_fetch_row($q) ) $data[] = $row;

if ( count($data) != 0 )
{
for( $i=0; $i<count($data)-1; $i++ )
{
if ( $data[$i][ "price_range" ] < $orderPrice
&& $orderPrice < $data[$i+1][ "price_range" ] )
return $data[$i][ "percent_discount" ];
}
if ( $data[ count($data)-1 ][ "price_range" ] < $orderPrice )
return $data[ count($data)-1 ][ "percent_discount" ];
}

return 0;
}


Если сумма заказа совпадает с суммой, от которой начинается новая скидка, то скидка будет ноль :).
Т.е. если до 5000руб скидка 4%, а от 5000руб - 5%, то на заказ 4999руб будет скидка 4%, на 5001руб - 5%, а вот на 5000руб - 0% :))).

В общем, зачем там такой развесистый код я не понял и заменил на:


function _calculateGeneralPriceDiscount( $orderPrice, $log )
{
$data = db_query("SELECT price_range, percent_discount FROM ".ORDER_PRICE_DISCOUNT_TABLE." ORDER BY price_range");
$discount = 0;
while( $row = db_fetch_row($data) ) if ($row['price_range'] <= $orderPrice) $discount = $row['percent_discount'];
return $discount;
}


===========================

Нашел не ошибку, но весьма странный стиль программирования.
файл cart_functions.php, функция cartGetCartContent()


$costUC = GetPriceProductWithOption( $variants, $shopping_cart_item["productID"] );
$tmp = array(
"productID" => $product["productID"],
...
"costUC" => $costUC,
"cost" => show_price($cart_item["Quantity"]*GetPriceProductWithOption($variants,$shopping_cart_item["productID"])),
...


Зачем вычислять второй раз GetPriceProductWithOption($variants,$shopping_cart_item["productID"]), когда ровно это же число находится в переменной $costUC строкой выше? Оно ведь нифига не бесплатно:


function GetPriceProductWithOption($variants, $productID)
{
$q=db_query("select Price from ".PRODUCTS_TABLE." where productID=".(int)$productID);
$r=db_fetch_row($q);
$base_price = (float)$r[0];
$full_price = (float)$base_price;
foreach($variants as $vars)
{
$q1=db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE.
" where productID=".(int)$productID." AND variantID=".(int)$vars);
$r1=db_fetch_row($q1);
$full_price += $r1["price_surplus"];
}
return $full_price;
}


т.е. при десяти возможных вариантах получаем лишних 11 SQL-запросов.

А если посмотреть, то и вообще всю функцию GetPriceProductWithOption можно заменить на "двухзапросную". Первым запросом получаем базовую цену, вторым - изменение от базовой для переданного набора вариантов.


function GetPriceProductWithOption($variants, $productID)
{
$row=db_fetch_assoc(db_query("SELECT Price FROM ".PRODUCTS_TABLE." WHERE productID=$productID LIMIT 1"));
if (!$variants) return $row['Price'];
$row1=db_fetch_assoc(db_query("SELECT SUM(price_surplus) AS price_surplus FROM ".PRODUCTS_OPTIONS_SET_TABLE." WHERE productID=$productID AND variantID IN (".implode(',',$variants).")"));
return $row['Price']+$row1['price_surplus'];
}




=================================

На этот раз ошибка ни на что не влияющая, но прикольная :).
файл product_functions.php
функция GetExtraParametrs
в SQL-запросе чудный текст (два раза повторяется одно условие):


WHERE povvt.optionID='.$_Row['optionID'].' AND post.productID='.$_Row['productID'].' AND povvt.optionID='.$_Row['optionID']


==================================

Ошибка: штатный и аж четыре раза встречающийся в index.php код совершенно бессмысленен:


if ($smarty -> get_template_vars("main_content_template") == ("category.tpl.html" || "category_search_result.tpl.html"))


Это кусок условия вывода блоков. Левого, правого, верхнего, нижнего. Четыре одинаковых куска кода.

Правильно так:


if ($smarty -> get_template_vars("main_content_template") == "category.tpl.html" || get_template_vars("main_content_template") == "category_search_result.tpl.html")


==================================

Не ошибка. Просто заменяем многострочное извращение с ob_start() на var_export(), появившийся в PHP5
Снимает проблему "белого экрана" в некоторых редких случаях.


function db_query($s) //database query

[...]

/*
ob_start();
var_dump($_GET);
var_dump($_POST);
$tmpa=ob_get_contents();
ob_end_clean();
$out .= $tmpa;
*/
$out .= var_export($_REQUEST,true);


====================================

Аналогично.


function error_reporting_log($error_num, $error_var, $error_file, $error_line) {

[...]

/*
ob_start();
var_dump($_GET);
var_dump($_POST);
$tmpa = ob_get_contents();
ob_end_clean();
$out .= $tmpa;
*/
$out .= var_export($_REQUEST,true);


========================================

Если разрешено задавать количество товара при добавлении в корзину (опция "Разрешить указывать количество товара для добавления в корзину"), а у товара задана не единица в минимальном заказе (скажем, купить можно начиная от N штук), то при задании в окошке выбранного количества числа M получим в корзине не М товаров, а M+N-1. Происходит это потому, что товар добавляется поштучно в цикле от 1 до M (см. shopping_cart.php)


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn++) cartAddToCart( $_GET["add2cart"], $variants );


но при каждом "поштучном" добавлении происходит проверка корзины и если товара там еще нет (первое добавление), то добавляется не 1, а N (см. cart_functions.php, cartAddToCart)


$count_to_order = 1;
....
if ( $item_index == -1 ) $count_to_order = $min_order_amount;
....
db_query("UPDATE ".SHOPPING_CARTS_TABLE." SET Quantity=".(int)$count_to_order....


Решение:

1. в файле cart_functions.php в функции cartAddToCart заменяем


return true;


на


return $count_to_order;


все равно нигде (ни в одном месте из двух :)) не проверяется, что вернула эта функция.

2. в файле cart.php находим строку cartAddToCart

и заменяем


for ( $mcn = 0; $mcn < $_GET["multyaddcount"]; $mcn++ )
cartAddToCart(( int ) $_GET["addproduct"], $variants);


на


for ( $mcn = 0; $mcn < $_GET["multyaddcount"]; $mcn+=$added )
if (!$added = cartAddToCart(( int ) $_GET["addproduct"], $variants)) break;


3. в файле shopping_cart.php находим строку cartAddToCart

и заменяем


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn++) cartAddToCart( $_GET["add2cart"], $variants );


на


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn+=$added) if (!$added = cartAddToCart( $_GET["add2cart"], $variants )) break;


============================================

В модулях курьерской доставки (файлы class.courier2.php и class.courier.php) SQL-таблица SS__courier_rates не имеет префикса, т.е. при двух и более сайтах в одной SQL-базе могут быть проблемы,
т.к. при удалении этого модуля доставки таблица чистится либо удаляется.

============================================

Не ошибка, просто упрощаем код:

1. в файле cart.php

заменяем


if ( isset ( $_SESSION["log"] ))
//taking products from database
{
$q = db_query("select itemID, Quantity FROM ".SHOPPING_CARTS_TABLE." WHERE customerID=".( int ) regGetIdByLogin($_SESSION["log"]));
while ( $row = db_fetch_row($q)) {
$q1 = db_query("select productID from ".SHOPPING_CART_ITEMS_TABLE." where itemID=".( int ) $row["itemID"]);
$r1 = db_fetch_row($q1);
$variants = GetConfigurationByItemId($row["itemID"]);
$k += GetPriceProductWithOption($variants, $r1["productID"]) * $row["Quantity"];
$cnt += $row["Quantity"];
}
}
else
if ( isset ( $_SESSION["gids"] ))
//...session vars
{
for ( $i = 0; $i < count($_SESSION["gids"]); $i++ ) {
if ( $_SESSION["gids"][$i] ) {
$t = db_query("select Price FROM ".PRODUCTS_TABLE." WHERE productID=".( int ) $_SESSION["gids"][$i]);
$rr = db_fetch_row($t);
$sum = $rr["Price"];
// $rr["Price"]
foreach ( $_SESSION["configurations"][$i] as $varconf ) {
$q1 = db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE." where variantID=".( int ) $varconf." AND productID=".( int ) $_SESSION["gids"][$i]);
$r1 = db_fetch_row($q1);
$sum += $r1["price_surplus"];
}
$k += $_SESSION["counts"][$i] * $sum;
$cnt += $_SESSION["counts"][$i];
}
}
}


на


$k = $resCart["total_price"];
#$k = $resCart["total_price"] - $resDiscount["discount_standart_unit"]; // если хотим видеть в корзине сумму сразу со скидкой
foreach ($resCart["cart_content"] as $rc) $cnt += $rc["quantity"];



2. в файле shopping_cart_info.php

заменяем


if (isset($_SESSION["log"])) //taking products from database
{
$q = db_query("select itemID, Quantity FROM ".SHOPPING_CARTS_TABLE.
" WHERE customerID=".regGetIdByLogin($_SESSION["log"]));
while ($row = db_fetch_row($q))
{
$q1=db_query("select productID from ".SHOPPING_CART_ITEMS_TABLE.
" where itemID=".$row["itemID"]);
$r1=db_fetch_row($q1);
if($r1["productID"]){
$variants=GetConfigurationByItemId( $row["itemID"] );
$k += GetPriceProductWithOption($variants, $r1["productID"])*$row["Quantity"];
$cnt+=$row["Quantity"];
}
}
}
else
if (isset($_SESSION["gids"])) //...session vars
{
for ($i=0; $i<count($_SESSION["gids"]); $i++)
{
if ($_SESSION["gids"][$i])
{
$t = db_query("select Price FROM ".PRODUCTS_TABLE." WHERE productID=".(int)$_SESSION["gids"][$i]);
$rr = db_fetch_row($t);

$sum=$rr["Price"];

// $rr["Price"]
foreach( $_SESSION["configurations"][$i] as $vars )
{
$q1=db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE.
" where variantID=".(int)$vars." AND productID=".(int)$_SESSION["gids"][$i]);
$r1=db_fetch_row($q1);
$sum+=$r1["price_surplus"];
}

$k += $_SESSION["counts"][$i]*$sum;
$cnt += $_SESSION["counts"][$i];
}
}
}


на


$resCart = cartGetCartContent();
$k = $resCart["total_price"];
#$resDiscount = dscCalculateDiscount($resCart["total_price"], isset ( $_SESSION["log"] ) ? $_SESSION["log"] : ""); // если хотим видеть в корзине сумму сразу со скидкой
#$k = $resCart["total_price"] - $resDiscount["discount_standart_unit"];
foreach ($resCart["cart_content"] as $rc) $cnt += $rc["quantity"];


=============================================

Не ошибка, хотя как посмотреть. Дополнение резко сокращает количество SQL-запросов при сохранении настроек товаров и категорий. Актуально для сайтов с большим количеством категорий. Например, штатно на тысяче категорий будет 16тысяч (!!!) SQL-запросов. Здесь, насколько я помню, четыре запроса не зависимо от количества категорий.


Установка:

В файле category_functions.php

1. в функции update_psCount

строку


update_pCount($parent);


заменяем на


update_pCount_new($parent);


2. куда-нибудь рядом добавляем две функции


function update_sCount_new($parent, $counts = array(1 => array ('subcats' => 0,'admin_count' => 0,'customer_count' => 0)))
{
global $mc;
foreach (array_keys ($mc,(int)$parent) as $val)
{
$counts[$val]['subcats'] = count(array_keys($mc, $val));
$counts[$val]['admin_count'] = 0;
$counts[$val]['customer_count'] = 0;
if ($counts[$val]['subcats']) $counts = update_sCount_new($val,$counts);
}
return $counts;
}

function update_pCount_new($parent)
{
global $fc;
$qstr = array(
"SELECT categoryID, COUNT(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".PRODUCTS_TABLE." GROUP BY categoryID",
"SELECT pc.categoryID, COUNT(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".CATEGORIY_PRODUCT_TABLE." AS pc JOIN ".PRODUCTS_TABLE." USING (productID) GROUP BY pc.categoryID");
$counts = update_sCount_new($parent);
foreach ($qstr as $str)
{
$data = db_query($str);
while ($row=db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
while ($categoryID)
{
$counts[$categoryID]['admin_count'] += (int)$row['admcount'];
$counts[$categoryID]['customer_count'] += (int)$row['count'];
$categoryID = $fc[$categoryID]['parent'];
}
}
}
$data = db_query("SELECT categoryID, subcount, products_count, products_count_admin FROM ".CATEGORIES_TABLE);
while ($row = db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
if ((int)$row['subcount'] != $counts[$categoryID]['subcats'] || (int)$row['products_count'] != $counts[$categoryID]['customer_count'] || (int)$row['products_count_admin'] != $counts[$categoryID]['admin_count'])
db_query("UPDATE ".CATEGORIES_TABLE." SET subcount=".$counts[$categoryID]['subcats'].", products_count=".$counts[$categoryID]['customer_count'].", products_count_admin=".$counts[$categoryID]['admin_count']." WHERE categoryID=$categoryID");
}
}

  • 6


#30142 Еще один фильтр. Теперь на AJAX.

Написано badisoft на 09 March 2014 - 06:01 PM

Новый фильтр. Сделан с использованием AJAX, т.е. не перезагружает страницу для вывода результатов работы фильтра.


Традиционное спасибо всем, кто помогал мне (явно или путем сообщения об ошибках) в предыдущем фильтре. Без него не было бы этого.Советы, рекомендации, пожелания, сообщения об ошибках продолжают приветствоваться.


Краткое описание:
-----------------

- Как и предыдущий этот фильтр не требует в каждой категории задавать список разрешенных к показу характеристик, а строит этот список сам суммируя характеристики всех товаров категории.

- Как и предыдущий этот фильтр работает ТОЛЬКО с характеристиками товаров, заданными в виде вариантов характеристик. Т.е. с характеристиками в виде текстовой строки этот фильтр НЕ РАБОТАЕТ.

- При установке-снятии галки на лету меняются количественные показатели у остальных вариантов выбора.
Варианты с "нулевым" количеством товаров дизаблятся.

- При перемещении движка цен аналогично, но "нулевые" варианты не дизаблятся, а убираются.

- выборка товаров (показ результата работы фильтра) делается сразу по нажатию любой галки.Точнее, по изменению любого элемента формы, т.е. галки чекбокса, движков, вида сортировки, количества товаров на странице. Но это отключаемо и изначально отключено (галка "Автопоказ").

- Я не стал (пока?) делать в этом фильтре изыски предыдущего (тип выбора - чекбосы, строка, селект, движки ).
По фактам установки предыдущего фильтра у меня сложилось уверенное впечатление, что никто этими возможностями не пользуется кроме заказчика возможности :). А все остальные просто оставляют дефолтовые чекбоксы, это самое удобное.

По сути, преимуществ перед штатным у этого фильтра всего два - выбор более одного варианта для характеристики и получение результата тут же, без нажатия кнопки "Показать" и перезагрузки страницы.

Ну а задание показа/непоказа характеристик в кратком/полном описаниях, бывшее в предыдущем фильтре и вообще к фильтру не относится, есть отдельный модуль на эту тему.


Установка проста до безобразия:
-------------------------------

1. копируем файлы (они не совпадают по имени со штатными, можно смело копировать).


filter.php -> core/includes/processor/
filter.tpl.html -> core/tpl/user/[шаблон]/
filter_new.tpl.html -> core/tpl/user/[шаблон]/blocks
jquery.blockui.js -> data/[шаблон]/
jquery.form.js -> data/[шаблон]/
loading.gif -> data/[шаблон]/


2. В head.tpl.html вписываем линки на jquery-ui и css от него. Ну и на сам jquery, если он еще не вписан


<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>



3. в файле index.php

строку


if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file" ))) {


заменяем на


# BEGIN filter-ajax
#if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file" ))) {
if ( in_array($_GET["do"], array( "captcha", "cart", "rss", "compare", "yandex", "invoice_jur", "invoice_phys", "stat", "get_file", "filter" ))) {
# END filter-ajax



4. в файле index.tpl.html задаем, куда и как выводить результат работы фильтра,
замещающий все содержимое блока с id="filterResult".

Например, если строки


{* вывод центральной страницы *}
{include file="$main_content_template"}


заменить на


<div id="filterResult">

{* вывод центральной страницы *}
{include file="$main_content_template"}

</div>


то список отфильтрованного выведется вместо основного содержимого сайта, но верхние и нижние блоки останутся.
А если заменить


{* верхние блоки *}
{include file="blocks.tpl.html" binfo=$top_blocks bclass="hdbtop" balign="left"}
{* вывод центральной страницы *}
{include file="$main_content_template"}
{* нижние блоки *}
{include file="blocks.tpl.html" binfo=$bottom_blocks bclass="hdbtop" balign="left"}


на


<div id="filterResult">

{* верхние блоки *}
{include file="blocks.tpl.html" binfo=$top_blocks bclass="hdbtop" balign="left"}
{* вывод центральной страницы *}
{include file="$main_content_template"}
{* нижние блоки *}
{include file="blocks.tpl.html" binfo=$bottom_blocks bclass="hdbtop" balign="left"}

</div>


то список отфильтрованного заместит все центральное содержимое.


5. Создаем в "Управлении блоками" через "Добавить блок из файла" новый блок из файла filter_new.tpl.html


Посмотреть, как это работает можно на http://cpu.badisoft.ru - слева ниже большой красной кнопки "мобильная версия" есть блок "Новый фильтр на Аяксе" и в нем кнопка "Развернуть".

Прикрепленные файлы

  • Прикрепленный файл  filter-ajax.zip   32.19К   170 Количество загрузок:

  • 6


#29943 Другой шаблон при заходе с мобильного

Написано badisoft на 12 February 2014 - 08:55 PM

Дополнение позволяет сделать так, чтобы для мобильных устройств и обычных грузились разные шаблоны.
Расположение мобильного шаблона штатное: tpl.html-файлы в core/tpl/user/[имя шаблона], а остальной набор данных (js, css, картинки) - при необходимости - в data/[имя шаблона].

Спонсор дополнения: kery

Установка:
=========

1. копируем файлы

addon.php -> core/includes/admin/
is_mobile.php -> core/functions/


2. создаем каталог core/cache/mobile/


3. в файле index.php

3.1 после строки


$smarty = new Smarty;


вставляем


# BEGIN Mobile-template
if (isset($_GET['mobile_template'])) $_SESSION['mobile_template'] = ($_GET['mobile_template'] == 'yes');
if (!isset($_SESSION['mobile_template'])) $_SESSION['mobile_template'] = is_mobile();
if ($_SESSION['mobile_template'])
{
$smarty->compile_dir = 'core/cache/mobile';
$smarty->cache_dir = 'core/cache/mobile';
}
# END Mobile-template


3.2 вместо строки


if (isset($_SESSION["CUSTOM_DESIGN"]))


вставляем


# BEGIN Mobile-template
# if (isset($_SESSION["CUSTOM_DESIGN"]))
if ($_SESSION['mobile_template'])
{
$smarty->template_dir = "core/tpl/user/".CONF_MOBILE_TEMPLATE;
define('TPL', CONF_MOBILE_TEMPLATE);
}
elseif (isset($_SESSION["CUSTOM_DESIGN"]))
# BEGIN Mobile-template


4. Заходим в админку. Это нужно, чтобы чтобы отработал файл addon.php и создалась настройка выбора "мобильного" шаблона.
В админке в "Общих настройках" появится возможность задать еще один шаблон - для показа мобильным устройствам.


Принудительная смена шаблона происходит путем GET-запроса mobile_template=yes или mobile_template=no
Например, путем создания ссылки <a href="/?mobile_template=no">Обычная версия сайта</a> в мобильной версии.

В комплекте идут три совершенно не отлаженных мобильных минимум-миниморум шаблончика на jquery-mobile, найденные в инете. Они не имеют ни малейшего отношения к товарному наполнению и тематике сайта и добавлены просто для понимания, как все это работает.

Прикрепленные файлы


  • 6


#27366 Картинки "Скидка", "Топ продаж", "Акция", "Новинк...

Написано badisoft на 10 July 2013 - 11:12 PM

Дополнение позволяет выводить поверх картинок в кратком и полном описании маленькие картинки "Новинка", "Топ продаж","Акция" либо "Скидка".
Ну и сортировать по этому критерию, как же без этого. Хотя и примитивненько, без красоты и изыска :).

Cпонсор дополнения: wwwsasa2, автор картинок (и спонсор предыдущего похожего дополнения) poloskun


Установка:
----------

1. файлы *.png копируем в каталог /data/[шаблон]/

Файлы весьма условные. Тестовые. Для красоты создайте свои. Лишь бы они были 46х62px, либо надо поправить соответствующие width и height в коде.


3. в файле catalog_products_categories.php

3.1 перед строкой


$callBackParam = array();


вставляем


# BEGIN New-Top-Action-products
if (!db_fetch_row(db_query("SHOW COLUMNS FROM ".PRODUCTS_TABLE." LIKE 'newtopact'"))) db_query("ALTER TABLE ".PRODUCTS_TABLE." ADD newtopact tinyint(1) DEFAULT 0");
# END New-Top-Action-products


3.2 вместо строк


//save changes in current category
$data = ScanPostVariableWithId( array( "price", "enable", "left", "sort_order" ) );


вставляем


//save changes in current category
# BEGIN New-Top-Action-products
#$data = ScanPostVariableWithId( array( "price", "enable", "left", "sort_order" ) );
$data = ScanPostVariableWithId( array( "price", "enable", "left", "sort_order", "newtopact" ) );
# END New-Top-Action-products


3.3 перед ВТОРОЙ (!) найденной строкой


if ( isset($val["enable"]) )


вставляем


# BEGIN New-Top-Action-products
if ( isset($val["newtopact"]) ) db_query( "update ".PRODUCTS_TABLE." set newtopact=".(int)$val["newtopact"]." WHERE productID=".(int)$key );
# END New-Top-Action-products



4. в файле category.php

перед строкой


$smarty->assign( "categoryID", $categoryID);


вставляем


# BEGIN New-Top-Action-products
$smarty->assign( "pictures", array("","new.png","top.png","action.png","discount.png"));
# END New-Top-Action-products



5. в файле product_detailed.php

перед строкой


$smarty->assign("main_content_template", "product_detailed.tpl.html");


вставляем


# BEGIN New-Top-Action-products
$smarty->assign( "pictures", array("","new.png","top.png","action.png","discount.png"));
# END New-Top-Action-products



6. в файле product_functions.php

6.2 в функции prdSearchProductByTemplateAdmin

6.2.1 после строк


$order_by_clause = " order by ".xEscSQL($callBackParam["sort"])." DESC ";
}


вставляем


# BEGIN New-Top-Action-products
elseif ($callBackParam["sort"] == "newtopact") $order_by_clause = " ORDER BY newtopact DESC, sort_order";
# END New-Top-Action-products


6.2.2 вместо строки


" customers_rating, Price, in_stock, ".


вставляем


# BEGIN New-Top-Action-products
#" customers_rating, Price, in_stock, ".
" customers_rating, Price, in_stock, newtopact, ".
# END New-Top-Action-products


6.3 в функции prdSearchProductByTemplate

6.3.1 после строк


$order_by_clause = " order by ".xEscSQL($callBackParam["sort"])." DESC ";
}


вставляем


# BEGIN New-Top-Action-products
elseif ($callBackParam["sort"] == "new") $order_by_clause = " ORDER BY newtopact=1 DESC, sort_order";
elseif ($callBackParam["sort"] == "top") $order_by_clause = " ORDER BY newtopact=2 DESC, sort_order";
elseif ($callBackParam["sort"] == "act") $order_by_clause = " ORDER BY newtopact=3 DESC, sort_order";
elseif ($callBackParam["sort"] == "dis") $order_by_clause = " ORDER BY newtopact=4 DESC, sort_order";
# END New-Top-Action-products


6.3.2 вместо строки


" customers_rating, Price, in_stock, ".


вставляем


# BEGIN New-Top-Action-products
#" customers_rating, Price, in_stock, ".
" customers_rating, Price, in_stock, newtopact, ".
# END New-Top-Action-products



7. в файле catalog_products_categories.tpl.html

7.1 после строки


<td align="center"><a href='{$urlToSort}&amp;sort=viewed_times&amp;sort_dir=DESC' title="{$smarty.const.ADMIN_ADMIN_MENUNEW10}" class="liv">VT</a></td>


вставляем


{* BEGIN New-Top-Action-products *}
<td align="center"><a href='{$urlToSort}&amp;sort=newtopact' title="Сортировка по Акция/Топ/Новинка/Скидка" class="liv">Доп.Картинка</a></td>
{* END New-Top-Action-products *}


7.2 после строки


<td align="center" {if !$products[i].enabled}class="toph3 gryy"{else}class="toph3"{/if}>{$products[i].viewed_times}</td>


вставляем


{* BEGIN New-Top-Action-products *}
<td align="center">
<select name="newtopact_{$products[i].productID}">
<option value="0"{if $products[i].newtopact==0} selected{/if}>---</option>
<option value="1"{if $products[i].newtopact==1} selected{/if}>Новинка</option>
<option value="2"{if $products[i].newtopact==2} selected{/if}>Топ продаж</option>
<option value="3"{if $products[i].newtopact==3} selected{/if}>Акция</option>
<option value="4"{if $products[i].newtopact==4} selected{/if}>Скидка</option>
</select>
</td>
{* END New-Top-Action-products *}



8. в файле category.tpl.html

вместо строк (таких строк обычно две, в начале страницы и в конце)


<td class="cattop" align="center">{$string_product_sort}</td>


вставляем


{* BEGIN New-Top-Action-products *}
{*<td class="cattop" align="center">{$string_product_sort}</td>*}
<td class="cattop" align="center">{$string_product_sort}
&nbsp;<a href="index.php?categoryID={$categoryID}&sort=new">(Новинки)</a>
&nbsp;<a href="index.php?categoryID={$categoryID}&sort=top">(Топ продаж)</a>
&nbsp;<a href="index.php?categoryID={$categoryID}&sort=act">(Акции)</a>
&nbsp;<a href="index.php?categoryID={$categoryID}&sort=dis">(Скидки)</a>
</td>
{* END New-Top-Action-products *}



9. в файле product_brief.tpl.html

вместо строки (в случае картинки справа)


<td class="imboxr"><a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}"><img src="data/small/{$product_info.picture}" alt="{$product_info.name}"></a></td>


вставляем


{* BEGIN New-Top-Action-products *}
{*<td class="imboxr"><a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}"><img src="data/small/{$product_info.picture}" alt="{$product_info.name}"></a></td>*}
<td class="imboxr">
{if $product_info.newtopact > 0}
<div style="position: relative;">
<div style="position: absolute; z-index: 1; top: 0px; left: 0px; background:url('data/{$smarty.const.TPL}/{$pictures[$product_info.newtopact]}'); height: 62px; width: 46px;">
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/{$smarty.const.TPL}/pixel.gif" width="46" height="62">
</a>
</div>
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/small/{$product_info.picture}" alt="{$product_info.name}">
</a>
</div>
{else}
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/small/{$product_info.picture}" alt="{$product_info.name}">
</a>
{/if}
</td>
{* END New-Top-Action-products *}



вместо строки (в случае картинки слева)


<td class="imboxl"><a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}"><img src="data/small/{$product_info.picture}" alt="{$product_info.name}"></a></td>


вставляем


{* BEGIN New-Top-Action-products *}
{*<td class="imboxl"><a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}"><img src="data/small/{$product_info.picture}" alt="{$product_info.name}"></a></td>*}
<td class="imboxl">
{if $product_info.newtopact > 0}
<div style="position: relative;">
<div style="position: absolute; z-index: 1; top: 0px; left: 0px; background:url('data/{$smarty.const.TPL}/{$pictures[$product_info.newtopact]}'); height: 62px; width: 46px;">
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/{$smarty.const.TPL}/pixel.gif" width="46" height="62">
</a>
</div>
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/small/{$product_info.picture}" alt="{$product_info.name}">
</a>
</div>
{else}
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_info.productID}.html{else}index.php?productID={$product_info.productID}{/if}">
<img src="data/small/{$product_info.picture}" alt="{$product_info.name}">
</a>
{/if}
</td>
{* END New-Top-Action-products *}



10. в файле product_detailed.tpl.html

10.1 после строки


hs.lang.fullExpandTitle = '{$smarty.const.STRING_HS_FULLEXPANDTITLE}';


вставляем


{* BEGIN New-Top-Action-products *}
hs.headingEval = 'this.thumb.alt';
{* END New-Top-Action-products *}


10.2 ищем строку class="imboxr" (либо "imboxl" для картинки слева) и чуть ниже вместо строки


{if $product_info.big_picture} <a href="data/big/{$product_info.big_picture}" class="highslide" onclick="return hs.expand(this)"><img src="data/medium/{$product_info.thumbnail}" alt="{$product_info.name}" id="{$product_info.big_picture}"></a>{*


вставляем


{* BEGIN New-Top-Action-products *}
{*{if $product_info.big_picture}<a href="data/big/{$product_info.big_picture}" class="highslide" onclick="return hs.expand(this)"><img src="data/medium/{$product_info.thumbnail}" alt="{$product_info.name}" id="{$product_info.big_picture}"></a>*}
{if $product_info.big_picture}
{if $product_info.newtopact > 0}
<div style="position: relative;">
<div style="position: absolute; z-index: 1; top: 0px; left: 0px; background:url('data/{$smarty.const.TPL}/{$pictures[$product_info.newtopact]}'); height: 62px; width: 46px;">
<img src="data/{$smarty.const.TPL}/pixel.gif" width="46" height="62">
</div>
<a href="data/big/{$product_info.big_picture}" class="highslide" onclick="return hs.expand(this)"><img src="data/medium/{$product_info.thumbnail}" alt="<img src='data/{$smarty.const.TPL}/{$pictures[$product_info.newtopact]}'>" id="{$product_info.big_picture}"></a>
</div>
{else}
<a href="data/big/{$product_info.big_picture}" class="highslide" onclick="return hs.expand(this)"><img src="data/medium/{$product_info.thumbnail}" alt="{$product_info.name}" id="{$product_info.big_picture}"></a>
{/if}
{* END New-Top-Action-products *}{*



Пункты (9) и (10) приведены для дефолтового шаблона. В других шаблонах html-код может (и наверняка будет!) отличаться, так что придется проявить смекалку.

Прикрепленные файлы

  • Прикрепленный файл  action.png   3.31К   99 Количество загрузок:
  • Прикрепленный файл  discount.png   3.76К   100 Количество загрузок:
  • Прикрепленный файл  new.png   2.77К   98 Количество загрузок:
  • Прикрепленный файл  top.png   2.65К   79 Количество загрузок:

  • 6


#26827 Расширенное управление характеристиками товаров

Написано micehide на 01 June 2013 - 05:54 PM

Расширенное управление характеристиками товаров 1.2
Актуально для версии ShopCMS 3.1.2

Прикрепленный файл  extra_features_v1.0.jpg   107.63К   230 Количество загрузок:

Список изменений:
  • Полностью сохранена изначальная функциональность редактирования характеристик;
  • Добавлена возможность "Конвертации" доп. характеристики из произвольного значения в набор возможных значений с корректной привязкой всех товаров каталога к соответствующему этим товарам значению выбранной характеристики.
  • Устранена штатная ошибка ShopCMS в файле catalog_extra.php, при которой возникала ошибка SQL при удалении варианта характеристики (спасибо: badisoft);
  • Регистронезависимая проверка, пример значения: Swarowski = SWAROVSKI)
Скачать: Расширенное управление характеристиками товаров 1.1 (инструкция по установке в архиве)

Пишите комментарии, кто будет себе ставить и пробуйте сначала на тестовом каталоге (на всякий случай, т.к я тестировал модуль в разных вариантах).
  • 6


#24956 Быстрый заказ v2.0 by vsupport.club

Написано R.Sergey на 29 January 2013 - 03:59 AM

Модуль "Быстрый заказ" v 2.0
Полностью изменена логика работы модуля.

Модуль позволяет покупателям сделать заказ в один клик.
По клику всплывает окошко с формой заказа.


1. Кнопку "Быстрый заказ" теперь можно добавлять в любой блок/шаблон где присутствует "product_id", т.е. в подробное описание товара, краткое описание товара, новинки, хиты, спец. предложения, рекомендуемые товары и т.д. и т.п.
2. Все заказы записываются в базу данных и отображаются в админке в Истории заказов и в Справочнике заказов вместе с заказами сделанными через корзину. Нумерация также общая.
3. Покупателю и администратору отправляются письма на email с тем же шаблоном что используется для заказов через корзину. Администратору отправляется на email, указанный в админке, а покупателю на email указанный при оформлении быстрого заказа.
4. Все дополнительные поля, добавленные в форму регистрации (через админку) отображаются в быстром заказе. При этом если при оформлении заказа, покупатель изменит какое-либо значение, например номер телефона, то после отправки заказа, этот номер изменится и в его Личном кабинете, т.е. при оформлении следующего заказа номер будет уже новый.
5. Если пользователь в аккаунте все поля заполняются автоматически, при этом он может изменить ФИО, email или другие данные о себе при отправке заказа.
6. Для медленных хостингов добавлен лоадер, т.е. индикатор отправки заказа. После успешной отправки заказа выводится сообщение "Ваш заказ принят, пожалуйста ожидайте звонка менеджера."
7. Учет валюты. При переключении валюты пользователем, заказ оформляется с выбранной им валютой.

Демонстрация:


Модуль не требует настройки. Для его использования достаточно залить файлы сохраняя структуру директорий. При этом замены файлов не происходит.

Установка:
1. Залить файлы.
2. В файл head.tpl.html добавить строки
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.js"></script>
- подключаем jquery если он еще не подключен.
<script type="text/javascript" src="data/{$smarty.const.TPL}/quick_order.js"></script>
- подключаем скрипт Быстрого заказа.
<link rel="stylesheet" type="text/css" href="data/{$smarty.const.TPL}/quick_order.css"/>
- подключаем стили.

3. В шаблонах в нужное место (обычно недалеко от корзины) добавить

<div class="quick_order" id="{$product_info.productID}">Быстрый заказ</div>
- в этом месте появится кнопка "Быстрый заказ".

Если нужно использовать кнопку в дополнительных блоках: Новинки, Хиты и т.д. вместо
{$product_info.productID}
используйте переменную "productID" для этих блоков.

Скачать модуль "Быстрый заказ v2.0" из нашего Архива.

Недоделал проверку на обязательность заполнения полей. Но уже сами кому нужно допиливайте ))))
  • 6


#22915 Пробел в окне редактора Fсkeditor

Написано 64j на 10 October 2012 - 04:03 PM

При создании товара или категории, в поле визуального редактора присутствует неразрывный пробел.
В коде показывает
&nbsp;
Всё бы хорошо, но если делать проверку на существование описания товара или категории, то описание не является пустым. То есть и описания нету, a и вроде как есть.
Обрыл кучу форумов с обсуждениями данного редактора, но советы , что были - не помогли.


Нашёл в чём причина.
в двух файлах
fckeditor/editor/js/fckeditorcode_gecko.js
fckeditor/editor/js/fckeditorcode_ie.js

найти в коде на 48 - 49 строке
A=E[1]+'&nbsp;'+F[1];
и заменить на
A=E[1]+''+F[1];

  • 6


#19545 Красивое двухуровневое меню категорий на JQ Lava lamp + Superfish

Написано drserg на 12 May 2012 - 05:59 PM

Здравствуйте, только начал создавать на Shop CMS'е. Хочу с вами поделится своим блоком category_tree. Для данного меню я использовал 2 JQ плагина: Lava lamp (первый уровень) + Superfish (2ой уровень). В архиве демо меню, и сам файл блока. Надеюсь Вам все будет понятно, и вы знаете как добавлять скрипты и стили и включать плагины )). По любым вопросам обращайтесь.

Добавил скриншот (но JQ скриншотом не опишешь).
Изображение

Прикрепленные файлы

  • Прикрепленный файл  lava_menu.rar   88.82К   67 Количество загрузок:

  • 6


#16885 Делаем развесистый фильтр товаров (обкатка, написание, дополнения)

Написано badisoft на 25 February 2012 - 02:57 AM

Решение находится в процессе написания. Если у Вас не получилось ожидаемое, то либо Вы где-то допустили ошибку, либо я. Второе тоже запросто. Не надо стесняться писать об этом, оно всем на пользу будет :).

Last update: 06.04.2014

Основные свойства модуля:

- модуль заменяет штатный фильтр товаров, позволяя фильтровать не по одной характеристике из выпадающего списка,
а по любому набору характеристик. Также этот фильтр работает не только в категориях, а везде.

- убрана необходимость в каждой категории задавать набор характеристик для фильтра, теперь этот набор строится
автоматически на лету. Характеристики и min/max-цены берутся по всем товарам выбранной категории, включая вложенные
любого уровня и дополнительные категории.
Заданные в "Редактировать категорию->Расширенный поиск->Выбрать параметры" галочки и точечки ни на что не влияют.

- добавлена возможность каждой характеристике задать ее тип при показе в фильтре (произвольная строка, набор чекбоксов, движки, выпадающий список с чекбоксами),

- добавлена возможность каждой характеристике задать ее показ/непоказ в фильтрах (см.ниже).

- фильтров теперь три. Первый (основной) и два дополнительных. Они совершенно равноправны, но в реальности второй и третий
нужны как дополнительные фильтры для каких-либо отдельных характеристик. Например, "Фильтр по производителю".
Для каждого фильтра показ/непоказ характеристики задается отдельно.


Установка:


1. переписываем файлы

ui.dropdownchecklist.standalone.css -> data\[шаблон]\
ui.dropdownchecklist-1.4-min.js -> data\[шаблон]\

jquery.selectBox.js -> data\[шаблон]\ (нужен только для filter3.tpl.html)
select-button.png -> data\[шаблон]\ (нужен только для filter3.tpl.html)

jquery.tinyTips.js -> data\[шаблон]\
tinyTips.css -> data\[шаблон]\
q.png -> data\[шаблон]\

filter1.tpl.html -> core\tpl\user\[шаблон]\blocks\
filter2.tpl.html -> core\tpl\user\[шаблон]\blocks\
filter3.tpl.html -> core\tpl\user\[шаблон]\blocks\

advanced_search_in_category_ef.php -> core\includes\

addon.php -> core\includes\admin

Файл addon.php нужен ОДИН РАЗ для создания в таблицах новых полей.
После первого же захода в админку его можно удалить, если он не удалился сам.


2. В head.tpl.html вписываем линки на jquery-ui и css от него. Ну и на сам jquery, если он еще не вписан


{* BEGIN ExtraFilter *}
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
{* END ExtraFilter *}



3. в файле catalog_extra.php (если он не менялся, то можно просто переписать файл из архива поверх)

вместо строки


$updateOptions = ScanPostVariableWithId( array( "extra_option", "extra_sort" ) );


вставляем


# BEGIN ExtraFilter
#$updateOptions = ScanPostVariableWithId( array( "extra_option", "extra_sort" ) );
$updateOptions = ScanPostVariableWithId( array( "extra_option", "extra_sort", "extra_filter1", "extra_filter2", "extra_filter3", "extra_type" ) );
# END ExtraFilter



4. в файле catalog_extra.tpl.html (если он не менялся, то можно просто переписать файл из архива поверх)

4.1 перед строкой


<td align="left" class="toph3">{$smarty.const.ADMIN_VALUE_VARIANTS}</td>


вставляем


{* BEGIN ExtraFilter *}
<td align="left">Фильтр1</td>
<td align="left">Фильтр2</td>
<td align="left">Фильтр3</td>
<td align="left">Тип фильтра</td>
{* END ExtraFilter *}


4.2 перед строкой


<td align="left" valign="middle" class="toph3"><span style="float: right;">({$options[i].count_variants})</span><a href="{$smarty.const.ADMIN_FILE}?dpt=catalog&amp;sub=extra&amp;optionID={$options[i][0]}" class="inl">{$smarty.const.ADMIN_VALUE_VARIANTS}</a></td>


вставляем


{* BEGIN ExtraFilter *}
<td align="left"><input type="checkbox" class="round" name="extra_filter1_{$options[i].optionID}" {if $options[i].filter1}checked{/if} title="Показывать характеристику в первом фильтре"></td>
<td align="left"><input type="checkbox" class="round" name="extra_filter2_{$options[i].optionID}" {if $options[i].filter2}checked{/if} title="Показывать характеристику во втором фильтре"></td>
<td align="left"><input type="checkbox" class="round" name="extra_filter3_{$options[i].optionID}" {if $options[i].filter3}checked{/if} title="Показывать характеристику в третьем фильтре"></td>
<td align="left">
<select name="extra_type_{$options[i].optionID}" title="Показывать характеристику как чекбоксы, строку ввода, слайдер или селект">
<option value="0"{if $options[i].filter_type==0} selected{/if}>Чекбоксы</option>
<option value="1"{if $options[i].filter_type==1} selected{/if}>Строка</option>
<option value="2"{if $options[i].filter_type==2} selected{/if}>Слайдер</option>
<option value="3"{if $options[i].filter_type==3} selected{/if}>Селект</option>
</select>
</td>
{* END ExtraFilter *}




5. в файле option_functions.php

5.1 в функции optGetOptions ищем строку


$SQL = 'select ps.optionID, ps.name, ps.sort_order, COUNT(povv.variantID) as count_variants FROM '.PRODUCT_OPTIONS_TABLE.' as ps


и заменяем ее на


# BEGIN ExtraFilter
#$SQL = 'select ps.optionID, ps.name, ps.sort_order, COUNT(povv.variantID) as count_variants FROM '.PRODUCT_OPTIONS_TABLE.' as ps
$SQL = 'select ps.optionID, ps.name, ps.sort_order, COUNT(povv.variantID) as count_variants, ps.filter1, ps.filter2, ps.filter3, ps.filter_type FROM '.PRODUCT_OPTIONS_TABLE.' as ps


5.2 в функции optUpdateOptions ищем строку


"', sort_order=".(int)$val["extra_sort"]." where optionID=".(int)$key);


и заменяем ее на


# BEGIN ExtraFilter
#"', sort_order=".(int)$val["extra_sort"]." where optionID=".(int)$key);
"', sort_order=".(int)$val["extra_sort"].
", filter1=".(isset($val["extra_filter1"])?1:0).
", filter2=".(isset($val["extra_filter2"])?1:0).
", filter3=".(isset($val["extra_filter3"])?1:0).
", filter_type=".(isset($val["extra_type"])?$val["extra_type"]:0).
" where optionID=".(int)$key);
# END ExtraFilter



6. в файле product_functions.php

6.2 в функции _testExtraParametrsTemplate

6.2.1 перед строками


// get category ID
$categoryID = $template["categoryID"];


вставляем


# BEGIN ExtraFilter
if (isset($_GET["extrafilter"])){
global $efTemplate;
$variants = array();
$filter_type = array();
foreach( $efTemplate as $key => $item )
if((string)$key != "categoryID" && isset($item["optionID"]))
{
if (is_array($item['value'])) $variants[$item["optionID"]] = $item['value'];
elseif ($item['value']>0) $variants[$item["optionID"]][] = $item['value'];
if (isset($item['filter_type'])) $filter_type[$item["optionID"]] = $item['filter_type'];
}

if (!$count = count($variants)) return true;

$filter = array();
foreach( $variants as $key => $item )
{
if (isset($filter_type[$key]))
{
switch ($filter_type[$key])
{
case '0':
$filter[] = "pos.variantID IN (".implode(",",$item).")";
break;
case '1':
$filter[] = "pos.optionID=".$key." AND povv.option_value LIKE '%".$item[0]."%'";
break;
case '2':
if ($item[2] == 'on') $count--;
else $filter[] = "pos.optionID=".$key." AND FLOOR(povv.option_value)>=".$item[0]." AND CEIL(povv.option_value)<=".$item[1];
break;
case '3':
$filter[] = "pos.variantID IN (".implode(',',$item).")";
break;
}
}
}
$row=db_fetch_row(db_query("SELECT count(DISTINCT pos.optionID) AS count FROM ".PRODUCTS_OPTIONS_SET_TABLE." AS pos
LEFT JOIN ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." AS povv USING (variantID)
WHERE productID=".$productID. " AND (".implode(" OR ",$filter).")"));

return $row['count'] == $count;
}else{
# END ExtraFilter



6.2.2 перед завершающей функцию фигурной скобкой } вставляем


# BEGIN ExtraFilter
}
# END ExtraFilter


Должен получиться код

if (isset($_GET["extrafilter"])){
новый код функции
}else{
старый код функции
}



7. в файле category.php в функциях _getUrlToNavigate и _getUrlToSort

7.1 добавляем (там довольно очевидно куда - в блок аналогичных строк)


# BEGIN ExtraFilter
if ( isset($_GET["extrafilter"]) )
$url .= "&extrafilter=".$_GET["extrafilter"];
# END ExtraFilter


7.2 вместо


$url .= "&param_".$key;
$url .= "=".$val["param"];


вставляем


# BEGIN ExtraFilter
#$url .= "&param_".$key;
#$url .= "=".$val["param"];
if (is_array($val["param"])) foreach ($val["param"] as $vkey => $variant) $url .= "&param_".$key."[".$vkey."]=".$variant;
else $url .= "&param_".$key."=".$val["param"];
# END ExtraFilter



8. Подключаем в админке в "Управление блоками" основной фильтр (filter1.tpl.html) и ставим нужные галочки в "Характеристики товаров".
Второй фильтр (filter2.tpl.html) и третий фильтр (filter3.tpl.html) аналогично :).


9. проверяем, пишем о проблемах.

Работающий пример можно посмотреть тут.

Характеристики там сгенерированы автоматически из описаний товаров, просто для демонстрации работы фильтра.

PS. Ну и, естественно, спасибо всем, кто тем или иным образом принимал и принимает участие в доделывании этого фильтра. Matit, micehide, R.Sergey и другие, кого я мог забыть или кто еще примет участие в будущем.

Прикрепленные файлы

  • Прикрепленный файл  ExtraFilter.zip   29.39К   68 Количество загрузок:

  • 6


#34408 Поиск заказа по дополнительному полю

Написано badisoft на 10 March 2016 - 02:48 PM

Дополнение позволяет искать заказы по содержимому дополнительных полей (см. раздел "Форма регистрации" в админке).
Писалось под конкретное дополнительное поле "Телефон", т.к. у заказчика оно было одно, но подходит для поиска по любому полю - индекс, девичья фамилия матери и т.п.

при одном доп.поле:
Прикрепленный файл  1.jpg   12.41К   4 Количество загрузок:

при нескольких:
Прикрепленный файл  2.jpg   13.21К   4 Количество загрузок:

Установка:
==========

1. в файле order_functions.php в функции ordGetOrders

перед


if ( isset($callBackParam["orderStatuses"]) )


вставляем


# BEGIN поиск по дополнительному полю
if ( isset($callBackParam['reg_field_id']) && isset($callBackParam['reg_field_value']))
{
#$where = " WHERE reg_field_ID=".$callBackParam['reg_field_id']." AND REPLACE(REPLACE(reg_field_value,'-',''),' ','') LIKE '%".$callBackParam['reg_field_value']."%'";
$where = " WHERE reg_field_ID=".$callBackParam['reg_field_id']." AND reg_field_value LIKE '%".$callBackParam['reg_field_value']."%'";
$select_registered = "SELECT customerID FROM ".CUSTOMER_REG_FIELDS_VALUES_TABLE.$where;
$select_quick = "SELECT orderID FROM ".CUSTOMER_REG_FIELDS_VALUES_TABLE_QUICKREG.$where;
$where_clause .= " customerID IN ($select_registered) OR orderID IN ($select_quick) AND customerID=0";
}
# END поиск по дополнительному полю



2. в файле custord_new_orders.php

2.1. в функции _setCallBackParamsToSearchOrders

в самый конец вставляем


# BEGIN поиск по дополнительному полю
else if ( $_GET["order_search_type"] == "reg_field" )
{
$callBackParam["reg_field_id"] = (int)$_GET["reg_field_id"];
$callBackParam["reg_field_value"] = trim($_GET["reg_field_value"]);
}
# END поиск по дополнительному полю


2.2. в функциях _getReturnUrl, _getUrlToNavigate и _getUrlToSort

после


$url .= "&orderID_textbox=".$_GET["orderID_textbox"];


вставляем


# BEGIN поиск по дополнительному полю
if (isset($_GET["reg_field_id"])) $url .= "&reg_field_id=".$_GET["reg_field_id"];
if (isset($_GET["reg_field_value"])) $url .= "&reg_field_value=".$_GET["reg_field_value"];
# END поиск по дополнительному полю



3. в файле menu.tpl.html

3.1. перед


<tr>
<td align="left"><input type=radio class="round" name=order_search_type id=order_search_type2 value='SearchByStatusID'


вставляем


{* BEGIN поиск по дополнительному полю *}
{assign var='reg_fields' value=0|GetRegFields}
{if $reg_fields|@count}
<tr>
<td align="left" width="16" valign="middle">
<input type=radio class="round" name=order_search_type id=order_search_type3 value='reg_field'{if $order_search_type == 'reg_field'} checked{/if} onclick='order_search_typeClickHandler()'>
</td>
<td valign="middle" height="20">Поиск по доп.полю</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left">
{if $reg_fields|@count==1}
<input type='hidden' name='reg_field_id' id='reg_field_id' value='{$reg_fields[0].reg_field_ID}'>{$reg_fields[0].reg_field_name}<br>
{else}
<select name='reg_field_id' id='reg_field_id' style='width:126px;'>
{foreach from=$reg_fields item=reg_field}
<option value="{$reg_field.reg_field_ID}"{if $reg_field.reg_field_ID==$smarty.get.reg_field_ID} selected{/if}>{$reg_field.reg_field_name}</option>
{/foreach}
</select>
{/if}
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left"><input type=text name='reg_field_value' id='reg_field_value' value='{$smarty.get.reg_field_value}' class="prc" size="21"></td>
</tr>
<tr><td height="6" colspan="2"></td></tr>
{/if}
{* END поиск по дополнительному полю *}


3.2. после


document.getElementById('id_checkall').disabled = true;


вставляем


// BEGIN поиск по дополнительному полю
document.getElementById('reg_field_id').disabled = true;
document.getElementById('reg_field_value').disabled = true;
// END поиск по дополнительному полю


3.3. после


document.getElementById('id_checkall').disabled = false;


вставляем


// BEGIN поиск по дополнительному полю
document.getElementById('reg_field_id').disabled = true;
document.getElementById('reg_field_value').disabled = true;
// END поиск по дополнительному полю


3.4. перед


{literal}}{/literal}
order_search_typeClickHandler();


вставляем


// BEGIN поиск по дополнительному полю
else if ( document.getElementById('order_search_type3').checked )
{literal}{{/literal}
{section name=i loop=$order_statuses}
document.getElementById('checkbox_order_status_{$order_statuses[i].statusID}').disabled = true;
{/section}
document.getElementById('id_checkall').disabled = true;
document.getElementById('orderID_textbox').disabled = true;
document.getElementById('reg_field_id').disabled = false;
document.getElementById('reg_field_value').disabled = false;
{literal}}{/literal}
// END поиск по дополнительному полю

  • 5


#30542 Постраничный вывод новостей

Написано VerstkaShopcms на 17 April 2014 - 01:37 PM

Делал один проект и нужно было вывести на странице новостей все новости с возможностью постарницной навигации.

Реализация лежит на поверхности. А именно в админке есть вывод новостей с разбивкой по страницам.

По сути нужно внести правки в несколько файлов, а именно:


core\functions\news_function.php
core\includes\news.php
core\tpl\user\НАЗВАНИЕ_ВАШЕГО_ШАБЛОНА\show_news.tpl.html
.htaccess



В файле core/includes/news.php находим такие строки -

	   $pre_news_array = newsGetPreNewsToCustomer();
	   $smarty->assign( "pre_news_array", $pre_news_array );

И удаляем. Потому как тут идет выборка новостей не зависимо от того на какой странице вы находитесь.

Находим ниже строку

		if ( isset($_GET["news"]) ) $smarty->assign( "main_content_template", "show_news.tpl.html" );

и меняем на

<!--pd_0-->

Кстати тут я использовал конcтанту из админки - CONF_NEWS_COUNT_IN_NEWS_PAGE, которая устанавливает сколько новостей выводить на одной странице. По сути эта константа будет дробить на нужное количество новостей для одной страницы.


В файле core/functions/news_function.php Добавляем функцию:

<!--pd_1-->


Нужно еще добавить пару строк в файл .htaccess по аналогии с правилами ЧПУ для категорий:

RewriteRule ^news_offset_([0-9]+)\.html$ index.php?news=yes&offset=$1 [L]
RewriteRule ^news_show_all\.html$ index.php?news=yes&show_all=yes [L]

Также я добавил в шаблон show_news.tpl.html переменную смарти выводящую навигацию по страницам - {$navigator_news} .

Сохраняем всё, заливаем на свой сайт и проверяем. Всё должно работать должным образом.
Кому пригодился мой пост - не стесняйтесь, поднимайте репутацию. Не сочтите за нескромность, но я не вижу пока другого способа заработать репутацию на данном форуме.

PS:. Cпрятал часть кода с условием наличия одного поста. Не обессутьте. Но увы, просмотров куча а репутацию так никто и не поднял. Неужели никому не пригодился мой код?
  • 5


#27572 Картинки для вариантов характеристик

Написано badisoft на 24 July 2013 - 05:33 PM

По необходимости (как часть другого модуля) понадобился этот модуль. По мере изучения модуля namer-а от него остались практически рожки да ножки, но исходным прообразом был таки он, т.е. писалось не с нуля.
Основные отличия от модуля namer-а:
- картинки можно присваивать не только новым создаваемым вариантам, но и любому уже имеющемуся
- файлы картинок удаляются при удалении варианта
- файл картинки сохраняет исходное имя если такого файла нет либо получает имя *_1.*, *_2.*, *_3.* и так далее, т.е. первое по счету не занятое.

Где-то получилось сложнее, чем в модуле namer-а, где-то проще. Изменения в коде product_brief.tpl.html и product_detailed.tpl.html (пункты 7 и 8) родные namer-овские, ничего не менял, т.к. "другой модуль" этих файлы не затрагивает.

Спонсор создания инструкции - l17l

Что не понятно - спрашивайте. Но не в личке, а тут.

Админка выглядит примерно так:
Прикрепленный файл  1.JPG   48.1К   167 Количество загрузок:

================================================
Инструкция по установке модуля картинок для вариантов характеристик и вывода их (картинок) в шаблонах краткого и полного описания.

1. в файле option_functions.php

1.1 в функции optGetOptionValues строку


$q = db_query("select variantID, optionID, option_value, sort_order from ".


заменяем на


# BEGIN variants-with-pictures
#$q = db_query("select variantID, optionID, option_value, sort_order from ".
$q = db_query("select variantID, optionID, option_value, sort_order, picture from ".
# END variants-with-pictures


1.2 в конец файла добавляем функцию


# BEGIN variants-with-pictures
function optaddoptionvalue_by_namer( $optionID, $value, $sort_order, $picture )
{
db_query( "insert into ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." (optionID, option_value, sort_order, picture) values('".$optionID."', '".xtotext($value)."', '".$sort_order."', '".xtotext($picture)."')");
return db_insert_id();
}
# END variants-with-pictures



2. в файле product_functions.php

2.1 в функции GetExtraParametrs

строку


$sql = 'select povvt.option_value, povvt.variantID, post.price_surplus


заменяем на


# BEGIN variants-with-pictures
#$sql = 'select povvt.option_value, povvt.variantID, post.price_surplus
$sql = 'select povvt.option_value, povvt.variantID, povvt.picture, post.price_surplus
# END variants-with-pictures


после строки


$_Row['values_to_select'][$i]['option_value'] = $_Rowue['option_value'];


вставляем


# BEGIN variants-with-pictures
$_Row['values_to_select'][$i]['picture'] = $_Rowue['picture'];
# END variants-with-pictures



3. в файле catalog_extra.php

3.1 перед строкой


if (isset($_GET["save_successful"])) //update was successful


вставляем


# BEGIN variants-with-pictures
if (!db_fetch_row(db_query("SHOW COLUMNS FROM ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." LIKE 'picture'"))) db_query("ALTER TABLE ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." ADD picture varchar(50) NULL");
if(!file_exists("data/option_image")) mkdir("data/option_image");
# END variants-with-pictures


3.2 перед строкой


// update existing values


вставляем


# BEGIN variants-with-pictures
$updatePictures = ScanFilesVariableWithId(array( "add_picture"));
foreach( $updatePictures as $key => $val )
{
if ( isset($val["add_picture"]) )
{
$picture = saveVariantsPicture('add_picture_'.$key);
if ($picture)
{
$row = db_fetch_assoc(db_query("SELECT picture from ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." WHERE variantID=$key"));
if ($picture != $row['picture'])
{
if (!empty($row['picture']) && file_exists("data/option_image/".$row['picture'])) unlink("data/option_image/".$row['picture']);
db_query("UPDATE ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." SET picture='$picture' WHERE variantID=$key");
}
}
}
}
# END variants-with-pictures



3.3 строки


optAddOptionValue($_POST["optionID"], $_POST["add_value"],
(int)$_POST["add_sort"] );


заменяем на


# BEGIN variants-with-pictures
#optAddOptionValue($_POST["optionID"], $_POST["add_value"],
#(int)$_POST["add_sort"] );
optAddOptionValue_by_namer($_POST["optionID"], $_POST["add_value"], (int)$_POST["add_sort"], saveVariantsPicture('add_option_picture'));
# END variants-with-pictures


3.4 после строки


$variantid = (int)$_GET["kill_value"];


вставляем


# BEGIN variants-with-pictures
$row = db_fetch_assoc(db_query("SELECT picture from ".PRODUCTS_OPTIONS_VALUES_VARIANTS_TABLE." WHERE variantID=".$variantid));
if (!empty($row['picture']) && file_exists("data/option_image/".$row['picture'])) unlink("data/option_image/".$row['picture']);
# END variants-with-pictures



3.5 в конец файла вставляем


# BEGIN variants-with-pictures
function saveVariantsPicture($add_picture)
{
if($_FILES[$add_picture]['tmp_name'])
{
if(!is_uploaded_file($_FILES[$add_picture]['tmp_name'])) die("Проблема загрузки файла");
if(substr($_FILES[$add_picture]['type'],0,5) != 'image') die ("Разрешена загрузка только изображений");
if (filesize($_FILES[$add_picture]['tmp_name']) > 20000) die ("Размер файла превышает допустимый (20 КБ)");
$picture = $_FILES[$add_picture]['name'];
$expl = explode(".",$picture,2);
$i=1;
while (file_exists("data/option_image/".$picture)) $picture = $expl[0]."_".$i++.".".$expl[1];
if (!move_uploaded_file($_FILES[$add_picture]['tmp_name'],"data/option_image/".$picture)) die("Не удалось скопировать файл из временного каталога сервера в каталог data/option_image");
return $picture;
}
else return NULL;
}
# END variants-with-pictures



4. в файле catalog_extra.tpl.html

4.1 вместо строки


<form action="{$smarty.const.ADMIN_FILE}" method=POST name="formext" id="formext">


вставляем


{* BEGIN variants-with-pictures *}
{*<form action="{$smarty.const.ADMIN_FILE}" method=POST name="formext" id="formext">*}
<form action="{$smarty.const.ADMIN_FILE}" method=POST name="formext" id="formext" enctype="multipart/form-data">
{* END variants-with-pictures *}


4.3 перед строкой


<td align="left" class="toph3" width="100%">{$smarty.const.ADMIN_ONE_VALUE}</td>


вставляем


{* BEGIN variants-with-pictures *}
<td align="left" class="toph3">Картинка</td>
{* END variants-with-pictures *}


4.4 строку


<td align="left"><input name="option_value_{$values[i].variantID}" type=text value="{$values[i].option_value}" class="textp" size="30"></td>


заменяем на


{* BEGIN variants-with-pictures *}
{*<td align="left"><input name="option_value_{$values[i].variantID}" type=text value="{$values[i].option_value}" class="textp" size="30"></td>*}
<td align="left" valign="middle">
{if $values[i].picture}
<img src="data/option_image/{$values[i].picture}" alt="" width="50" style="vertical-align:middle;">&nbsp;&nbsp;
{else}
<img src="data/admin/pixel.gif" alt="" width="50" height="1">&nbsp;&nbsp;
{/if}
</td>
<td align="left">
<input name="option_value_{$values[i].variantID}" type=text value="{$values[i].option_value}" class="textp" size="70">
<input type=file class="file" name="add_picture_{$values[i].variantID}" value="" size="26">
</td>
{* END variants-with-pictures *}


4.5 строки


<td align="left" width="100%">{$smarty.const.ADMIN_SORT_ORDER}</td></tr>
<tr class="lins">
<td align="left"><input name="add_value" type=text value="" class="textp" size="46"></td>


заменяем на


{* BEGIN variants-with-pictures *}
{*
<td align="left" width="100%">{$smarty.const.ADMIN_SORT_ORDER}</td></tr>
<tr class="lins">
<td align="left"><input name="add_value" type=text value="" class="textp" size="46"></td>
*}
<td align="left" width="20%">{$smarty.const.ADMIN_SORT_ORDER}</td></tr>
<tr class="lins">
<td align="left">
<input type=text class="textp" name="add_value" value="" size="70">
<input type=file class="file" name="add_option_picture" value="" size="26">
</td>
{* END variants-with-pictures *}



5. Заходим в админке в "характристики товаров". При этом создадутся новые необходимые поля в таблицах.


7. в файле product_brief.tpl.html

7.1 ниже строки


{if $smarty.section.k.index == 0}


находится шаблон select-а примерно такого вида (пустые строки и пробелы удалены):


<select name='option_select_{$select_counter_var}_{$product_info.productID}' onchange='GetCurrentCurrency_{$product_info.productID}();' class="WCHhider">
{section name=j loop=$product_info.product_extra[i].values_to_select}
<option value='{$product_info.product_extra[i].values_to_select[j].price_surplus}:{$product_info.product_extra[i].values_to_select[j].variantID}' {if $product_info.product_extra[i].values_to_select[j].variantID eq $product_info.product_extra[i].variantID}selected{/if}>{$product_info.product_extra[i].values_to_select[j].option_value}</option>
{/section}
</select>


его надо заменить на


{section name=j loop=$product_info.product_extra[i].values_to_select}
<br>
{if $product_info.product_extra[i].values_to_select[j].picture ne NULL}
<img src="data/option_image/{$product_info.product_extra[i].values_to_select[j].picture}" alt="" width="50" style="vertical-align:middle;">
{/if}
<input type="radio" onclick="GetCurrentCurrency_{$product_info.productID}({$product_info.product_extra[i].values_to_select[j].price_surplus}, {$product_info.product_extra[i].values_to_select[j].variantID});" name='option_select_{$select_counter_var}_{$product_info.productID}' value='{$product_info.product_extra[i].values_to_select[j].price_surplus}:{$product_info.product_extra[i].values_to_select[j].variantID}' {if $product_info.product_extra[i].values_to_select[j].variantID eq $product_info.product_extra[i].variantID}checked{/if}>
{$product_info.product_extra[i].values_to_select[j].option_value}
<br>
{/section}


7.2 в JS-функции GetCurrentCurrency_{$product_info.productID}()

строку


_value=document.MainForm1_{$product_info.productID}.option_select_{$select_counter_var2}_{$product_info.productID}.value;


заменяем на


_value = "";
for (var i=0; i < document.MainForm1_{$product_info.productID}.option_select_{$select_counter_var2}_{$product_info.productID}.length; i++)
if (document.MainForm1_{$product_info.productID}.option_select_{$select_counter_var2}_{$product_info.productID}[i].checked)
_value=document.MainForm1_{$product_info.productID}.option_select_{$select_counter_var2}_{$product_info.productID}[i].value;



8. в файле product_detailed.tpl.html

8.1 ниже строки


{if $smarty.section.k.index == 0}


находится шаблон select-а примерно такого вида (пустые строки и пробелы удалены):


<select name='option_select_{$select_counter_var}' onchange='GetCurrentCurrency();' class="WCHhider">
{section name=j loop=$product_extra[i].values_to_select}
<option value='{$product_extra[i].values_to_select[j].price_surplus}:{$product_extra[i].values_to_select[j].variantID}' {if $product_extra[i].values_to_select[j].variantID eq $product_extra[i].variantID}selected{/if}>{$product_extra[i].values_to_select[j].option_value}</option>
{/section}
</select>


его надо заменить на


{section name=j loop=$product_extra[i].values_to_select}
<br>
{if $product_extra[i].values_to_select[j].picture ne NULL}
<img src="data/option_image/{$product_extra[i].values_to_select[j].picture}" alt="" width="50" style="vertical-align:middle;">
{/if}
<input type="radio" onclick="GetCurrentCurrency();" name='option_select_{$select_counter_var}' value='{$product_extra[i].values_to_select[j].price_surplus}:{$product_extra[i].values_to_select[j].variantID}' {if $product_extra[i].values_to_select[j].variantID eq $product_extra[i].variantID}checked{/if}>
{$product_extra[i].values_to_select[j].option_value}
<br>
{/section}


8.2 в JS-функции GetCurrentCurrency()

строку


_value = document.MainForm.option_select_{$select_counter_var2}.value;


заменяем на


_value = "";
for (var i=0; i < document.MainForm.option_select_{$select_counter_var2}.length; i++)
if (document.MainForm.option_select_{$select_counter_var2}[i].checked)
_value=document.MainForm.option_select_{$select_counter_var2}[i].value;

  • 5


#26259 Задолбали просители "пришлите мне файл, который я не могу скачать"

Написано badisoft на 10 April 2013 - 10:21 PM

Основной текст уже в сабжекте-заголовке :).
Написано в основном для того, чтобы я не писал в личке одно и то же в двудесятый раз, а просто - бдыщ! - запостил ссылку на готовый текст. Так вот!

Я исключительно положительно и с пониманием отношусь к тому, что весьма не любой зарегистрировашийся пользователь может скачать что угодно из даунлоада или даже по ссылке в теме. Мне нравится этот сайт. Мне нравятся принципы его администрирования. Какого хрена я должен обманывать администрацию сайта втихую отдавая емейлом какой-либо недоступный контент с этого сайта? Не будет этого. Задолбали просить.
  • 5


#26053 Редактирование заказа v.2.0 by vsupport.club

Написано R.Sergey на 02 April 2013 - 02:58 AM

Редактирование заказа в админ-панели.
Модуль позволяет редактировать все данные заказа:
- e-mail,
- Имя,
- Фамилия,
- Телефон,
- Адрес,
- Способ доставки (можно вводить произвольное значение, например если у Вас нет способа доставки Самовывоз, но Вы индивидуально договорились об этом с заказчиком, можно написать способ Самовывоз),
- Способ платы (так как и в доставке можно ввести произвольное значение),
- Характеристики товаров,
- Кол-во товара,
- Стоимость товара,
- Скидку в процентах, т.е. если у Вашего заказчика не было скидки, но Вы индивидуально ее предоставили это можно внести в заказ,
- Стоимость доставки.

Есть возможность добавлять/удалять товары в заказе.
Есть возможно добавлять комментарий администратора к заказу.

Изменена логика вывода информации о заказе, более нужная информация выведена в вернюю часть (см. скрин.), для удобства добавлены кнопки сохранить изменения, чтобы не путаться кнопка Изменить статус размещена отдельно от сохранения заказа.

Прикрепленный файл  edit_order.jpg   606.64К   189 Количество загрузок:


Скачать модуль "Редактирование заказа в админ. панели"
  • 5