Необходимо было реализовать функционал отправки электронных ключей в подарок.
Т.е. пользоватлеь покупает электронный ключ, оплачивает покупку и во время оплаты указывает дату/время отправки подарка и на какой email отправлять.
Для продажи электронных ключей используется модуль
Вроде все нормально, повешал событие OnBeforeEventSend , в котором хотел отпинывать неактуальные письма до тех пор, пока бы не пришел их час.
Код события довольно простой (SEND_DATE -- свойство в письме, содержащее дату в которую необходимо отправить письмо):
Т.е. если дата отправки не задана, то письмо улетает без проблем. Если дата задана и еще не наступила, то откладываем письмо в недолгий ящик.
И тут пришла она, проблема! В файле /bitrix/modules/main/classes/general/event.php , в функции CEvent::HandleEvent() вызывается обработчик OnBeforeEventSend, но не важно что вернет этот обработчик, письмо отошлется.
Теперь расскажу, как я это допилил, в ядре, стыд, да. Но я это делал с надеждой, что в скором времени разработчики ядра исполнят мое пожелание, так как оно вполне логично обоснуемо!
Файл /bitrix/modules/main/classes/general/event.php .
заменил
на
По человечески говоря, если событие вернет false, то письмо не отправляется и статус ему присваевается N , якобы оно еще не отсылалось. Насчет устанавливаемого статуса можно поспорить, конечно, но мне было нужно именно такое поведение
.
Файл /bitrix/modules/main/classes/mysql/event.php .
Изменил немного mysql запросы в функции CheckEvents(), добавив условие
То есть, если отправка письма еще не запускалась, либо с последней отправки уже прошло 10 минут, причем отправляются сначала письма, которые еще ни разу не пытались отправиться, у них DATE_EXEC NULL и они будут в выборке первыми. Если их не выбирать первыми, то очередь отправки забьется подарочными письмами, если у вас конечно хотя бы не по 10 хитов в минуту и 10 подарочных писем всего, грубо говоря.
Получилось два запроса в итоге.
и
Теперь все прекрасно работает, создается событие через CEvent::Send(), потом неважно где пытается отправиться письмо, вызывается обработчик события OnBeforeEventSend и если он не разрешает отправку письма, то у письма остается статус N, если же обработчик разрешает отправку, то письмо пытается отправиться с обработкой статусов стандартной F,P,0 и так далее.
Вот так вот были потрачены часы жизни, что бы подумать как решить без костылей, но нет, в итоге пришлось к ним прибегнуть.
P.S. Повторюсь
.
Т.е. пользоватлеь покупает электронный ключ, оплачивает покупку и во время оплаты указывает дату/время отправки подарка и на какой email отправлять.
Для продажи электронных ключей используется модуль
Вроде все нормально, повешал событие OnBeforeEventSend , в котором хотел отпинывать неактуальные письма до тех пор, пока бы не пришел их час.
Код события довольно простой (SEND_DATE -- свойство в письме, содержащее дату в которую необходимо отправить письмо):
function OnBeforeEventSend($arFields) {
if (empty($arFields['SEND_DATE'])) {
return true;
}
if (strtotime($arFields['SEND_DATE']) <= time()) {
return true;
}
return false;
}
|
Т.е. если дата отправки не задана, то письмо улетает без проблем. Если дата задана и еще не наступила, то откладываем письмо в недолгий ящик.
И тут пришла она, проблема! В файле /bitrix/modules/main/classes/general/event.php , в функции CEvent::HandleEvent() вызывается обработчик OnBeforeEventSend, но не важно что вернет этот обработчик, письмо отошлется.
Лирическое отступление... Разработчики ядра Битрикс, обращение к вам! Хотелось бы, что бы вы допилили логику отправки event'ов, что бы была реакция на обработчик OnBeforeEventSend . |
Теперь расскажу, как я это допилил, в ядре, стыд, да. Но я это делал с надеждой, что в скором времени разработчики ядра исполнят мое пожелание, так как оно вполне логично обоснуемо!
Файл /bitrix/modules/main/classes/general/event.php .
заменил
while ($event = $events->Fetch()) ExecuteModuleEventEx($event, array(&$arFields, &$db_mail_result_array)); |
while ($event = $events->Fetch())
if(ExecuteModuleEventEx($event, array(&$arFields, &$db_mail_result_array)) === false) {
return 'N';
} |
По человечески говоря, если событие вернет false, то письмо не отправляется и статус ему присваевается N , якобы оно еще не отсылалось. Насчет устанавливаемого статуса можно поспорить, конечно, но мне было нужно именно такое поведение
.Файл /bitrix/modules/main/classes/mysql/event.php .
Изменил немного mysql запросы в функции CheckEvents(), добавив условие
AND (NOW() > ADDTIME(DATE_EXEC, '0:1:0') OR ISNULL(DATE_EXEC)) ORDER BY DATE_EXEC ASC |
Получилось два запроса в итоге.
$strSql= "SEL ECT 'x' ". "FR OM b_event ". "WHERE SUCCESS_EXEC='N' ". "AND (NOW() > ADDTIME(DATE_EXEC, '0:10:0') OR ISNULL(DATE_EXEC)) ". "ORDER BY DATE_EXEC ASC " . "LIMIT 1"; |
$strSql = " SELECT ID, C_FIELDS, EVENT_NAME, MESSAGE_ID, LID, DATE_FORMAT(DATE_INSERT, '%d.%m.%Y %H:%i:%s') as DATE_INSERT, DUPLICATE FR OM b_event WH ERE SUCCESS_EXEC='N' AND (NOW() > ADDTIME(DATE_EXEC, '0:10:0') OR ISNULL(DATE_EXEC)) ORDER BY DATE_EXEC, ID LIMIT ".$bulk; |
Теперь все прекрасно работает, создается событие через CEvent::Send(), потом неважно где пытается отправиться письмо, вызывается обработчик события OnBeforeEventSend и если он не разрешает отправку письма, то у письма остается статус N, если же обработчик разрешает отправку, то письмо пытается отправиться с обработкой статусов стандартной F,P,0 и так далее.
Вот так вот были потрачены часы жизни, что бы подумать как решить без костылей, но нет, в итоге пришлось к ним прибегнуть.
P.S. Повторюсь
.Разработчики ядра Битрикс, обращение к вам! Хотелось бы, что бы вы допилили логику отправки event'ов, что бы была реакция на обработчик OnBeforeEventSend . |