61 private static $oldProductAvailable =
array();
62 private static $agentNoticeCreated =
false;
63 private static $agentRepeatedNoticeCreated =
false;
72 return 'b_catalog_subscribe';
84 'data_type' =>
'integer',
86 'autocomplete' =>
true,
89 'data_type' =>
'datetime',
91 'default_value' => fn() =>
new DateTime(),
94 'data_type' =>
'datetime',
96 'USER_CONTACT' =>
array(
97 'data_type' =>
'string',
100 'CONTACT_TYPE' =>
array(
101 'data_type' =>
'integer',
105 'data_type' =>
'integer',
108 'data_type' =>
'Bitrix\Main\UserTable',
109 'reference' =>
array(
'=this.USER_ID' =>
'ref.ID'),
112 'data_type' =>
'integer',
115 'data_type' =>
'Bitrix\Catalog\ProductTable',
116 'reference' =>
array(
'=this.ITEM_ID' =>
'ref.ID'),
118 'IBLOCK_ELEMENT' =>
array(
119 'data_type' =>
'Bitrix\Iblock\ElementTable',
120 'reference' =>
array(
'=this.ITEM_ID' =>
'ref.ID'),
122 'NEED_SENDING' =>
array(
123 'data_type' =>
'boolean',
124 'values' =>
array(
'N',
'Y'),
125 'default_value' =>
'N',
126 'validation' =>
array(__CLASS__,
'validateNeedSending'),
129 'data_type' =>
'string',
131 'validation' =>
array(__CLASS__,
'validateSiteId'),
133 'LANDING_SITE_ID' =>
array(
134 'data_type' =>
'integer',
180 'delete from ' . $helper->quote(static::getTableName())
181 .
' where ' . $helper->quote(
'USER_ID') .
' = ' .
$userId
194 $productId = (int)$productId;
200 $connection->queryExecute(
'delete from '.$helper->quote(static::getTableName()).
' where '
201 .$helper->quote(
'ITEM_ID').
' = '.$productId
214 public static function onSaleOrderSaved(
Event $event)
216 if(!
$event->getParameter(
'IS_NEW'))
225 $basketObject =
$order->getBasket();
226 $listProductId =
array();
228 foreach ($basketObject->getBasketItems() as $item)
229 $listProductId[] = $item->getProductId();
231 if(!
$userId || empty($listProductId))
234 $user = \CUser::getList(
'ID',
'ASC',
239 $listSubscribe = static::getList(
array(
240 'select' =>
array(
'ID'),
242 '=USER_CONTACT' =>
$user[
'EMAIL'],
244 'ITEM_ID' => $listProductId,
247 $listSubscribeId =
array();
248 foreach($listSubscribe as $subscribe)
249 $listSubscribeId[] = $subscribe[
'ID'];
251 static::unSubscribe($listSubscribeId);
265 $contactTypes =
array();
267 $event =
new Event(
'catalog', static::EVENT_ADD_CONTACT_TYPE,
array(&$contactTypes));
270 if(!is_array($contactTypes))
273 $availableFields =
array(
'ID',
'NAME',
'RULE',
'HANDLER');
274 foreach($contactTypes as $typeId => $typeData)
276 $currentFields = array_keys($typeData);
277 $divergenceFields = array_diff($availableFields, $currentFields);
278 if(!empty($divergenceFields))
280 unset($contactTypes[$typeId]);
283 if(!is_string($typeData[
'NAME']) || !is_string($typeData[
'RULE']) || !is_callable($typeData[
'HANDLER']))
285 unset($contactTypes[$typeId]);
289 return $contactTypes;
300 $contactTypes[static::CONTACT_TYPE_EMAIL] =
array(
301 'ID' => static::CONTACT_TYPE_EMAIL,
302 'NAME' => Loc::getMessage(
'CONTACT_TYPE_EMAIL_NAME'),
306 $eventData =
$event->getParameters();
307 $eventObject = new \CEvent;
308 foreach($eventData as $userContact => $dataList)
310 foreach($dataList as
$data)
330 return static::checkOldProductAvailable($productId,
$fields);
342 return static::checkOldProductAvailable($productId,
$fields);
353 $productId = (int)$productId;
359 $connection->queryExecute(
'update '.$helper->quote(static::getTableName()).
' set '
360 .$helper->quote(
'NEED_SENDING').
' = \'Y\' where '.$helper->quote(
'ITEM_ID').
' = '.$productId
361 .
' and ('.$helper->quote(
'DATE_TO').
' is null or '.$helper->quote(
'DATE_TO').
' > '
362 .$helper->getCurrentDateTimeFunction().
')'
365 if (!static::$agentNoticeCreated)
367 $t = DateTime::createFromTimestamp(time() + static::AGENT_TIME_OUT);
368 static::$agentNoticeCreated =
true;
370 '\Bitrix\Catalog\SubscribeTable::sendNotice();',
373 static::AGENT_INTERVAL,
394 $productId = (int)$productId;
395 if ($productId <= 0 || (
string)Option::get(
'catalog',
'subscribe_repeated_notify') !=
'Y')
400 $connection->queryExecute(
'update '.$helper->quote(static::getTableName()).
' set '
401 .$helper->quote(
'NEED_SENDING').
' = \'Y\' where '.$helper->quote(
'ITEM_ID').
' = '.$productId
402 .
' and ('.$helper->quote(
'DATE_TO').
' is null or '.$helper->quote(
'DATE_TO').
' > '
403 .$helper->getCurrentDateTimeFunction().
')'
406 if (!static::$agentRepeatedNoticeCreated)
408 $t = DateTime::createFromTimestamp(time() + static::AGENT_TIME_OUT);
409 static::$agentRepeatedNoticeCreated =
true;
411 'Bitrix\Catalog\SubscribeTable::sendRepeatedNotice();',
414 static::AGENT_INTERVAL,
436 return $subscribe ==
'Y' || ($subscribe ==
'D' && (string)Option::get(
'catalog',
'default_subscribe') ==
'Y');
448 if(!$productId || !$available)
453 static::$oldProductAvailable[$productId][
'AVAILABLE'] = $available;
465 if(static::checkLastUpdate())
466 return '\Bitrix\Catalog\SubscribeTable::sendNotice();';
468 list($listSubscribe,
$totalCount) = static::getSubscriptionsData();
470 if(empty($listSubscribe))
472 static::$agentNoticeCreated =
false;
476 $anotherStep = (int)
$totalCount[
'CNT'] > static::LIMIT_SEND;
478 list($dataSendToNotice, $listNotifiedSubscribeId) =
479 static::prepareDataForNotice($listSubscribe,
'CATALOG_PRODUCT_SUBSCRIBE_NOTIFY');
481 static::startEventNotification($dataSendToNotice);
483 if($listNotifiedSubscribeId)
484 static::setNeedSending($listNotifiedSubscribeId);
488 return '\Bitrix\Catalog\SubscribeTable::sendNotice();';
492 static::$agentNoticeCreated =
false;
504 if(static::checkLastUpdate())
505 return 'Bitrix\Catalog\SubscribeTable::sendRepeatedNotice();';
507 list($listSubscribe,
$totalCount) = static::getSubscriptionsData();
509 if(empty($listSubscribe))
511 static::$agentRepeatedNoticeCreated =
false;
515 $anotherStep = (int)
$totalCount[
'CNT'] > static::LIMIT_SEND;
517 list($dataSendToNotice, $listNotifiedSubscribeId) =
518 static::prepareDataForNotice($listSubscribe,
'CATALOG_PRODUCT_SUBSCRIBE_NOTIFY_REPEATED');
520 static::startEventNotification($dataSendToNotice);
522 if($listNotifiedSubscribeId)
523 static::setNeedSending($listNotifiedSubscribeId);
527 return 'Bitrix\Catalog\SubscribeTable::sendRepeatedNotice();';
531 static::$agentRepeatedNoticeCreated =
false;
545 $productId = (int)$productId;
546 if ($productId <= 0 || (empty(static::$oldProductAvailable[$productId]))
547 || !static::checkPermissionSubscribe(
$fields[
'SUBSCRIBE']))
555 static::runAgentToSendNotice($productId);
560 static::runAgentToSendRepeatedNotice($productId);
563 unset(static::$oldProductAvailable[$productId]);
577 'select' =>
array(
'TIMESTAMP_X'),
578 'order' =>
array(
'TIMESTAMP_X' =>
'DESC'),
582 if (empty($lastUpdate) || !($lastUpdate[
'TIMESTAMP_X'] instanceof
DateTime))
585 return (time() - $lastUpdate[
'TIMESTAMP_X']->getTimestamp() < static::AGENT_TIME_OUT);
593 '=NEED_SENDING' =>
'Y',
594 '!=PRODUCT.SUBSCRIBE' =>
'N',
597 array(
'=DATE_TO' =>
false),
598 array(
'>DATE_TO' => date(
$DB->dateFormatToPHP(\CLang::getDateFormat(
'FULL')), time()))
603 $notifyOption = Option::get(
'sale',
'subscribe_prod');
605 if($notifyOption <>
'')
606 $notify = unserialize($notifyOption, [
'allowed_classes' =>
false]);
607 if(is_array($notify))
609 $listSiteId =
array();
612 if ((
$data[
'use'] ??
'N') !==
'Y')
618 $filter[
'!=SITE_ID'] = $listSiteId;
621 $listSubscribe = static::getList(
array(
627 'PRODUCT_NAME' =>
'IBLOCK_ELEMENT.NAME',
628 'DETAIL_PAGE_URL' =>
'IBLOCK_ELEMENT.IBLOCK.DETAIL_PAGE_URL',
629 'IBLOCK_ID' =>
'IBLOCK_ELEMENT.IBLOCK_ID',
630 'TYPE' =>
'PRODUCT.TYPE',
634 'USER_NAME' =>
'USER.NAME',
635 'USER_LAST_NAME' =>
'USER.LAST_NAME',
638 'limit' => static::LIMIT_SEND,
642 'select' =>
array(
'CNT'),
653 $itemIdGroupByIblock =
array();
654 foreach($listSubscribe as
$key => $subscribeData)
655 $itemIdGroupByIblock[$subscribeData[
'IBLOCK_ID']][$subscribeData[
'ITEM_ID']] = $subscribeData[
'ITEM_ID'];
657 $detailPageUrlGroupByItemId =
array();
658 if(!empty($itemIdGroupByIblock))
660 foreach($itemIdGroupByIblock as
$iblockId => $listItemId)
662 $queryObject = \CIBlockElement::getList(
array(
'ID'=>
'ASC'),
663 array(
'IBLOCK_ID' =>
$iblockId,
'ID' => $listItemId),
false,
false,
array(
'DETAIL_PAGE_URL'));
664 while(
$result = $queryObject->getNext())
665 $detailPageUrlGroupByItemId[
$result[
'ID']] =
$result[
'DETAIL_PAGE_URL'];
669 $dataSendToNotice =
array();
670 $listNotifiedSubscribeId =
array();
671 foreach($listSubscribe as
$key => $subscribeData)
673 $pageUrl = self::getPageUrl($subscribeData, $detailPageUrlGroupByItemId);
679 $listNotifiedSubscribeId[] = $subscribeData[
'ID'];
681 $subscribeData[
'EVENT_NAME'] = $eventName;
682 $subscribeData[
'USER_NAME'] = $subscribeData[
'USER_NAME'] ?
683 $subscribeData[
'USER_NAME'] : Loc::getMessage(
'EMAIL_TEMPLATE_USER_NAME');
684 $subscribeData[
'EMAIL_TO'] = $subscribeData[
'USER_CONTACT'];
685 $subscribeData[
'NAME'] = $subscribeData[
'PRODUCT_NAME'];
686 $subscribeData[
'PAGE_URL'] = $pageUrl;
687 $subscribeData[
'PRODUCT_ID'] = $subscribeData[
'ITEM_ID'];
689 'action' =>
'BUY',
'id' => $subscribeData[
'PRODUCT_ID']));
691 'action' =>
'BUY',
'id' => $subscribeData[
'PRODUCT_ID']));
693 self::getUnsubscribeUrl($subscribeData),
694 array(
'unSubscribe' =>
'Y',
'subscribeId' => $subscribeData[
'ID'],
695 'userContact' => $subscribeData[
'USER_CONTACT'],
'productId' => $subscribeData[
'PRODUCT_ID']));
697 array(
'unSubscribe' =>
'Y',
'subscribeId' => $subscribeData[
'ID'],
698 'userContact' => $subscribeData[
'USER_CONTACT'],
'productId' => $subscribeData[
'PRODUCT_ID']));
700 $dataSendToNotice[$subscribeData[
'CONTACT_TYPE']][$subscribeData[
'USER_CONTACT']][
$key] = $subscribeData;
703 return array($dataSendToNotice, $listNotifiedSubscribeId);
706 private static function getPageUrl(
array $subscribeData,
array $detailPageUrlGroupByItemId)
710 if (!empty($subscribeData[
'LANDING_SITE_ID']))
712 $pageUrl = Loader::includeModule(
'landing') ?
713 IblockConnector::getElementUrl($subscribeData[
'LANDING_SITE_ID'], $subscribeData[
'ITEM_ID']) :
"";
715 elseif (!empty($detailPageUrlGroupByItemId[$subscribeData[
'ITEM_ID']]))
717 $pageUrl = self::getProtocol().self::getServerName($subscribeData[
'SITE_ID']).
718 $detailPageUrlGroupByItemId[$subscribeData[
'ITEM_ID']];
724 private static function getUnsubscribeUrl(
array $subscribeData)
726 if (!empty($subscribeData[
'LANDING_SITE_ID']))
728 $unsubscribeUrl =
'';
729 if (Loader::includeModule(
'landing'))
731 $unsubscribeUrl = \Bitrix\Landing\Syspage::getSpecialPage(
732 $subscribeData[
'LANDING_SITE_ID'],
734 [
'SECTION' =>
'subscribe']
740 $unsubscribeUrl = self::getProtocol().self::getServerName(
741 $subscribeData[
'SITE_ID']).
'/personal/subscribe/';
744 return $unsubscribeUrl;
747 private static function getProtocol()
749 $currentApplication = Application::getInstance();
750 $context = $currentApplication->getContext();
752 if (
$protocol = Option::get(
'main',
'mail_link_protocol'))
754 if (mb_strrpos(
$protocol,
'://') ===
false)
759 if (
$context->getServer()->getServerName())
769 unset($currentApplication);
775 private static function getServerName(
$siteId)
782 $serverName = (string)
$site[
'SERVER_NAME'];
784 if ($serverName ==
'')
786 $serverName = (defined(
'SITE_SERVER_NAME') && SITE_SERVER_NAME !=
'' ?
787 SITE_SERVER_NAME : (string)Option::get(
'main',
'server_name',
'',
$siteId)
789 if ($serverName ==
'')
791 $currentApplication = Application::getInstance();
792 $context = $currentApplication->getContext();
793 $serverName =
$context->getServer()->getServerName();
794 unset($currentApplication);
804 $contactTypes = static::getContactTypes();
805 foreach($contactTypes as $typeId => $typeData)
807 if (empty($dataSendToNotice[$typeId]))
812 $eventKey = EventManager::getInstance()
813 ->addEventHandler(
'catalog',
'OnSubscribeSubmit', $typeData[
'HANDLER']);
815 $event =
new Event(
'catalog',
'OnSubscribeSubmit', $dataSendToNotice[$typeId]);
818 EventManager::getInstance()->removeEventHandler(
'catalog',
'OnSubscribeSubmit', $eventKey);
822 private static function setNeedSending(
array $listSubscribeId, $needSending =
'N')
824 if(empty($listSubscribeId))
829 $connection->queryExecute(
'update '.$helper->quote(static::getTableName()).
' set '
830 .$helper->quote(
'NEED_SENDING').
' = \''.$needSending.
'\' where
'
831 .$helper->quote('ID
').' in (
'.implode(',
', $listSubscribeId).')
'
835 private static function unSubscribe(array $listSubscribeId)
837 if(empty($listSubscribeId))
840 $connection = Application::getConnection();
841 $helper = $connection->getSqlHelper();
842 $connection->queryExecute('update
'.$helper->quote(static::getTableName()).' set '
843 .$helper->quote('NEED_SENDING
').' = \
'N\', '.$helper->quote(
'DATE_TO').
' ='
844 .$helper->getCurrentDateTimeFunction().
' where '
845 .$helper->quote(
'ID').
' in ('.implode(
',', $listSubscribeId).
')'
static getList(array $parameters=array())
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)