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

Cuser update кто изменил

  • автор:

Roman

Как в Битриксе записать последние изменения в свойство?

Нужно навешать обработчик на OnBeforeIBlockElementUpdate, потому что при OnIBlockElementUpdate нельзя делать CIBlockElement:Update() (это вызовет циклический вызов обработчика). При OnIBlockElementUpdate значения в changes нужно будет писать через SetPropertyValuesEx. Хотя с OnIBlockElementUpdate/SetPropertyValuesEx вариант вполне рабочий.

Примерный код с OnBeforeIBlockElementUpdate:

 тайтл 8 => "Some prop", ]; $changesPropId = 9; // ID свойства changes $resOldElem = CIBlockElement::GetList( [], ["IBLOCK_ID" => $arFields["IBLOCK_ID"], "ID" => $arFields["ID"]], false, false, array_map(function($propId) < return "PROPERTY_"; >, array_keys($propMap)) )->Fetch(); $newChanges = []; foreach ($propMap as $propId => $propTitle) < $propValueKey = "PROPERTY__VALUE"; $oldPropValue = $resOldElem[$propValueKey]; $newPropValue = $propValues[$propId][array_key_first($propValues[$propId])]["VALUE"]; // Для множественных свойств нужна своя логика обработки if ($oldPropValue != $newPropValue) < // Если значение из справочника, то его надо разыменовать, достать значение из ИБ/Хайлоад ИБ $newChanges[] = "Юзер изменил : -> "; > > if (!empty($newChanges)) < $arFields['PROPERTY_VALUES'][$changesPropId] = array_merge($arFields['PROPERTY_VALUES'][$changesPropId], $newChanges); >> > >

Решение так себе, потому что:
a) множественных значений свойств
b) некрасиво сработает со значениями из справочников
c) захардкоженные ID свойств и их заголовки
d) не достает имя пользователя

Но, как старт для запила фичи дает, я думаю

PS: Хранить изменения товара в самом товаре так себе идея, лучше завести отдельную таблицу с быстрым чтением и записью (HL-инфблоки подойдут) и сделать кастомный вывод истории в админке в карточке редактирования товара

Ответ написан более года назад

Как реализовать в Битриксе функционал редактирования в Режиме правки (Эрмитаж)?

С хранением картинки в элементе ИБ можно сделать как-то вот так:

GetShowIncludeAreas()) < $cache = new CPHPCache(); if ($cache->StartDataCache(30*60, array($iblockId, $elementId, 'mykey'), false)) < CModule::IncludeModule('iblock'); $arIBlockElement = GetIBlockElement($elementId); $path = CFile::GetPath($arIBlockElement['DETAIL_PICTURE']); if(!$path) < echo "
Файл не загружен
"; > else < echo ""; > $cache->EndDataCache(); > > else < CModule::IncludeModule('iblock'); $url = "/bitrix/admin/" . CIBlock::GetAdminElementEditLink( $iblockId, $elementId, array( "bxpublic" =>"Y", "from_module" => "iblock" ) ); $action = $APPLICATION->GetPopupLink( array( "URL" => $url, "PARAMS" => array( 'width' => 700, 'height' => 400, 'resize' => false ) ) ); $arIcons = Array(); $arIcons[] = Array( "URL" => 'javascript:'.$action, "ICON" => "bx-context-toolbar-edit-icon", "TITLE" => "Редактировать" ); $arIBlockElement = GetIBlockElement($elementId); $path = CFile::GetPath($arIBlockElement['DETAIL_PICTURE']); if(!$path) < $str = "
Файл не загружен
"; > else < $str = ""; > echo $APPLICATION->IncludeString( $str, $arIcons ); >

Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать

Как вывести сумму заказа?

 CSaleBasket::GetBasketUserID(), "LID" => SITE_ID, "ORDER_ID" => NULL, "CAN_BUY" => "Y" ), false, false, array( "QUANTITY", "BASE_PRICE", "PRICE", "DISCOUNT_PRICE" ) ); $totalPrice = 0; // Temp array with cart items $arItems = array(); // Fetching query while($arFields = $res->Fetch()) < // Check for base price if(!isset($arFields['BASE_PRICE']) || (float)$arFields['BASE_PRICE'] // Calculate total price without discount $totalPrice += $arFields["PRICE"] * $arFields["QUANTITY"]; $arItems[] = $arFields; > // Make array for discount calculation $arOrder = array( 'SITE_ID' => SITE_ID, 'ORDER_PRICE' => $totalPrice, 'BASKET_ITEMS' => $arItems ); // Checking for authorized user if(is_object($GLOBALS["USER"]))< $arOrder['USER_ID'] = $GLOBALS["USER"]->GetID(); $arErrors = array(); // Calculate discount CSaleDiscount::DoProcessOrder($arOrder, array(), $arErrors); > // All done! echo $arOrder['ORDER_PRICE'];

Ответ написан более трёх лет назад
Нравится 1 1 комментарий

При запросе файлов добавляется заголовок Cache-control: no-cache. Почему?

У вас nginx отдает статику. Т.е. до апача и до .htaccess дело даже не доходит.
Ответ написан более трёх лет назад
Нравится 1 1 комментарий

Как получить ссылки на файлы?

Если вы пишете свой в компонент (что вряд ли), то делайте так:

$res = CIBlockElement::GetList( array(), array( 'IBLOCK_ID' = 1, // Идентификатор ИБ статей ), false, false, array( 'PROPERTY_FILES.PROPERTY_DOC', // Коды свойств с файлами 'PROPERTY_FILES.PROPERTY_PDF' ) ); while($arFields = $res->GetNext())< // Смотрите, что тут находится в $arFields, и доставайте файлы по идентификатору, с помощью метода CFile::GetByID либо CFile::GetPath >

Если вы хотите отобразить в шаблоне стандартного компонента, (news.detail, судя по всему), тогда используйте файл result_modifier.php шаблона компонента, доставайте ссылки на файлы там и записывайте в $arResult (дока). Примерно так:

if(!empty($arResult['PROPERTIES']['FILES']['VALUE'])) < $res = CIBlockElement::GetList( array(), array( 'IBLOCK_ID' =>$arResult['PROPERTIES']['FILES']['IBLOCK_ID'], 'ID' => $arResult['PROPERTIES']['FILES']['VALUE'], 'ACTIVE' => 'Y' ), false, false, array( 'PROPERTY_DOC', // Коды свойств с файлами 'PROPERTY_PDF' ) ); $files = array(); while($arFields = $res->GetNext()) < foreach(array('PDF', 'DOC') as $code)< $fullCode = "PROPERTY_$code_VALUE"; if($filePath = CFile::GetPath($arFields[$fullCode]))< $files[] = $filePath; >> > $arResult['PROPERTIES']['FILES']['LINKS'] = $files; >

Работоспособность кода не гарантирую, писал по памяти, но идея, я думаю, ясна.

Найти в файле по id пользователя и заменить его значения. Поиск по id выполнил.Может кто-нибудь помочь с заменой значений?

Реализация очень сложная , мало того, ваш интерфейс и его имплементация некорреткны. В целом понятие айди говорит о его уникальности, а у вас, исходя их сигнатуры методов, айди — непонятно что (там метод поиска по айди список возвращает, этого не может быть в природе). Кроме того, операции чтения/записи в файл производятся проще, а операцию чтения не стоит заталкивать в метод findall, ведь чтение с файла — не самая быстрая операция. В целом попробуйте для начала сделать так:

 import java.util.Optional; import java.util.Scanner; public class Main < public static void main(String[] args) < Scanner scanner = new Scanner(System.in); UsersRepository usersRepository = UsersRepository.of("users.txt"); System.out.println("Введите ID пользователя: "); Optionaluser = usersRepository.findById(scanner.nextInt()); if (user.isPresent()) System.out.println(user); else System.out.println("Такой записи не существует"); > > import java.io.IOException; import java.util.Collection; import java.util.Optional; public interface UsersRepository < CollectionfindAll(); Optional findById(Integer id); User update(User user); void save() throws IOException; static UsersRepository of(String fileName) < return new UsersRepositoryFileImpl(fileName); >> import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; public class UsersRepositoryFileImpl implements UsersRepository < private final Mapusers; private final String fileName; public UsersRepositoryFileImpl(String fileName) < this.users = read(fileName); this.fileName = fileName; >private Map read(String fileName) < try (Streamstream = Files.lines(Paths.get(fileName))) < return stream .map(User::new) .collect(Collectors.toMap(User::getId, user ->user, (k1, k2) -> k1, LinkedHashMap::new)); > catch (IOException ex) < throw new RuntimeException(ex); >> @Override public Collection findAll() < return users.values(); >@Override public Optional findById(Integer id) < return Optional.ofNullable(users.get(id)); >@Override public User update(User user) < return users.put(user.getId(), user); >@Override public void save() throws IOException < Files.write(Paths.get(fileName), users.values().stream() .map(User::toTextLine) .collect(Collectors.joining("\n")).getBytes()); >> public class User < private Integer id; private String name; private Integer age; private Boolean isWorker; public User(String line) < String[] parts = line.split("\\|"); this.id = Integer.parseInt(parts[0]); this.name = parts[1]; this.age = Integer.parseInt(parts[2]); this.isWorker = Boolean.parseBoolean(parts[3]); >public Integer getId() < return id; >public void setId(Integer id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >public Integer getAge() < return age; >public void setAge(Integer age) < this.age = age; >public Boolean isIsWorker() < return isWorker; >public void setIsWorker(Boolean isWorker) < this.isWorker = isWorker; >public String toTextLine() < return new StringBuilder() .append(id).append("|") .append(name).append("|") .append(age).append("|") .append(isWorker) .toString(); >@Override public String toString() < return "User'; > > 

Форум

Мне нужно обновить свойство пользователя при оплате заказа, но почему-то код не работает в init.php.
Флаг оплаты проставляю в панели администратора. Может быть, в этом и кроется проблема, но администратор сам будет проставлять оплату заказа, поэтому тестирую именно так.

AddEventHandler("sale", "OnSalePayOrder", array("MyClass", "UserDiscount")); class MyClass < function UserDiscount($id,$val) < $arOrder=CSaleOrder::GetByID($id); $UserDiscount= new CUser; if ($val=='Y') < $user = new CUser; $fields = Array( "UF_LAST" =>1 ); $user->Update($arOrder['USER_ID'], $fields); > elseif($val=='N') < $user = new CUser; $fields = Array( "UF_LAST" =>0 ); $user->Update($arOrder['USER_ID'], $fields); > > >

Заглянувший
Сообщений: 2 Регистрация: 31.03.2015
27.05.2016 09:46:58

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

AddEventHandler("sale", "OnSalePayOrder", "UserDiscount"); AddEventHandler("sale", "OnSaleStatusOrder","saleOrderHandler"); function UserDiscount($id,$val) < file_put_contents($_SERVER[DOCUMENT_ROOT]."/log.txt",var_export($id,true)); $arOrder=CSaleOrder::GetByID($id); if ($val=='Y') < $user = new CUser; $fields = Array( "UF_LAST" =>1 ); $user->Update($arOrder['USER_ID'], $fields); > elseif($val=='N') < $user = new CUser; $fields = Array( "UF_LAST" =>0 ); $user->Update($arOrder['USER_ID'], $fields); > > function saleOrderHandler($id,$val) < file_put_contents($_SERVER[DOCUMENT_ROOT]."/log.txt",var_export($id,true)); $arOrder=CSaleOrder::GetByID($id); if ($val=='P') < $user = new CUser; $fields = Array( "UF_LAST" =>1 ); $user->Update($arOrder['USER_ID'], $fields); > else < $user = new CUser; $fields = Array( "UF_LAST" =>0 ); $user->Update($arOrder['USER_ID'], $fields); > >

Сообщений: 1146 Баллов: 101 Регистрация: 16.03.2013
16.06.2016 14:13:47
Возможно не хватает подключения модуля sale .

use Bitrix\Main\Loader; AddEventHandler("sale", "OnSalePayOrder", "UserDiscount"); AddEventHandler("sale", "OnSaleStatusOrder","saleOrderHandler"); function UserDiscount($id, $val) < if (Loader::includeModule('sale')) < . >> function saleOrderHandler($id, $val) < if (Loader::includeModule('sale')) < . >>

Постоянный посетитель
Сообщений: 133 Баллов: 21 Регистрация: 05.04.2017
21.10.2021 11:46:53

но если вы меняете именно флаг оплаты заказа (это отдельная кнопка) то все верно надо использовать «OnSalePayOrder»

С ув. Вячеслав Докукин
Страницы: 1

Центр поддержки

Продукты

Управление сайтом
Битрикс24
Интернет-магазин + CRM

Решения

Для интернет-магазинов
Каталог готовых решений

Внедрение

Выбрать партнера
Проверить партнера
Стать партнером

1С-Битрикс http://www.1c-bitrix.ru Общие вопросы info@1c-bitrix.ru Приобретение и лицензирование продуктов : sales@1c-bitrix.ru Маркетинг/мероприятия/PR marketing@1c-bitrix.ru Партнерская программа partners@1c-bitrix.ru Мы работаем с 10:00 до 19:00 по московскому времени. Офис в Москве 127287 Россия Московская область Москва 2-я Хуторская улица дом 38А строение 9 Офис в Калининграде +7 (4012) 51-05-64 Офис в Калининграде 236001 Россия Калининградская область Калининград Московский проспект 261 Офис в Киеве ukraine@1c-bitrix.ru Телефон в Киеве +3 (8044)221-55-33 Офис в Киеве 01033 Украина Калининградская область Киев улица Шота Руставели 39/41 офис 1507

Контент для лиц от 16 лет и старше

© 2001-2024 «Битрикс», «1С-Битрикс». Работает на 1С-Битрикс: Управление сайтом. Политика конфиденциальности

ShvetsGroup

activities.png

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

Цель рассматриваемых модулей отследить действия пользователя и вывести в удобном виде. Чем больше действий модуль может фиксировать тем лучше. Другой важный показатель — интеграция с другими модулями и наличие развитого API.

Логика работы всех рассматриваемых модулей одинакова. Отслеживаем необходимый хук (hook) и записываем событие в свою таблицу базы данных. Все рассматриваемые модули работают в связке с Views, поэтому вывод результатов не вызывает сложностей — создается обычный вид и при необходимости его темизируем в своем модуле или теме.

Activity

http://drupal.org/project/activity
Актуальная ветка модуля 6.x-2.x (6.x-1.x более не поддерживается и нет возможности апгрейда к ветке 2.х). Зависит от модулей Token и Trigger. В комплекте с модулем есть под модуль Activity comments с помощью которого любое зафиксированное действие можно комментировать.

Готовые интеграции с другими модулями:

  • Comment, Node, User — реализовано в самом модуле;
  • Flag, Organic groups — реализовано в этих модулях.

Модуль позволяет фиксировать такие действия пользователей:

  • insert: После сохранения нового комментария
  • update: После обновления комментария
  • delete: После удаления материала
  • insert: После создания материала
  • update: После обновления материала
  • view: При просмотре материала зарегистрированным пользователем
  • insert: После регистрации пользователя
  • update: После обновления учетной записи пользователя
  • login: После входа в учетную запись
  • logout: После выходя пользователя из учетной записи
  • view: При просмотре профиля пользователя
  • flag: Когда содержимое отмечается
  • unflag: При удаление метки содержимого
  • user insert: Присоединение пользователя к группе
  • user update: Пользователь изменил подписки на группы
  • user delete: Пользователь удалил подписки на группы
  • user approve: Пользователя приняли в группу
  • user deny: Пользователю отказано в участие группы
  • user request: Пользователь запросил участие в группе
  • admin new: Пользователь назначен администратором группы

Модуль имеем качественный код и API, есть описание реализованных хуков и документация по использованию. В качестве примера можно рассмотреть уже готовые реализации для интеграции модулей. Модуль позволяет гибко настраивать права доступа к регистрации активности и просмотру.

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

Данные хранятся в 4х таблицах:

  • activity — все события активности
  • activity_targets — связь между сообщением, языком и событием.
  • activity_messages — сообщения
  • activity_access — связь между событиями и модулями дающими права на событие.

Heartbeat

http://drupal.org/project/heartbeat
Достаточно мощный модуль в состав которого включено еще 10 под модулей: Flag heartbeat, friendlist activity, Heartbeat comments, Heartbeat displays, Heartbeat example module, Heartbeat rules, Heartbeat test helper, Heartbeat views, organic group activity, Shouts. Здесь полный набор от интеграции с другими модулям до тестов и модуля примера.

Интеграция с модулями: comment, node, user, flag, OG, system, taxonomy, flag_friend, friendlist, User relationships, выводит результаты через Views, связан с модулем Rule.

Этот модуль как выглядит мощно, так же мощно и реализован, почти для всего есть фиксация событий. Например, можно через админ страницы реализовать проверку на сколько процентов заполнен профиль пользователя и соответственно выводить сообщение: профиль создан; профиль заполнен на 30%, профиль заполнен полностью или сделать проверку заполнения обязательных полей и дополнительных.
Все данные записываются в таблицы:

  • heartbeat_activity — таблица с сообщениями о активности, каждое сообщение; сохраняется сразу на всех включенных языках сайта;
  • heartbeat_tags — теги для сообщений модуля;
  • heartbeat_mt — связь тегов и сообщений;
  • heartbeat_translations — связь таблиц переводов и активности;
  • heartbeat_messages — таблица сообщений для событий.

Есть поддержка многоязычности и сообщения записываются сразу на нескольких языках. К сожалению сам модуль не переведен на русский и украинский языки, примерно 10% перевода в наличии, но это легко исправимая ситуация. Несмотря на интеграцию с большим количеством модулей, есть мощное и гибкое API c необходимой документацией для разработчика и модуль уже поддерживает Drupal 7.х.

Message

http://drupal.org/project/message
Несмотря на то что разработчики на странице модуля написали что модуль аналогичен activity и привели список отличий, на самом деле отличий намного больше, часть из которых необходимо записать в минус. Проблемы начали еще во время настройки появилась ошибка отсутствие функции i18nstrings_update() в модуле i18, как выяснилось позже эта функция добавлена в последних версиях i18, поэтому для начала необходимо обновиться.

В продолжение казусов у нас есть документация — видео, где показано как настроить модуль через подмодуль UI, но в новых версиях этого подмодуля уже нет, а сам модуль это API и из подмодулей есть в наличии Message example и Message follow.
По статистике drupal.org модулем пользуется около 20 человек.
Из интеграции есть связь с flag. Также модуль работает вместе с i18, Views, ctools, rule.
Сообщения хранятся в таблицах:

  • message — шаблоны сообщений;
  • message_instance — сообщения;
  • message_realm — сфера действия сообщений (пользователь, нода, органик групп).

Для разработчика есть пример, модуля с использованием API, документации практически нет.

Итог

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

API первых двух модулей схож и с его помощью можно реализовать фиксацию любых действий пользователей или сайта.
По статистике использования модуль activity успел покорить 2000 человек против 1000 у heartbeat, хотя это скорее из-за рождения первого в ветке 5.x Друпала.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *