Server IP : 85.193.89.191 / Your IP : 3.21.98.78 Web Server : Apache System : Linux 956367-cx40159.tmweb.ru 3.10.0-1160.105.1.el7.x86_64 #1 SMP Thu Dec 7 15:39:45 UTC 2023 x86_64 User : bitrix ( 600) PHP Version : 8.1.27 Disable Function : NONE MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /home/bitrix/www/bitrix/components/bitrix/catalog.bigdata.products/ |
Upload File : |
<?php use Bitrix\Main, Bitrix\Iblock, Bitrix\Catalog, Bitrix\Main\Localization\Loc as Loc, Bitrix\Main\SystemException; if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); Loc::loadMessages(__FILE__); CBitrixComponent::includeComponentClass("bitrix:sale.bestsellers"); /** * Class \CatalogBigdataProductsComponent * * No longer used by internal code and not recommended. Use "catalog.section" instead. * * @deprecated deprecated since catalog 17.0.5 * @use \CatalogSectionComponent */ class CatalogBigdataProductsComponent extends CSaleBestsellersComponent { protected $rcmParams; protected $ajaxItemsIds; protected $recommendationIdToProduct = array(); /** * Prepare Component Params * * @param array $params * @return array */ public function onPrepareComponentParams($params) { global $APPLICATION; if (!isset($params['RCM_CUR_BASE_PAGE'])) { $params['RCM_CUR_BASE_PAGE'] = $APPLICATION->GetCurPage(); } // uniq identifier for the component on the page if (!isset($params['UNIQ_COMPONENT_ID'])) { $params['UNIQ_COMPONENT_ID'] = 'bigdata_recommended_products_'.$this->randString(); } // remember src params for further ajax query $this->arResult['_ORIGINAL_PARAMS'] = $params; // bestselling $params['FILTER'] = array('PAYED'); $params['PERIOD'] = 30; return parent::onPrepareComponentParams($params); } /** * set prices for all items * @return array currency list */ protected function setItemsPrices() { parent::setItemsPrices(); // rewrite urls foreach ($this->items as &$item) { // ajax mode only - get from signed parameters $item["~BUY_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=BUY&" . $this->arParams["PRODUCT_ID_VARIABLE"] . "=" . $item["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $item["~ADD_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=ADD2BASKET&" . $this->arParams["PRODUCT_ID_VARIABLE"] . "=" . $item["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $item["~COMPARE_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], "action=ADD_TO_COMPARE_LIST&id=" . $item["ID"], array("action", "id") ); $item["~SUBSCRIBE_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=SUBSCRIBE_PRODUCT&" . $this->arParams["PRODUCT_ID_VARIABLE"] . "=" . $item["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $item["BUY_URL"] = htmlspecialcharsbx($item["~BUY_URL"]); $item["ADD_URL"] = htmlspecialcharsbx($item["~ADD_URL"]); $item["COMPARE_URL"] = htmlspecialcharsbx($item["~COMPARE_URL"]); $item["SUBSCRIBE_URL"] = htmlspecialcharsbx($item["~SUBSCRIBE_URL"]); } } /** * Add offers for each catalog product. * @return void */ protected function setItemsOffers() { parent::setItemsOffers(); foreach ($this->items as &$item) { if (!empty($item['OFFERS']) && is_array($item['OFFERS'])) { foreach ($item['OFFERS'] as &$offer) { $offer["~BUY_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=BUY&" . $this->arParams["PRODUCT_ID_VARIABLE"] . "=" . $offer["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $offer["~ADD_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=ADD2BASKET&" . $this->arParams["PRODUCT_ID_VARIABLE"] . "=" . $offer["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $offer["~COMPARE_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], "action=ADD_TO_COMPARE_LIST&id=" . $offer["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $offer["~SUBSCRIBE_URL"] = $this->getPageParam( $this->arParams['RCM_CUR_BASE_PAGE'], $this->arParams["ACTION_VARIABLE"] . "=SUBSCRIBE_PRODUCT&id=" . $offer["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"]) ); $offer["BUY_URL"] = htmlspecialcharsbx($offer["~BUY_URL"]); $offer["ADD_URL"] = htmlspecialcharsbx($offer["~ADD_URL"]); $offer["COMPARE_URL"] = htmlspecialcharsbx($offer["~COMPARE_URL"]); $offer["SUBSCRIBE_URL"] = htmlspecialcharsbx($offer["~SUBSCRIBE_URL"]); } } } } protected function getPageParam($sUrlPath, $strParam="", $arParamKill=array(), $get_index_page=null) { $strNavQueryString = DeleteParam($arParamKill); if($strNavQueryString <> "" && $strParam <> "") $strNavQueryString = "&".$strNavQueryString; if($strNavQueryString == "" && $strParam == "") return $sUrlPath; else return $sUrlPath."?".$strParam.$strNavQueryString; } protected function getProductIds() { $ids = array(); // try cloud if (!empty($this->ajaxItemsIds)) { $recommendationId = Main\Context::getCurrent()->getRequest()->get('RID'); $ids = $this->ajaxItemsIds; $ids = $this->filterByParams($ids); $ids = $this->filterByAvailability($ids); foreach ($ids as $id) { $this->recommendationIdToProduct[$id] = $recommendationId; } } // try bestsellers if (count($ids) < $this->arParams['PAGE_ELEMENT_COUNT']) { // increase element count $this->arParams['PAGE_ELEMENT_COUNT'] = $this->arParams['PAGE_ELEMENT_COUNT']*10; $bestsellers = parent::getProductIds(); $this->arParams['PAGE_ELEMENT_COUNT'] = $this->arParams['PAGE_ELEMENT_COUNT']/10; if (!empty($bestsellers)) { $recommendationId = 'bestsellers'; $bestsellers = Main\Analytics\Catalog::getProductIdsByOfferIds($bestsellers); $bestsellers = $this->filterByParams($bestsellers); $bestsellers = $this->filterByAvailability($bestsellers); foreach ($bestsellers as $id) { if (!isset($this->recommendationIdToProduct[$id])) { $this->recommendationIdToProduct[$id] = $recommendationId; } } $ids = array_unique(array_merge($ids, $bestsellers)); } } // try top viewed if (count($ids) < $this->arParams['PAGE_ELEMENT_COUNT']) { $recommendationId = 'mostviewed'; $duplicate = array(); $mostviewed = array(); $result = Catalog\CatalogViewedProductTable::getList(array( 'select' => array( 'ELEMENT_ID', new Main\Entity\ExpressionField('SUM_HITS', 'SUM(%s)', 'VIEW_COUNT') ), 'filter' => array( '=SITE_ID' => $this->getSiteId(), '>ELEMENT_ID' => 0, '>DATE_VISIT' => new Main\Type\DateTime(date('Y-m-d H:i:s', strtotime('-30 days')), 'Y-m-d H:i:s') ), 'order' => array('SUM_HITS' => 'DESC'), 'limit' => $this->arParams['PAGE_ELEMENT_COUNT']*10 )); while ($row = $result->fetch()) { if (!isset($duplicate[$row['ELEMENT_ID']])) $mostviewed[] = $row['ELEMENT_ID']; $duplicate[$row['ELEMENT_ID']] = true; } unset($row, $result, $duplicate); $mostviewed = $this->filterByParams($mostviewed); $mostviewed = $this->filterByAvailability($mostviewed); foreach ($mostviewed as $id) { if (!isset($this->recommendationIdToProduct[$id])) { $this->recommendationIdToProduct[$id] = $recommendationId; } } $ids = array_unique(array_merge($ids, $mostviewed)); } // limit $ids = array_slice($ids, 0, $this->arParams['PAGE_ELEMENT_COUNT']); return $ids; } protected function filterByParams($ids) { if (empty($ids)) { return array(); } $ids = array_values(array_unique($ids)); // remove duplicate of current item if (!empty($this->arParams['ID']) && in_array($this->arParams['ID'], $ids)) { $key = array_search($this->arParams['ID'], $ids); if ($key !== false) { unset($ids[$key]); $ids = array_values($ids); } } // general filter $this->prepareFilter(); $filter = $this->filter; $filter['ID'] = $ids; $r = CIBlockElement::GetList(array(), $filter, false, false, array('ID')); $ids = array(); while ($row = $r->Fetch()) { $ids[] = $row['ID']; } // filtering by section if ($this->arParams['SHOW_FROM_SECTION'] != 'Y') { return $ids; } $sectionSearch = $this->arParams["SECTION_ID"] > 0 || $this->arParams["SECTION_CODE"] !== ''; if ($sectionSearch) $sectionId = ($this->arParams["SECTION_ID"] > 0) ? $this->arParams["SECTION_ID"] : $this->getSectionIdByCode($this->arParams["SECTION_CODE"]); else $sectionId = $this->getSectionIdByElement($this->arParams["SECTION_ELEMENT_ID"], $this->arParams["SECTION_ELEMENT_CODE"]); $map = $this->filterIdBySection( $ids, $this->arParams['IBLOCK_ID'], $sectionId, $this->arParams['PAGE_ELEMENT_COUNT'], $this->arParams['DEPTH'] ); return $map; } protected function filterIdBySection($elementIds, $iblockId, $sectionId, $limit, $depth = 0) { $map = array(); Main\Type\Collection::normalizeArrayValuesByInt($elementIds); if (empty($elementIds)) return $map; $iblockId = (int)$iblockId; $sectionId = (int)$sectionId; $limit = (int)$limit; $depth = (int)$depth; if ($iblockId <= 0 ||$depth < 0) return $map; $subSections = array(); if ($depth > 0) { $parentSectionId = Catalog\Product\Viewed::getParentSection($sectionId, $depth); if ($parentSectionId !== null) $subSections[$parentSectionId] = $parentSectionId; unset($parentSectionId); } if (empty($subSections) && $sectionId <= 0) { $getListParams = array( 'select' => array('ID'), 'filter' => array( '@ID' => $elementIds, '=IBLOCK_ID' => $iblockId, '=WF_STATUS_ID' => 1, '=WF_PARENT_ELEMENT_ID' => null ), ); if ($limit > 0) $getListParams['limit'] = $limit; $iterator = Iblock\ElementTable::getList($getListParams); } else { if (empty($subSections)) $subSections[$sectionId] = $sectionId; $sectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity()); $sectionQuery->setTableAliasPostfix('_parent'); $sectionQuery->setSelect(array('ID', 'LEFT_MARGIN', 'RIGHT_MARGIN')); $sectionQuery->setFilter(array('@ID' => $subSections)); $subSectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity()); $subSectionQuery->setTableAliasPostfix('_sub'); $subSectionQuery->setSelect(array('ID')); $subSectionQuery->setFilter(array('=IBLOCK_ID' => $iblockId)); $subSectionQuery->registerRuntimeField( '', new Main\Entity\ReferenceField( 'BS', Main\Entity\Base::getInstanceByQuery($sectionQuery), array('>=this.LEFT_MARGIN' => 'ref.LEFT_MARGIN', '<=this.RIGHT_MARGIN' => 'ref.RIGHT_MARGIN'), array('join_type' => 'INNER') ) ); $sectionElementQuery = new Main\Entity\Query(Iblock\SectionElementTable::getEntity()); $sectionElementQuery->setSelect(array('IBLOCK_ELEMENT_ID')); $sectionElementQuery->setGroup(array('IBLOCK_ELEMENT_ID')); $sectionElementQuery->setFilter(array('=ADDITIONAL_PROPERTY_ID' => null)); $sectionElementQuery->registerRuntimeField( '', new Main\Entity\ReferenceField( 'BSUB', Main\Entity\Base::getInstanceByQuery($subSectionQuery), array('=this.IBLOCK_SECTION_ID' => 'ref.ID'), array('join_type' => 'INNER') ) ); $elementQuery = new Main\Entity\Query(Iblock\ElementTable::getEntity()); $elementQuery->setSelect(array('ID')); $elementQuery->setFilter(array('=IBLOCK_ID' => $iblockId, '=WF_STATUS_ID' => 1, '=WF_PARENT_ELEMENT_ID' => null)); $elementQuery->registerRuntimeField( '', new Main\Entity\ReferenceField( 'BSE', Main\Entity\Base::getInstanceByQuery($sectionElementQuery), array('=this.ID' => 'ref.IBLOCK_ELEMENT_ID'), array('join_type' => 'INNER') ) ); if ($limit > 0) $elementQuery->setLimit($limit); $iterator = $elementQuery->exec(); unset($elementQuery, $sectionElementQuery, $subSectionQuery, $sectionQuery); } while ($row = $iterator->fetch()) $map[] = $row['ID']; unset($row, $iterator); return $map; } protected function filterByAvailability($ids) { if (!empty($ids) && $this->arParams['HIDE_NOT_AVAILABLE'] == 'Y') { $filter = (count($ids) > 1000 ? array('ID' => $ids) : array('@ID' => $ids)); $ids = array_fill_keys($ids, true); $productIterator = CCatalogProduct::GetList( array(), $filter, false, false, array('ID', 'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO') ); while ($product = $productIterator->Fetch()) { if (isset($ids[$product['ID']]) && !CCatalogProduct::isAvailable($product)) unset($ids[$product['ID']]); } unset($product, $productIterator, $filter); $ids = array_keys($ids); } return $ids; } /** * Extract data from cache. No action by default. * @return bool */ protected function extractDataFromCache() { if($this->arParams['CACHE_TYPE'] == 'N') return false; return !($this->startResultCache(false, $this->getAdditionalCacheId(), '/'.$this->getSiteId().'/bitrix/catalog.bigdata.products/common')); } protected function getAdditionalCacheId() { $rcmParams = $this->rcmParams; // cut productid from non-product recommendations if ($rcmParams['op'] == 'sim_domain_items' || $rcmParams['op'] == 'recommend') { unset($this->arParams['ID'], $this->arParams['~ID']); } // cut userid from non-personal recommendations if ($rcmParams['op'] == 'sim_domain_items' || $rcmParams['op'] == 'simitems') { unset($rcmParams['uid']); } return $rcmParams; } protected function getServiceRequestParamsByType($type) { $a = array( 'uid' => $_COOKIE['BX_USER_ID'], 'aid' => \Bitrix\Main\Analytics\Counter::getAccountId(), 'count' => max($this->arParams['PAGE_ELEMENT_COUNT']*2, 30) ); // random choices if ($type == 'any_similar') { $possible = array('similar_sell', 'similar_view', 'similar'); $type = $possible[array_rand($possible)]; } elseif ($type == 'any_personal') { $possible = array('bestsell', 'personal'); $type = $possible[array_rand($possible)]; } elseif ($type == 'any') { $possible = array('similar_sell', 'similar_view', 'similar', 'bestsell', 'personal'); $type = $possible[array_rand($possible)]; } // configure if ($type == 'bestsell') { $a['op'] = 'sim_domain_items'; $a['type'] = 'order'; $a['domain'] = Bitrix\Main\Context::getCurrent()->getServer()->getHttpHost(); } elseif ($type == 'personal') { $a['op'] = 'recommend'; } elseif ($type == 'similar_sell') { $a['op'] = 'simitems'; $a['eid'] = $this->arParams['ID']; $a['type'] = 'order'; } elseif ($type == 'similar_view') { $a['op'] = 'simitems'; $a['eid'] = $this->arParams['ID']; $a['type'] = 'view'; } elseif ($type == 'similar') { $a['op'] = 'simitems'; $a['eid'] = $this->arParams['ID']; } else { // unkonwn type, personal by default $a['op'] = 'recommend'; } // get iblocks $iblocks = array(); if (!empty($this->arParams['IBLOCK_ID'])) { $iblocks = array($this->arParams['IBLOCK_ID']); } else { $iblockList = array(); /* catalog */ $iblockIterator = \Bitrix\Catalog\CatalogIblockTable::getList(array( 'select' => array('IBLOCK_ID', 'PRODUCT_IBLOCK_ID') )); while ($iblock = $iblockIterator->fetch()) { $iblock['IBLOCK_ID'] = (int)$iblock['IBLOCK_ID']; $iblock['PRODUCT_IBLOCK_ID'] = (int)$iblock['PRODUCT_IBLOCK_ID']; $iblockList[$iblock['IBLOCK_ID']] = $iblock['IBLOCK_ID']; if ($iblock['PRODUCT_IBLOCK_ID'] > 0) $iblockList[$iblock['PRODUCT_IBLOCK_ID']] = $iblock['PRODUCT_IBLOCK_ID']; } /* iblock */ $iblockIterator = \Bitrix\Iblock\IblockSiteTable::getList(array( 'select' => array('IBLOCK_ID'), 'filter' => array('@IBLOCK_ID' => $iblockList, '=SITE_ID' => $this->getSiteId()) )); while ($iblock = $iblockIterator->fetch()) { $iblocks[] = $iblock['IBLOCK_ID']; } } $a['ib'] = join('.', $iblocks); return $a; } /** * Check action variable. * * @param array $params Component params. * @return string */ protected function prepareActionVariable($params) { $actionVariable = (isset($params['ACTION_VARIABLE']) ? trim($params['ACTION_VARIABLE']) : ''); if ($actionVariable === '' || !preg_match("/^[A-Za-z_][A-Za-z01-9_]*$/", $actionVariable)) $actionVariable = 'action_cbdp'; return $actionVariable; } /** * Get additional data for cache * * @return array */ protected function getAdditionalReferences() { return array(); } /** * Start Component */ public function executeComponent() { global $APPLICATION; $context = Main\Context::getCurrent(); // mark usage $lastUsage = Main\Config\Option::get('main', 'rcm_component_usage', 0); if ($lastUsage == 0 || (time() - $lastUsage) > 3600) { Main\Config\Option::set('main', 'rcm_component_usage', time()); } // execute try { $this->checkModules(); } catch (SystemException $e) { ShowError($e->getMessage()); return; } $this->processRequest(); // define what to do and check cache $this->rcmParams = $this->getServiceRequestParamsByType($this->arParams['RCM_TYPE']); $showByIds = ($context->getServer()->getRequestMethod() == 'POST' && $context->getRequest()->getPost('rcm') == 'yes'); if (!$showByIds) { // check if ids are already in cache try { if (!$this->extractDataFromCache()) { // echo js for requesting items from recommendation service $this->arResult['REQUEST_ITEMS'] = true; $this->arResult['RCM_PARAMS'] = $this->rcmParams; $this->arResult['RCM_TEMPLATE'] = $this->getTemplateName(); // abort cache, we will write it on next request with the same parameters $this->abortDataCache(); // clear cache for ajax call if (Main\Context::getCurrent()->getRequest()->get('clear_cache') == 'Y') { $this->clearResultCache($this->getAdditionalCacheId(), '/'.$this->getSiteId().'/bitrix/catalog.bigdata.products/common'); } $this->includeComponentTemplate(); $this->setResultCacheKeys(array()); } // show cache and die return null; } catch (SystemException $e) { $this->abortDataCache(); if ($this->isAjax()) { $APPLICATION->restartBuffer(); header('Content-Type: application/json'); echo Main\Web\Json::encode(array('STATUS' => 'ERROR', 'MESSAGE' => $e->getMessage())); die(); } ShowError($e->getMessage()); } } if ($showByIds) { // we have an ajax query to get items html // and there was no cache $ajaxItemIds = $context->getRequest()->get('AJAX_ITEMS'); if (!empty($ajaxItemIds) && is_array($ajaxItemIds)) { $this->ajaxItemsIds = $ajaxItemIds; } else { // show something $this->ajaxItemsIds = null; // last viewed will be shown } // draw products with collected ids $this->prepareData(); $this->formatResult(); } if (!$this->extractDataFromCache()) { // output js before template to be caught in cache if (!empty($this->arResult['ITEMS'])) { echo $this->getInjectedJs($this->arResult['ITEMS'], $this->arParams['UNIQ_COMPONENT_ID']); } $this->setResultCacheKeys(array()); $this->includeComponentTemplate(); } } protected function getInjectedJs($items, $uniqId) { $jsItems = array(); foreach ($items as $item) { $jsItems[] = array( "productId" => $item['ID'], "productUrl" => $item['DETAIL_PAGE_URL'], "recommendationId" => $this->recommendationIdToProduct[$item['ID']] ); } global $APPLICATION; $jsCookiePrefix = CUtil::JSEscape(COption::GetOptionString("main", "cookie_name", "BITRIX_SM")); $jsCookieDomain = CUtil::JSEscape($APPLICATION->GetCookieDomain()); $jsServerTime = time(); $jsUniqId = CUtil::JSEscape($uniqId."_items"); $jsonItems = CUtil::PhpToJSObject($jsItems); // static data for JCCatalogBigdataProducts (SendToBasket) $jsToBasket = ""; foreach ($items as $item) { $jsToBasket .= "JCCatalogBigdataProducts.productsByRecommendation[{$item['ID']}] = \"{$this->recommendationIdToProduct[$item['ID']]}\";\n"; } return "<script type=\"text/javascript\"> BX.cookie_prefix = '{$jsCookiePrefix}'; BX.cookie_domain = '{$jsCookieDomain}'; BX.current_server_time = '{$jsServerTime}'; if (!JCCatalogBigdataProducts.productsByRecommendation) { JCCatalogBigdataProducts.productsByRecommendation = []; } {$jsToBasket} BX.ready(function(){ bx_rcm_adaptive_recommendation_event_attaching({$jsonItems}, '{$jsUniqId}'); }); </script>"; } }