Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
catalogviewedproduct.php
1<?php
2namespace Bitrix\Catalog;
3
10
11Loc::loadMessages(__FILE__);
12
29class CatalogViewedProductTable extends Main\Entity\DataManager
30{
36 public static function getTableName()
37 {
38 return 'b_catalog_viewed_product';
39 }
40
46 public static function getMap()
47 {
48 return array(
49 'ID' => new Main\Entity\IntegerField('ID', array(
50 'primary' => true,
51 'autocomplete' => true,
52 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_ID_FIELD')
53 )),
54 'FUSER_ID' => new Main\Entity\IntegerField('FUSER_ID', array(
55 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_FUSER_ID_FIELD')
56 )),
57 'DATE_VISIT' => new Main\Entity\DatetimeField('DATE_VISIT', array(
58 'default_value' => function(){ return new Main\Type\DateTime(); },
59 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_DATE_VISIT_FIELD')
60 )),
61 'PRODUCT_ID' => new Main\Entity\IntegerField('PRODUCT_ID', array(
62 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_PRODUCT_ID_FIELD')
63 )),
64 'ELEMENT_ID' => new Main\Entity\IntegerField('ELEMENT_ID', array(
65 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_ELEMENT_ID_FIELD')
66 )),
67 'SITE_ID' => new Main\Entity\StringField('SITE_ID', array(
68 'validation' => array(__CLASS__, 'validateSiteId'),
69 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_SITE_ID_FIELD')
70 )),
71 'VIEW_COUNT' => new Main\Entity\IntegerField('VIEW_COUNT', array(
72 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_VIEW_COUNT_FIELD')
73 )),
74 'RECOMMENDATION' => new Main\Entity\StringField('RECOMMENDATION', array(
75 'validation' => array(__CLASS__, 'validateRecommendation'),
76 'title' => Loc::getMessage('VIEWED_PRODUCT_ENTITY_RECOMMENDATION_FIELD')
77 )),
78 'ELEMENT' => new Main\Entity\ReferenceField(
79 'ELEMENT',
80 '\Bitrix\Iblock\Element',
81 array('=this.PRODUCT_ID' => 'ref.ID'),
82 array('join_type' => 'INNER')
83 ),
84 'PRODUCT' => new Main\Entity\ReferenceField(
85 'PRODUCT',
86 '\Bitrix\Sale\Internals\Product',
87 array('=this.PRODUCT_ID' => 'ref.ID'),
88 array('join_type' => 'INNER')
89 ),
90 'PARENT_ELEMENT' => new Main\Entity\ReferenceField(
91 'PARENT_ELEMENT',
92 '\Bitrix\Iblock\Element',
93 array('=this.ELEMENT_ID' => 'ref.ID'),
94 array('join_type' => 'INNER')
95 ),
96 'FUSER' => new Main\Entity\ReferenceField(
97 'FUSER',
98 '\Bitrix\Sale\Internals\Fuser',
99 array('=this.FUSER_ID' => 'ref.ID'),
100 array('join_type' => 'LEFT')
101 )
102 );
103 }
104
110 public static function validateSiteId()
111 {
112 return array(
113 new Main\Entity\Validator\Length(null, 2),
114 );
115 }
116
122 public static function validateRecommendation()
123 {
124 return array(
125 new Main\Entity\Validator\Length(null, 40),
126 );
127 }
128
140 public static function refresh($productId, $fuserId, $siteId = SITE_ID, $elementId = 0, $recommendationId = '')
141 {
142 $rowId = -1;
143
144 if (Option::get('catalog', 'enable_viewed_products') !== 'Y')
145 {
146 return $rowId;
147 }
148
149 $productId = (int)$productId;
150 $fuserId = (int)$fuserId;
151 $siteId = (string)$siteId;
152 $elementId = (int)$elementId;
153 $recommendationId = (string)$recommendationId;
154 if ($productId <= 0 || $fuserId <= 0 || $siteId == '')
155 return $rowId;
156
157 if (!Catalog\Product\Basket::isNotCrawler())
158 return $rowId;
159
160 $filter = array('=FUSER_ID' => $fuserId, '=SITE_ID' => $siteId);
161
162 $connection = Application::getConnection();
163 $helper = $connection->getSqlHelper();
164
165 $sqlSiteId = $helper->forSql($siteId);
166
167 if ($elementId > 0)
168 {
169 $filter["=ELEMENT_ID"] = $elementId;
170
171 // Delete parent product id (for capability)
172 if ($elementId != $productId)
173 $connection->query(
174 "delete from b_catalog_viewed_product where PRODUCT_ID = ".$elementId." and FUSER_ID = ".$fuserId." and SITE_ID = '".$sqlSiteId."'"
175 );
176 }
177 else
178 {
180 $productInfo = \CCatalogSku::getProductInfo($productId);
181 // Real SKU ID
182 if (!empty($productInfo))
183 {
184 $elementId = $productInfo['ID'];
185 $siblings = array();
186 // Delete parent product id (for capability)
187 $connection->query("delete from b_catalog_viewed_product
188 where PRODUCT_ID = ".$productInfo['ID']." and FUSER_ID = ".$fuserId." and SITE_ID = '" .$sqlSiteId. "'"
189 );
190
191 $skus = \CIBlockElement::getList(
192 array(),
193 array('IBLOCK_ID' => $productInfo['OFFER_IBLOCK_ID'], '=PROPERTY_'.$productInfo['SKU_PROPERTY_ID'] => $productInfo['ID']),
194 false,
195 false,
196 array('ID', 'IBLOCK_ID')
197 );
199 while ($oneSku = $skus->fetch())
200 $siblings[] = $oneSku['ID'];
201 unset($oneSku, $skus);
202
203 $filter['@PRODUCT_ID'] = $siblings;
204 }
205 else
206 {
207 $elementId = $productId;
208 $filter['=PRODUCT_ID'] = $productId;
209 }
210 }
211
212 // recommendation
213 if (!empty($elementId))
214 {
215 global $APPLICATION;
216
217 $recommendationCookie = $APPLICATION->get_cookie(Main\Analytics\Catalog::getCookieLogName());
218 if (!empty($recommendationCookie))
219 {
220 $recommendations = Main\Analytics\Catalog::decodeProductLog($recommendationCookie);
221 if (is_array($recommendations) && isset($recommendations[$elementId]))
222 $recommendationId = $recommendations[$elementId][0];
223 }
224 }
225
226 $iterator = static::getList(array(
227 'select' => array('ID', 'FUSER_ID', 'DATE_VISIT', 'PRODUCT_ID', 'SITE_ID', 'VIEW_COUNT'),
228 'filter' => $filter
229 ));
230
231 if ($row = $iterator->fetch())
232 {
233 $update = array(
234 "PRODUCT_ID" => $productId,
235 "DATE_VISIT" => new Main\Type\DateTime,
236 'VIEW_COUNT' => $row['VIEW_COUNT'] + 1,
237 "ELEMENT_ID" => $elementId
238 );
239 if (!empty($recommendationId))
240 $update["RECOMMENDATION"] = $recommendationId;
241
242 $result = static::update($row['ID'], $update);
243 }
244 else
245 {
246 $result = static::add(array(
247 "FUSER_ID" => $fuserId,
248 "DATE_VISIT" => new Main\Type\DateTime(),
249 "PRODUCT_ID" => $productId,
250 "ELEMENT_ID" => $elementId,
251 "SITE_ID" => $siteId,
252 "VIEW_COUNT" => 1,
253 "RECOMMENDATION" => $recommendationId
254 ));
255 }
256
257 if ($result->isSuccess(true))
258 {
259 $rowId = $result->getId();
260 self::truncateUserViewedProducts($fuserId, $siteId);
261 }
262
263 return $rowId;
264 }
265
272 public static function getProductsMap(array $originalIds = array())
273 {
274 if (empty($originalIds) && !is_array($originalIds))
275 return array();
276
277 $result = array();
278 $productList = \CCatalogSku::getProductList($originalIds);
279 if ($productList === false)
280 $productList = array();
281 foreach ($originalIds as $oneId)
282 $result[$oneId] = (isset($productList[$oneId]) ? $productList[$oneId]['ID'] : $oneId);
283 unset($oneId, $productList);
284 return $result;
285 }
286
299 public static function getProductSkuMap($iblockId, $sectionId, $fuserId, $excludeProductId, $limit, $depth = 0, $siteId = null)
300 {
301 $map = array();
302
303 $iblockId = (int)$iblockId;
304 $sectionId = (int)$sectionId;
305 $fuserId = (int)$fuserId;
306 $excludeProductId = (int)$excludeProductId;
307 $limit = (int)$limit;
308 $depth = (int)$depth;
309 if ($iblockId <= 0 || $depth < 0 || $fuserId <= 0)
310 return $map;
311
312 if (empty($siteId))
313 {
314 $context = Application::getInstance()->getContext();
315 $siteId = $context->getSite();
316 }
317 if (empty($siteId))
318 return $map;
319
320 $subSections = array();
321 if ($depth > 0)
322 {
323 $parentSectionId = Product\Viewed::getParentSection($sectionId, $depth);
324 if ($parentSectionId !== null)
325 $subSections[$parentSectionId] = $parentSectionId;
326 unset($parentSectionId);
327 }
328
329 if (empty($subSections) && $sectionId <= 0)
330 {
331 $getListParams = array(
332 'select' => array('PRODUCT_ID', 'ELEMENT_ID', 'DATE_VISIT'),
333 'filter' => array(
334 '=FUSER_ID' => $fuserId,
335 '=SITE_ID' => $siteId,
336 '=PARENT_ELEMENT.IBLOCK_ID' => $iblockId,
337 '=PARENT_ELEMENT.WF_STATUS_ID' => 1,
338 '=PARENT_ELEMENT.WF_PARENT_ELEMENT_ID' => null
339 ),
340 'order' => array('DATE_VISIT' => 'DESC')
341 );
342 if ($excludeProductId > 0)
343 $getListParams['filter']['!=PARENT_ELEMENT.ID'] = $excludeProductId;
344 if ($limit > 0)
345 $getListParams['limit'] = $limit;
346 $iterator = static::getList($getListParams);
347 unset($getListParams);
348 }
349 else
350 {
351 if (empty($subSections))
352 $subSections[$sectionId] = $sectionId;
353
354 $sectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity());
355 $sectionQuery->setTableAliasPostfix('_parent');
356 $sectionQuery->setSelect(array('ID', 'LEFT_MARGIN', 'RIGHT_MARGIN'));
357 $sectionQuery->setFilter(array('@ID' => $subSections));
358
359 $subSectionQuery = new Main\Entity\Query(Iblock\SectionTable::getEntity());
360 $subSectionQuery->setTableAliasPostfix('_sub');
361 $subSectionQuery->setSelect(array('ID'));
362 $subSectionQuery->setFilter(array('=IBLOCK_ID' => $iblockId));
363 $subSectionQuery->registerRuntimeField(
364 '',
365 new Main\Entity\ReferenceField(
366 'BS',
367 Main\Entity\Base::getInstanceByQuery($sectionQuery),
368 array('>=this.LEFT_MARGIN' => 'ref.LEFT_MARGIN', '<=this.RIGHT_MARGIN' => 'ref.RIGHT_MARGIN'),
369 array('join_type' => 'INNER')
370 )
371 );
372
373 $sectionElementQuery = new Main\Entity\Query(Iblock\SectionElementTable::getEntity());
374 $sectionElementQuery->setSelect(array('IBLOCK_ELEMENT_ID'));
375 $sectionElementQuery->setGroup(array('IBLOCK_ELEMENT_ID'));
376 $filter = array('=ADDITIONAL_PROPERTY_ID' => null);
377 if ($excludeProductId > 0)
378 $filter['!=IBLOCK_ELEMENT_ID'] = $excludeProductId;
379 $sectionElementQuery->setFilter($filter);
380 unset($filter);
381 $sectionElementQuery->registerRuntimeField(
382 '',
383 new Main\Entity\ReferenceField(
384 'BSUB',
385 Main\Entity\Base::getInstanceByQuery($subSectionQuery),
386 array('=this.IBLOCK_SECTION_ID' => 'ref.ID'),
387 array('join_type' => 'INNER')
388 )
389 );
390
391 $elementQuery = new Main\Entity\Query(Iblock\ElementTable::getEntity());
392 $elementQuery->setSelect(array('ID'));
393 $filter = array('=IBLOCK_ID' => $iblockId, '=WF_STATUS_ID' => 1, '=WF_PARENT_ELEMENT_ID' => null);
394 if ($excludeProductId > 0)
395 $filter['!=ID'] = $excludeProductId;
396 $elementQuery->setFilter($filter);
397 unset($filter);
398 $elementQuery->registerRuntimeField(
399 '',
400 new Main\Entity\ReferenceField(
401 'BSE',
402 Main\Entity\Base::getInstanceByQuery($sectionElementQuery),
403 array('=this.ID' => 'ref.IBLOCK_ELEMENT_ID'),
404 array('join_type' => 'INNER')
405 )
406 );
407
408 $query = static::query();
409 $query->setSelect(array('PRODUCT_ID', 'ELEMENT_ID', 'DATE_VISIT'));
410 $query->setFilter(array('=FUSER_ID' => $fuserId, '=SITE_ID' => $siteId));
411 $query->setOrder(array('DATE_VISIT' => 'DESC'));
412
413 $query->registerRuntimeField(
414 '',
415 new Main\Entity\ReferenceField(
416 'BE',
417 Main\Entity\Base::getInstanceByQuery($elementQuery),
418 array('=this.ELEMENT_ID' => 'ref.ID'),
419 array('join_type' => 'INNER')
420 )
421 );
422 if ($limit > 0)
423 $query->setLimit($limit);
424
425 $iterator = $query->exec();
426
427 unset($query, $elementQuery, $sectionElementQuery, $subSectionQuery, $sectionQuery);
428 }
429
430 while ($row = $iterator->fetch())
431 $map[$row['PRODUCT_ID']] = $row['ELEMENT_ID'];
432 unset($row, $iterator);
433 unset($subSections);
434
435 return $map;
436 }
437
444 public static function clear($liveTime = 10)
445 {
446 $liveTime = (int)$liveTime;
447 if ($liveTime <= 0)
448 return;
449
450 $connection = Application::getConnection();
451 $helper = $connection->getSqlHelper();
452 $liveTo = $helper->addSecondsToDateTime($liveTime * 86400, $helper->quote('DATE_VISIT'));
453
454 $connection->query(
455 'delete from '.$helper->quote(self::getTableName()).
456 ' where '.$liveTo.' < '.$helper->getCurrentDateTimeFunction()
457 );
458 unset($liveTo, $helper, $connection);
459 }
460
466 public static function clearAgent(): string
467 {
468 if (Option::get('catalog', 'enable_viewed_products') !== 'Y')
469 {
470 return '';
471 }
472 self::clear((int)Option::get('catalog', 'viewed_time'));
473 return '\Bitrix\Catalog\CatalogViewedProductTable::clearAgent();';
474 }
475
476 private static function truncateUserViewedProducts($fuserId, $siteId)
477 {
478 $fuserId = (int)$fuserId;
479 $siteId = (string)$siteId;
480
481 if ($fuserId <= 0 || $siteId == '')
482 return;
483
484 $maxCount = (int)Main\Config\Option::get('catalog', 'viewed_count');
485 if ($maxCount <= 0)
486 return;
487
488 $iterator = self::getList(array(
489 'select' => array('DATE_VISIT', 'FUSER_ID', 'SITE_ID'),
490 'filter' => array('=FUSER_ID' => $fuserId, '=SITE_ID' => $siteId),
491 'order' => array('FUSER_ID' => 'ASC', 'SITE_ID' => 'ASC', 'DATE_VISIT' => 'DESC'),
492 'limit' => 1,
493 'offset' => $maxCount
494 ));
495 $row = $iterator->fetch();
496 unset($iterator);
497 if (!empty($row) && $row['DATE_VISIT'] instanceof Main\Type\DateTime)
498 {
499 $connection = Application::getConnection();
500 $helper = $connection->getSqlHelper();
501
502 $query = 'delete from '.$helper->quote(self::getTableName()).
503 ' where '.$helper->quote('FUSER_ID').' = '.$fuserId.
504 ' and '.$helper->quote('SITE_ID').' = \''.$helper->forSql($siteId).'\''.
505 ' and '.$helper->quote('DATE_VISIT').' <= '.$helper->convertToDbDateTime($row['DATE_VISIT']);
506 $connection->query($query);
507 unset($query, $helper, $connection);
508 }
509 unset($row);
510 }
511}
static refresh($productId, $fuserId, $siteId=SITE_ID, $elementId=0, $recommendationId='')
static getProductSkuMap($iblockId, $sectionId, $fuserId, $excludeProductId, $limit, $depth=0, $siteId=null)
static getProductsMap(array $originalIds=array())
static getConnection($name="")
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29