Как отличить 1С-ку от обычного пользователя при обновлении элемента инфоблока? Вешаю обработчик на OnBeforeIBlockElementUpdate, нужно отличить 1С от обычного пользователя (администратора) и запрещать 1С-ке внусить некоторые изменения. На сколько знаю определение пользователя $USER происходит после инициализации init.php (порядок выполнения страницы https://dev.1c-bitrix.ru/api_help/main/general/pageplan.php ) и вариант "создать для обмена 1С отдельного пользователя с правами админа" не подходит.
Никак в текущей реализации фреймворка. В связи с этим вспоминается анекдот, перефразируя который его можно рассказать и так: "Приходит к нормальному программисту программист ядра одной известной CMS и говорит: - Слушай, глянь на программу, меня задолбали уже с претензиями, у меня на тестах все работает! Я учел все что можно. Где у меня ошибка?! Нормальный внимательно изучает листинг и мрачно выдает: - В ДНК, @@@@@! "
class ExchangeHandlers
{
private static $inExchange = false;
/**
* Обработчики событий модуля catalog
*/
public function OnBeforeCatalogImport1C($arParams, $file) {
self::$inExchange = true;
)
public function OnSuccessCatalogImport1C($arParams, $file) {
self::$inExchange = false;
}
/**
* Обработчики событий модуля iblock
*/
public function OnBeforeIBlockElementUpdate(&$arParams) {
if (self::$inExchange) {
}
}
}
Александр Воробьев, нет не так. Что будет если обмен прервется? Где вы OnSuccessCatalogImport1C получите? И что будет, если во время обмена я отредактирую свойство элемента инфоблока через админку? Анекдот актуален, к сожалению.
1. Если обмен прервется, то и событие OnBeforeIBlockElementUpdate не будет больше происходить. Следовательно необходимость в этом флаге отпадет.. Так что тут вообще нет ни какой проблемы абсолютно.
2. Ни чего не будет. По скольку сточки зрения сервера это разные хиты. Соответственно $inExchange будет у вас разное. Так что и тут нет ни каких проблем.
Прежде чем бочку катить на битрикс со своим анекдотом, вы бы вспомнили как работает PHP на веб сервере. И подумали как работает вышеприведенный код...
Если коротко: общение с веб сервером это не постоянный канал связи. А передача запроса серверу и получение от него ответа. (Хит). На каждом (абсоютно) хите переменная $inExchange будет равна false. Даже если в параллель будет 100 обменов идти. И лишь при появлении события OnBeforeCatalogImport1C оно будет изменять на true. И значение это будет изменено только и исключительно в рамках данного хита. Это, даже, не переменная сессии, не говоря о том что она ни как не связана между хитами разных клиентов. Если произойдет обрыв...... То будет просто обрыв хита.... все. Данная переменная и ее новое значение (если не будет багов ПО сервера) будет удалено из памяти (или точнееэта область будет помечена как свободная)
Александр Воробьев, написано интересно, можно вас попросить написать не коротко. Как я понял, обуславливать обработку для OnBeforeIBlockElementUpdate в зависимости от пользователя, все равно нельзя (или нет?). Вы говорите, что на хите (в хите, у хита - как правильно?) надо отследить наступление события OnBeforeCatalogImport1C и далее опять же в рамках хита выполнять все нужные действия для OnBeforeIBlockElementUpdate. Если так, то нельзя ли сразу пользователя (считаем, что для обмена у нас отдельный пользователь) на хите определить и задать аналогично $inExchange?
Судя по протоколу обмена OnBeforeCatalogImport1C вызывается между шагом C и D, а событие OnSuccessCatalogImport1C непосредствено по окончании шага D.
Получается, что при пакетной обработке у вас обработается только первая порция товаров? Согласно вашей же логике, ведь это будут разные хиты, и на всех шагах после первого OnBeforeCatalogImport1C не будет запускаться. Поправьте если ошибаюсь, не претендую на истину.
По сабжу, я бы предложил в файлик, на который настроен обмен 1С (можно его переложить в папку local чтобы не затронули обновления) перед вызовом компонента catalog.import.1c определить какую-нибудь константу, или в принципе вначале файла. В обработчике же проверять
нет не проверял. согласно документации OnBeforeCatalogImport1C - событие, вызываемое перед началом процедуры обмена: перед загрузкой XML в базу данных после загрузки файла на сервер. (т.е. это то же этап D) OnSuccessCatalogImport1C - событие, вызываемое после окончания обмена одним XML-файлом
Т.е. вполне логично, что между этими двумя событиями и происходит работа с элементами инфоблока. Т.е пришел следующий файл - опять возникает эта же последовательность событий. Хотя несколько стал менее уверенным в методе - надо проверять - добавить в этиобработчики вывод в логфайл - да убедиться.
Да вполне рабочий вариант и с кастомизацие файла 1c_exchange.php. Сделать переменную ExchangeHandlers::$inExchange Это даже лучше чем мой. Я бы сделал так: создал файл my_1c_exchage.php в нем устанавливал флаг из моего кода и дальше инклуд битриксного. 1Ску настроить на my_1c_excahnge.php
Дмитрий Чебыкин написал: Как я понял, обуславливать обработку для OnBeforeIBlockElementUpdate в зависимости от пользователя, все равно нельзя (или нет?).
Можно... Просто тогда условие видоизменяется: конкретного пользователя всегда считать процессом обмена.... Это отличается от исходного
Цитата
Дмитрий Чебыкин написал: Если так, то нельзя ли сразу пользователя (считаем, что для обмена у нас отдельный пользователь) на хите определить и задать аналогично $inExchange
Если. Конкертный пользователь означает обмен и только обмен, тогда и проблемы то нет. Переменная $inExchage совсем не нужна - просто анаизируем текущего юзера...