Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
catalog.php
1<?php
20
21if (!Loader::includeModule('catalog'))
22 return;
23
29{
30 protected static $cookieLogName = 'RCM_PRODUCT_LOG';
31
32 // basket (sale:OnSaleBasketItemSaved)
33 public static function catchCatalogBasket(Event $event)
34 {
35 $isNew = $event->getParameter("IS_NEW");
36
37 // new items only
38 if (!$isNew)
39 {
40 return;
41 }
42
43 // exclude empty cookie
44 if (!static::getBxUserId())
45 {
46 return;
47 }
48
49 // alter b_sale_basket - add recommendation, update it here
50 if (!static::isOn())
51 {
52 return;
53 }
54
56 $basketItem = $event->getParameter("ENTITY");
57
58 // get product id by offer id
59 $iblockId = 0;
60 $realProductId = $basketItem->getProductId();
61 $isCatalog = $basketItem->getField('MODULE') == 'catalog';
62
63 if ($isCatalog)
64 {
65 $productInfo = \CCatalogSKU::GetProductInfo($realProductId);
66
67 if (!empty($productInfo['ID']))
68 {
69 $realProductId = $productInfo['ID'];
70 $iblockId = $productInfo['IBLOCK_ID'];
71 }
72 else
73 {
74 // get iblock id
75 $element = \Bitrix\Iblock\ElementTable::getRow(array(
76 'select' => array('IBLOCK_ID'),
77 'filter' => array('=ID' => $realProductId)
78 ));
79
80 if (!empty($element))
81 {
82 $iblockId = $element['IBLOCK_ID'];
83 }
84 }
85 }
86
87 // select site user id & recommendation id
88 $siteUserId = 0;
89 $recommendationId = '';
90
91 // first, try to find in cookies
92 $recommendationCookie = Context::getCurrent()->getRequest()->getCookie(static::getCookieLogName());
93
94 if (!empty($recommendationCookie))
95 {
96 $recommendations = static::decodeProductLog($recommendationCookie);
97
98 if (is_array($recommendations) && isset($recommendations[$realProductId]))
99 {
100 $recommendationId = $recommendations[$realProductId][0];
101 }
102 }
103
104 if (empty($recommendationId) && $isCatalog)
105 {
106 // ok then, lets see in views history
107 //if(\COption::GetOptionString("sale", "encode_fuser_id", "N") == "Y")
108 if (!is_numeric($basketItem->getFUserId()))
109 {
110 $filter = array('CODE' => $basketItem->getFUserId());
111 }
112 else
113 {
114 $filter = array('ID' => $basketItem->getFUserId());
115 }
116
117 $result = \CSaleUser::getList($filter);
118
119 if (!empty($result))
120 {
121 $siteUserId = $result['USER_ID'];
122
123 // select recommendation id
124 $fuser = $result['ID'];
125
126 $viewResult = CatalogViewedProductTable::getList(array(
127 'select' => array('RECOMMENDATION'),
128 'filter' => array(
129 '=FUSER_ID' => $fuser,
130 '=PRODUCT_ID' => $basketItem->getProductId()
131 ),
132 'order' => array('DATE_VISIT' => 'DESC')
133 ))->fetch();
134
135 if (!empty($viewResult['RECOMMENDATION']))
136 {
137 $recommendationId = $viewResult['RECOMMENDATION'];
138 }
139 }
140 }
141
142 // prepare data
143 $data = array(
144 'product_id' => $realProductId,
145 'iblock_id' => $iblockId,
146 'user_id' => $siteUserId,
147 'bx_user_id' => static::getBxUserId(),
148 'domain' => Context::getCurrent()->getServer()->getHttpHost(),
149 'recommendation' => $recommendationId,
150 'date' => date(DATE_ISO8601)
151 );
152
153 // debug info
154 global $USER;
155
156 $data['real_user_id'] = $USER->getId() ?: 0;
157 $data['is_admin'] = (int) $USER->IsAdmin();
158 $data['admin_section'] = (int) (defined('ADMIN_SECTION') && ADMIN_SECTION);
159 $data['admin_panel'] = (int) \CTopPanel::shouldShowPanel();
160
161 // try to guess unnatural baskets
162 $data['artificial_basket'] = (int) (
163 ($data['user_id'] > 0 && $data['user_id'] != $data['real_user_id'])
164 || $data['is_admin'] || $data['admin_section'] || $data['admin_panel']
165 );
166
167 // save
168 CounterDataTable::add(array(
169 'TYPE' => 'basket',
170 'DATA' => $data
171 ));
172
173 // update basket with recommendation id
174 if (!empty($recommendationId))
175 {
177 $helper = $conn->getSqlHelper();
178
179 $conn->query(
180 "UPDATE ".$helper->quote('b_sale_basket')
181 ." SET RECOMMENDATION='".$helper->forSql($recommendationId)."' WHERE ID=".(int) $basketItem->getId()
182 );
183 }
184 }
185
186 // order detailed info (sale:OnSaleOrderSaved)
187 public static function catchCatalogOrder(Event $event)
188 {
189 if (!static::isOn())
190 {
191 return;
192 }
193
194 $isNew = $event->getParameter("IS_NEW");
195
196 if (!$isNew)
197 {
198 // only new orders
199 return;
200 }
201
203 $orderItem = $event->getParameter("ENTITY");
204
205 $data = static::getOrderInfo($orderItem->getId());
206
207 if (empty($data['products']))
208 {
209 return;
210 }
211
212 // add bxuid
213 $data['bx_user_id'] = static::getBxUserId();
214
215 if (empty($data['bx_user_id']) && !empty($data['user_id']))
216 {
217 $orderUser = UserTable::getRow(array(
218 'select' => array('BX_USER_ID'),
219 'filter' => array('=ID' => $data['user_id'])
220 ));
221
222 if (!empty($orderUser) && !empty($orderUser['BX_USER_ID']))
223 {
224 $data['bx_user_id'] = $orderUser['BX_USER_ID'];
225 }
226 }
227
228 // add general info
229 $data['paid'] = '0';
230 $data['domain'] = Context::getCurrent()->getServer()->getHttpHost();
231 $data['date'] = date(DATE_ISO8601);
232
233 // add debug info
234 global $USER;
235
236 $data['real_user_id'] = $USER->getId() ?: 0;
237 $data['cookie_size'] = count($_COOKIE);
238 $data['is_admin'] = (int) $USER->IsAdmin();
239 $data['admin_section'] = (int) (defined('ADMIN_SECTION') && ADMIN_SECTION);
240 $data['admin_panel'] = (int) \CTopPanel::shouldShowPanel();
241
242 // try to guess unnatural orders
243 $data['artificial_order'] = (int) (
244 ($data['user_id'] != $data['real_user_id']) || !$data['cookie_size']
245 || $data['is_admin'] || $data['admin_section'] || $data['admin_panel']
246 );
247
248 CounterDataTable::add(array(
249 'TYPE' => 'order',
250 'DATA' => $data
251 ));
252
253 // set bxuid to the order
254 if (!empty($data['bx_user_id']))
255 {
256 // if sale version is fresh enough
257 if (OrderTable::getEntity()->hasField('BX_USER_ID'))
258 {
259 OrderTable::update($data['order_id'], array('BX_USER_ID' => $data['bx_user_id']));
260 }
261 }
262 }
263
264 // order payment (sale:OnSaleOrderPaid)
265 public static function catchCatalogOrderPayment(Event $event)
266 {
267 if (!static::isOn())
268 {
269 return;
270 }
271
273 $orderItem = $event->getParameter("ENTITY");
274
275 $data = static::getOrderInfo($orderItem->getId());
276
277 if (empty($data['products']))
278 {
279 return;
280 }
281
282 // add bxuid
283 $data['bx_user_id'] = static::getBxUserId();
284
285 if (empty($data['bx_user_id']) && OrderTable::getEntity()->hasField('BX_USER_ID'))
286 {
287 $order = OrderTable::getRow(array(
288 'select' => array('BX_USER_ID'),
289 'filter' => array('=ID' => $orderItem->getId())
290 ));
291
292 if (!empty($order) && !empty($order['BX_USER_ID']))
293 {
294 $data['bx_user_id'] = $order['BX_USER_ID'];
295 }
296 }
297
298 // add general info
299 $data['paid'] = '1';
300 $data['domain'] = Context::getCurrent()->getServer()->getHttpHost();
301 $data['date'] = date(DATE_ISO8601);
302
303 CounterDataTable::add(array(
304 'TYPE' => 'order_pay',
305 'DATA' => $data
306 ));
307 }
308
309 public static function getOrderInfo($orderId)
310 {
311 // order itself
312 $order = \CSaleOrder::getById($orderId);
313
314 // buyer info
315 $siteUserId = $order['USER_ID'];
316
317 $phone = '';
318 $phone256 = '';
319 $phone256_e164 = '';
320
321 $email = '';
322 $email256 = '';
323
324 $result = \CSaleOrderPropsValue::GetList(array(), array("ORDER_ID" => $orderId));
325 while ($row = $result->fetch())
326 {
327 if (empty($phone) && mb_stripos($row['CODE'], 'PHONE') !== false)
328 {
329 $stPhone = static::normalizePhoneNumber($row['VALUE']);
330
331 if (!empty($stPhone))
332 {
333 $phone = sha1($stPhone);
334 $phone256 = hash('sha256', $stPhone);
335 $phone256_e164 = hash('sha256', '+'.$stPhone);
336 }
337 }
338
339 if (empty($email) && mb_stripos($row['CODE'], 'EMAIL') !== false)
340 {
341 if (!empty($row['VALUE']))
342 {
343 $email = sha1($row['VALUE']);
344 $email256 = hash('sha256', mb_strtolower(trim($row['VALUE'])));
345 }
346 }
347 }
348
349 // products info
350 $products = array();
351
352 $result = \CSaleBasket::getList(
353 array(), $arFilter = array('ORDER_ID' => $orderId), false, false,
354 array('PRODUCT_ID', 'RECOMMENDATION', 'QUANTITY', 'PRICE', 'CURRENCY', 'MODULE')
355 );
356
357 while ($row = $result->fetch())
358 {
359 $realProductId = $row['PRODUCT_ID'];
360 $iblockId = 0;
361
362 // get iblock id for catalog products
363 if ($row['MODULE'] == 'catalog')
364 {
365 $productInfo = \CCatalogSKU::GetProductInfo($row['PRODUCT_ID']);
366
367 if (!empty($productInfo['ID']))
368 {
369 $realProductId = $productInfo['ID'];
370 $iblockId = $productInfo['IBLOCK_ID'];
371 }
372 else
373 {
374 // get iblock id
375 $element = \Bitrix\Iblock\ElementTable::getRow(array(
376 'select' => array('IBLOCK_ID'),
377 'filter' => array('=ID' => $realProductId)
378 ));
379
380 if (!empty($element))
381 {
382 $iblockId = $element['IBLOCK_ID'];
383 }
384 }
385 }
386
387 $products[] = array(
388 'product_id' => $realProductId,
389 'iblock_id' => $iblockId,
390 'quantity' => $row['QUANTITY'],
391 'price' => $row['PRICE'],
392 'currency' => $row['CURRENCY'],
393 'recommendation' => $row['RECOMMENDATION']
394 );
395 }
396
397 // all together
398 $data = array(
399 'order_id' => $orderId,
400 'user_id' => $siteUserId,
401 'phone' => $phone,
402 'phone256' => $phone256,
403 'phone256_e164' => $phone256_e164,
404 'email' => $email,
405 'email256' => $email256,
406 'products' => $products,
407 'price' => $order['PRICE'],
408 'currency' => $order['CURRENCY']
409 );
410
411 return $data;
412 }
413
414 protected static function getBxUserId()
415 {
416 return $_COOKIE['BX_USER_ID'];
417 }
418
419 public static function normalizePhoneNumber($phone)
420 {
421 $phone = preg_replace('/[^\d]/', '', $phone);
422
423 $cleanPhone = \NormalizePhone($phone, 6);
424
425 if (mb_strlen($cleanPhone) == 10)
426 {
427 $cleanPhone = '7'.$cleanPhone;
428 }
429
430 return $cleanPhone;
431 }
432
433 public static function isOn()
434 {
435 return SiteSpeed::isOn()
436 && Option::get("main", "gather_catalog_stat", "Y") === "Y"
437 && !Application::getInstance()->getLicense()->isDemoKey()
438 ;
439 }
440
441 public static function getProductIdsByOfferIds($offerIds)
442 {
443 if (empty($offerIds))
444 return array();
445
446 $bestList = array();
447 $iblockGroup = array();
448 $itemIterator = \Bitrix\Iblock\ElementTable::getList(array(
449 'select' => array('ID', 'IBLOCK_ID'),
450 'filter' => array('@ID' => $offerIds, '=ACTIVE'=> 'Y')
451 ));
452 while ($item = $itemIterator->fetch())
453 {
454 if (!isset($iblockGroup[$item['IBLOCK_ID']]))
455 $iblockGroup[$item['IBLOCK_ID']] = array();
456 $iblockGroup[$item['IBLOCK_ID']][] = $item['ID'];
457 $bestList[$item['ID']] = array();
458 }
459
460 if (empty($iblockGroup))
461 {
462 return array();
463 }
464
465 $iblockSku = array();
466 $iblockOffers = array();
467
468 $iblockIterator = \Bitrix\Catalog\CatalogIblockTable::getList(array(
469 'select' => array('IBLOCK_ID', 'PRODUCT_IBLOCK_ID', 'SKU_PROPERTY_ID', 'VERSION' => 'IBLOCK.VERSION'),
470 'filter' => array('=IBLOCK_ID' => array_keys($iblockGroup), '!=PRODUCT_IBLOCK_ID' => 0)
471 ));
472 while ($iblock = $iblockIterator->fetch())
473 {
474 $iblock['IBLOCK_ID'] = (int)$iblock['IBLOCK_ID'];
475 $iblock['PRODUCT_IBLOCK_ID'] = (int)$iblock['PRODUCT_IBLOCK_ID'];
476 $iblock['SKU_PROPERTY_ID'] = (int)$iblock['SKU_PROPERTY_ID'];
477 $iblock['VERSION'] = (int)$iblock['VERSION'];
478 $iblockSku[$iblock['IBLOCK_ID']] = $iblock;
479 $iblockOffers[$iblock['IBLOCK_ID']] = $iblockGroup[$iblock['IBLOCK_ID']];
480 }
481 unset($iblock, $iblockIterator);
482
483 if (empty($iblockOffers))
484 return array();
485
486 $offerLink = array();
487 foreach ($iblockOffers as $iblockId => $items)
488 {
489 $skuProperty = 'PROPERTY_'.$iblockSku[$iblockId]['SKU_PROPERTY_ID'];
490 $iblockFilter = array(
491 'IBLOCK_ID' => $iblockId,
492 '=ID' => $items
493 );
494 $iblockFields = array('ID', 'IBLOCK_ID', $skuProperty);
495 $skuProperty .= '_VALUE';
496 $offersIterator = \CIBlockElement::getList(
497 array('ID' => 'ASC'),
498 $iblockFilter,
499 false,
500 false,
501 $iblockFields
502 );
503
504 while ($offer = $offersIterator->Fetch())
505 {
506 $productId = (int)$offer[$skuProperty];
507 if ($productId <= 0)
508 {
509 unset($bestList[$offer['ID']]);
510 }
511 else
512 {
513 $bestList[$offer['ID']]['PARENT_ID'] = $productId;
514 $bestList[$offer['ID']]['PARENT_IBLOCK'] = $iblockSku[$iblockId]['PRODUCT_IBLOCK_ID'];
515 if (!isset($offerLink[$productId]))
516 $offerLink[$productId] = array();
517 $offerLink[$productId][] = $offer['ID'];
518 }
519 }
520 }
521 if (!empty($offerLink))
522 {
523 $productIterator = \Bitrix\Iblock\ElementTable::getList(array(
524 'select' => array('ID'),
525 'filter' => array('@ID' => array_keys($offerLink), '=ACTIVE' => 'N')
526 ));
527 while ($product = $productIterator->fetch())
528 {
529 if (empty($offerLink[$product['ID']]))
530 continue;
531 foreach ($offerLink[$product['ID']] as $value)
532 {
533 unset($bestList[$value]);
534 }
535 }
536 }
537
538 if (empty($bestList))
539 return array();
540
541 $finalIds = array();
542 $dublicate = array();
543 foreach ($bestList as $id => $info)
544 {
545 if (empty($info))
546 {
547 if (!isset($dublicate[$id]))
548 $finalIds[] = $id;
549 $dublicate[$id] = true;
550 }
551 else
552 {
553 if (!isset($dublicate[$id]))
554 $finalIds[] = $info['PARENT_ID'];
555 $dublicate[$info['PARENT_ID']] = true;
556 }
557 }
558 unset($id, $info, $dublicate);
559
560 return $finalIds;
561 }
562
568 public static function encodeProductLog(array $log)
569 {
570 $value = array();
571
572 foreach ($log as $itemId => $recommendation)
573 {
574 $rcmId = $recommendation[0];
575 $rcmTime = $recommendation[1];
576
577 $value[] = $itemId.'-'.$rcmId.'-'.$rcmTime;
578 }
579
580 return join('.', $value);
581 }
582
588 public static function decodeProductLog($log)
589 {
590 $value = array();
591 $tmp = explode('.', $log);
592
593 foreach ($tmp as $tmpval)
594 {
595 $meta = explode('-', $tmpval);
596
597 if (count($meta) > 2)
598 {
599 $itemId = $meta[0];
600 $rcmId = $meta[1];
601 $rcmTime = $meta[2];
602
603 if ($itemId && $rcmId && $rcmTime)
604 {
605 $value[(int)$itemId] = array($rcmId, (int) $rcmTime);
606 }
607 }
608 }
609
610 return $value;
611 }
612
616 public static function getCookieLogName()
617 {
619 }
620}
static normalizePhoneNumber($phone)
Definition catalog.php:419
static getProductIdsByOfferIds($offerIds)
Definition catalog.php:441
static encodeProductLog(array $log)
Definition catalog.php:568
static getOrderInfo($orderId)
Definition catalog.php:309
static getConnection($name="")
static getCurrent()
Definition context.php:241
getParameter($key)
Definition event.php:80
static includeModule($moduleName)
Definition loader.php:69
static getRow(array $parameters)