Current Path : /home/bitrix/vorobey-clubru/bitrix/modules/sender/lib/ |
Current File : /home/bitrix/vorobey-clubru/bitrix/modules/sender/lib/postingmanager.php |
<?php /** * Bitrix Framework * @package bitrix * @subpackage sender * @copyright 2001-2012 Bitrix */ namespace Bitrix\Sender; use Bitrix\Main\Config\Option; use Bitrix\Main\Event; use Bitrix\Main\Localization\Loc; use Bitrix\Main\Type; use Bitrix\Main\Mail; Loc::loadMessages(__FILE__); class PostingManager { const SEND_RESULT_ERROR = false; const SEND_RESULT_SENT = true; const SEND_RESULT_CONTINUE = 'CONTINUE'; protected static $checkStatusStep = 20; protected static $emailSentPerIteration = 0; protected static $currentMailingChainFields = null; /** * Handler of read event * * @param array $data * @return array */ public static function onMailEventMailRead(array $data) { $id = intval($data['RECIPIENT_ID']); if ($id > 0) static::read($id); return $data; } /** * Handler of click event * * @param array $data * @return array */ public static function onMailEventMailClick(array $data) { $id = intval($data['RECIPIENT_ID']); $url = $data['URL']; if ($id > 0 && strlen($url) > 0) static::click($id, $url); return $data; } /** * Do read actions * * @param $recipientId * @return void */ public static function read($recipientId) { $postingContactPrimary = array('ID' => $recipientId); $recipient = PostingRecipientTable::getRowById($postingContactPrimary); if ($recipient && $recipient['ID']) { PostingReadTable::add(array( 'POSTING_ID' => $recipient['POSTING_ID'], 'RECIPIENT_ID' => $recipient['ID'], )); } } /** * Do click actions * * @param $recipientId * @param $url * @return void * @throws \Bitrix\Main\ArgumentException */ public static function click($recipientId, $url) { $postingContactPrimary = array('ID' => $recipientId); $recipient = PostingRecipientTable::getRowById($postingContactPrimary); if ($recipient && $recipient['ID']) { $read = PostingReadTable::getRowById(array( 'POSTING_ID' => $recipient['POSTING_ID'], 'RECIPIENT_ID' => $recipient['ID'] )); if ($read === null) { static::read($recipientId); } $postingDb = PostingTable::getList(array( 'select' => array('ID'), 'filter' => array('ID' => $recipient['POSTING_ID']), )); if ($postingDb->fetch()) { $uri = new \Bitrix\Main\Web\Uri($url); $fixedUrl = $uri->deleteParams(array('bx_sender_conversion_id'))->getLocator(); $addClickDb = PostingClickTable::add(array( 'POSTING_ID' => $recipient['POSTING_ID'], 'RECIPIENT_ID' => $recipient['ID'], 'URL' => $fixedUrl )); if($addClickDb->isSuccess()) { // send event $eventData = array( 'URL' => $url, 'URL_FIXED' => $fixedUrl, 'CLICK_ID' => $addClickDb->getId(), 'RECIPIENT' => $recipient ); $event = new Event('sender', 'OnAfterRecipientClick', array($eventData)); $event->send(); } } } } /** * Get chain list for resending * * @param $mailingId * @return array|null * @throws \Bitrix\Main\ArgumentException */ public static function getChainReSend($mailingId) { $result = array(); $mailChainDb = MailingChainTable::getList(array( 'select' => array('ID'), 'filter' => array( 'MAILING.ID' => $mailingId, 'MAILING.ACTIVE' => 'Y', 'REITERATE' => 'N', 'MAILING_CHAIN.STATUS' => MailingChainTable::STATUS_END, ) )); while($mailChain = $mailChainDb->fetch()) { $result[] = $mailChain['ID']; } return (empty($result) ? null : $result); } protected static function fillHeadersByOptionHeaders(array $headers = array()) { static $headerList = null; if ($headerList === null) { $headerList = array(); // add headers from module options $optionHeaders = Option::get('sender', 'mail_headers', ''); $optionHeaders = !empty($optionHeaders) ? unserialize($optionHeaders) : array(); foreach ($optionHeaders as $optionHeader) { $optionHeader = trim($optionHeader); if (!$optionHeader) { continue; } $optionHeaderParts = explode(':', $optionHeader); $optionHeaderName = isset($optionHeaderParts[0]) ? $optionHeaderParts[0] : ''; $optionHeaderName = trim($optionHeaderName); $optionHeaderValue = isset($optionHeaderParts[1]) ? $optionHeaderParts[1] : ''; $optionHeaderValue = trim($optionHeaderValue); if (!$optionHeaderName || !$optionHeaderValue) { continue; } $headerList[$optionHeaderName] = $optionHeaderValue; } } foreach ($headerList as $optionHeaderName => $optionHeaderValue) { $headers[$optionHeaderName] = $optionHeaderValue; } return $headers; } /** * * @param $mailingChainId * @param array $params * @return string * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\DB\Exception */ protected static function sendInternal($mailingChainId, array $params) { // event before sending $eventSendParams = $params; $eventSendParams['MAILING_CHAIN_ID'] = $mailingChainId; $event = new Event('sender', 'OnBeforePostingSendRecipient', array($eventSendParams)); $event->send(); foreach ($event->getResults() as $eventResult) { if($eventResult->getType() == \Bitrix\Main\EventResult::ERROR) { return PostingRecipientTable::SEND_RESULT_ERROR; } if(is_array($eventResult->getParameters())) { $eventSendParams = array_merge($eventSendParams, $eventResult->getParameters()); } } unset($eventSendParams['MAILING_CHAIN_ID']); $params = $eventSendParams; // prepare common params if(static::$currentMailingChainFields !== null) { if(static::$currentMailingChainFields['ID'] != $mailingChainId) static::$currentMailingChainFields = null; } if(static::$currentMailingChainFields === null) { $mailingChainDb = MailingChainTable::getList(array( 'select' => array('*', 'SITE_ID' => 'MAILING.SITE_ID'), 'filter' => array('=ID' => $mailingChainId) )); if(!($mailingChain = $mailingChainDb->fetch())) { return PostingRecipientTable::SEND_RESULT_ERROR; } $charset = false; $siteDb = \Bitrix\Main\SiteTable::getList(array( 'select'=>array('SERVER_NAME', 'NAME', 'CULTURE_CHARSET'=>'CULTURE.CHARSET'), 'filter' => array('=LID' => $mailingChain['SITE_ID']) )); if($site = $siteDb->fetch()) { $charset = $site['CULTURE_CHARSET']; $serverName = $site['SERVER_NAME']; } else { throw new \Bitrix\Main\DB\Exception(Loc::getMessage('SENDER_POSTING_MANAGER_ERR_SITE', array('#SITE_ID#' => $mailingChain['SITE_ID']))); } if(!$charset) { throw new \Bitrix\Main\DB\Exception(Loc::getMessage('SENDER_POSTING_MANAGER_ERR_CHARSET', array('#SITE_ID#' => "[".$mailingChain['SITE_ID']."]".$site['NAME']))); } $attachmentList = array(); $attachmentDb = \Bitrix\Sender\MailingAttachmentTable::getList(array( 'select' => array('FILE_ID'), 'filter' => array('CHAIN_ID' => $mailingChainId) )); while($attachment = $attachmentDb->fetch()) { $attachmentList[] = $attachment['FILE_ID']; } static::$currentMailingChainFields = array(); static::$currentMailingChainFields['EVENT'] = array( 'FILE' => $attachmentList ); static::$currentMailingChainFields['ID'] = $mailingChain['ID']; // create final mail-text due to filling template by blocks static::$currentMailingChainFields['IS_MESSAGE_WITH_TEMPLATE'] = false; if($mailingChain['TEMPLATE_TYPE'] && $mailingChain['TEMPLATE_ID']) { $chainTemplate = \Bitrix\Sender\Preset\Template::getById($mailingChain['TEMPLATE_TYPE'], $mailingChain['TEMPLATE_ID']); if($chainTemplate && $chainTemplate['HTML']) { $document = new \Bitrix\Main\Web\DOM\Document; $document->loadHTML($chainTemplate['HTML']); \Bitrix\Main\Loader::includeModule('fileman'); if(\Bitrix\Fileman\Block\Editor::fillDocumentBySliceContent($document, $mailingChain['MESSAGE'])) { \Bitrix\Main\Web\DOM\StyleInliner::inlineDocument($document); $mailingChain['MESSAGE'] = $document->saveHTML(); static::$currentMailingChainFields['IS_MESSAGE_WITH_TEMPLATE'] = true; } else { unset($document); } } } static::$currentMailingChainFields['MESSAGE'] = array( 'BODY_TYPE' => 'html', 'EMAIL_FROM' => $mailingChain['EMAIL_FROM'], 'EMAIL_TO' => '#EMAIL_TO#', 'PRIORITY' => $mailingChain['PRIORITY'], 'SUBJECT' => $mailingChain['SUBJECT'], 'MESSAGE' => $mailingChain['MESSAGE'], 'MESSAGE_PHP' => \Bitrix\Main\Mail\Internal\EventMessageTable::replaceTemplateToPhp($mailingChain['MESSAGE']), ); static::$currentMailingChainFields['SITE'] = array($mailingChain['SITE_ID']); static::$currentMailingChainFields['CHARSET'] = $charset; static::$currentMailingChainFields['SERVER_NAME'] = $serverName; static::$currentMailingChainFields['LINK_PROTOCOL'] = \Bitrix\Main\Config\Option::get("sender", "link_protocol", 'http'); static::$currentMailingChainFields['LINK_PARAMS'] = $mailingChain['LINK_PARAMS']; } $trackClick = isset($params['TRACK_CLICK']) ? $params['TRACK_CLICK'] : null; if($trackClick && static::$currentMailingChainFields['LINK_PARAMS']) { if(!is_array($trackClick['URL_PARAMS'])) { $trackClick['URL_PARAMS'] = array(); } parse_str(static::$currentMailingChainFields['LINK_PARAMS'], $trackClickTmp); if(is_array($trackClickTmp)) { $trackClick['URL_PARAMS'] = array_merge($trackClick['URL_PARAMS'], $trackClickTmp); } } $params['FIELDS']['SUBJECT'] = htmlspecialcharsbx(strip_tags( static::$currentMailingChainFields['MESSAGE']['SUBJECT'] )); // prepare params for send email $messageParams = array( 'EVENT' => static::$currentMailingChainFields['EVENT'], 'FIELDS' => $params['FIELDS'], 'MESSAGE' => static::$currentMailingChainFields['MESSAGE'], 'SITE' => static::$currentMailingChainFields['SITE'], 'CHARSET' => static::$currentMailingChainFields['CHARSET'], ); if(!empty($params['FIELDS']['UNSUBSCRIBE_LINK'])) { if(substr($params['FIELDS']['UNSUBSCRIBE_LINK'], 0, 4) !== 'http') { if(!empty(static::$currentMailingChainFields['SERVER_NAME'])) { $serverName = static::$currentMailingChainFields['SERVER_NAME']; } else { $serverName = \Bitrix\Main\Config\Option::get("main", "server_name", $GLOBALS["SERVER_NAME"]); } $linkProtocol = static::$currentMailingChainFields['LINK_PROTOCOL']; $params['FIELDS']['UNSUBSCRIBE_LINK'] = $linkProtocol . '://' . $serverName . $params['FIELDS']['UNSUBSCRIBE_LINK']; } } // event on sending $eventMessageParams = $messageParams; $eventMessageParams['MAILING_CHAIN_ID'] = $mailingChainId; $eventMessageParams['IS_MESSAGE_WITH_TEMPLATE'] = static::$currentMailingChainFields['IS_MESSAGE_WITH_TEMPLATE']; $event = new Event('sender', 'OnPostingSendRecipient', array($eventMessageParams)); $event->send(); foreach ($event->getResults() as $eventResult) { if($eventResult->getType() == \Bitrix\Main\EventResult::ERROR) { return PostingRecipientTable::SEND_RESULT_ERROR; } if(is_array($eventResult->getParameters())) { $eventMessageParams = array_merge($eventMessageParams, $eventResult->getParameters()); } } static::$currentMailingChainFields['IS_MESSAGE_WITH_TEMPLATE'] = $eventMessageParams['IS_MESSAGE_WITH_TEMPLATE']; unset($eventMessageParams['IS_MESSAGE_WITH_TEMPLATE']); unset($eventMessageParams['MAILING_CHAIN_ID']); $messageParams = $eventMessageParams; $message = Mail\EventMessageCompiler::createInstance($messageParams); $message->compile(); // add unsubscribe info to header $mailHeaders = $message->getMailHeaders(); if(!empty($params['FIELDS']['UNSUBSCRIBE_LINK'])) { $unsubUrl = $params['FIELDS']['UNSUBSCRIBE_LINK']; $mailHeaders['List-Unsubscribe'] = '<'.$unsubUrl.'>'; } // add header "Precedence: bulk" $mailHeaders['Precedence'] = 'bulk'; // add headers from module options $mailHeaders = self::fillHeadersByOptionHeaders($mailHeaders); $mailBody = null; if(static::$currentMailingChainFields['IS_MESSAGE_WITH_TEMPLATE'] && Option::get('sender', 'use_inliner_for_each_template_mail', 'N') == 'Y') { // inline styles $mailBody = \Bitrix\Main\Web\DOM\StyleInliner::inlineHtml($message->getMailBody()); } if(!$mailBody) { $mailBody = $message->getMailBody(); } // set email params $mailParams = array( 'TO' => $message->getMailTo(), 'SUBJECT' => $message->getMailSubject(), 'BODY' => $mailBody, 'HEADER' => $mailHeaders, 'CHARSET' => $message->getMailCharset(), 'CONTENT_TYPE' => $message->getMailContentType(), 'MESSAGE_ID' => '', 'ATTACHMENT' => $message->getMailAttachment(), 'LINK_PROTOCOL' => static::$currentMailingChainFields['LINK_PROTOCOL'], 'LINK_DOMAIN' => static::$currentMailingChainFields['SERVER_NAME'], 'TRACK_READ' => (isset($params['TRACK_READ']) ? $params['TRACK_READ'] : null), 'TRACK_CLICK' => $trackClick ); // event on sending email $eventMailParams = $mailParams; $eventMailParams['MAILING_CHAIN_ID'] = $mailingChainId; $event = new Event('sender', 'OnPostingSendRecipientEmail', array($eventMailParams)); $event->send(); foreach ($event->getResults() as $eventResult) { if($eventResult->getType() == \Bitrix\Main\EventResult::ERROR) { return PostingRecipientTable::SEND_RESULT_ERROR; } if(is_array($eventResult->getParameters())) { $eventMailParams = array_merge($eventMailParams, $eventResult->getParameters()); } } unset($eventMailParams['MAILING_CHAIN_ID']); $mailParams = $eventMailParams; // send mail $result = Mail\Mail::send($mailParams); if($result) return PostingRecipientTable::SEND_RESULT_SUCCESS; else return PostingRecipientTable::SEND_RESULT_ERROR; } /** * Send letter by message from posting to address. * * @param $mailingChainId * @param $address * @return bool * @throws \Bitrix\Main\DB\Exception */ public static function sendToAddress($mailingChainId, $address) { $recipientEmail = $address; $emailParts = explode('@', $recipientEmail); $recipientName = $emailParts[0]; global $USER; $mailingChain = MailingChainTable::getRowById(array('ID' => $mailingChainId)); $sendParams = array( 'FIELDS' => array( 'NAME' => $recipientName, 'EMAIL_TO' => $address, 'USER_ID' => $USER->GetID(), 'SENDER_CHAIN_ID' => $mailingChain["ID"], 'SENDER_CHAIN_CODE' => 'sender_chain_item_' . $mailingChain["ID"], 'UNSUBSCRIBE_LINK' => Subscription::getLinkUnsub(array( 'MAILING_ID' => !empty($mailingChain) ? $mailingChain['MAILING_ID'] : 0, 'EMAIL' => $address, 'TEST' => 'Y' )) ), 'TRACK_READ' => array( 'MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => 0), ), 'TRACK_CLICK' => array( 'MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => 0), 'URL_PARAMS' => array('bx_sender_conversion_id' => 0) ) ); $mailSendResult = static::sendInternal($mailingChainId, $sendParams); switch($mailSendResult) { case PostingRecipientTable::SEND_RESULT_SUCCESS: $mailResult = static::SEND_RESULT_SENT; break; case PostingRecipientTable::SEND_RESULT_ERROR: default: $mailResult = static::SEND_RESULT_ERROR; } return $mailResult; } /** * Send posting. * * @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')); } $isStopped = false; $checkStatusCounter = 0; static::$checkStatusStep = intval(Option::get('sender', 'send_check_status_step', static::$checkStatusStep)); // 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()) { // check pause or stop status if(++$checkStatusCounter >= static::$checkStatusStep) { $checkStatusDb = MailingChainTable::getList(array( 'select' => array('ID'), 'filter' => array( '=ID' => $postingData["MAILING_CHAIN_ID"], '=STATUS' => MailingChainTable::STATUS_SEND ) )); if(!$checkStatusDb->fetch()) { break; } $checkStatusCounter = 0; } // 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_ID' => $postingData["MAILING_CHAIN_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 try { $mailSendResult = static::sendInternal($postingData['MAILING_CHAIN_ID'], $sendParams); } catch(\Bitrix\Main\Mail\StopException $e) { $isStopped = true; break; } 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($isStopped) { $STATUS = PostingTable::STATUS_ABORT; $DATE = new Type\DateTime(); } elseif(!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 $postingUpdateFields = array( 'STATUS' => $STATUS, 'DATE_SENT' => $DATE, 'COUNT_SEND_ALL' => 0 ); $recipientStatusToPostingFieldMap = PostingTable::getRecipientStatusToPostingFieldMap(); foreach($recipientStatusToPostingFieldMap as $recipientStatus => $postingFieldName) { if(!array_key_exists($recipientStatus, $statusList)) { $postingCountFieldValue = 0; } else { $postingCountFieldValue = $statusList[$recipientStatus]; } $postingUpdateFields['COUNT_SEND_ALL'] += $postingCountFieldValue; $postingUpdateFields[$postingFieldName] = $postingCountFieldValue; } PostingTable::update(array('ID' => $id), $postingUpdateFields); // return status to continue or end of sending if($STATUS == PostingTable::STATUS_PART) return static::SEND_RESULT_CONTINUE; else return static::SEND_RESULT_SENT; } /** * Lock posting for preventing double sending * * @param $id * @return bool * @throws \Bitrix\Main\Db\SqlQueryException * @throws \Exception */ public static function lockPosting($id) { $id = intval($id); $uniq = \COption::GetOptionString("main", "server_uniq_id", ""); if($uniq == '') { $uniq = md5(uniqid(rand(), true)); \COption::SetOptionString("main", "server_uniq_id", $uniq); } $connection = \Bitrix\Main\Application::getInstance()->getConnection(); if($connection instanceof \Bitrix\Main\DB\MysqlCommonConnection) { $lockDb = $connection->query("SELECT GET_LOCK('".$uniq."_sendpost_".$id."', 0) as L", false, "File: ".__FILE__."<br>Line: ".__LINE__); $lock = $lockDb->fetch(); if($lock["L"]=="1") return true; else return false; } elseif($connection instanceof \Bitrix\Main\DB\MssqlConnection) { //Clean up locks $i=\COption::GetOptionInt("sender", "posting_interval"); //For at least 5 seconds if($i<5) $i=5; $connection->query("DELETE FROM B_SENDER_POSTING_LOCK WHERE DATEDIFF(SECOND, TIMESTAMP_X, GETDATE())>".$i); $connection->query("SET LOCK_TIMEOUT 1"); $lockDb = $connection->query("INSERT INTO B_SENDER_POSTING_LOCK (ID, TIMESTAMP_X) VALUES (".$id.", GETDATE())"); $connection->query("SET LOCK_TIMEOUT -1"); return $lockDb->getResource()!==false; } elseif($connection instanceof \Bitrix\Main\DB\OracleConnection) { try { $lockDb = $connection->query(" declare my_lock_id number; my_result number; lock_failed exception; pragma exception_init(lock_failed, -54); begin my_lock_id:=dbms_utility.get_hash_value(to_char('" . $uniq . "_sendpost_" . $id . "'), 0, 1024); my_result:=dbms_lock.request(my_lock_id, dbms_lock.x_mode, 0, true); -- Return value: -- 0 - success -- 1 - timeout -- 2 - deadlock -- 3 - parameter error -- 4 - already own lock specified by 'id' or 'lockhandle' -- 5 - illegal lockhandle if(my_result<>0 and my_result<>4)then raise lock_failed; end if; end; "); } catch(\Bitrix\Main\Db\SqlQueryException $exception) { if(strpos($exception->getDatabaseMessage(), "ORA-00054") === false) throw $exception; } return $lockDb->getResource()!==false; } return false; } /** * UnLock posting that was locking for preventing double sending * * @param $id * @return bool */ public static function unlockPosting($id) { $id = intval($id); $connection = \Bitrix\Main\Application::getInstance()->getConnection(); if($connection instanceof \Bitrix\Main\DB\MysqlCommonConnection) { $uniq = \COption::GetOptionString("main", "server_uniq_id", ""); if(strlen($uniq)>0) { $lockDb = $connection->query("SELECT RELEASE_LOCK('".$uniq."_sendpost_".$id."') as L"); $lock = $lockDb->fetch(); if($lock["L"] == "0") return false; else return true; } } elseif($connection instanceof \Bitrix\Main\DB\MssqlConnection) { $connection->query("DELETE FROM B_SENDER_POSTING_LOCK WHERE ID=".$id); return true; } elseif($connection instanceof \Bitrix\Main\DB\OracleConnection) { //lock released on commit return true; } return false; } }