/** @return \CDBResult */ public function getData() { $mailingId = $this->getFieldValue('MAILING_ID', 0); $send = $this->getFieldValue('SEND', null); $read = $this->getFieldValue('READ', null); $click = $this->getFieldValue('CLICK', null); $unsub = $this->getFieldValue('UNSUB', null); $filter = array('POSTING.MAILING_ID' => $mailingId); if ($send == 'Y') { $filter['!STATUS'] = PostingRecipientTable::SEND_RESULT_NONE; } elseif ($send == 'N') { $filter['STATUS'] = PostingRecipientTable::SEND_RESULT_NONE; } if ($read == 'Y') { $filter['!POSTING_READ.ID'] = null; } elseif ($read == 'N') { $filter['POSTING_READ.ID'] = null; } if ($click == 'Y') { $filter['!POSTING_CLICK.ID'] = null; } elseif ($click == 'N') { $filter['POSTING_CLICK.ID'] = null; } if ($unsub == 'Y') { $filter['!POSTING_UNSUB.ID'] = null; } elseif ($unsub == 'N') { $filter['POSTING_UNSUB.ID'] = null; } $recipientDb = PostingRecipientTable::getList(array('select' => array('NAME', 'EMAIL'), 'filter' => $filter, 'group' => array('NAME', 'EMAIL'))); return new \CDBResult($recipientDb); }
public static function onSetDayContextAttributes(DayContext $context) { $id = null; if (isset($_SESSION[self::CLICK_PARAM_NAME])) { $id = $_SESSION[self::CLICK_PARAM_NAME]; } if (!is_numeric($id) || $id <= 0) { return; } $recipientDb = PostingRecipientTable::getList(array('select' => array('MAILING_CHAIN_ID' => 'POSTING.MAILING_CHAIN_ID'), 'filter' => array('ID' => $id))); if ($recipient = $recipientDb->fetch()) { $context->setAttribute('sender_chain_source', $recipient['MAILING_CHAIN_ID']); } }
<td> <input type="text" id="SUBJECT" name="SUBJECT" value="<?php echo $str_SUBJECT; ?> " style="width: 450px;"> </td> </tr> <tr class="hidden-when-show-template-list" <?php echo empty($str_MESSAGE) ? 'style="display: none;"' : ''; ?> > <td> </td> <td> <?php $arPersonalizeList = \Bitrix\Sender\PostingRecipientTable::getPersonalizeList(); ?> <?php echo GetMessage("sender_chain_edit_field_subject_personalize"); ?> <?php foreach ($arPersonalizeList as $arPersonalize) { ?> <a class="sender-link-email" onclick="SetAddressToControl('SUBJECT', ' #<?php echo htmlspecialcharsbx($arPersonalize['CODE']); ?> #', true)" title="<?php echo htmlspecialcharsbx($arPersonalize['DESC']); ?> "> <?php
/** * @param $id * @param int $timeout * @param int $maxMailCount * @return bool|string * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\DB\Exception * @throws \Bitrix\Main\Db\SqlQueryException * @throws \Exception */ public static function send($id, $timeout = 0, $maxMailCount = 0) { $start_time = getmicrotime(); @set_time_limit(0); static::$emailSentPerIteration = 0; $postingDb = PostingTable::getList(array('select' => array('ID', 'STATUS', 'MAILING_ID', 'MAILING_CHAIN_ID', 'MAILING_CHAIN_REITERATE' => 'MAILING_CHAIN.REITERATE', 'MAILING_CHAIN_IS_TRIGGER' => 'MAILING_CHAIN.IS_TRIGGER'), 'filter' => array('ID' => $id, 'MAILING.ACTIVE' => 'Y', 'MAILING_CHAIN.STATUS' => MailingChainTable::STATUS_SEND))); $postingData = $postingDb->fetch(); // posting not found if (!$postingData) { return static::SEND_RESULT_ERROR; } // if posting in new status, then import recipients from groups and set right status for sending $isInitGroupRecipients = false; $isChangeStatusToPart = false; if ($postingData["STATUS"] == PostingTable::STATUS_NEW) { $isInitGroupRecipients = true; $isChangeStatusToPart = true; } if ($postingData["STATUS"] != PostingTable::STATUS_PART && $postingData["MAILING_CHAIN_IS_TRIGGER"] == 'Y') { $isInitGroupRecipients = false; $isChangeStatusToPart = true; } if ($isInitGroupRecipients) { PostingTable::initGroupRecipients($postingData['ID']); } if ($isChangeStatusToPart) { PostingTable::update(array('ID' => $postingData['ID']), array('STATUS' => PostingTable::STATUS_PART)); $postingData["STATUS"] = PostingTable::STATUS_PART; } // posting not in right status if ($postingData["STATUS"] != PostingTable::STATUS_PART) { return static::SEND_RESULT_ERROR; } // lock posting for exclude double parallel sending if (static::lockPosting($id) === false) { throw new \Bitrix\Main\DB\Exception(Loc::getMessage('SENDER_POSTING_MANAGER_ERR_LOCK')); } // select all recipients of posting, only not processed $recipientDataDb = PostingRecipientTable::getList(array('filter' => array('POSTING_ID' => $postingData['ID'], 'STATUS' => PostingRecipientTable::SEND_RESULT_NONE), 'limit' => $maxMailCount)); while ($recipientData = $recipientDataDb->fetch()) { // create name from email $recipientEmail = $recipientData["EMAIL"]; if (empty($recipientData["NAME"])) { $recipientEmailParts = explode('@', $recipientEmail); $recipientName = $recipientEmailParts[0]; } else { $recipientName = $recipientData["NAME"]; } // prepare params for send $sendParams = array('FIELDS' => array('EMAIL_TO' => $recipientEmail, 'NAME' => $recipientName, 'USER_ID' => $recipientData["USER_ID"], 'SENDER_CHAIN_CODE' => 'sender_chain_item_' . $postingData["MAILING_CHAIN_ID"], 'UNSUBSCRIBE_LINK' => Subscription::getLinkUnsub(array('MAILING_ID' => $postingData['MAILING_ID'], 'EMAIL' => $recipientEmail, 'RECIPIENT_ID' => $recipientData["ID"]))), 'TRACK_READ' => array('MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => $recipientData["ID"])), 'TRACK_CLICK' => array('MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => $recipientData["ID"]), 'URL_PARAMS' => array('bx_sender_conversion_id' => $recipientData["ID"]))); if (is_array($recipientData['FIELDS']) && count($recipientData) > 0) { $sendParams['FIELDS'] = $sendParams['FIELDS'] + $recipientData['FIELDS']; } // set sending result to recipient $mailSendResult = static::sendInternal($postingData['MAILING_CHAIN_ID'], $sendParams); PostingRecipientTable::update(array('ID' => $recipientData["ID"]), array('STATUS' => $mailSendResult, 'DATE_SENT' => new Type\DateTime())); // send event $eventData = array('SEND_RESULT' => $mailSendResult == PostingRecipientTable::SEND_RESULT_SUCCESS, 'RECIPIENT' => $recipientData, 'POSTING' => $postingData); $event = new Event('sender', 'OnAfterPostingSendRecipient', array($eventData)); $event->send(); // limit executing script by time if ($timeout > 0 && getmicrotime() - $start_time >= $timeout) { break; } // increment sending statistic static::$emailSentPerIteration++; } //set status and delivered and error emails $statusList = PostingTable::getRecipientCountByStatus($id); if (!array_key_exists(PostingRecipientTable::SEND_RESULT_NONE, $statusList)) { if (array_key_exists(PostingRecipientTable::SEND_RESULT_ERROR, $statusList)) { $STATUS = PostingTable::STATUS_SENT_WITH_ERRORS; } else { $STATUS = PostingTable::STATUS_SENT; } $DATE = new Type\DateTime(); } else { $STATUS = PostingTable::STATUS_PART; $DATE = null; } // unlock posting for exclude double parallel sending static::unlockPosting($id); // update status of posting PostingTable::update(array('ID' => $id), array('STATUS' => $STATUS, 'DATE_SENT' => $DATE)); // return status to continue or end of sending if ($STATUS == PostingTable::STATUS_PART) { return static::SEND_RESULT_CONTINUE; } else { return static::SEND_RESULT_SENT; } }
function getSenderItemContainer($id, array $chain = array()) { $i = '%SENDER_LETTER_TEMPLATE_BODY_NUM%'; ob_start(); ?> <div class="sender-trigger-chain-container-letter"> <div class="sender-trigger-status-mailing-time"> <?php echo GetMessage("sender_chain_edit_field_time_thr"); ?> <span class="sender_letter_container_time_text">*</span> <?php echo GetMessage("sender_chain_edit_field_time_after"); ?> <span class="sender_letter_container_time_text_first"> <?php echo GetMessage("sender_chain_edit_field_time_event"); ?> </span> <span style="display: none;" class="sender_letter_container_time_text_nonfirst"> <?php echo GetMessage("sender_chain_edit_field_time_letter"); ?> </span> <a id="SENDER_TRIGGER_CHAIN_TIME_BNT_<?php echo $i; ?> " href="javascript: void(0);" class="sender_letter_container_time_button sender-link-email"><?php echo GetMessage("sender_chain_edit_field_time_change"); ?> </a> </div> <div class="sender_letter_container" id="SENDER_TRIGGER_CHAIN_<?php echo $i; ?> "> <input type="hidden" name="CHAIN[<?php echo $i; ?> ][ID]" value="<?php echo htmlspecialcharsbx($chain['ID']); ?> "> <input class="sender_letter_container_sorter" type="hidden" name="CHAIN[<?php echo $i; ?> ][ITEM_SORT]" value="<?php echo $i; ?> "> <input class="sender_letter_container_time" type="hidden" name="CHAIN[<?php echo $i; ?> ][TIME_SHIFT]" value="<?php echo intval($chain['TIME_SHIFT']); ?> "> <div class="sender_letter_container_head"> <div class="sender_letter_container_move"><div class="sender_letter_container_burger"></div></div> <div class="sender_letter_container_sorter_view"> <span class="sender_letter_container_sorter_icon"> <span class="sender_letter_container_sorter_text"><?php echo $i; ?> </span> </span> </div> <h3><span class="sender_letter_container_caption"><?php echo htmlspecialcharsbx($chain['SUBJECT']); ?> </span></h3> <span class="sender_letter_container-info"> <?php if (!empty($chain['ID']) && empty($chain['DATE_INSERT'])) { ?> <span><?php echo GetMessage("sender_chain_edit_field_created_exists_but_not_save"); ?> </span> <?php } elseif (!empty($chain['ID'])) { ?> <span class="sender_letter_container-create"><?php echo GetMessage("sender_chain_edit_field_created"); ?> </span> <span> <?php echo GetMessage("sender_chain_edit_field_created_text", array('%DATE_CREATE%' => htmlspecialcharsbx(is_object($chain['DATE_INSERT']) ? \Bitrix\Main\Type\Date::createFromTimestamp($chain['DATE_INSERT']->getTimestamp()) : $chain['DATE_INSERT']), '%AUTHOR%' => '<a class="sender_letter_container-author" href="/bitrix/admin/user_edit.php?ID=' . htmlspecialcharsbx($chain['CREATED_BY']) . '&lang=' . LANGUAGE_ID . '">' . htmlspecialcharsbx($chain['CREATED_BY_NAME']) . ' ' . htmlspecialcharsbx($chain['CREATED_BY_LAST_NAME']) . '</a>')); ?> </span> <?php } else { ?> <span><?php echo GetMessage("sender_chain_edit_field_created_new"); ?> </span> <?php } ?> </span> <a class="sender_letter_container_button_delete" href="javascript: void(0);" title="<?php echo GetMessage("sender_chain_edit_field_delete"); ?> "></a> <?php if (strlen($chain['SUBJECT']) > 0 && strlen($chain['MESSAGE']) > 0) { ?> <a class="sender_letter_container_button_show" href="javascript: void(0);"> <?php echo GetMessage('SENDER_MAILING_TRIG_LETTER_MESSAGE_SHOW'); ?> </a> <?php } else { ?> <a class="sender_letter_container_button_show sender_letter_container_button_hide" href="javascript: void(0);"> <?php echo GetMessage('SENDER_MAILING_TRIG_LETTER_MESSAGE_HIDE'); ?> </a> <?php } ?> </div> <div class="sender_letter_container_body" <?php echo strlen($chain['SUBJECT']) > 0 && strlen($chain['MESSAGE']) > 0 ? 'style="display:none;"' : ''; ?> > <div class="sender_letter_container_body_tmpl" id="CHAIN_TEMPLATE_NUM_<?php echo $i; ?> " <?php echo strlen($chain['MESSAGE']) > 0 ? 'style="display:none;"' : ''; ?> > <?php echo \Bitrix\Sender\Preset\Template::getTemplateListHtml('SENDER_TRIGGER_CHAIN_' . $i); ?> </div> <div class="sender_letter_container_body_fields" <?php echo strlen($chain['MESSAGE']) > 0 ? '' : 'style="display:none;"'; ?> > <table class="trigger_chain_item"> <tr> <td><?php echo GetMessage("sender_chain_edit_field_sel_templ"); ?> </td> <td> <span class="sender-template-message-caption-container"></span> <a href="javascript:void(0);" class="sender-template-message-caption-container-btn sender-link-email"> <?php echo GetMessage("sender_chain_edit_field_sel_templ_another"); ?> </a> </td> </tr> <tr> <td><?php echo GetMessage("sender_chain_edit_field_subject"); ?> </td> <td> <input class="sender_letter_container_subject" type="text" id="CHAIN_<?php echo $i; ?> _SUBJECT" name="CHAIN[<?php echo $i; ?> ][SUBJECT]" value="<?php echo htmlspecialcharsbx($chain['SUBJECT']); ?> "> </td> </tr> <tr> <td> </td> <td> <?php $arPersonalizeList = \Bitrix\Sender\PostingRecipientTable::getPersonalizeList(); ?> <?php echo GetMessage("sender_chain_edit_field_subject_personalize"); ?> <?php foreach ($arPersonalizeList as $arPersonalize) { ?> <a class="sender-link-email" onclick="SetAddressToControl('CHAIN_<?php echo $i; ?> _SUBJECT', ' #<?php echo htmlspecialcharsbx($arPersonalize['CODE']); ?> #', true)" title="#<?php echo htmlspecialcharsbx($arPersonalize['CODE']); ?> # - <?php echo htmlspecialcharsbx($arPersonalize['DESC']); ?> "> <?php echo htmlspecialcharsbx($arPersonalize['NAME']); ?> </a><?php echo end($arPersonalizeList) === $arPersonalize ? '' : ','; ?> <?php } ?> <span style="cursor: pointer;" class="hidden-when-show-template-list-info" onclick="ShowPersonalizeDescDialog(this);"> </span> </td> </tr> <tr> <td colspan="2"> <b><?php echo GetMessage("sender_chain_edit_field_message"); ?> </b> <br> <br> %SENDER_LETTER_TEMPLATE_MESSAGE% </td> </tr> </table> </div> </div> </div> </div> <?php return ob_get_clean(); }
<td> <input type="text" name="find_name" size="47" value="<?php echo htmlspecialcharsbx($find_name); ?> "> </td> </tr> <tr> <td><?php echo GetMessage("rub_f_sent"); ?> :</td> <td> <?php $arRecipientStatus = \Bitrix\Sender\PostingRecipientTable::getStatusList(); $arr = array("reference" => array_values($arRecipientStatus), "reference_id" => array_keys($arRecipientStatus)); echo SelectBoxFromArray("find_sent", $arr, $find_sent, GetMessage("MAIN_ALL"), ""); ?> </td> </tr> <tr> <td><?php echo GetMessage("rub_f_read"); ?> :</td> <td> <?php $arr = array("reference" => array(GetMessage("MAIN_YES"), GetMessage("MAIN_NO")), "reference_id" => array("Y", "N")); echo SelectBoxFromArray("find_read", $arr, $find_read, GetMessage("MAIN_ALL"), ""); ?>
/** * @param $arData * @return bool * @throws \Bitrix\Main\ArgumentException */ public static function unsubscribe($arData) { $result = false; if (isset($arData['TEST']) && $arData['TEST'] == 'Y') { return true; } $arPosting = null; if ($arData['RECIPIENT_ID']) { $postingDb = PostingRecipientTable::getList(array('select' => array('POSTING_ID', 'POSTING_MAILING_ID' => 'POSTING.MAILING_ID'), 'filter' => array('ID' => $arData['RECIPIENT_ID'], 'EMAIL' => $arData['EMAIL']))); $arPosting = $postingDb->fetch(); } $mailingDb = MailingTable::getList(array('select' => array('ID'), 'filter' => array('ID' => $arData['UNSUBSCRIBE_LIST']))); while ($mailing = $mailingDb->fetch()) { $unsub = null; if ($arPosting && $arPosting['POSTING_MAILING_ID'] == $mailing['ID']) { $unsub = array('POSTING_ID' => $arPosting['POSTING_ID'], 'RECIPIENT_ID' => $arData['RECIPIENT_ID']); } else { $mailingPostingDb = PostingRecipientTable::getList(array('select' => array('RECIPIENT_ID' => 'ID', 'POSTING_ID'), 'filter' => array('=POSTING.MAILING_ID' => $mailing['ID'], 'EMAIL' => $arData['EMAIL']))); if ($arMailingPosting = $mailingPostingDb->fetch()) { $unsub = $arMailingPosting; } } if (!empty($unsub)) { $unsubExists = PostingUnsubTable::getRowById($unsub); if (!$unsubExists) { PostingUnsubTable::add($unsub); } $result = true; } $contactDb = ContactTable::getList(array('select' => array('ID'), 'filter' => array('=EMAIL' => $arData['EMAIL']))); while ($contact = $contactDb->fetch()) { MailingSubscriptionTable::delete(array('MAILING_ID' => $mailing['ID'], 'CONTACT_ID' => $contact['ID'])); $result = true; } } return $result; }
/** * @param array $arParams * @return string */ public static function initEditor(array $arParams) { $fieldName = $arParams['FIELD_NAME']; $fieldValue = $arParams['FIELD_VALUE']; $isUserHavePhpAccess = $arParams['HAVE_USER_ACCESS']; $showSaveTemplate = isset($arParams['SHOW_SAVE_TEMPLATE']) ? $arParams['SHOW_SAVE_TEMPLATE'] : true; if (!empty($arParams['PERSONALIZE_LIST']) && is_array($arParams['PERSONALIZE_LIST'])) { PostingRecipientTable::setPersonalizeList($arParams['PERSONALIZE_LIST']); } \CJSCore::RegisterExt("editor_mailblock", array("js" => "/bitrix/js/sender/editor_mailblock.js", "rel" => array())); static $isInit; $editorHeight = 650; $editorWidth = '100%'; ob_start(); if (\Bitrix\Main\Config\Option::get('fileman', 'use_editor_3') == 'Y') { \Bitrix\Main\Loader::includeModule('fileman'); \CJSCore::Init(array("editor_mailblock")); ?> <script> //BX.ready(function(){ <?php if (!$isInit) { $isInit = true; ?> letterManager = new SenderLetterManager; letterManager.setMailBlockList(<?php echo \CUtil::PhpToJSObject(\Bitrix\Sender\Preset\MailBlock::getBlockForVisualEditor()); ?> ); <?php } ?> //}); BX.message({"BXEdMailBlocksTitle" : "<?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_MAILBLOCK'); ?> "}); BX.message({"BXEdMailBlocksSearchPlaceHolder" : "<?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_MAILBLOCK_SEARCH'); ?> "}); </script> <?php \CFileMan::AddHTMLEditorFrame($fieldName, $fieldValue, false, "html", array('height' => $editorHeight, 'width' => $editorWidth), "N", 0, "", "onfocus=\"t=this\"", false, !$isUserHavePhpAccess, false, array('componentFilter' => array('TYPE' => 'mail'), 'limit_php_access' => !$isUserHavePhpAccess)); ?> <?php } else { $fieldValue = htmlspecialcharsback($fieldValue); ?> <br> <?php echo Loc::getMessage("SENDER_ENTITY_TEMPLATE_NOTE_OLD_EDITOR", array("%LINK_START%" => '<a href="/bitrix/admin/settings.php?mid=fileman&lang=' . LANGUAGE_ID . '">', "%LINK_END%" => '</a>')); ?> <br> <br> <textarea class="typearea" style="width:<?php echo $editorWidth; ?> ;height:<?php echo $editorHeight; ?> px;" name="<?php echo $fieldName; ?> " id="bxed_<?php echo $fieldName; ?> " wrap="virtual"><?php echo htmlspecialcharsbx($fieldValue); ?> </textarea> <?php } if ($showSaveTemplate) { ?> <script> function ToggleTemplateSaveDialog() { BX('TEMPLATE_ACTION_SAVE_NAME_CONT').value = ''; var currentDisplay = BX('TEMPLATE_ACTION_SAVE_NAME_CONT').style.display; BX('TEMPLATE_ACTION_SAVE_NAME_CONT').style.display = BX.toggle(currentDisplay, ['inline', 'none']); } </script> <div class="adm-detail-content-item-block-save"> <span> <input type="checkbox" value="Y" name="TEMPLATE_ACTION_SAVE" id="TEMPLATE_ACTION_SAVE" onclick="ToggleTemplateSaveDialog();"> <label for="TEMPLATE_ACTION_SAVE"><?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_SAVE'); ?> </label> </span> <span id="TEMPLATE_ACTION_SAVE_NAME_CONT" style="display: none;"> <?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_SAVE_NAME'); ?> <input type="text" name="TEMPLATE_ACTION_SAVE_NAME"></span> </div> <?php } return ob_get_clean(); }
/** * @param $id * @return array * @throws \Bitrix\Main\ArgumentException */ public static function getRecipientCountByStatus($id) { $arStatus = array(); $arSelect = array('CNT', 'STATUS'); $arFilter = array('POSTING_ID' => $id); $postingContactDb = PostingRecipientTable::getList(array('select' => $arSelect, 'filter' => $arFilter, 'runtime' => array(new Entity\ExpressionField('CNT', 'COUNT(*)')))); while ($arPostingContact = $postingContactDb->fetch()) { $arStatus[$arPostingContact['STATUS']] = intval($arPostingContact['CNT']); } return $arStatus; }
{ ksort($arPostingReiterateList); $arPostingReiterateList = array_values($arPostingReiterateList); } } } if(!empty($arPosting)) { $statListDb = \Bitrix\Sender\PostingRecipientTable::getList(array( 'select' => array( 'STATUS', 'CNT', 'READ_CNT', 'CLICK_CNT', 'UNSUB_CNT' ), 'filter' => array('POSTING_ID' => $arPosting['ID']), 'runtime' => array( new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(DISTINCT %s)', 'ID'), new \Bitrix\Main\Entity\ExpressionField('READ_CNT', 'COUNT(DISTINCT %s)', 'POSTING_READ.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('CLICK_CNT', 'COUNT(DISTINCT %s)', 'POSTING_CLICK.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('UNSUB_CNT', 'COUNT(DISTINCT %s)', 'POSTING_UNSUB.RECIPIENT_ID') ), //'group' => array('STATUS') )); while($stat = $statListDb->fetch()) { switch($stat['STATUS']) { case \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS: $arStatDeliveried = $stat; break; case \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_ERROR:
/** * @return array */ public static function getList() { $resultList = array(); $arBlockByType = static::getBlockListByType(); foreach ($arBlockByType as $type => $arBlock) { foreach ($arBlock as $blockName) { $result = static::getById($blockName); if (!empty($result)) { $resultList[] = $result; } } } $resultListPersonal = array(); foreach (\Bitrix\Sender\PostingRecipientTable::getPersonalizeList() as $arPersonalizeBlock) { $resultListPersonal[] = array('TYPE' => Loc::getMessage('TYPE_PRESET_MAILBLOCK_PERSONALISE'), 'CODE' => $arPersonalizeBlock['CODE'], 'NAME' => $arPersonalizeBlock['NAME'], 'DESC' => $arPersonalizeBlock['DESC'], 'ICON' => '', 'HTML' => '#' . $arPersonalizeBlock['CODE'] . '#'); } $resultList = array_merge($resultListPersonal, $resultList); return $resultList; }
/** * @param $data * @return bool * @throws \Bitrix\Main\ArgumentException */ public static function unsubscribe($data) { $result = false; if(isset($data['TEST']) && $data['TEST'] == 'Y') return true; $posting = null; if($data['RECIPIENT_ID']) { $postingDb = PostingRecipientTable::getList(array( 'select' => array('POSTING_ID', 'POSTING_MAILING_ID' => 'POSTING.MAILING_ID'), 'filter' => array('ID' => $data['RECIPIENT_ID'], 'EMAIL' => $data['EMAIL']) )); $posting = $postingDb->fetch(); } $mailingDb = MailingTable::getList(array( 'select' => array('ID'), 'filter' => array( 'ID' => $data['UNSUBSCRIBE_LIST'], ) )); while($mailing = $mailingDb->fetch()) { $unsub = null; if($posting && $posting['POSTING_MAILING_ID'] == $mailing['ID']) { $unsub = array( 'POSTING_ID' => $posting['POSTING_ID'], 'RECIPIENT_ID' => $data['RECIPIENT_ID'], ); } else { $mailingPostingDb = PostingRecipientTable::getList(array( 'select' => array('RECIPIENT_ID' => 'ID', 'POSTING_ID'), 'filter' => array('=POSTING.MAILING_ID' => $mailing['ID'], 'EMAIL' => $data['EMAIL']) )); if($mailingPosting = $mailingPostingDb->fetch()) { $unsub = $mailingPosting; } } if(!empty($unsub)) { $unsubExists = PostingUnsubTable::getRowById($unsub); if(!$unsubExists) { $unsubResult = PostingUnsubTable::add($unsub); if($unsubResult->isSuccess()) { $eventData = array( 'MAILING_ID' => $mailing['ID'], 'RECIPIENT_ID' => $unsub['RECIPIENT_ID'], 'EMAIL' => $data['EMAIL'], ); $event = new \Bitrix\Main\Event('sender', 'OnAfterRecipientUnsub', array($eventData)); $event->send(); } } $result = true; } $contactDb = ContactTable::getList(array( 'select' => array('ID'), 'filter' => array('=EMAIL' => $data['EMAIL']) )); while($contact = $contactDb->fetch()) { MailingSubscriptionTable::delete(array('MAILING_ID' => $mailing['ID'], 'CONTACT_ID' => $contact['ID'])); $result = true; } } return $result; }
$cntDivider = $arPostingReiterate['CNT'] > 0 ? $arPostingReiterate['CNT'] : 1; $cntDivider = $cntDivider / 100; $defaultDateTimeStamp = $arPostingReiterate['DATE_SENT']->getTimestamp(); $arPostingReiterateList[$defaultDateTimeStamp] = array('date' => $arPostingReiterate['DATE_SENT']->format("d/m"), 'sent' => $arPostingReiterate['CNT'], 'read' => $arPostingReiterate['READ_CNT'], 'click' => $arPostingReiterate['CLICK_CNT'], 'unsub' => $arPostingReiterate['UNSUB_CNT'], 'sent_prsnt' => '100', 'read_prsnt' => round($arPostingReiterate['READ_CNT'] / $cntDivider, 2), 'click_prsnt' => round($arPostingReiterate['CLICK_CNT'] / $cntDivider, 2), 'unsub_prsnt' => round($arPostingReiterate['UNSUB_CNT'] / $cntDivider, 2)); } if (!empty($arPostingReiterateList)) { if (count($arPostingReiterateList) < 2) { $arPostingReiterateList = array(); } else { ksort($arPostingReiterateList); $arPostingReiterateList = array_values($arPostingReiterateList); } } } if (!empty($arPosting)) { $statListDb = \Bitrix\Sender\PostingRecipientTable::getList(array('select' => array('STATUS', 'CNT'), 'filter' => array('POSTING_ID' => $arPosting['ID']), 'runtime' => array(new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(%s)', 'ID')))); while ($stat = $statListDb->fetch()) { $statResult['all'] += $stat['CNT']; switch ($stat['STATUS']) { case \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS: $statResult['delivered'] = $stat['CNT']; break; case \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_ERROR: $statResult['error'] = $stat['CNT']; break; case \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_NONE: $statResult['not_send'] = $stat['CNT']; break; } } $statResult['all_print'] = $statResult['all'];
/** * Init editor * * @param array $params * @return string */ public static function initEditor(array $params) { $fieldName = $params['FIELD_NAME']; $fieldValue = $params['FIELD_VALUE']; $isUserHavePhpAccess = $params['HAVE_USER_ACCESS']; $showSaveTemplate = isset($params['SHOW_SAVE_TEMPLATE']) ? $params['SHOW_SAVE_TEMPLATE'] : true; $site = isset($params['SITE']) ? $params['SITE'] : ''; $charset = isset($params['CHARSET']) ? $params['CHARSET'] : ''; $contentUrl = isset($params['CONTENT_URL']) ? $params['CONTENT_URL'] : ''; $templateTypeInput = isset($params['TEMPLATE_TYPE_INPUT']) ? $params['TEMPLATE_TYPE_INPUT'] : 'TEMPLATE_TYPE'; $templateIdInput = isset($params['TEMPLATE_ID_INPUT']) ? $params['TEMPLATE_ID_INPUT'] : 'TEMPLATE_ID'; $templateType = isset($params['TEMPLATE_TYPE']) ? $params['TEMPLATE_TYPE'] : ''; $templateId = isset($params['TEMPLATE_ID']) ? $params['TEMPLATE_ID'] : ''; $isTemplateMode = isset($params['IS_TEMPLATE_MODE']) ? (bool) $params['IS_TEMPLATE_MODE'] : true; if (!empty($params['PERSONALIZE_LIST']) && is_array($params['PERSONALIZE_LIST'])) { PostingRecipientTable::setPersonalizeList($params['PERSONALIZE_LIST']); } \CJSCore::RegisterExt("editor_mailblock", array("js" => array("/bitrix/js/sender/editor_mailblock.js"), "rel" => array())); \CJSCore::Init(array("editor_mailblock")); static $isInit; $isDisplayBlockEditor = $templateType && $templateId || static::isContentForBlockEditor($fieldValue); $editorHeight = 650; $editorWidth = '100%'; ob_start(); ?> <div id="bx-sender-visual-editor-<?php echo $fieldName; ?> " style="<?php if ($isDisplayBlockEditor) { ?> display: none;<?php } ?> "> <?php if (\Bitrix\Main\Config\Option::get('fileman', 'use_editor_3') == 'Y') { \Bitrix\Main\Loader::includeModule('fileman'); ?> <script> BX.ready(function(){ <?php if (!$isInit) { $isInit = true; ?> var letterManager = new SenderLetterManager; letterManager.setMailBlockList(<?php echo \CUtil::PhpToJSObject(\Bitrix\Sender\Preset\MailBlock::getBlockForVisualEditor()); ?> ); letterManager.setPlaceHolderList(<?php echo \CUtil::PhpToJSObject(\Bitrix\Sender\PostingRecipientTable::getPersonalizeList()); ?> ); <?php } ?> }); BX.message({ "BXEdMailBlocksTitle" : "<?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_MAILBLOCK'); ?> ", "BXEdMailBlocksSearchPlaceHolder" : "<?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_MAILBLOCK_SEARCH'); ?> ", "BXEdPlaceHolderSelectorTitle" : "<?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_PLACEHOLDER'); ?> " }); </script> <?php \CFileMan::AddHTMLEditorFrame($fieldName, $fieldValue, false, "text", array('height' => $editorHeight, 'width' => $editorWidth), "N", 0, "", "onfocus=\"t=this\"", false, !$isUserHavePhpAccess, false, array('componentFilter' => array('TYPE' => 'mail'), 'limit_php_access' => !$isUserHavePhpAccess)); ?> <?php } else { $fieldValue = htmlspecialcharsback($fieldValue); ?> <br> <?php echo Loc::getMessage("SENDER_ENTITY_TEMPLATE_NOTE_OLD_EDITOR", array("%LINK_START%" => '<a href="/bitrix/admin/settings.php?mid=fileman&lang=' . LANGUAGE_ID . '">', "%LINK_END%" => '</a>')); ?> <br> <br> <textarea class="typearea" style="width:<?php echo $editorWidth; ?> ;height:<?php echo $editorHeight; ?> px;" name="<?php echo $fieldName; ?> " id="bxed_<?php echo $fieldName; ?> " wrap="virtual"><?php echo htmlspecialcharsbx($fieldValue); ?> </textarea> <?php } ?> </div> <div id="bx-sender-block-editor-<?php echo $fieldName; ?> " style="<?php if (!$isDisplayBlockEditor) { ?> display: none;<?php } ?> "> <br/> <input type="hidden" name="<?php echo htmlspecialcharsbx($templateTypeInput); ?> " value="<?php echo htmlspecialcharsbx($templateType); ?> " /> <input type="hidden" name="<?php echo htmlspecialcharsbx($templateIdInput); ?> " value="<?php echo htmlspecialcharsbx($templateId); ?> " /> <?php $url = ''; if ($isDisplayBlockEditor) { if ($templateType && $templateId) { $url = '/bitrix/admin/sender_template_admin.php?'; $url .= 'action=get_template&template_type=' . $templateType . '&template_id=' . $templateId; $url .= '&lang=' . LANGUAGE_ID . '&' . bitrix_sessid_get(); } else { $url = $contentUrl; } } echo \Bitrix\Fileman\Block\EditorMail::show(array('id' => $fieldName, 'charset' => $charset, 'site' => $site, 'own_result_id' => 'bxed_' . $fieldName, 'url' => $url, 'templateType' => $templateType, 'templateId' => $templateId, 'isTemplateMode' => $isTemplateMode, 'isUserHavePhpAccess' => $isUserHavePhpAccess)); ?> </div> <?php if ($showSaveTemplate) { ?> <script> function ToggleTemplateSaveDialog() { BX('TEMPLATE_ACTION_SAVE_NAME_CONT').value = ''; var currentDisplay = BX('TEMPLATE_ACTION_SAVE_NAME_CONT').style.display; BX('TEMPLATE_ACTION_SAVE_NAME_CONT').style.display = BX.toggle(currentDisplay, ['inline', 'none']); } </script> <div class="adm-detail-content-item-block-save"> <span> <input type="checkbox" value="Y" name="TEMPLATE_ACTION_SAVE" id="TEMPLATE_ACTION_SAVE" onclick="ToggleTemplateSaveDialog();"> <label for="TEMPLATE_ACTION_SAVE"><?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_SAVE'); ?> </label> </span> <span id="TEMPLATE_ACTION_SAVE_NAME_CONT" style="display: none;"> <?php echo Loc::getMessage('SENDER_TEMPLATE_EDITOR_SAVE_NAME'); ?> <input type="text" name="TEMPLATE_ACTION_SAVE_NAME"></span> </div> <?php } return ob_get_clean(); }
/** * @param array $chain * @param TriggerSettings $settings * @param array $rpnt * @return void */ protected static function addRecipient($chain, $settings, $rpnt) { if (!$rpnt || empty($rpnt['EMAIL'])) { return; } $rpnt['EMAIL'] = strtolower($rpnt['EMAIL']); // check email to unsubscription if (Subscription::isUnsubscibed($chain['MAILING_ID'], $rpnt['EMAIL'])) { return; } // if this is event for child if (!empty($chain['PARENT_ID'])) { $recipientDb = PostingRecipientTable::getList(array('select' => array('ID', 'EMAIL', 'NAME', 'STATUS', 'USER_ID'), 'filter' => array('=EMAIL' => $rpnt['EMAIL'], '=POSTING.MAILING_CHAIN_ID' => $chain['ID'], '=POSTING.STATUS' => array(PostingTable::STATUS_NEW, PostingTable::STATUS_PART)))); while ($recipient = $recipientDb->fetch()) { // check if event should came or didn't came $statusNew = null; if ($settings->isEventOccur() && $recipient['STATUS'] == PostingRecipientTable::SEND_RESULT_WAIT) { $statusNew = PostingRecipientTable::SEND_RESULT_NONE; } elseif (!$settings->isEventOccur() && $recipient['STATUS'] == PostingRecipientTable::SEND_RESULT_NONE) { $statusNew = PostingRecipientTable::SEND_RESULT_WAIT; } if ($statusNew !== null) { $updateDb = PostingRecipientTable::update(array('ID' => $recipient['ID']), array('STATUS' => $statusNew)); if ($updateDb->isSuccess()) { } else { } } } } else { // check email to have not finished mailing $recipientExistsDb = PostingRecipientTable::getList(array('select' => array('ID', 'ROOT_ID', 'POSTING_ID', 'STATUS', 'POSTING_STATUS' => 'POSTING.STATUS'), 'filter' => array('=EMAIL' => $rpnt['EMAIL'], '=POSTING.MAILING_ID' => $chain['MAILING_ID'], '=STATUS' => array(PostingRecipientTable::SEND_RESULT_NONE, PostingRecipientTable::SEND_RESULT_WAIT)), 'limit' => 1)); if ($recipientExistsDb->fetch()) { return; } if (static::$postingId) { $postingId = static::$postingId; } else { $postingAddDb = PostingTable::add(array('MAILING_ID' => $chain['MAILING_ID'], 'MAILING_CHAIN_ID' => $chain['ID'])); if (!$postingAddDb->isSuccess()) { return; } $postingId = $postingAddDb->getId(); static::$postingId = $postingId; } $recipient = array('EMAIL' => $rpnt['EMAIL'], 'POSTING_ID' => $postingId); if (!empty($rpnt['NAME'])) { $recipient['NAME'] = $rpnt['NAME']; } if (!empty($rpnt['USER_ID'])) { $recipient['USER_ID'] = $rpnt['USER_ID']; } if (is_array($rpnt['FIELDS']) && count($rpnt['FIELDS']) > 0) { $recipient['FIELDS'] = $rpnt['FIELDS']; } $addDb = PostingRecipientTable::add($recipient); if ($addDb->isSuccess()) { } else { } } }
/** * Handler of after add event * * @param Entity\Event $event * @return Entity\EventResult */ public static function onAfterAdd(Entity\Event $event) { $result = new Entity\EventResult(); $data = $event->getParameters(); $data = $data['fields']; // update unsub flag of recipient PostingRecipientTable::update(array('ID' => $data['RECIPIENT_ID']), array('IS_UNSUB' => 'Y')); // update unsub counter of posting $resultDb = static::getList(array('filter' => array('RECIPIENT_ID' => $data['RECIPIENT_ID']))); if ($resultDb->getSelectedRowsCount() == 1) { PostingTable::update(array('ID' => $data['POSTING_ID']), array('COUNT_UNSUB' => new \Bitrix\Main\DB\SqlExpression('?# + 1', 'COUNT_UNSUB'))); } return $result; }
/** * Change status of recipients and mailing chain for resending mails to recipients who have error sending * * @param $id * @return void */ public static function prepareReSendErrorRecipients($id) { if (!static::canReSendErrorRecipients($id)) { return; } $mailingChain = static::getRowById(array('ID' => $id)); $updateSql = 'UPDATE ' . PostingRecipientTable::getTableName() . " SET STATUS='" . PostingRecipientTable::SEND_RESULT_NONE . "'" . " WHERE POSTING_ID=" . intval($mailingChain['POSTING_ID']) . " AND STATUS='" . PostingRecipientTable::SEND_RESULT_ERROR . "'"; \Bitrix\Main\Application::getConnection()->query($updateSql); PostingTable::update(array('ID' => $mailingChain['POSTING_ID']), array('STATUS' => PostingTable::STATUS_PART)); static::update(array('ID' => $id), array('STATUS' => static::STATUS_SEND)); }
} $statList = array(); if ($MAILING_ID > 0) { $i = 1; $chainList = \Bitrix\Sender\MailingTable::getChain($MAILING_ID); foreach ($chainList as $chain) { $stat = array('NAME' => GetMessage("sender_stat_trig_letter") . $i++, 'SUBJECT' => $chain['SUBJECT'], 'CNT' => array('SENT_SUCCESS' => 0, 'SENT_ERROR' => 0, 'READ' => 0, 'CLICK' => 0, 'UNSUB' => 0, 'GOAL' => 0, 'START' => 0)); $statRawDb = \Bitrix\Sender\PostingRecipientTable::getList(array('select' => array('CNT', 'READ_CNT', 'CLICK_CNT', 'UNSUB_CNT'), 'filter' => array('=POSTING.MAILING_CHAIN_ID' => $chain['ID'], '=STATUS' => array(\Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS)), 'runtime' => array(new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(DISTINCT %s)', 'ID'), new \Bitrix\Main\Entity\ExpressionField('READ_CNT', 'COUNT(DISTINCT %s)', 'POSTING_READ.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('CLICK_CNT', 'COUNT(DISTINCT %s)', 'POSTING_CLICK.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('UNSUB_CNT', 'COUNT(DISTINCT %s)', 'POSTING_UNSUB.RECIPIENT_ID')))); while ($statRaw = $statRawDb->fetch()) { $stat['CNT']['SENT_SUCCESS'] += $statRaw['CNT']; $stat['CNT']['READ'] += $statRaw['READ_CNT']; $stat['CNT']['CLICK'] += $statRaw['CLICK_CNT']; $stat['CNT']['UNSUB'] += $statRaw['UNSUB_CNT']; $stat['CNT']['START'] += $statRaw['CNT']; } $statRawDb = \Bitrix\Sender\PostingRecipientTable::getList(array('select' => array('ID'), 'filter' => array('=POSTING.MAILING_CHAIN_ID' => $chain['ID'], '=STATUS' => array(\Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS, \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_DENY), '!DATE_DENY' => null))); $stat['CNT']['GOAL'] = $statRawDb->getSelectedRowsCount(); $statList['CHAIN'][] = $stat; } } if (!empty($statList)) { foreach ($statList['CHAIN'] as $chain) { foreach ($chain['CNT'] as $k => $v) { if (!isset($statList['CNT'][$k])) { $statList['CNT'][$k] = 0; } $statList['CNT'][$k] += $v; } } $statList['CNT']['START'] = $statList['CHAIN'][0]['CNT']['START']; $goalStart = 0;
/** * @param $postingId * @param bool $checkDuplicate * @return bool * @throws \Bitrix\Main\ArgumentException */ public static function initGroupRecipients($postingId, $checkDuplicate = false) { $arPosting = \Bitrix\Sender\PostingTable::getRowById(array('ID' => $postingId)); if (!$arPosting) { return false; } $checkRecipientDuplicate = $checkDuplicate; if (!$checkDuplicate) { if ($arPosting['STATUS'] == \Bitrix\Sender\PostingTable::STATUS_NEW) { $primary = array('POSTING_ID' => $postingId); \Bitrix\Sender\PostingRecipientTable::delete($primary); $checkRecipientDuplicate = false; } } // fetch all unsubscribed emails of current mailing for excluding from recipients $arEmailNotSend = array(); $recipientUnsubDb = \Bitrix\Sender\PostingUnsubTable::getList(array('select' => array('EMAIL' => 'POSTING_RECIPIENT.EMAIL'), 'filter' => array('POSTING.MAILING_ID' => $arPosting['MAILING_ID']))); while ($recipientUnsub = $recipientUnsubDb->fetch()) { $arEmailNotSend[] = $recipientUnsub['EMAIL']; } $groupConnectorsDataCount = array(); $connection = \Bitrix\Main\Application::getConnection(); $conHelper = $connection->getSqlHelper(); $statusRecipientNone = \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_NONE; // fetch all connectors for getting emails $groupDb = \Bitrix\Sender\MailingGroupTable::getList(array('select' => array('INCLUDE', 'CONNECTOR_ENDPOINT' => 'GROUP.GROUP_CONNECTOR.ENDPOINT', 'GROUP_ID'), 'filter' => array('MAILING_ID' => $arPosting['MAILING_ID']), 'order' => array('INCLUDE' => 'DESC', 'GROUP_ID' => 'ASC'))); while ($group = $groupDb->fetch()) { $connector = \Bitrix\Sender\ConnectorManager::getConnector($group['CONNECTOR_ENDPOINT']); if (!$connector) { continue; } $connectorDataCount = 0; $connector->setFieldValues($group['CONNECTOR_ENDPOINT']['FIELDS']); $connectorDataDb = $connector->getData(); while (true) { $emailList = array(); $connectorDataList = array(); $maxPart = 200; while ($arConnectorData = $connectorDataDb->Fetch()) { // collect connectors counter of addresses $connectorDataCount++; // exclude unsubscribed addresses $arConnectorData['EMAIL'] = trim(strtolower($arConnectorData['EMAIL'])); if (strlen($arConnectorData['EMAIL']) <= 0 || in_array($arConnectorData['EMAIL'], $arEmailNotSend)) { continue; } $emailList[] = $arConnectorData['EMAIL']; $connectorDataList[$arConnectorData['EMAIL']] = $arConnectorData; $maxPart--; if ($maxPart == 0) { break; } } if (empty($emailList)) { break; } foreach ($emailList as &$email) { $email = $conHelper->forSql($email); } $emailListString = "'" . implode("', '", $emailList) . "'"; if ($group['INCLUDE']) { // add address if not exists if ($checkRecipientDuplicate) { $recipientEmailDb = $connection->query("select EMAIL from b_sender_posting_recipient where EMAIL in (" . $emailListString . ") and POSTING_ID=" . intval($postingId)); while ($recipientEmail = $recipientEmailDb->fetch()) { unset($connectorDataList[$recipientEmail['EMAIL']]); } } if (!empty($connectorDataList)) { foreach ($connectorDataList as $email => $arConnectorData) { $arRecipient = array('NAME' => "'" . $conHelper->forSql($arConnectorData['NAME']) . "'", 'EMAIL' => "'" . $conHelper->forSql($arConnectorData['EMAIL']) . "'", 'STATUS' => "'" . $statusRecipientNone . "'", 'POSTING_ID' => intval($postingId)); if (array_key_exists('USER_ID', $arConnectorData) && intval($arConnectorData['USER_ID']) > 0) { $arRecipient['USER_ID'] = intval($arConnectorData['USER_ID']); } $insertColumnNamesString = implode(", ", array_keys($arRecipient)); $insertColumnValuesString = implode(", ", array_values($arRecipient)); $connection->query("insert into b_sender_posting_recipient(" . $insertColumnNamesString . ") values(" . $insertColumnValuesString . ")"); } } } else { // delete address from posting $connection->query("delete from b_sender_posting_recipient where EMAIL in (" . $emailListString . ") and POSTING_ID=" . intval($postingId)); } } //\Bitrix\Sender\GroupConnectorTable::update(array('ID' => $group['GROUP_CONNECTOR_ID']), array('ADDRESS_COUNT' => $connectorDataCount)); // collect groups counter of addresses if (array_key_exists($group['GROUP_ID'], $groupConnectorsDataCount)) { $groupConnectorsDataCount[$group['GROUP_ID']] += $connectorDataCount; } else { $groupConnectorsDataCount[$group['GROUP_ID']] = $connectorDataCount; } } // update group counter of addresses foreach ($groupConnectorsDataCount as $groupId => $groupDataCount) { \Bitrix\Sender\GroupTable::update($groupId, array('ADDRESS_COUNT' => $groupDataCount)); } return true; }
public static function updatePostingReadCounters($type) { $dataDb = \Bitrix\Sender\PostingRecipientTable::getList(array('select' => array('POSTING_ID', 'CNT'), 'filter' => array('=UPDATE_POSTING.COUNT_' . $type => 0, '>CNT' => 0, '=IS_' . $type => 'Y'), 'runtime' => array(new \Bitrix\Main\Entity\ReferenceField('UPDATE_POSTING', 'Bitrix\\Sender\\PostingTable', array('=this.POSTING_ID' => 'ref.ID'), array('join_type' => 'INNER')), new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(%s)', 'ID')), 'order' => array('CNT' => 'DESC', 'POSTING_ID' => 'ASC'))); while ($item = $dataDb->fetch()) { if (self::isTimeUp()) { return true; } \Bitrix\Sender\PostingTable::update(array('ID' => $item['POSTING_ID']), array('COUNT_' . $type => $item['CNT'])); } return false; }