PageRenderTime 27ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/components/bitrix/catalog.bigdata.products/class.php

https://gitlab.com/alexprowars/bitrix
PHP | 731 lines | 550 code | 106 blank | 75 comment | 88 complexity | 443974cad00099a3984ff98eaa97e875 MD5 | raw file
  1. <?php
  2. use Bitrix\Main,
  3. Bitrix\Iblock,
  4. Bitrix\Catalog,
  5. Bitrix\Main\Localization\Loc as Loc,
  6. Bitrix\Main\SystemException;
  7. if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
  8. Loc::loadMessages(__FILE__);
  9. CBitrixComponent::includeComponentClass("bitrix:sale.bestsellers");
  10. /**
  11. * Class \CatalogBigdataProductsComponent
  12. *
  13. * No longer used by internal code and not recommended. Use "catalog.section" instead.
  14. *
  15. * @deprecated deprecated since catalog 17.0.5
  16. * @use \CatalogSectionComponent
  17. */
  18. class CatalogBigdataProductsComponent extends CSaleBestsellersComponent
  19. {
  20. protected $rcmParams;
  21. protected $ajaxItemsIds;
  22. protected $recommendationIdToProduct = array();
  23. /**
  24. * Prepare Component Params
  25. *
  26. * @param array $params
  27. * @return array
  28. */
  29. public function onPrepareComponentParams($params)
  30. {
  31. global $APPLICATION;
  32. if (!isset($params['RCM_CUR_BASE_PAGE']))
  33. {
  34. $params['RCM_CUR_BASE_PAGE'] = $APPLICATION->GetCurPage();
  35. }
  36. // uniq identifier for the component on the page
  37. if (!isset($params['UNIQ_COMPONENT_ID']))
  38. {
  39. $params['UNIQ_COMPONENT_ID'] = 'bigdata_recommended_products_'.$this->randString();
  40. }
  41. // remember src params for further ajax query
  42. $this->arResult['_ORIGINAL_PARAMS'] = $params;
  43. // bestselling
  44. $params['FILTER'] = array('PAYED');
  45. $params['PERIOD'] = 30;
  46. return parent::onPrepareComponentParams($params);
  47. }
  48. /**
  49. * set prices for all items
  50. * @return array currency list
  51. */
  52. protected function setItemsPrices()
  53. {
  54. parent::setItemsPrices();
  55. // rewrite urls
  56. foreach ($this->items as &$item)
  57. { // ajax mode only - get from signed parameters
  58. $item["~BUY_URL"] = $this->getPageParam(
  59. $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"])
  60. );
  61. $item["~ADD_URL"] = $this->getPageParam(
  62. $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"])
  63. );
  64. $item["~COMPARE_URL"] = $this->getPageParam(
  65. $this->arParams['RCM_CUR_BASE_PAGE'], "action=ADD_TO_COMPARE_LIST&id=" . $item["ID"], array("action", "id")
  66. );
  67. $item["~SUBSCRIBE_URL"] = $this->getPageParam(
  68. $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"])
  69. );
  70. $item["BUY_URL"] = htmlspecialcharsbx($item["~BUY_URL"]);
  71. $item["ADD_URL"] = htmlspecialcharsbx($item["~ADD_URL"]);
  72. $item["COMPARE_URL"] = htmlspecialcharsbx($item["~COMPARE_URL"]);
  73. $item["SUBSCRIBE_URL"] = htmlspecialcharsbx($item["~SUBSCRIBE_URL"]);
  74. }
  75. }
  76. /**
  77. * Add offers for each catalog product.
  78. * @return void
  79. */
  80. protected function setItemsOffers()
  81. {
  82. parent::setItemsOffers();
  83. foreach ($this->items as &$item)
  84. {
  85. if (!empty($item['OFFERS']) && is_array($item['OFFERS']))
  86. {
  87. foreach ($item['OFFERS'] as &$offer)
  88. {
  89. $offer["~BUY_URL"] = $this->getPageParam(
  90. $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"])
  91. );
  92. $offer["~ADD_URL"] = $this->getPageParam(
  93. $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"])
  94. );
  95. $offer["~COMPARE_URL"] = $this->getPageParam(
  96. $this->arParams['RCM_CUR_BASE_PAGE'], "action=ADD_TO_COMPARE_LIST&id=" . $offer["ID"], array($this->arParams["PRODUCT_ID_VARIABLE"], $this->arParams["ACTION_VARIABLE"])
  97. );
  98. $offer["~SUBSCRIBE_URL"] = $this->getPageParam(
  99. $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"])
  100. );
  101. $offer["BUY_URL"] = htmlspecialcharsbx($offer["~BUY_URL"]);
  102. $offer["ADD_URL"] = htmlspecialcharsbx($offer["~ADD_URL"]);
  103. $offer["COMPARE_URL"] = htmlspecialcharsbx($offer["~COMPARE_URL"]);
  104. $offer["SUBSCRIBE_URL"] = htmlspecialcharsbx($offer["~SUBSCRIBE_URL"]);
  105. }
  106. }
  107. }
  108. }
  109. protected function getPageParam($sUrlPath, $strParam="", $arParamKill=array(), $get_index_page=null)
  110. {
  111. $strNavQueryString = DeleteParam($arParamKill);
  112. if($strNavQueryString <> "" && $strParam <> "")
  113. $strNavQueryString = "&".$strNavQueryString;
  114. if($strNavQueryString == "" && $strParam == "")
  115. return $sUrlPath;
  116. else
  117. return $sUrlPath."?".$strParam.$strNavQueryString;
  118. }
  119. protected function getProductIds()
  120. {
  121. $ids = array();
  122. // try cloud
  123. if (!empty($this->ajaxItemsIds))
  124. {
  125. $recommendationId = Main\Context::getCurrent()->getRequest()->get('RID');
  126. $ids = $this->ajaxItemsIds;
  127. $ids = $this->filterByParams($ids);
  128. $ids = $this->filterByAvailability($ids);
  129. foreach ($ids as $id)
  130. {
  131. $this->recommendationIdToProduct[$id] = $recommendationId;
  132. }
  133. }
  134. // try bestsellers
  135. if (count($ids) < $this->arParams['PAGE_ELEMENT_COUNT'])
  136. {
  137. // increase element count
  138. $this->arParams['PAGE_ELEMENT_COUNT'] = $this->arParams['PAGE_ELEMENT_COUNT']*10;
  139. $bestsellers = parent::getProductIds();
  140. $this->arParams['PAGE_ELEMENT_COUNT'] = $this->arParams['PAGE_ELEMENT_COUNT']/10;
  141. if (!empty($bestsellers))
  142. {
  143. $recommendationId = 'bestsellers';
  144. $bestsellers = Main\Analytics\Catalog::getProductIdsByOfferIds($bestsellers);
  145. $bestsellers = $this->filterByParams($bestsellers);
  146. $bestsellers = $this->filterByAvailability($bestsellers);
  147. foreach ($bestsellers as $id)
  148. {
  149. if (!isset($this->recommendationIdToProduct[$id]))
  150. {
  151. $this->recommendationIdToProduct[$id] = $recommendationId;
  152. }
  153. }
  154. $ids = array_unique(array_merge($ids, $bestsellers));
  155. }
  156. }
  157. // try top viewed
  158. if (count($ids) < $this->arParams['PAGE_ELEMENT_COUNT'])
  159. {
  160. $recommendationId = 'mostviewed';
  161. $duplicate = array();
  162. $mostviewed = array();
  163. $result = Catalog\CatalogViewedProductTable::getList(array(
  164. 'select' => array(
  165. 'ELEMENT_ID',
  166. new Main\Entity\ExpressionField('SUM_HITS', 'SUM(%s)', 'VIEW_COUNT')
  167. ),
  168. 'filter' => array(
  169. '=SITE_ID' => $this->getSiteId(), '>ELEMENT_ID' => 0,
  170. '>DATE_VISIT' => new Main\Type\DateTime(date('Y-m-d H:i:s', strtotime('-30 days')), 'Y-m-d H:i:s')
  171. ),
  172. 'order' => array('SUM_HITS' => 'DESC'),
  173. 'limit' => $this->arParams['PAGE_ELEMENT_COUNT']*10
  174. ));
  175. while ($row = $result->fetch())
  176. {
  177. if (!isset($duplicate[$row['ELEMENT_ID']]))
  178. $mostviewed[] = $row['ELEMENT_ID'];
  179. $duplicate[$row['ELEMENT_ID']] = true;
  180. }
  181. unset($row, $result, $duplicate);
  182. $mostviewed = $this->filterByParams($mostviewed);
  183. $mostviewed = $this->filterByAvailability($mostviewed);
  184. foreach ($mostviewed as $id)
  185. {
  186. if (!isset($this->recommendationIdToProduct[$id]))
  187. {
  188. $this->recommendationIdToProduct[$id] = $recommendationId;
  189. }
  190. }
  191. $ids = array_unique(array_merge($ids, $mostviewed));
  192. }
  193. // limit
  194. $ids = array_slice($ids, 0, $this->arParams['PAGE_ELEMENT_COUNT']);
  195. return $ids;
  196. }
  197. protected function filterByParams($ids)
  198. {
  199. if (empty($ids))
  200. {
  201. return array();
  202. }
  203. $ids = array_values(array_unique($ids));
  204. // remove duplicate of current item
  205. if (!empty($this->arParams['ID']) && in_array($this->arParams['ID'], $ids))
  206. {
  207. $key = array_search($this->arParams['ID'], $ids);
  208. if ($key !== false)
  209. {
  210. unset($ids[$key]);
  211. $ids = array_values($ids);
  212. }
  213. }
  214. // general filter
  215. $this->prepareFilter();
  216. $filter = $this->filter;
  217. $filter['ID'] = $ids;
  218. $r = CIBlockElement::GetList(array(), $filter, false, false, array('ID'));
  219. $ids = array();
  220. while ($row = $r->Fetch())
  221. {
  222. $ids[] = $row['ID'];
  223. }
  224. // filtering by section
  225. if ($this->arParams['SHOW_FROM_SECTION'] != 'Y')
  226. {
  227. return $ids;
  228. }
  229. $sectionSearch = $this->arParams["SECTION_ID"] > 0 || $this->arParams["SECTION_CODE"] !== '';
  230. if ($sectionSearch)
  231. $sectionId = ($this->arParams["SECTION_ID"] > 0) ? $this->arParams["SECTION_ID"] : $this->getSectionIdByCode($this->arParams["SECTION_CODE"]);
  232. else
  233. $sectionId = $this->getSectionIdByElement($this->arParams["SECTION_ELEMENT_ID"], $this->arParams["SECTION_ELEMENT_CODE"]);
  234. $map = $this->filterIdBySection(
  235. $ids,
  236. $this->arParams['IBLOCK_ID'],
  237. $sectionId,
  238. $this->arParams['PAGE_ELEMENT_COUNT'],
  239. $this->arParams['DEPTH']
  240. );
  241. return $map;
  242. }
  243. protected function filterIdBySection($elementIds, $iblockId, $sectionId, $limit, $depth = 0)
  244. {
  245. $map = array();
  246. Main\Type\Collection::normalizeArrayValuesByInt($elementIds);
  247. if (empty($elementIds))
  248. return $map;
  249. $iblockId = (int)$iblockId;
  250. $sectionId = (int)$sectionId;
  251. $limit = (int)$limit;
  252. $depth = (int)$depth;
  253. if ($iblockId <= 0 ||$depth < 0)
  254. return $map;
  255. $subSections = array();
  256. if ($depth > 0)
  257. {
  258. $parentSectionId = Catalog\Product\Viewed::getParentSection($sectionId, $depth);
  259. if ($parentSectionId !== null)
  260. $subSections[$parentSectionId] = $parentSectionId;
  261. unset($parentSectionId);
  262. }
  263. if (empty($subSections) && $sectionId <= 0)
  264. {
  265. $getListParams = array(
  266. 'select' => array('ID'),
  267. 'filter' => array(
  268. '@ID' => $elementIds,
  269. '=IBLOCK_ID' => $iblockId,
  270. '=WF_STATUS_ID' => 1,
  271. '=WF_PARENT_ELEMENT_ID' => null
  272. ),
  273. );
  274. if ($limit > 0)
  275. $getListParams['limit'] = $limit;
  276. $iterator = Iblock\ElementTable::getList($getListParams);
  277. }
  278. else
  279. {
  280. if (empty($subSections))
  281. $subSections[$sectionId] = $sectionId;
  282. $sectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity());
  283. $sectionQuery->setTableAliasPostfix('_parent');
  284. $sectionQuery->setSelect(array('ID', 'LEFT_MARGIN', 'RIGHT_MARGIN'));
  285. $sectionQuery->setFilter(array('@ID' => $subSections));
  286. $subSectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity());
  287. $subSectionQuery->setTableAliasPostfix('_sub');
  288. $subSectionQuery->setSelect(array('ID'));
  289. $subSectionQuery->setFilter(array('=IBLOCK_ID' => $iblockId));
  290. $subSectionQuery->registerRuntimeField(
  291. '',
  292. new Main\Entity\ReferenceField(
  293. 'BS',
  294. Main\Entity\Base::getInstanceByQuery($sectionQuery),
  295. array('>=this.LEFT_MARGIN' => 'ref.LEFT_MARGIN', '<=this.RIGHT_MARGIN' => 'ref.RIGHT_MARGIN'),
  296. array('join_type' => 'INNER')
  297. )
  298. );
  299. $sectionElementQuery = new Main\Entity\Query(Iblock\SectionElementTable::getEntity());
  300. $sectionElementQuery->setSelect(array('IBLOCK_ELEMENT_ID'));
  301. $sectionElementQuery->setGroup(array('IBLOCK_ELEMENT_ID'));
  302. $sectionElementQuery->setFilter(array('=ADDITIONAL_PROPERTY_ID' => null));
  303. $sectionElementQuery->registerRuntimeField(
  304. '',
  305. new Main\Entity\ReferenceField(
  306. 'BSUB',
  307. Main\Entity\Base::getInstanceByQuery($subSectionQuery),
  308. array('=this.IBLOCK_SECTION_ID' => 'ref.ID'),
  309. array('join_type' => 'INNER')
  310. )
  311. );
  312. $elementQuery = new Main\Entity\Query(Iblock\ElementTable::getEntity());
  313. $elementQuery->setSelect(array('ID'));
  314. $elementQuery->setFilter(array('=IBLOCK_ID' => $iblockId, '=WF_STATUS_ID' => 1, '=WF_PARENT_ELEMENT_ID' => null));
  315. $elementQuery->registerRuntimeField(
  316. '',
  317. new Main\Entity\ReferenceField(
  318. 'BSE',
  319. Main\Entity\Base::getInstanceByQuery($sectionElementQuery),
  320. array('=this.ID' => 'ref.IBLOCK_ELEMENT_ID'),
  321. array('join_type' => 'INNER')
  322. )
  323. );
  324. if ($limit > 0)
  325. $elementQuery->setLimit($limit);
  326. $iterator = $elementQuery->exec();
  327. unset($elementQuery, $sectionElementQuery, $subSectionQuery, $sectionQuery);
  328. }
  329. while ($row = $iterator->fetch())
  330. $map[] = $row['ID'];
  331. unset($row, $iterator);
  332. return $map;
  333. }
  334. protected function filterByAvailability($ids)
  335. {
  336. if (!empty($ids) && $this->arParams['HIDE_NOT_AVAILABLE'] == 'Y')
  337. {
  338. $filter = (count($ids) > 1000 ? array('ID' => $ids) : array('@ID' => $ids));
  339. $ids = array_fill_keys($ids, true);
  340. $productIterator = CCatalogProduct::GetList(
  341. array(),
  342. $filter,
  343. false,
  344. false,
  345. array('ID', 'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO')
  346. );
  347. while ($product = $productIterator->Fetch())
  348. {
  349. if (isset($ids[$product['ID']]) && !CCatalogProduct::isAvailable($product))
  350. unset($ids[$product['ID']]);
  351. }
  352. unset($product, $productIterator, $filter);
  353. $ids = array_keys($ids);
  354. }
  355. return $ids;
  356. }
  357. /**
  358. * Extract data from cache. No action by default.
  359. * @return bool
  360. */
  361. protected function extractDataFromCache()
  362. {
  363. if($this->arParams['CACHE_TYPE'] == 'N')
  364. return false;
  365. return !($this->startResultCache(false, $this->getAdditionalCacheId(), '/'.$this->getSiteId().'/bitrix/catalog.bigdata.products/common'));
  366. }
  367. protected function getAdditionalCacheId()
  368. {
  369. $rcmParams = $this->rcmParams;
  370. // cut productid from non-product recommendations
  371. if ($rcmParams['op'] == 'sim_domain_items' || $rcmParams['op'] == 'recommend')
  372. {
  373. unset($this->arParams['ID'], $this->arParams['~ID']);
  374. }
  375. // cut userid from non-personal recommendations
  376. if ($rcmParams['op'] == 'sim_domain_items' || $rcmParams['op'] == 'simitems')
  377. {
  378. unset($rcmParams['uid']);
  379. }
  380. return $rcmParams;
  381. }
  382. protected function getServiceRequestParamsByType($type)
  383. {
  384. $a = array(
  385. 'uid' => $_COOKIE['BX_USER_ID'],
  386. 'aid' => \Bitrix\Main\Analytics\Counter::getAccountId(),
  387. 'count' => max($this->arParams['PAGE_ELEMENT_COUNT']*2, 30)
  388. );
  389. // random choices
  390. if ($type == 'any_similar')
  391. {
  392. $possible = array('similar_sell', 'similar_view', 'similar');
  393. $type = $possible[array_rand($possible)];
  394. }
  395. elseif ($type == 'any_personal')
  396. {
  397. $possible = array('bestsell', 'personal');
  398. $type = $possible[array_rand($possible)];
  399. }
  400. elseif ($type == 'any')
  401. {
  402. $possible = array('similar_sell', 'similar_view', 'similar', 'bestsell', 'personal');
  403. $type = $possible[array_rand($possible)];
  404. }
  405. // configure
  406. if ($type == 'bestsell')
  407. {
  408. $a['op'] = 'sim_domain_items';
  409. $a['type'] = 'order';
  410. $a['domain'] = Bitrix\Main\Context::getCurrent()->getServer()->getHttpHost();
  411. }
  412. elseif ($type == 'personal')
  413. {
  414. $a['op'] = 'recommend';
  415. }
  416. elseif ($type == 'similar_sell')
  417. {
  418. $a['op'] = 'simitems';
  419. $a['eid'] = $this->arParams['ID'];
  420. $a['type'] = 'order';
  421. }
  422. elseif ($type == 'similar_view')
  423. {
  424. $a['op'] = 'simitems';
  425. $a['eid'] = $this->arParams['ID'];
  426. $a['type'] = 'view';
  427. }
  428. elseif ($type == 'similar')
  429. {
  430. $a['op'] = 'simitems';
  431. $a['eid'] = $this->arParams['ID'];
  432. }
  433. else
  434. {
  435. // unkonwn type, personal by default
  436. $a['op'] = 'recommend';
  437. }
  438. // get iblocks
  439. $iblocks = array();
  440. if (!empty($this->arParams['IBLOCK_ID']))
  441. {
  442. $iblocks = array($this->arParams['IBLOCK_ID']);
  443. }
  444. else
  445. {
  446. $iblockList = array();
  447. /* catalog */
  448. $iblockIterator = \Bitrix\Catalog\CatalogIblockTable::getList(array(
  449. 'select' => array('IBLOCK_ID', 'PRODUCT_IBLOCK_ID')
  450. ));
  451. while ($iblock = $iblockIterator->fetch())
  452. {
  453. $iblock['IBLOCK_ID'] = (int)$iblock['IBLOCK_ID'];
  454. $iblock['PRODUCT_IBLOCK_ID'] = (int)$iblock['PRODUCT_IBLOCK_ID'];
  455. $iblockList[$iblock['IBLOCK_ID']] = $iblock['IBLOCK_ID'];
  456. if ($iblock['PRODUCT_IBLOCK_ID'] > 0)
  457. $iblockList[$iblock['PRODUCT_IBLOCK_ID']] = $iblock['PRODUCT_IBLOCK_ID'];
  458. }
  459. /* iblock */
  460. $iblockIterator = \Bitrix\Iblock\IblockSiteTable::getList(array(
  461. 'select' => array('IBLOCK_ID'),
  462. 'filter' => array('@IBLOCK_ID' => $iblockList, '=SITE_ID' => $this->getSiteId())
  463. ));
  464. while ($iblock = $iblockIterator->fetch())
  465. {
  466. $iblocks[] = $iblock['IBLOCK_ID'];
  467. }
  468. }
  469. $a['ib'] = join('.', $iblocks);
  470. return $a;
  471. }
  472. /**
  473. * Check action variable.
  474. *
  475. * @param array $params Component params.
  476. * @return string
  477. */
  478. protected function prepareActionVariable($params)
  479. {
  480. $actionVariable = (isset($params['ACTION_VARIABLE']) ? trim($params['ACTION_VARIABLE']) : '');
  481. if ($actionVariable === '' || !preg_match("/^[A-Za-z_][A-Za-z01-9_]*$/", $actionVariable))
  482. $actionVariable = 'action_cbdp';
  483. return $actionVariable;
  484. }
  485. /**
  486. * Get additional data for cache
  487. *
  488. * @return array
  489. */
  490. protected function getAdditionalReferences()
  491. {
  492. return array();
  493. }
  494. /**
  495. * Start Component
  496. */
  497. public function executeComponent()
  498. {
  499. global $APPLICATION;
  500. $context = Main\Context::getCurrent();
  501. // mark usage
  502. $lastUsage = Main\Config\Option::get('main', 'rcm_component_usage', 0);
  503. if ($lastUsage == 0 || (time() - $lastUsage) > 3600)
  504. {
  505. Main\Config\Option::set('main', 'rcm_component_usage', time());
  506. }
  507. // execute
  508. try
  509. {
  510. $this->checkModules();
  511. }
  512. catch (SystemException $e)
  513. {
  514. ShowError($e->getMessage());
  515. return;
  516. }
  517. $this->processRequest();
  518. // define what to do and check cache
  519. $this->rcmParams = $this->getServiceRequestParamsByType($this->arParams['RCM_TYPE']);
  520. $showByIds = ($context->getServer()->getRequestMethod() == 'POST' && $context->getRequest()->getPost('rcm') == 'yes');
  521. if (!$showByIds)
  522. {
  523. // check if ids are already in cache
  524. try
  525. {
  526. if (!$this->extractDataFromCache())
  527. {
  528. // echo js for requesting items from recommendation service
  529. $this->arResult['REQUEST_ITEMS'] = true;
  530. $this->arResult['RCM_PARAMS'] = $this->rcmParams;
  531. $this->arResult['RCM_TEMPLATE'] = $this->getTemplateName();
  532. // abort cache, we will write it on next request with the same parameters
  533. $this->abortDataCache();
  534. // clear cache for ajax call
  535. if (Main\Context::getCurrent()->getRequest()->get('clear_cache') == 'Y')
  536. {
  537. $this->clearResultCache($this->getAdditionalCacheId(), '/'.$this->getSiteId().'/bitrix/catalog.bigdata.products/common');
  538. }
  539. $this->includeComponentTemplate();
  540. $this->setResultCacheKeys(array());
  541. }
  542. // show cache and die
  543. return null;
  544. }
  545. catch (SystemException $e)
  546. {
  547. $this->abortDataCache();
  548. if ($this->isAjax())
  549. {
  550. $APPLICATION->restartBuffer();
  551. header('Content-Type: application/json');
  552. echo Main\Web\Json::encode(array('STATUS' => 'ERROR', 'MESSAGE' => $e->getMessage()));
  553. die();
  554. }
  555. ShowError($e->getMessage());
  556. }
  557. }
  558. if ($showByIds)
  559. {
  560. // we have an ajax query to get items html
  561. // and there was no cache
  562. $ajaxItemIds = $context->getRequest()->get('AJAX_ITEMS');
  563. if (!empty($ajaxItemIds) && is_array($ajaxItemIds))
  564. {
  565. $this->ajaxItemsIds = $ajaxItemIds;
  566. }
  567. else
  568. {
  569. // show something
  570. $this->ajaxItemsIds = null;
  571. // last viewed will be shown
  572. }
  573. // draw products with collected ids
  574. $this->prepareData();
  575. $this->formatResult();
  576. }
  577. if (!$this->extractDataFromCache())
  578. {
  579. // output js before template to be caught in cache
  580. if (!empty($this->arResult['ITEMS']))
  581. {
  582. echo $this->getInjectedJs($this->arResult['ITEMS'], $this->arParams['UNIQ_COMPONENT_ID']);
  583. }
  584. $this->setResultCacheKeys(array());
  585. $this->includeComponentTemplate();
  586. }
  587. }
  588. protected function getInjectedJs($items, $uniqId)
  589. {
  590. $jsItems = array();
  591. foreach ($items as $item)
  592. {
  593. $jsItems[] = array(
  594. "productId" => $item['ID'],
  595. "productUrl" => $item['DETAIL_PAGE_URL'],
  596. "recommendationId" => $this->recommendationIdToProduct[$item['ID']]
  597. );
  598. }
  599. global $APPLICATION;
  600. $jsCookiePrefix = CUtil::JSEscape(COption::GetOptionString("main", "cookie_name", "BITRIX_SM"));
  601. $jsCookieDomain = CUtil::JSEscape($APPLICATION->GetCookieDomain());
  602. $jsServerTime = time();
  603. $jsUniqId = CUtil::JSEscape($uniqId."_items");
  604. $jsonItems = CUtil::PhpToJSObject($jsItems);
  605. // static data for JCCatalogBigdataProducts (SendToBasket)
  606. $jsToBasket = "";
  607. foreach ($items as $item)
  608. {
  609. $jsToBasket .= "JCCatalogBigdataProducts.productsByRecommendation[{$item['ID']}] = \"{$this->recommendationIdToProduct[$item['ID']]}\";\n";
  610. }
  611. return "<script type=\"text/javascript\">
  612. BX.cookie_prefix = '{$jsCookiePrefix}';
  613. BX.cookie_domain = '{$jsCookieDomain}';
  614. BX.current_server_time = '{$jsServerTime}';
  615. if (!JCCatalogBigdataProducts.productsByRecommendation)
  616. {
  617. JCCatalogBigdataProducts.productsByRecommendation = [];
  618. }
  619. {$jsToBasket}
  620. BX.ready(function(){
  621. bx_rcm_adaptive_recommendation_event_attaching({$jsonItems}, '{$jsUniqId}');
  622. });
  623. </script>";
  624. }
  625. }