1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
ratings.php
См. документацию.
1<?php
2
4
6{
7 const REACTION_DEFAULT = 'like';
8 const REACTION_KISS = 'kiss';
9 const REACTION_LAUGH = 'laugh';
10 const REACTION_ANGRY = 'angry';
11 const REACTION_WONDER = 'wonder';
12 const REACTION_CRY = 'cry';
13
14 // get specified rating record
15 public static function GetByID($ID)
16 {
17 global $DB;
18
19 $ID = (int)$ID;
20
21 if ($ID <= 0)
22 {
23 return false;
24 }
25
26 return $DB->Query("
27 SELECT
28 R.*,
29 " . $DB->DateToCharFunction("R.CREATED") . " as CREATED,
30 " . $DB->DateToCharFunction("R.LAST_MODIFIED") . " as LAST_MODIFIED,
31 " . $DB->DateToCharFunction("R.LAST_CALCULATED") . " as LAST_CALCULATED
32 FROM
33 b_rating R
34 WHERE
35 ID=" . $ID
36 );
37 }
38
39 public static function GetArrayByID($ID)
40 {
41 global $DB;
42
43 $ID = (int)$ID;
44 $strID = "b" . $ID;
45 if (CACHED_b_rating === false)
46 {
47 $res = $DB->Query("
48 SELECT
49 R.*,
50 " . $DB->DateToCharFunction("R.CREATED") . " as CREATED,
51 " . $DB->DateToCharFunction("R.LAST_MODIFIED") . " as LAST_MODIFIED,
52 " . $DB->DateToCharFunction("R.LAST_CALCULATED") . " as LAST_CALCULATED
53 FROM
54 b_rating R
55 WHERE
56 ID=" . $ID
57 );
58 $arResult = $res->Fetch();
59 }
60 else
61 {
62 global $stackCacheManager;
63 $stackCacheManager->SetLength("b_rating", 100);
64 $stackCacheManager->SetTTL("b_rating", CACHED_b_rating);
65 if ($stackCacheManager->Exist("b_rating", $strID))
66 {
67 $arResult = $stackCacheManager->Get("b_rating", $strID);
68 }
69 else
70 {
71 $res = $DB->Query("
72 SELECT
73 R.*,
74 " . $DB->DateToCharFunction("R.CREATED") . " as CREATED,
75 " . $DB->DateToCharFunction("R.LAST_MODIFIED") . " as LAST_MODIFIED,
76 " . $DB->DateToCharFunction("R.LAST_CALCULATED") . " as LAST_CALCULATED
77 FROM
78 b_rating R
79 WHERE
80 ID=" . $ID
81 );
82 $arResult = $res->Fetch();
83 if ($arResult)
84 {
85 $stackCacheManager->Set("b_rating", $strID, $arResult);
86 }
87 }
88 }
89
90 return $arResult;
91 }
92
93 // get rating record list
94 public static function GetList($arSort = [], $arFilter = [])
95 {
96 global $DB;
97
98 $arSqlSearch = [];
99
100 if (is_array($arFilter))
101 {
102 foreach ($arFilter as $key => $val)
103 {
104 if ((string)$val == '' || $val === "NOT_REF")
105 {
106 continue;
107 }
108 switch (mb_strtoupper($key))
109 {
110 case "ID":
111 $arSqlSearch[] = GetFilterQuery("R.ID", $val, "N");
112 break;
113 case "ACTIVE":
114 if (in_array($val, ['Y', 'N']))
115 {
116 $arSqlSearch[] = "R.ACTIVE = '" . $val . "'";
117 }
118 break;
119 case "AUTHORITY":
120 if (in_array($val, ['Y', 'N']))
121 {
122 $arSqlSearch[] = "R.AUTHORITY = '" . $val . "'";
123 }
124 break;
125 case "POSITION":
126 if (in_array($val, ['Y', 'N']))
127 {
128 $arSqlSearch[] = "R.POSITION = '" . $val . "'";
129 }
130 break;
131 case "CALCULATED":
132 if (in_array($val, ['Y', 'N', 'C']))
133 {
134 $arSqlSearch[] = "R.CALCULATED = '" . $val . "'";
135 }
136 break;
137 case "NAME":
138 $arSqlSearch[] = GetFilterQuery("R.NAME", $val);
139 break;
140 case "ENTITY_ID":
141 $arSqlSearch[] = GetFilterQuery("R.ENTITY_ID", $val);
142 break;
143 }
144 }
145 }
146
147 $sOrder = "";
148 foreach ($arSort as $key => $val)
149 {
150 $ord = (mb_strtoupper($val) <> "ASC" ? "DESC" : "ASC");
151 switch (mb_strtoupper($key))
152 {
153 case "ID":
154 $sOrder .= ", R.ID " . $ord;
155 break;
156 case "NAME":
157 $sOrder .= ", R.NAME " . $ord;
158 break;
159 case "CREATED":
160 $sOrder .= ", R.CREATED " . $ord;
161 break;
162 case "LAST_MODIFIED":
163 $sOrder .= ", R.LAST_MODIFIED " . $ord;
164 break;
165 case "LAST_CALCULATED":
166 $sOrder .= ", R.LAST_CALCULATED " . $ord;
167 break;
168 case "ACTIVE":
169 $sOrder .= ", R.ACTIVE " . $ord;
170 break;
171 case "AUTHORITY":
172 $sOrder .= ", R.AUTHORITY " . $ord;
173 break;
174 case "POSITION":
175 $sOrder .= ", R.POSITION " . $ord;
176 break;
177 case "STATUS":
178 $sOrder .= ", R.CALCULATED " . $ord;
179 break;
180 case "CALCULATED":
181 $sOrder .= ", R.CALCULATED " . $ord;
182 break;
183 case "CALCULATION_METHOD":
184 $sOrder .= ", R.CALCULATION_METHOD " . $ord;
185 break;
186 case "ENTITY_ID":
187 $sOrder .= ", R.ENTITY_ID " . $ord;
188 break;
189 }
190 }
191
192 if ($sOrder == '')
193 {
194 $sOrder = "R.ID DESC";
195 }
196
197 $strSqlOrder = " ORDER BY " . trim($sOrder, ", ");
198
199 $strSqlSearch = GetFilterSqlSearch($arSqlSearch);
200 $strSql = "
201 SELECT
202 R.ID, R.NAME, R.ACTIVE, R.CALCULATED, R.AUTHORITY, R.POSITION, R.ENTITY_ID, R.CALCULATION_METHOD,
203 " . $DB->DateToCharFunction("R.CREATED") . " CREATED,
204 " . $DB->DateToCharFunction("R.LAST_MODIFIED") . " LAST_MODIFIED,
205 " . $DB->DateToCharFunction("R.LAST_CALCULATED") . " LAST_CALCULATED
206 FROM
207 b_rating R
208 WHERE
209 " . $strSqlSearch . "
210 " . $strSqlOrder;
211 return $DB->Query($strSql);
212 }
213
214 public static function GetRatingValueInfo($ratingId)
215 {
216 global $DB;
217
218 $ratingId = (int)$ratingId;
219
220 $strSql = "
221 SELECT
222 MAX(CURRENT_VALUE) as MAX,
223 MIN(CURRENT_VALUE) as MIN,
224 AVG(CURRENT_VALUE) as AVG,
225 COUNT(*) as CNT
226 FROM b_rating_results
227 WHERE RATING_ID = " . $ratingId;
228 return $DB->Query($strSql);
229 }
230
231 //Addition rating
232 public static function Add($arFields)
233 {
234 global $DB, $stackCacheManager;
235
236 // check only general field
238 {
239 return false;
240 }
241
242 $arFields_i = [
243 "ACTIVE" => $arFields["ACTIVE"] === 'Y' ? 'Y' : 'N',
244 "POSITION" => $arFields["POSITION"] === 'Y' ? 'Y' : 'N',
245 "AUTHORITY" => $arFields["AUTHORITY"] === 'Y' ? 'Y' : 'N',
246 "NAME" => $arFields["NAME"],
247 "ENTITY_ID" => $arFields["ENTITY_ID"],
248 "CALCULATION_METHOD" => $arFields["CALCULATION_METHOD"],
249 "~CREATED" => $DB->GetNowFunction(),
250 "~LAST_MODIFIED" => $DB->GetNowFunction(),
251 ];
252 $ID = $DB->Add("b_rating", $arFields_i);
253
254 // queries modules and give them to inspect the field settings
255 foreach (GetModuleEvents("main", "OnAfterAddRating", true) as $arEvent)
256 {
258 }
259
261
262 $arFields_u = [
263 "CONFIGS" => "'" . $DB->ForSQL(serialize($arFields["CONFIGS"])) . "'",
264 ];
265
266 $DB->Update("b_rating", $arFields_u, "WHERE ID = " . $ID);
267
268 if ($arFields['AUTHORITY'] === 'Y')
269 {
271 }
272
273 CAgent::AddAgent("CRatings::Calculate($ID);", "main", "N", 3600, "", "Y", "");
274
275 $stackCacheManager->Clear("b_rating");
276
277 return $ID;
278 }
279
280 //Update rating
281 public static function Update($ID, $arFields)
282 {
283 global $DB, $stackCacheManager;
284
285 $ID = (int)$ID;
286
287 // check only general field
289 {
290 return false;
291 }
292
293 $arFields_u = [
294 "ACTIVE" => $arFields['ACTIVE'] === 'Y' ? 'Y' : 'N',
295 "NAME" => $arFields["NAME"],
296 "ENTITY_ID" => $arFields["ENTITY_ID"],
297 "CALCULATION_METHOD" => $arFields["CALCULATION_METHOD"],
298 "~LAST_MODIFIED" => $DB->GetNowFunction(),
299 ];
300 $strUpdate = $DB->PrepareUpdate("b_rating", $arFields_u);
301 if (!$DB->Query("UPDATE b_rating SET " . $strUpdate . " WHERE ID=" . $ID))
302 {
303 return false;
304 }
305
306 if (!isset($arFields["CONFIGS"]))
307 {
308 $stackCacheManager->Clear("b_rating");
309 return true;
310 }
311 // queries modules and give them to inspect the field settings
312 foreach (GetModuleEvents("main", "OnAfterUpdateRating", true) as $arEvent)
313 {
315 }
316
318
319 $arFields_u = [
320 "POSITION" => "'" . ($arFields['POSITION'] === 'Y' ? 'Y' : 'N') . "'",
321 "AUTHORITY" => "'" . ($arFields['AUTHORITY'] === 'Y' ? 'Y' : 'N') . "'",
322 "CONFIGS" => "'" . $DB->ForSQL(serialize($arFields["CONFIGS"])) . "'",
323 ];
324 $DB->Update("b_rating", $arFields_u, "WHERE ID = " . $ID);
325
326 if ($arFields['AUTHORITY'] === 'Y')
327 {
329 }
330
331 if ($arFields['NEW_CALC'] === 'Y')
332 {
333 $DB->Query("UPDATE b_rating_results SET PREVIOUS_VALUE = 0 WHERE RATING_ID=" . $ID . " and ENTITY_TYPE_ID='" . $DB->ForSql($arFields["ENTITY_ID"]) . "'");
334 }
335
336 $strSql = "SELECT COMPLEX_NAME FROM b_rating_component WHERE RATING_ID = $ID and ACTIVE = 'N'";
337 $res = $DB->Query($strSql);
338 $arrRatingComponentId = [];
339 while ($arRes = $res->Fetch())
340 {
341 $arrRatingComponentId[] = $arRes['COMPLEX_NAME'];
342 }
343
344 if (!empty($arrRatingComponentId))
345 {
346 $DB->Query("DELETE FROM b_rating_component_results WHERE RATING_ID = $ID AND COMPLEX_NAME IN ('" . implode("','", $arrRatingComponentId) . "')");
347 }
348
350
351 CAgent::RemoveAgent("CRatings::Calculate($ID);", "main");
352 $AID = CAgent::AddAgent("CRatings::Calculate($ID);", "main", "N", 3600, "", "Y", "");
353
354 $stackCacheManager->Clear("b_rating");
355
356 return true;
357 }
358
359 // delete rating
360 public static function Delete($ID)
361 {
362 global $DB, $stackCacheManager;
363
364 $ID = (int)$ID;
365
366 foreach (GetModuleEvents("main", "OnBeforeDeleteRating", true) as $arEvent)
367 {
368 ExecuteModuleEventEx($arEvent, [$ID]);
369 }
370
371 $DB->Query("DELETE FROM b_rating WHERE ID=$ID");
372 $DB->Query("DELETE FROM b_rating_user WHERE RATING_ID=$ID");
373 $DB->Query("DELETE FROM b_rating_component WHERE RATING_ID=$ID");
374 $DB->Query("DELETE FROM b_rating_component_results WHERE RATING_ID=$ID");
375 $DB->Query("DELETE FROM b_rating_results WHERE RATING_ID=$ID");
376
377 CAgent::RemoveAgent("CRatings::Calculate($ID);", "main");
378
379 $stackCacheManager->Clear("b_rating");
380
381 return true;
382 }
383
384 // start calculation rating-component
385 public static function Calculate($ID, $bForceRecalc = false)
386 {
387 global $DB;
388
389 $ID = (int)$ID;
390
391 $strSql = "SELECT
392 RC.*,
393 " . $DB->DateToCharFunction("RC.LAST_MODIFIED") . " LAST_MODIFIED,
394 " . $DB->DateToCharFunction("RC.LAST_CALCULATED") . " LAST_CALCULATED,
395 " . $DB->DateToCharFunction("RC.NEXT_CALCULATION") . " NEXT_CALCULATION
396 FROM
397 b_rating_component RC
398 WHERE
399 RATING_ID = $ID
400 and ACTIVE = 'Y' " . ($bForceRecalc ? '' : 'AND NEXT_CALCULATION <= ' . $DB->GetNowFunction());
401 $res = $DB->Query($strSql);
402 while ($arRes = $res->Fetch())
403 {
404 if (CModule::IncludeModule(mb_strtolower($arRes['MODULE_ID'])))
405 {
406 $arRes['CONFIG'] = unserialize($arRes['CONFIG'], ['allowed_classes' => false]);
407 // If the type is automatic calculation of parameters * global vote weight
408 $sRatingWeightType = COption::GetOptionString("main", "rating_weight_type", "auto");
409 if ($sRatingWeightType === 'auto')
410 {
411 $voteWeight = COption::GetOptionString("main", "rating_vote_weight", 1);
412 $arRes['CONFIG']['COEFFICIENT'] = ($arRes['CONFIG']['COEFFICIENT'] ?? 1) * $voteWeight;
413 }
414 if ($arRes['EXCEPTION_METHOD'] <> '')
415 {
416 if (method_exists($arRes['CLASS'], $arRes['EXCEPTION_METHOD']))
417 {
418 $exceptionText = call_user_func([$arRes['CLASS'], $arRes['EXCEPTION_METHOD']]);
419 if ($exceptionText === false)
420 {
421 if (method_exists($arRes['CLASS'], $arRes['CALC_METHOD']))
422 {
423 $result = call_user_func([$arRes['CLASS'], $arRes['CALC_METHOD']], $arRes);
424 }
425 }
426 }
427 }
428 else
429 {
430 if (method_exists($arRes['CLASS'], $arRes['CALC_METHOD']))
431 {
432 $result = call_user_func([$arRes['CLASS'], $arRes['CALC_METHOD']], $arRes);
433 }
434 }
435 }
436 }
437
439
440 return "CRatings::Calculate($ID);";
441 }
442
443 // queries modules and get all the available objects
444 public static function GetRatingObjects()
445 {
446 $arObjects = [];
447
448 foreach (GetModuleEvents("main", "OnGetRatingsObjects", true) as $arEvent)
449 {
450 $arConfig = ExecuteModuleEventEx($arEvent);
451 foreach ($arConfig as $OBJ_TYPE)
452 {
453 if (!in_array($OBJ_TYPE, $arObjects))
454 {
455 $arObjects[] = $OBJ_TYPE;
456 }
457 }
458 }
459 return $arObjects;
460 }
461
462 // queries modules and get all the available entity types
463 public static function GetRatingEntityTypes($objectType = null)
464 {
465 $arEntityTypes = [];
466
467 foreach (GetModuleEvents("main", "OnGetRatingsConfigs", true) as $arEvent)
468 {
469 $arConfig = ExecuteModuleEventEx($arEvent);
470 if (is_null($objectType))
471 {
472 foreach ($arConfig as $OBJ_TYPE => $OBJ_VALUE)
473 {
474 foreach ($OBJ_VALUE['VOTE'] as $VOTE_VALUE)
475 {
476 $EntityTypeId = $VOTE_VALUE['MODULE_ID'] . '_' . $VOTE_VALUE['ID'];
477 if (!in_array($arEntityTypes[$OBJ_TYPE], $EntityTypeId))
478 {
479 $arEntityTypes[$OBJ_TYPE][] = $EntityTypeId;
480 }
481 }
482 }
483 }
484 else
485 {
486 foreach ($arConfig[$objectType]['VOTE'] as $VOTE_VALUE)
487 {
488 $EntityTypeId = $VOTE_VALUE['MODULE_ID'] . '_' . $VOTE_VALUE['ID'];
489 $arEntityTypes[$EntityTypeId] = $EntityTypeId;
490 }
491 }
492 }
493
494 return $arEntityTypes;
495 }
496
497 // queries modules and assemble an array of settings
498 public static function GetRatingConfigs($objectType = null, $withRatingType = true)
499 {
500 $arConfigs = [];
501
502 foreach (GetModuleEvents("main", "OnGetRatingsConfigs", true) as $arEvent)
503 {
504 $arConfig = ExecuteModuleEventEx($arEvent);
505 if (is_null($objectType))
506 {
507 foreach ($arConfig["COMPONENT"] as $OBJ_TYPE => $TYPE_VALUE)
508 {
509 foreach ($TYPE_VALUE as $RAT_TYPE => $RAT_VALUE)
510 {
511 foreach ($RAT_VALUE as $VALUE)
512 {
513 if ($withRatingType)
514 {
515 $arConfigs[$OBJ_TYPE][$arConfig['MODULE_ID']][$RAT_TYPE][$arConfig['MODULE_ID'] . "_" . $RAT_TYPE . "_" . $VALUE['ID']] = $VALUE;
516 }
517 else
518 {
519 $arConfigs[$OBJ_TYPE][$arConfig['MODULE_ID']][$arConfig['MODULE_ID'] . "_" . $RAT_TYPE . "_" . $VALUE['ID']] = $VALUE;
520 }
521 }
522 }
523 }
524 }
525 else
526 {
527 foreach ($arConfig["COMPONENT"][$objectType] as $RAT_TYPE => $RAT_VALUE)
528 {
529 $arConfigs[$arConfig['MODULE_ID']]['MODULE_ID'] = $arConfig['MODULE_ID'];
530 $arConfigs[$arConfig['MODULE_ID']]['MODULE_NAME'] = $arConfig['MODULE_NAME'];
531 foreach ($RAT_VALUE as $VALUE)
532 {
533 if ($withRatingType)
534 {
535 $arConfigs[$arConfig['MODULE_ID']][$RAT_TYPE][$arConfig['MODULE_ID'] . "_" . $RAT_TYPE . "_" . $VALUE['ID']] = $VALUE;
536 }
537 else
538 {
539 $arConfigs[$arConfig['MODULE_ID']][$arConfig['MODULE_ID'] . "_" . $RAT_TYPE . "_" . $VALUE['ID']] = $VALUE;
540 }
541 }
542 }
543 }
544 }
545
546 return $arConfigs;
547 }
548
549 public static function GetRatingVoteResult($entityTypeId, $entityId, $user_id = 0)
550 {
551 global $USER;
552
553 $arResult = [];
554 $user_id = (int)$user_id;
555
556 if ($user_id == 0)
557 {
558 if (!($USER instanceof CUser))
559 {
560 return $arResult;
561 }
562 $user_id = $USER->GetID();
563 }
564
565 if (is_array($entityId))
566 {
567 foreach ($entityId as $currentEntityId)
568 {
569 $arResult[$currentEntityId] = self::GetRatingVoteResultCache($entityTypeId, $currentEntityId, $user_id);
570 }
571 }
572 else
573 {
574 $arResult = self::GetRatingVoteResultCache($entityTypeId, $entityId, $user_id);
575 }
576
577 return $arResult;
578 }
579
580 public static function GetRatingVoteResultCache($entityTypeId, $entityId, $user_id = 0)
581 {
582 global $DB, $CACHE_MANAGER;
583
584 $arResult = [];
585 $entityId = (int)$entityId;
586 $user_id = (int)$user_id;
587
588 if ($entityTypeId == '' || $entityId <= 0)
589 {
590 return $arResult;
591 }
592
593 if ($user_id == 0)
594 {
595 $user_id = $GLOBALS["USER"]->GetID();
596 }
597
598 $bucket_size = (int)CACHED_b_rating_bucket_size;
599 if ($bucket_size <= 0)
600 {
601 $bucket_size = 100;
602 }
603
604 $bucket = (int)($entityId / $bucket_size);
605 if ($CACHE_MANAGER->Read(CACHED_b_rating_vote, $cache_id = "b_rvg_" . $entityTypeId . $bucket, "b_rating_voting"))
606 {
607 $arResult = $CACHE_MANAGER->Get($cache_id);
608 }
609 else
610 {
611 $total = [];
612
613 $sql_str = "SELECT
614 RVG.ID,
615 RVG.ENTITY_ID,
616 RVG.TOTAL_VALUE,
617 RVG.TOTAL_VOTES,
618 RVG.TOTAL_POSITIVE_VOTES,
619 RVG.TOTAL_NEGATIVE_VOTES
620 FROM
621 b_rating_voting RVG
622 WHERE
623 RVG.ENTITY_TYPE_ID = '" . $DB->ForSql($entityTypeId) . "'
624 and RVG.ENTITY_ID between " . ($bucket * $bucket_size) . " AND " . (($bucket + 1) * $bucket_size - 1) . "
625 and RVG.ACTIVE = 'Y'";
626 $res = $DB->Query($sql_str);
627 while ($row = $res->Fetch())
628 {
629 $arResult[$row['ENTITY_ID']] = [
630 'USER_VOTE' => 0,
631 'USER_REACTION' => false,
632 'USER_HAS_VOTED' => 'N',
633 'USER_VOTE_LIST' => [],
634 'USER_REACTION_LIST' => [],
635 'TOTAL_VALUE' => $row['TOTAL_VALUE'],
636 'TOTAL_VOTES' => (int)$row['TOTAL_VOTES'],
637 'TOTAL_POSITIVE_VOTES' => (int)$row['TOTAL_POSITIVE_VOTES'],
638 'TOTAL_NEGATIVE_VOTES' => (int)$row['TOTAL_NEGATIVE_VOTES'],
639 'REACTIONS_LIST' => [
640 self::REACTION_DEFAULT => (int)$row['TOTAL_POSITIVE_VOTES'],
641 ],
642 ];
643
644 if (!isset($total[$row['ENTITY_ID']]))
645 {
646 $total[$row['ENTITY_ID']] = (int)$row['TOTAL_POSITIVE_VOTES'];
647 }
648 }
649
650 $count = [];
651 $foundDefault = [];
652 $entityIdList = [];
653
654 $sql_str = "SELECT
655 RVGR.ENTITY_ID,
656 RVGR.REACTION,
657 RVGR.TOTAL_VOTES
658 FROM
659 b_rating_voting_reaction RVGR
660 WHERE
661 RVGR.ENTITY_TYPE_ID = '" . $DB->ForSql($entityTypeId) . "'
662 and RVGR.ENTITY_ID between " . ($bucket * $bucket_size) . " AND " . (($bucket + 1) * $bucket_size - 1);
663 $res = $DB->Query($sql_str);
664 while ($row = $res->Fetch())
665 {
666 if (!in_array($row['ENTITY_ID'], $entityIdList))
667 {
668 $entityIdList[] = $row['ENTITY_ID'];
669 }
670
671 $arResult[$row['ENTITY_ID']]['REACTIONS_LIST'][$row['REACTION']] = (int)$row['TOTAL_VOTES'];
672
673 if (!isset($count[$row['ENTITY_ID']]))
674 {
675 $count[$row['ENTITY_ID']] = 0;
676 }
677 $count[$row['ENTITY_ID']] += ((int)$row['TOTAL_VOTES'] >= 0 ? (int)$row['TOTAL_VOTES'] : 0);
678
679 if (
680 !isset($foundDefault[$row['ENTITY_ID']])
681 && $row['REACTION'] == self::REACTION_DEFAULT
682 )
683 {
684 $foundDefault[$row['ENTITY_ID']] = true;
685 }
686 }
687
688 foreach ($entityIdList as $eId)
689 {
690 if (
691 !isset($foundDefault[$eId])
692 && isset($count[$eId])
693 && isset($total[$eId])
694 && $count[$eId] >= $total[$eId]
695 )
696 {
697 $arResult[$eId]['REACTIONS_LIST'][self::REACTION_DEFAULT] = 0;
698 }
699 }
700
701 $sql = "SELECT RVG.ENTITY_ID, RVG.USER_ID, RVG.VALUE, RVG.REACTION
702 FROM b_rating_vote RVG
703 WHERE RVG.ENTITY_TYPE_ID = '" . $DB->ForSql($entityTypeId) . "'
704 and RVG.ENTITY_ID between " . ($bucket * $bucket_size) . " AND " . (($bucket + 1) * $bucket_size - 1);
705 $res = $DB->Query($sql);
706 while ($row = $res->Fetch())
707 {
708 $arResult[$row['ENTITY_ID']]['USER_VOTE_LIST'][$row['USER_ID']] = $row['VALUE'];
709 $arResult[$row['ENTITY_ID']]['USER_REACTION_LIST'][$row['USER_ID']] = (!empty($row['REACTION']) ? $row['REACTION'] : self::REACTION_DEFAULT);
710 }
711
712 $CACHE_MANAGER->Set($cache_id, $arResult);
713 }
714
715 if (isset($arResult[$entityId]['USER_VOTE_LIST'][$user_id]))
716 {
717 $arResult[$entityId]['USER_VOTE'] = $arResult[$entityId]['USER_VOTE_LIST'][$user_id];
718 $arResult[$entityId]['USER_REACTION'] = (
719 !empty($arResult[$entityId]['USER_REACTION_LIST'][$user_id])
720 ? $arResult[$entityId]['USER_REACTION_LIST'][$user_id]
721 : self::REACTION_DEFAULT
722 );
723 $arResult[$entityId]['USER_HAS_VOTED'] = 'Y';
724 }
725
726 return $arResult[$entityId] ?? [];
727 }
728
729 public static function GetRatingResult($ID, $entityId)
730 {
731 global $DB;
732
733 $ID = (int)$ID;
734
735 static $cacheRatingResult = [];
736 if (!array_key_exists($ID, $cacheRatingResult))
737 {
738 $cacheRatingResult[$ID] = [];
739 }
740
741 $arResult = [];
742 $arToSelect = [];
743 if (is_array($entityId))
744 {
745 foreach ($entityId as $value)
746 {
747 $value = (int)$value;
748 if ($value > 0)
749 {
750 if (array_key_exists($value, $cacheRatingResult[$ID]))
751 {
752 $arResult[$value] = $cacheRatingResult[$ID][$value];
753 }
754 else
755 {
756 $arResult[$value] = $cacheRatingResult[$ID][$value] = [];
757 $arToSelect[$value] = $value;
758 }
759 }
760 }
761 }
762 else
763 {
764 $value = (int)$entityId;
765 if ($value > 0)
766 {
767 if (isset($cacheRatingResult[$ID][$value]))
768 {
769 $arResult[$value] = $cacheRatingResult[$ID][$value];
770 }
771 else
772 {
773 $arResult[$value] = $cacheRatingResult[$ID][$value] = [];
774 $arToSelect[$value] = $value;
775 }
776 }
777 }
778
779 if (!empty($arToSelect))
780 {
781 $strSql = "
782 SELECT ENTITY_TYPE_ID, ENTITY_ID, PREVIOUS_VALUE, CURRENT_VALUE, PREVIOUS_POSITION, CURRENT_POSITION
783 FROM b_rating_results
784 WHERE RATING_ID = '" . $ID . "' AND ENTITY_ID IN (" . implode(',', $arToSelect) . ")
785 ";
786 $res = $DB->Query($strSql);
787 while ($arRes = $res->Fetch())
788 {
789 $arRes['PROGRESS_VALUE'] = $arRes['CURRENT_VALUE'] - $arRes['PREVIOUS_VALUE'];
790 $arRes['PROGRESS_VALUE'] = round($arRes['PROGRESS_VALUE'], 2);
791 $arRes['PROGRESS_VALUE'] = $arRes['PROGRESS_VALUE'] > 0 ? "+" . $arRes['PROGRESS_VALUE'] : $arRes['PROGRESS_VALUE'];
792 $arRes['ROUND_CURRENT_VALUE'] = round($arRes['CURRENT_VALUE']) == 0 ? 0 : round($arRes['CURRENT_VALUE']);
793 $arRes['ROUND_PREVIOUS_VALUE'] = round($arRes['PREVIOUS_VALUE']) == 0 ? 0 : round($arRes['CURRENT_VALUE']);
794 $arRes['CURRENT_POSITION'] = $arRes['CURRENT_POSITION'] > 0 ? $arRes['CURRENT_POSITION'] : GetMessage('RATING_NO_POSITION');
795 if ($arRes['PREVIOUS_POSITION'] > 0)
796 {
797 $arRes['PROGRESS_POSITION'] = $arRes['PREVIOUS_POSITION'] - $arRes['CURRENT_POSITION'];
798 $arRes['PROGRESS_POSITION'] = $arRes['PROGRESS_POSITION'] > 0 ? "+" . $arRes['PROGRESS_POSITION'] : $arRes['PROGRESS_POSITION'];
799 }
800 else
801 {
802 $arRes['PREVIOUS_POSITION'] = 0;
803 $arRes['PROGRESS_POSITION'] = 0;
804 }
805
806 $arResult[$arRes["ENTITY_ID"]] = $cacheRatingResult[$ID][$arRes["ENTITY_ID"]] = $arRes;
807 }
808 }
809 if (!is_array($entityId) && !empty($arResult))
810 {
811 $arResult = array_pop($arResult);
812 }
813
814 return $arResult;
815 }
816
817 public static function AddRatingVote($arParam)
818 {
819 global $DB, $CACHE_MANAGER;
821 $helper = $connection->getSqlHelper();
822
823 if ($arParam['ENTITY_TYPE_ID'] === 'USER' && isset(\Bitrix\Main\Application::getInstance()->getSession()['RATING_VOTE_COUNT']))
824 {
825 if (\Bitrix\Main\Application::getInstance()->getSession()['RATING_VOTE_COUNT'] >= \Bitrix\Main\Application::getInstance()->getSession()['RATING_USER_VOTE_COUNT'])
826 {
827 return false;
828 }
829
830 \Bitrix\Main\Application::getInstance()->getSession()['RATING_VOTE_COUNT']++;
831 }
832
833 $arParam['ENTITY_TYPE_ID'] = mb_substr($arParam['ENTITY_TYPE_ID'], 0, 50);
834 $arParam['REACTION'] = ($arParam['REACTION'] <> '' ? $arParam['REACTION'] : self::REACTION_DEFAULT);
835
837
838 $votePlus = $arParam['VALUE'] >= 0 ? true : false;
839
840 $ratingId = CRatings::GetAuthorityRating();
841
842 $arRatingUserProp = CRatings::GetRatingUserProp($ratingId, $arParam['USER_ID']);
843 $voteUserWeight = $arRatingUserProp['VOTE_WEIGHT'];
844
845 $sRatingWeightType = COption::GetOptionString("main", "rating_weight_type", "auto");
846 if ($sRatingWeightType === 'auto')
847 {
848 if ($arParam['ENTITY_TYPE_ID'] === 'USER')
849 {
850 $sRatingAuthrorityWeight = COption::GetOptionString("main", "rating_authority_weight_formula", 'Y');
851 if ($sRatingAuthrorityWeight === 'Y')
852 {
853 $communitySize = COption::GetOptionString("main", "rating_community_size", 1);
854 $communityAuthority = COption::GetOptionString("main", "rating_community_authority", 1);
855 $voteWeight = COption::GetOptionString("main", "rating_vote_weight", 1);
856 $arParam['VALUE'] = $arParam['VALUE'] * ($communitySize * ($voteUserWeight / $voteWeight) / $communityAuthority);
857 }
858 }
859 else
860 {
861 $arParam['VALUE'] = $arParam['VALUE'] * $voteUserWeight;
862 }
863 }
864 else
865 {
866 $arParam['VALUE'] = $arParam['VALUE'] * $voteUserWeight;
867 }
868 $arFields = [
869 'ACTIVE' => "'Y'",
870 'TOTAL_VOTES' => "TOTAL_VOTES+1",
871 'TOTAL_VALUE' => "TOTAL_VALUE" . ($votePlus ? '+' : '') . (float)$arParam['VALUE'],
872 'LAST_CALCULATED' => $DB->GetNowFunction(),
873 ];
874 $arFields[($votePlus ? 'TOTAL_POSITIVE_VOTES' : 'TOTAL_NEGATIVE_VOTES')] = ($votePlus ? 'TOTAL_POSITIVE_VOTES+1' : 'TOTAL_NEGATIVE_VOTES+1');
875
876 // GetOwnerDocument
877 $arParam['OWNER_ID'] = 0;
878 foreach (GetModuleEvents("main", "OnGetRatingContentOwner", true) as $arEvent)
879 {
880 $result = ExecuteModuleEventEx($arEvent, [$arParam]);
881 if ($result !== false)
882 {
883 $arParam['OWNER_ID'] = (int)$result;
884 }
885 }
886
887 $rowAffected = $DB->Update("b_rating_voting", $arFields, "WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
888 if ($rowAffected > 0)
889 {
890 $rsRV = $DB->Query("SELECT ID, TOTAL_POSITIVE_VOTES FROM b_rating_voting WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
891 $arRV = $rsRV->Fetch();
892 $arParam['RATING_VOTING_ID'] = $arRV['ID'];
893 $arParam['TOTAL_POSITIVE_VOTES'] = $arRV['TOTAL_POSITIVE_VOTES'];
894 $arParam['REACTIONS_LIST'] = [
895 self::REACTION_DEFAULT => (int)$arParam['TOTAL_POSITIVE_VOTES'],
896 ];
897
898 if ($votePlus)
899 {
900 $rsRVR = $DB->Query("SELECT TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
901 if (!($arRVR = $rsRVR->fetch())) // reactions not initialized
902 {
903 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
904 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
905 'ENTITY_ID' => $arParam['ENTITY_ID'],
906 'REACTION' => self::REACTION_DEFAULT,
907 'TOTAL_VOTES' => $arRV['TOTAL_POSITIVE_VOTES'],
908 ], [
909 'TOTAL_VOTES' => $arRV['TOTAL_POSITIVE_VOTES'],
910 ]);
911 if ($merge[0])
912 {
913 $DB->query($merge[0]);
914 }
915 }
916
917 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
918 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
919 'ENTITY_ID' => $arParam['ENTITY_ID'],
920 'REACTION' => $arParam['REACTION'],
921 'TOTAL_VOTES' => 1,
922 ], [
923 'TOTAL_VOTES' => new \Bitrix\Main\DB\SqlExpression('b_rating_voting_reaction.TOTAL_VOTES + 1'),
924 ]);
925 if ($merge[0])
926 {
927 $DB->query($merge[0]);
928 }
929 }
930 }
931 else
932 {
933 $arFields = [
934 "ENTITY_TYPE_ID" => "'" . $DB->ForSql($arParam["ENTITY_TYPE_ID"]) . "'",
935 "ENTITY_ID" => (int)$arParam['ENTITY_ID'],
936 "OWNER_ID" => (int)$arParam['OWNER_ID'],
937 "ACTIVE" => "'Y'",
938 "CREATED" => $DB->GetNowFunction(),
939 "LAST_CALCULATED" => $DB->GetNowFunction(),
940 "TOTAL_VOTES" => 1,
941 "TOTAL_VALUE" => (float)$arParam['VALUE'],
942 "TOTAL_POSITIVE_VOTES" => ($votePlus ? 1 : 0),
943 "TOTAL_NEGATIVE_VOTES" => ($votePlus ? 0 : 1),
944 ];
945 $arParam['RATING_VOTING_ID'] = $DB->Insert("b_rating_voting", $arFields);
946 $arParam['TOTAL_POSITIVE_VOTES'] = ($votePlus ? 1 : 0);
947
948 $arParam['REACTIONS_LIST'] = [
949 self::REACTION_DEFAULT => (int)$arParam['TOTAL_POSITIVE_VOTES'],
950 ];
951
952 if ($votePlus)
953 {
954 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
955 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
956 'ENTITY_ID' => $arParam['ENTITY_ID'],
957 'REACTION' => $arParam['REACTION'],
958 'TOTAL_VOTES' => 1,
959 ], [
960 'TOTAL_VOTES' => 1,
961 ]);
962 if ($merge[0])
963 {
964 $DB->query($merge[0]);
965 }
966 }
967 }
968
969 $rsRVR = $DB->Query("SELECT REACTION, TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
970 while ($arRVR = $rsRVR->fetch())
971 {
972 $arParam['REACTIONS_LIST'][$arRVR['REACTION']] = $arRVR['TOTAL_VOTES'];
973 }
974
975 $arFields = [
976 "RATING_VOTING_ID" => (int)$arParam['RATING_VOTING_ID'],
977 "ENTITY_TYPE_ID" => "'" . $DB->ForSql($arParam["ENTITY_TYPE_ID"]) . "'",
978 "ENTITY_ID" => (int)$arParam['ENTITY_ID'],
979 "VALUE" => (float)$arParam['VALUE'],
980 "ACTIVE" => "'Y'",
981 "CREATED" => $DB->GetNowFunction(),
982 "USER_ID" => (int)$arParam['USER_ID'],
983 "USER_IP" => "'" . $DB->ForSql($arParam["USER_IP"]) . "'",
984 "OWNER_ID" => (int)$arParam['OWNER_ID'],
985 "REACTION" => "'" . $DB->ForSql($arParam["REACTION"]) . "'",
986 ];
987 $ID = $DB->Insert("b_rating_vote", $arFields);
988
989 foreach (GetModuleEvents("main", "OnAddRatingVote", true) as $arEvent)
990 {
991 ExecuteModuleEventEx($arEvent, [(int)$ID, $arParam]);
992 }
993
994 $userData = static::getUserData((int)$arParam['USER_ID'], (float)$arParam['VALUE']);
995 if (CModule::IncludeModule('pull'))
996 {
997 CPullStack::AddShared([
998 'module_id' => 'main',
999 'command' => 'rating_vote',
1000 'params' => [
1001 "TYPE" => "ADD",
1002 "USER_ID" => (int)$arParam['USER_ID'],
1003 "ENTITY_TYPE_ID" => $arParam["ENTITY_TYPE_ID"],
1004 "ENTITY_ID" => (int)$arParam['ENTITY_ID'],
1005 "TOTAL_POSITIVE_VOTES" => $arParam['TOTAL_POSITIVE_VOTES'],
1006 "RESULT" => $votePlus ? 'PLUS' : 'MINUS',
1007 "USER_DATA" => $userData,
1008 "REACTION" => $arParam['REACTION'],
1009 "REACTIONS_LIST" => $arParam['REACTIONS_LIST'],
1010 ],
1011 ]);
1012 }
1013
1014 if (CACHED_b_rating_vote !== false)
1015 {
1016 $bucket_size = (int)CACHED_b_rating_bucket_size;
1017 if ($bucket_size <= 0)
1018 {
1019 $bucket_size = 100;
1020 }
1021 $bucket = (int)((int)$arParam['ENTITY_ID'] / $bucket_size);
1022 $CACHE_MANAGER->Clean("b_rvg_" . $DB->ForSql($arParam["ENTITY_TYPE_ID"]) . $bucket, "b_rating_voting");
1023 }
1024
1025 return $userData;
1026 }
1027
1028 public static function ChangeRatingVote($arParam)
1029 {
1030 global $DB, $CACHE_MANAGER;
1032 $helper = $connection->getSqlHelper();
1033
1034 $arParam['ENTITY_TYPE_ID'] = mb_substr($arParam['ENTITY_TYPE_ID'], 0, 50);
1035 $arParam['REACTION'] = ($arParam['REACTION'] <> '' ? $arParam['REACTION'] : self::REACTION_DEFAULT);
1036 $userData = static::getUserData((int)$arParam['USER_ID'], (float)$arParam['VALUE']);
1037
1038 $sqlStr = "
1039 SELECT
1040 RVG.ID,
1041 RV.ID AS VOTE_ID,
1042 RV.REACTION AS REACTION,
1043 RV.VALUE AS VOTE_VALUE,
1044 RVG.TOTAL_POSITIVE_VOTES
1045 FROM
1046 b_rating_voting RVG,
1047 b_rating_vote RV
1048 WHERE
1049 RVG.ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "'
1050 and RVG.ENTITY_ID = " . (int)$arParam['ENTITY_ID'] . "
1051 and RVG.ID = RV.RATING_VOTING_ID
1052 and RV.USER_ID = " . (int)$arParam['USER_ID'];
1053
1054 $res = $DB->Query($sqlStr);
1055 if ($arVote = $res->Fetch())
1056 {
1057 // GetOwnerDocument
1058 $arParam['OWNER_ID'] = 0;
1059 foreach (GetModuleEvents("main", "OnGetRatingContentOwner", true) as $arEvent)
1060 {
1061 $result = ExecuteModuleEventEx($arEvent, [$arParam]);
1062 if ($result !== false)
1063 {
1064 $arParam['OWNER_ID'] = (int)$result;
1065 }
1066 }
1067
1068 $votePlus = $arVote['VOTE_VALUE'] >= 0 ? true : false;
1069 $arVote['REACTION_OLD'] = ($arVote['REACTION'] <> '' ? $arVote['REACTION'] : self::REACTION_DEFAULT);
1070
1071 if (!$votePlus)
1072 {
1073 return false;
1074 }
1075
1076 $rsRV = $DB->Query("SELECT ID, TOTAL_POSITIVE_VOTES FROM b_rating_voting WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
1077 if ($arRV = $rsRV->Fetch())
1078 {
1079 $arParam['RATING_VOTING_ID'] = $arRV['ID'];
1080 $arParam['TOTAL_POSITIVE_VOTES'] = $arRV['TOTAL_POSITIVE_VOTES'];
1081 $arParam['REACTIONS_LIST'] = [
1082 self::REACTION_DEFAULT => (int)$arParam['TOTAL_POSITIVE_VOTES'],
1083 ];
1084 }
1085 else
1086 {
1087 return false;
1088 }
1089
1090 $rsRVR = $DB->Query("SELECT TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
1091 if (!($arRVR = $rsRVR->fetch())) // reactions not initialized
1092 {
1093 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
1094 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
1095 'ENTITY_ID' => $arParam['ENTITY_ID'],
1096 'REACTION' => self::REACTION_DEFAULT,
1097 'TOTAL_VOTES' => $arRV['TOTAL_POSITIVE_VOTES'],
1098 ], [
1099 'TOTAL_VOTES' => $arRV['TOTAL_POSITIVE_VOTES'],
1100 ]);
1101 if ($merge[0])
1102 {
1103 $DB->query($merge[0]);
1104 }
1105 }
1106
1107 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
1108 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
1109 'ENTITY_ID' => $arParam['ENTITY_ID'],
1110 'REACTION' => $arParam['REACTION'],
1111 'TOTAL_VOTES' => 1,
1112 ], [
1113 'TOTAL_VOTES' => new \Bitrix\Main\DB\SqlExpression('b_rating_voting_reaction.TOTAL_VOTES + 1'),
1114 ]);
1115 if ($merge[0])
1116 {
1117 $DB->query($merge[0]);
1118 }
1119
1120 if (!empty($arVote['REACTION_OLD']))
1121 {
1122 $DB->Query("UPDATE b_rating_voting_reaction SET TOTAL_VOTES = TOTAL_VOTES - 1 WHERE ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID = '" . (int)$arParam['ENTITY_ID'] . "' AND REACTION = '" . $DB->ForSql($arVote['REACTION_OLD']) . "'");
1123 }
1124
1125 $rsRVR = $DB->Query("SELECT REACTION, TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
1126 while ($arRVR = $rsRVR->fetch())
1127 {
1128 $arParam['REACTIONS_LIST'][$arRVR['REACTION']] = $arRVR['TOTAL_VOTES'];
1129 }
1130
1131 $arFields = [
1132 "CREATED" => $DB->GetNowFunction(),
1133 "USER_IP" => "'" . $DB->ForSql($arParam["USER_IP"]) . "'",
1134 "REACTION" => "'" . $DB->ForSql($arParam["REACTION"]) . "'",
1135 ];
1136
1137 $ID = $DB->Update("b_rating_vote", $arFields, "WHERE RATING_VOTING_ID=" . (int)$arParam['RATING_VOTING_ID'] . " AND USER_ID=" . (int)$arParam['USER_ID']);
1138 if (!$ID)
1139 {
1140 return false;
1141 }
1142
1143 foreach (GetModuleEvents("main", "OnChangeRatingVote", true) as $arEvent)
1144 {
1145 ExecuteModuleEventEx($arEvent, [(int)$ID, $arParam]);
1146 }
1147
1148 if (CModule::IncludeModule('pull'))
1149 {
1150 CPullStack::AddShared([
1151 'module_id' => 'main',
1152 'command' => 'rating_vote',
1153 'params' => [
1154 "TYPE" => "CHANGE",
1155 "USER_ID" => (int)$arParam['USER_ID'],
1156 "ENTITY_TYPE_ID" => $arParam["ENTITY_TYPE_ID"],
1157 "ENTITY_ID" => (int)$arParam['ENTITY_ID'],
1158 "TOTAL_POSITIVE_VOTES" => $arParam['TOTAL_POSITIVE_VOTES'],
1159 "RESULT" => 'CHANGE',
1160 "USER_DATA" => $userData,
1161 "REACTION" => $arParam['REACTION'],
1162 "REACTION_OLD" => $arVote['REACTION'],
1163 "REACTIONS_LIST" => $arParam['REACTIONS_LIST'],
1164 ],
1165 ]);
1166 }
1167
1168 if (CACHED_b_rating_vote !== false)
1169 {
1170 $bucket_size = (int)CACHED_b_rating_bucket_size;
1171 if ($bucket_size <= 0)
1172 {
1173 $bucket_size = 100;
1174 }
1175 $bucket = (int)((int)$arParam['ENTITY_ID'] / $bucket_size);
1176 $CACHE_MANAGER->Clean("b_rvg_" . $DB->ForSql($arParam["ENTITY_TYPE_ID"]) . $bucket, "b_rating_voting");
1177 }
1178 }
1179
1180 return $userData;
1181 }
1182
1183 public static function CancelRatingVote($arParam)
1184 {
1185 global $DB, $CACHE_MANAGER;
1187 $helper = $connection->getSqlHelper();
1188
1189 $sqlStr = "
1190 SELECT
1191 RVG.ID,
1192 RV.ID AS VOTE_ID,
1193 RV.REACTION AS REACTION,
1194 RV.VALUE AS VOTE_VALUE,
1195 RVG.TOTAL_POSITIVE_VOTES
1196 FROM
1197 b_rating_voting RVG,
1198 b_rating_vote RV
1199 WHERE
1200 RVG.ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "'
1201 and RVG.ENTITY_ID = " . (int)$arParam['ENTITY_ID'] . "
1202 and RVG.ID = RV.RATING_VOTING_ID
1203 and RV.USER_ID = " . (int)$arParam['USER_ID'];
1204
1205 $res = $DB->Query($sqlStr);
1206 if ($arVote = $res->Fetch())
1207 {
1208 $votePlus = $arVote['VOTE_VALUE'] >= 0 ? true : false;
1209 $arVote['REACTION'] = ($arVote['REACTION'] <> '' ? $arVote['REACTION'] : self::REACTION_DEFAULT);
1210
1211 if ($votePlus)
1212 {
1213 $rsRVR = $DB->Query("SELECT TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
1214 if (!($arRVR = $rsRVR->fetch())) // reactions not initialized
1215 {
1216 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
1217 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
1218 'ENTITY_ID' => $arParam['ENTITY_ID'],
1219 'REACTION' => self::REACTION_DEFAULT,
1220 'TOTAL_VOTES' => $arVote['TOTAL_POSITIVE_VOTES'],
1221 ], [
1222 'TOTAL_VOTES' => $arVote['TOTAL_POSITIVE_VOTES'],
1223 ]);
1224 if ($merge[0])
1225 {
1226 $DB->query($merge[0]);
1227 }
1228 }
1229 }
1230
1231 $arFields = [
1232 'TOTAL_VOTES' => "TOTAL_VOTES-1",
1233 'TOTAL_VALUE' => "TOTAL_VALUE" . ($votePlus ? '-' . (float)$arVote['VOTE_VALUE'] : '+' . (float)(-1 * $arVote['VOTE_VALUE'])),
1234 'LAST_CALCULATED' => $DB->GetNowFunction(),
1235 ];
1236 $arFields[($votePlus ? 'TOTAL_POSITIVE_VOTES' : 'TOTAL_NEGATIVE_VOTES')] = ($votePlus ? 'TOTAL_POSITIVE_VOTES-1' : 'TOTAL_NEGATIVE_VOTES-1');
1237 $DB->Update("b_rating_voting", $arFields, "WHERE ID=" . (int)$arVote['ID']);
1238 if ($votePlus)
1239 {
1240 $merge = $helper->prepareMerge('b_rating_voting_reaction', ['ENTITY_TYPE_ID', 'ENTITY_ID', 'REACTION'], [
1241 'ENTITY_TYPE_ID' => $arParam['ENTITY_TYPE_ID'],
1242 'ENTITY_ID' => $arParam['ENTITY_ID'],
1243 'REACTION' => $arVote['REACTION'],
1244 'TOTAL_VOTES' => 0,
1245 ], [
1246 'TOTAL_VOTES' => new \Bitrix\Main\DB\SqlExpression('b_rating_voting_reaction.TOTAL_VOTES - 1'),
1247 ]);
1248 if ($merge[0])
1249 {
1250 $DB->query($merge[0]);
1251 }
1252 }
1253 $DB->Query("DELETE FROM b_rating_vote WHERE ID=" . (int)$arVote['VOTE_ID']);
1254
1255 $arParam['REACTIONS_LIST'] = [];
1256 $rsRVR = $DB->Query("SELECT REACTION, TOTAL_VOTES FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "' AND ENTITY_ID='" . (int)$arParam['ENTITY_ID'] . "'");
1257 while ($arRVR = $rsRVR->fetch())
1258 {
1259 $arParam['REACTIONS_LIST'][$arRVR['REACTION']] = $arRVR['TOTAL_VOTES'];
1260 }
1261
1262 foreach (GetModuleEvents("main", "OnCancelRatingVote", true) as $arEvent)
1263 {
1264 ExecuteModuleEventEx($arEvent, [(int)$arVote['VOTE_ID'], $arParam]);
1265 }
1266
1267 $userData = static::getUserData((int)$arParam['USER_ID'], (float)$arVote['VOTE_VALUE']);
1268
1269 if (CModule::IncludeModule('pull'))
1270 {
1271 CPullStack::AddShared([
1272 'module_id' => 'main',
1273 'command' => 'rating_vote',
1274 'params' => [
1275 "TYPE" => "CANCEL",
1276 "USER_ID" => (int)$arParam['USER_ID'],
1277 "ENTITY_TYPE_ID" => $arParam["ENTITY_TYPE_ID"],
1278 "ENTITY_ID" => (int)$arParam['ENTITY_ID'],
1279 "TOTAL_POSITIVE_VOTES" => (int)($arVote['TOTAL_POSITIVE_VOTES'] + ($votePlus ? -1 : 1)),
1280 "RESULT" => $votePlus ? 'PLUS' : 'MINUS',
1281 "USER_DATA" => $userData,
1282 "REACTION" => $arVote['REACTION'],
1283 "REACTIONS_LIST" => $arParam['REACTIONS_LIST'],
1284 ],
1285 ]);
1286 }
1287
1288 if (CACHED_b_rating_vote !== false)
1289 {
1290 $bucket_size = (int)CACHED_b_rating_bucket_size;
1291 if ($bucket_size <= 0)
1292 {
1293 $bucket_size = 100;
1294 }
1295 $bucket = (int)((int)$arParam['ENTITY_ID'] / $bucket_size);
1296 $CACHE_MANAGER->Clean("b_rvg_" . $DB->ForSql($arParam["ENTITY_TYPE_ID"]) . $bucket, "b_rating_voting");
1297 }
1298
1299 return $userData;
1300 }
1301
1302 return false;
1303 }
1304
1305 public static function UpdateRatingUserBonus($arParam)
1306 {
1307 global $DB;
1308
1309 $arParam['RATING_ID'] = (int)$arParam['RATING_ID'];
1310 $arParam['ENTITY_ID'] = (int)$arParam['ENTITY_ID'];
1311 $arParam['BONUS'] = (float)$arParam['BONUS'];
1312
1313 $arFields = [
1314 'RATING_ID' => $arParam['RATING_ID'],
1315 'ENTITY_ID' => $arParam['ENTITY_ID'],
1316 'BONUS' => $arParam['BONUS'],
1317 ];
1318
1319 if (isset($arParam['VOTE_WEIGHT']))
1320 {
1321 $arFields['VOTE_WEIGHT'] = (float)$arParam['VOTE_WEIGHT'];
1322 }
1323
1324 if (isset($arParam['VOTE_COUNT']))
1325 {
1326 $arFields['VOTE_COUNT'] = (int)$arParam['VOTE_COUNT'];
1327 }
1328
1329 $rows = $DB->Update("b_rating_user", $arFields, "WHERE RATING_ID = " . $arParam['RATING_ID'] . " AND ENTITY_ID = " . $arParam['ENTITY_ID']);
1330 if ($rows == 0)
1331 {
1332 $rsRB = $DB->Query("SELECT * FROM b_rating_user WHERE RATING_ID = " . $arParam['RATING_ID'] . " AND ENTITY_ID = " . $arParam['ENTITY_ID']);
1333 if (!$rsRB->SelectedRowsCount())
1334 {
1335 $DB->Insert("b_rating_user", $arFields);
1336 }
1337 }
1338 if (CACHED_b_rating_vote !== false)
1339 {
1340 global $CACHE_MANAGER;
1341 $bucket_size = (int)CACHED_b_rating_bucket_size;
1342 if ($bucket_size <= 0)
1343 {
1344 $bucket_size = 100;
1345 }
1346
1347 $CACHE_MANAGER->Clean("b_rvu_" . $arParam['RATING_ID'] . (int)($arParam['ENTITY_ID'] / $bucket_size), "b_rating_user");
1348 }
1349 return true;
1350 }
1351
1352 public static function GetRatingUserProp($ratingId, $entityId)
1353 {
1354 global $DB;
1355
1356 $ratingId = (int)$ratingId;
1357
1358 static $cache = [];
1359 if (!array_key_exists($ratingId, $cache))
1360 {
1361 $cache[$ratingId] = [];
1362 }
1363
1364 $arResult = [];
1365 $arToSelect = [];
1366 if (is_array($entityId))
1367 {
1368 foreach ($entityId as $value)
1369 {
1370 $value = (int)$value;
1371 if ($value > 0)
1372 {
1373 if (array_key_exists($value, $cache[$ratingId]))
1374 {
1375 $arResult[$value] = $cache[$ratingId][$value];
1376 }
1377 else
1378 {
1379 $arResult[$value] = $cache[$ratingId][$value] = [];
1380 $arToSelect[$value] = $value;
1381 }
1382 }
1383 }
1384 }
1385 else
1386 {
1387 $value = (int)$entityId;
1388 if ($value > 0)
1389 {
1390 if (isset($cache[$ratingId][$value]))
1391 {
1392 $arResult[$value] = $cache[$ratingId][$value];
1393 }
1394 else
1395 {
1396 $arResult[$value] = $cache[$ratingId][$value] = [];
1397 $arToSelect[$value] = $value;
1398 }
1399 }
1400 }
1401
1402 if (!empty($arToSelect))
1403 {
1404 $strSql = "
1405 SELECT RATING_ID, ENTITY_ID, BONUS, VOTE_WEIGHT, VOTE_COUNT
1406 FROM b_rating_user
1407 WHERE RATING_ID = '" . $ratingId . "' AND ENTITY_ID IN (" . implode(',', $arToSelect) . ")
1408 ";
1409 $res = $DB->Query($strSql);
1410 while ($arRes = $res->Fetch())
1411 {
1412 $arResult[$arRes["ENTITY_ID"]] = $cache[$ratingId][$arRes["ENTITY_ID"]] = $arRes;
1413 }
1414 }
1415
1416 if (!is_array($entityId) && !empty($arResult))
1417 {
1418 $arResult = array_pop($arResult);
1419 }
1420
1421 return $arResult;
1422 }
1423
1424 public static function GetRatingUserPropEx($ratingId, $entityId)
1425 {
1426 global $DB, $CACHE_MANAGER;
1427
1428 $ratingId = (int)$ratingId;
1429 $entityId = (int)$entityId;
1430
1431 $arDefaultResult = [
1432 "RATING_ID" => $ratingId,
1433 "ENTITY_ID" => $entityId,
1434 "BONUS" => 0,
1435 "VOTE_WEIGHT" => 0,
1436 "VOTE_COUNT" => 0,
1437 ];
1438 if ($ratingId <= 0 || $entityId <= 0)
1439 {
1440 return $arDefaultResult;
1441 }
1442
1443 $bucket_size = (int)CACHED_b_rating_bucket_size;
1444 if ($bucket_size <= 0)
1445 {
1446 $bucket_size = 100;
1447 }
1448
1449 $bucket = (int)($entityId / $bucket_size);
1450 $arResult = $CACHE_MANAGER->Read(CACHED_b_rating, $cache_id = "b_rvu_" . $ratingId . $bucket, "b_rating_user");
1451 if ($arResult)
1452 {
1453 $arResult = $CACHE_MANAGER->Get($cache_id);
1454 }
1455 if (!$arResult)
1456 {
1457 $sql_str = "
1458 SELECT RATING_ID, ENTITY_ID, BONUS, VOTE_WEIGHT, VOTE_COUNT
1459 FROM b_rating_user
1460 WHERE RATING_ID = '" . $ratingId . "'
1461 and ENTITY_ID between " . ($bucket * $bucket_size) . " AND " . (($bucket + 1) * $bucket_size - 1) . "
1462 ";
1463 $res = $DB->Query($sql_str);
1464 while ($arRes = $res->Fetch())
1465 {
1466 $arResult[$arRes["ENTITY_ID"]] = $arRes;
1467 }
1468
1469 $CACHE_MANAGER->Set($cache_id, $arResult);
1470 }
1471
1472 return $arResult[$entityId] ?? $arDefaultResult;
1473 }
1474
1475 public static function GetAuthorityRating()
1476 {
1477 global $DB;
1478
1479 $authorityRatingId = COption::GetOptionString("main", "rating_authority_rating", null);
1480 if (is_null($authorityRatingId))
1481 {
1482 $db_res = CRatings::GetList(["ID" => "ASC"], ["ENTITY_ID" => "USER", "AUTHORITY" => "Y"]);
1483 $res = $db_res->Fetch();
1484
1485 $authorityRatingId = (int)$res['ID'];
1486 COption::SetOptionString("main", "rating_authority_rating", $authorityRatingId);
1487 }
1488
1489 return $authorityRatingId;
1490 }
1491
1492 public static function GetWeightList($arSort = [], $arFilter = [])
1493 {
1494 global $DB;
1495
1496 $arSqlSearch = [];
1497 $strSqlSearch = "";
1498
1499 if (is_array($arFilter))
1500 {
1501 foreach ($arFilter as $key => $val)
1502 {
1503 if ((string)$val == '' || $val === "NOT_REF")
1504 {
1505 continue;
1506 }
1507 switch (strtoupper($key))
1508 {
1509 case "ID":
1510 $arSqlSearch[] = GetFilterQuery("RW.ID", $val, "N");
1511 break;
1512 case "RATING_FROM":
1513 $arSqlSearch[] = GetFilterQuery("RW.RATING_FROM", $val, "N");
1514 break;
1515 case "RATING_TO":
1516 $arSqlSearch[] = GetFilterQuery("RW.RATING_TO", $val, "N");
1517 break;
1518 case "WEIGHT":
1519 $arSqlSearch[] = GetFilterQuery("RW.WEIGHT", $val, "N");
1520 break;
1521 case "COUNT":
1522 $arSqlSearch[] = GetFilterQuery("RW.COUNT", $val, "N");
1523 break;
1524 case "MAX":
1525 if (in_array($val, ['Y', 'N']))
1526 {
1527 $arSqlSearch[] = "R.MAX = '" . $val . "'";
1528 }
1529 break;
1530 }
1531 }
1532 }
1533
1534 $sOrder = "";
1535 foreach ($arSort as $key => $val)
1536 {
1537 $ord = (mb_strtoupper($val) <> "ASC" ? "DESC" : "ASC");
1538 switch (mb_strtoupper($key))
1539 {
1540 case "ID":
1541 $sOrder .= ", RW.ID " . $ord;
1542 break;
1543 case "RATING_FROM":
1544 $sOrder .= ", RW.RATING_FROM " . $ord;
1545 break;
1546 case "RATING_TO":
1547 $sOrder .= ", RW.RATING_TO " . $ord;
1548 break;
1549 case "WEIGHT":
1550 $sOrder .= ", RW.WEIGHT " . $ord;
1551 break;
1552 case "COUNT":
1553 $sOrder .= ", RW.COUNT " . $ord;
1554 break;
1555 }
1556 }
1557
1558 if ($sOrder == '')
1559 {
1560 $sOrder = "RW.ID DESC";
1561 }
1562
1563 $strSqlOrder = " ORDER BY " . trim($sOrder, ", ");
1564
1565 $strSqlSearch = GetFilterSqlSearch($arSqlSearch);
1566 $strSql = "
1567 SELECT
1568 RW.ID, RW.RATING_FROM, RW.RATING_TO, RW.WEIGHT, RW.COUNT
1569 FROM
1570 b_rating_weight RW
1571 WHERE
1572 " . $strSqlSearch . "
1573 " . $strSqlOrder;
1574 return $DB->Query($strSql);
1575 }
1576
1577 public static function SetWeight($arConfigs)
1578 {
1579 global $DB;
1580
1581 usort($arConfigs, ['CRatings', '__SortWeight']);
1582 // prepare insert
1583 $arAdd = [];
1584 foreach ($arConfigs as $key => $arConfig)
1585 {
1586 //If the first condition is restricted to the bottom, otherwise we take the previous high value
1587 if ($key == 0)
1588 {
1589 $arConfig['RATING_FROM'] = -1000000;
1590 }
1591 else
1592 {
1593 $arConfig['RATING_FROM'] = (float)$arConfigs[$key - 1]['RATING_TO'] + 0.0001;
1594 }
1595 // If this last condition is restricted to the top
1596 if (!array_key_exists('RATING_TO', $arConfig))
1597 {
1598 $arConfig['RATING_TO'] = 1000000;
1599 }
1600 elseif ($arConfig['RATING_TO'] > 1000000)
1601 {
1602 $arConfig['RATING_TO'] = 1000000;
1603 }
1604
1605 $arAdd[$key]['RATING_FROM'] = (float)$arConfig['RATING_FROM'];
1606 $arAdd[$key]['RATING_TO'] = (float)$arConfig['RATING_TO'];
1607 $arAdd[$key]['WEIGHT'] = (float)$arConfig['WEIGHT'];
1608 $arAdd[$key]['COUNT'] = (int)$arConfig['COUNT'];
1609 $arConfigs[$key] = $arAdd[$key];
1610 }
1611 // insert
1612 $DB->Query("DELETE FROM b_rating_weight");
1613 foreach ($arAdd as $key => $arFields)
1614 {
1615 $DB->Insert("b_rating_weight", $arFields);
1616 }
1617
1618 return true;
1619 }
1620
1621 public static function SetVoteGroup($arGroupId, $type)
1622 {
1623 global $DB, $CACHE_MANAGER;
1624
1625 if (!in_array($type, ['R', 'A']))
1626 {
1627 return false;
1628 }
1629
1630 if (!is_array($arGroupId))
1631 {
1632 return false;
1633 }
1634
1635 $arFields = [];
1636
1637 foreach ($arGroupId as $key => $value)
1638 {
1639 $arField = [];
1640 $arField['GROUP_ID'] = (int)$value;
1641 $arField['TYPE'] = "'" . $type . "'";
1642 $arFields[$key] = $arField;
1643 }
1644
1645 $DB->Query("DELETE FROM b_rating_vote_group WHERE TYPE = '" . $type . "'");
1646 foreach ($arFields as $key => $arField)
1647 {
1648 $DB->Insert("b_rating_vote_group", $arField);
1649 }
1650
1651 $CACHE_MANAGER->Clean("ratings_vg");
1652
1653 return true;
1654 }
1655
1656 public static function GetVoteGroup($type = '')
1657 {
1658 global $DB;
1659
1660 $bAllType = false;
1661 if (!in_array($type, ['R', 'A']))
1662 {
1663 $bAllType = true;
1664 }
1665
1666 $strSql = "SELECT ID, GROUP_ID, TYPE FROM b_rating_vote_group RVG";
1667
1668 if (!$bAllType)
1669 {
1670 $strSql .= " WHERE TYPE = '" . $type . "'";
1671 }
1672
1673 return $DB->Query($strSql);
1674 }
1675
1676 public static function GetVoteGroupEx($type = '')
1677 {
1678 global $DB, $CACHE_MANAGER;
1679
1680 $res = $CACHE_MANAGER->Read(2592000, "ratings_vg");
1681 if ($res)
1682 {
1683 $arResult = $CACHE_MANAGER->Get("ratings_vg");
1684 }
1685 else
1686 {
1687 $strSql = "SELECT GROUP_ID, TYPE FROM b_rating_vote_group RVG";
1688 $res = $DB->Query($strSql);
1689 while ($arRes = $res->Fetch($res))
1690 {
1691 $arResult[] = $arRes;
1692 }
1693 $CACHE_MANAGER->Set("ratings_vg", $arResult);
1694 }
1695 if ($type != '')
1696 {
1697 foreach ($arResult as $key => $value)
1698 {
1699 if ($value['TYPE'] != $type)
1700 {
1701 unset($arResult[$key]);
1702 }
1703 }
1704 }
1705 return $arResult;
1706 }
1707
1708 public static function ClearData()
1709 {
1710 global $DB, $CACHE_MANAGER;
1711
1712 $DB->Query("TRUNCATE TABLE b_rating_prepare");
1713 $DB->Query("TRUNCATE TABLE b_rating_voting_prepare");
1714
1715 $DB->Query("TRUNCATE TABLE b_rating_results");
1716 $DB->Query("TRUNCATE TABLE b_rating_component_results");
1717
1718 $DB->Query("TRUNCATE TABLE b_rating_vote");
1719 $DB->Query("TRUNCATE TABLE b_rating_voting");
1720 $DB->Query("TRUNCATE TABLE b_rating_voting_reaction");
1721
1722 $DB->Query("UPDATE b_rating_user SET VOTE_WEIGHT = 0, VOTE_COUNT = 0");
1723
1724 $CACHE_MANAGER->CleanDir("b_rating_voting");
1725 $CACHE_MANAGER->CleanDir("b_rating_user");
1726
1727 return true;
1728 }
1729
1730 public static function OnUserDelete($ID)
1731 {
1733 return true;
1734 }
1735
1736 public static function OnAfterUserRegister($arFields)
1737 {
1738 global $DB;
1739
1740 if (isset($arFields['EXTERNAL_AUTH_ID']) && in_array($arFields['EXTERNAL_AUTH_ID'], \Bitrix\Main\UserTable::getExternalUserTypes(), true))
1741 {
1742 return false;
1743 }
1744
1745 $userId = isset($arFields["USER_ID"]) ? (int)$arFields["USER_ID"] : (isset($arFields["ID"]) ? (int)$arFields["ID"] : 0);
1746 if ($userId > 0)
1747 {
1748 $authorityRatingId = CRatings::GetAuthorityRating();
1749 $ratingStartValue = COption::GetOptionString("main", "rating_start_authority", 3);
1750 $ratingCountVote = COption::GetOptionString("main", "rating_count_vote", 10);
1751
1752 $arParam = [
1753 'RATING_ID' => $authorityRatingId,
1754 'ENTITY_ID' => $userId,
1755 'BONUS' => (int)$ratingStartValue,
1756 'VOTE_WEIGHT' => (int)$ratingStartValue * COption::GetOptionString("main", "rating_vote_weight", 1),
1757 'VOTE_COUNT' => (int)$ratingCountVote + (int)$ratingStartValue,
1758 ];
1760
1761 if (IsModuleInstalled("intranet"))
1762 {
1763 $strSql = "INSERT INTO b_rating_subordinate (RATING_ID, ENTITY_ID, VOTES) VALUES ('" . $authorityRatingId . "', '" . $userId . "', '" . ((int)$ratingCountVote + (int)$ratingStartValue) . "')";
1764 $DB->Query($strSql);
1765 }
1766
1767 $sRatingAssignType = COption::GetOptionString("main", "rating_assign_type", 'manual');
1768 if ($sRatingAssignType === 'auto')
1769 {
1770 $assignRatingGroup = COption::GetOptionString("main", "rating_assign_rating_group", 0);
1771 $assignAuthorityGroup = COption::GetOptionString("main", "rating_assign_authority_group", 0);
1772 if ($assignRatingGroup == 0 && $assignAuthorityGroup == 0)
1773 {
1774 return false;
1775 }
1776
1777 $arGroups = [];
1778 if ($assignRatingGroup > 0)
1779 {
1780 $arGroups[] = (int)$assignRatingGroup;
1781 }
1782 if ($assignAuthorityGroup > 0 && $assignRatingGroup != $assignAuthorityGroup)
1783 {
1784 $arGroups[] = (int)$assignAuthorityGroup;
1785 }
1786
1787 if (!empty($arGroups))
1788 {
1789 CUser::AppendUserGroup($userId, $arGroups);
1790 }
1791 }
1792 if (CACHED_b_rating_vote !== false)
1793 {
1794 global $CACHE_MANAGER;
1795 $bucket_size = (int)CACHED_b_rating_bucket_size;
1796 if ($bucket_size <= 0)
1797 {
1798 $bucket_size = 100;
1799 }
1800
1801 $bucket = (int)($userId / $bucket_size);
1802 $CACHE_MANAGER->Clean("b_rvu_" . $authorityRatingId . $bucket, "b_rating_user");
1803 }
1804 }
1805 }
1806
1807 public static function __SortWeight($a, $b)
1808 {
1809 if (isset($a['RATING_FROM']) || isset($b['RATING_FROM']))
1810 {
1811 return 1;
1812 }
1813
1814 return (float)$a['RATING_TO'] < (float)$b['RATING_TO'] ? -1 : 1;
1815 }
1816
1817 // check only general field
1818 public static function __CheckFields($arFields)
1819 {
1820 $aMsg = [];
1821
1822 if (is_set($arFields, "NAME") && trim($arFields["NAME"]) == "")
1823 {
1824 $aMsg[] = ["id" => "NAME", "text" => GetMessage("RATING_GENERAL_ERR_NAME")];
1825 }
1826 if (is_set($arFields, "ACTIVE") && !($arFields["ACTIVE"] === 'Y' || $arFields["ACTIVE"] === 'N'))
1827 {
1828 $aMsg[] = ["id" => "ACTIVE", "text" => GetMessage("RATING_GENERAL_ERR_ACTIVE")];
1829 }
1830 if (is_set($arFields, "ENTITY_ID"))
1831 {
1832 $arObjects = CRatings::GetRatingObjects();
1833 if (!in_array($arFields['ENTITY_ID'], $arObjects))
1834 {
1835 $aMsg[] = ["id" => "ENTITY_ID", "text" => GetMessage("RATING_GENERAL_ERR_ENTITY_ID")];
1836 }
1837 }
1838 if (is_set($arFields, "CALCULATION_METHOD") && trim($arFields["CALCULATION_METHOD"]) == "")
1839 {
1840 $aMsg[] = ["id" => "CALCULATION_METHOD", "text" => GetMessage("RATING_GENERAL_ERR_CAL_METHOD")];
1841 }
1842
1843 if (!empty($aMsg))
1844 {
1845 $e = new CAdminException($aMsg);
1846 $GLOBALS["APPLICATION"]->ThrowException($e);
1847 return false;
1848 }
1849
1850 return true;
1851 }
1852
1853 // creates a configuration record for each item rating
1854 public static function __AddComponents($ID, $arFields)
1855 {
1856 global $DB;
1857
1858 $arRatingConfigs = CRatings::GetRatingConfigs($arFields["ENTITY_ID"], false);
1859
1860 $ID = (int)$ID;
1861
1862 foreach ($arFields['CONFIGS'] as $MODULE_ID => $RAT_ARRAY)
1863 {
1864 if (!is_array($RAT_ARRAY))
1865 {
1866 continue;
1867 }
1868
1869 foreach ($RAT_ARRAY as $RAT_TYPE => $COMPONENT)
1870 {
1871 if (!is_array($COMPONENT))
1872 {
1873 continue;
1874 }
1875
1876 foreach ($COMPONENT as $COMPONENT_NAME => $COMPONENT_VALUE)
1877 {
1878 if (!isset($arRatingConfigs[$MODULE_ID][$MODULE_ID . "_" . $RAT_TYPE . "_" . $COMPONENT_NAME]))
1879 {
1880 continue;
1881 }
1882
1883 $arFields_i = [
1884 "RATING_ID" => $ID,
1885 "ACTIVE" => isset($COMPONENT_VALUE["ACTIVE"]) && $COMPONENT_VALUE["ACTIVE"] === 'Y' ? 'Y' : 'N',
1886 "ENTITY_ID" => $arFields["ENTITY_ID"],
1887 "MODULE_ID" => $MODULE_ID,
1888 "RATING_TYPE" => $RAT_TYPE,
1889 "NAME" => $COMPONENT_NAME,
1890 "COMPLEX_NAME" => $arFields["ENTITY_ID"] . '_' . $MODULE_ID . '_' . $RAT_TYPE . '_' . $COMPONENT_NAME,
1891 "CLASS" => $arRatingConfigs[$MODULE_ID][$MODULE_ID . "_" . $RAT_TYPE . "_" . $COMPONENT_NAME]["CLASS"],
1892 "CALC_METHOD" => $arRatingConfigs[$MODULE_ID][$MODULE_ID . "_" . $RAT_TYPE . "_" . $COMPONENT_NAME]["CALC_METHOD"],
1893 "EXCEPTION_METHOD" => $arRatingConfigs[$MODULE_ID][$MODULE_ID . "_" . $RAT_TYPE . "_" . $COMPONENT_NAME]["EXCEPTION_METHOD"],
1894 "REFRESH_INTERVAL" => $arRatingConfigs[$MODULE_ID][$MODULE_ID . "_" . $RAT_TYPE . "_" . $COMPONENT_NAME]["REFRESH_TIME"],
1895 "~LAST_MODIFIED" => $DB->GetNowFunction(),
1896 "~NEXT_CALCULATION" => $DB->GetNowFunction(),
1897 "IS_CALCULATED" => "N",
1898 "~CONFIG" => "'" . serialize($COMPONENT_VALUE) . "'",
1899 ];
1900
1901 $DB->Add("b_rating_component", $arFields_i);
1902 }
1903 }
1904 }
1905
1906 return true;
1907 }
1908
1909 public static function __UpdateComponents($ID, $arFields)
1910 {
1911 global $DB;
1912
1913 $ID = (int)$ID;
1914
1915 $DB->Query("DELETE FROM b_rating_component WHERE RATING_ID=$ID");
1916
1918
1919 return true;
1920 }
1921
1925 public static function err_mess()
1926 {
1927 return "";
1928 }
1929
1930 public static function getRatingVoteReaction($arParam)
1931 {
1932 global $DB;
1933
1934 static $cache = [];
1935
1936 $bplus = (mb_strtoupper($arParam['LIST_TYPE']) !== 'MINUS');
1937 $key = $arParam['ENTITY_TYPE_ID'] . '_' . (int)$arParam['ENTITY_ID'] . '_' . ($bplus ? '1' : '0');
1938
1939 if (
1940 isset($arParam['USE_REACTIONS_CACHE'])
1941 && $arParam['USE_REACTIONS_CACHE'] === 'Y'
1942 && isset($cache[$key])
1943 )
1944 {
1945 $result = $cache[$key];
1946 }
1947 else
1948 {
1949 $sqlStr = "
1950 SELECT
1951 REACTION,
1952 COUNT(RV.ID) as CNT
1953 FROM
1954 b_rating_vote RV
1955 WHERE
1956 RV.ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "'
1957 AND RV.ENTITY_ID = " . (int)$arParam['ENTITY_ID'] . " " .
1958// ($bplus ? " AND RV.VALUE > 0 ": " and RV.VALUE < 0 ")
1959 "GROUP BY REACTION";
1960 $res_cnt = $DB->Query($sqlStr);
1961
1962 $cnt = 0;
1963 $cntReactions = [];
1964 while ($ar_cnt = $res_cnt->fetch())
1965 {
1966 $key = (!empty($ar_cnt["REACTION"]) ? $ar_cnt["REACTION"] : self::REACTION_DEFAULT);
1967 if (!isset($cntReactions[$key]))
1968 {
1969 $cntReactions[$key] = 0;
1970 }
1971 $cntReactions[$key] += $ar_cnt["CNT"];
1972 $cnt += $ar_cnt["CNT"];
1973 }
1974
1975 $result = $cache[$key] = [
1976 'items_all' => $cnt,
1977 'reactions' => $cntReactions,
1978 ];
1979 }
1980
1981 return $result;
1982 }
1983
1984 public static function getRatingVoteList($arParam)
1985 {
1986 global $USER;
1987
1988 $reactionResult = self::GetRatingVoteReaction($arParam);
1989 $cnt = $reactionResult['items_all'];
1990 $cntReactions = $reactionResult['reactions'];
1991
1992 $bplus = (mb_strtoupper($arParam['LIST_TYPE']) !== 'MINUS');
1993
1994 $bIntranetInstalled = IsModuleInstalled("intranet");
1995
1996 $bExtended = false;
1997 $arUserID = [];
1998 $includeReaction = ($arParam['INCLUDE_REACTION'] ?? 'N') === 'Y';
1999
2000 if (
2001 (
2002 array_key_exists("USER_FIELDS", $arParam)
2003 && is_array($arParam["USER_FIELDS"])
2004 )
2005 || (
2006 array_key_exists("USER_SELECT", $arParam)
2007 && is_array($arParam["USER_SELECT"])
2008 )
2009 )
2010 {
2011 $bExtended = true;
2012 $sqlStr = CRatings::GetRatingVoteListSQLExtended($arParam, $bplus, $bIntranetInstalled, $includeReaction);
2013 }
2014 else
2015 {
2016 $sqlStr = CRatings::GetRatingVoteListSQL($arParam, $bplus, $bIntranetInstalled, $includeReaction);
2017 }
2018
2019 $arList = [];
2020 $arVoteList = [];
2021 if ($arParam['LIST_LIMIT'] != 0 && ceil($cnt / (int)$arParam['LIST_LIMIT']) >= (int)$arParam['LIST_PAGE'])
2022 {
2023 $res = new CDBResult();
2024 $res->NavQuery($sqlStr, $cnt, ['iNumPage' => (int)$arParam['LIST_PAGE'], 'nPageSize' => (int)$arParam['LIST_LIMIT']]);
2025
2026 while ($row = $res->Fetch())
2027 {
2028 $ar = $row;
2029
2030 if (!$bExtended)
2031 {
2032 $ar["PHOTO"] = $ar["PHOTO_SRC"] = '';
2033 if (!empty($ar["PERSONAL_PHOTO"]))
2034 {
2035 $arFileTmp = CFile::ResizeImageGet(
2036 $row["PERSONAL_PHOTO"],
2037 ['width' => 58, 'height' => 58],
2039 false
2040 );
2041 $ar['PHOTO'] = CFile::ShowImage($arFileTmp['src'], 21, 21, 'border=0');
2042 $ar['PHOTO_SRC'] = $arFileTmp['src'];
2043 }
2044 $ar['FULL_NAME'] = CUser::FormatName(CSite::GetNameFormat(false), $row, true);
2045 }
2046 else
2047 {
2048 $arUserID[] = $row["ID"];
2049 }
2050
2051 if ($ar['ID'] != $USER->GetId())
2052 {
2053 $arList[$ar['ID']] = $ar;
2054 }
2055 else
2056 {
2057 $arVoteList[$ar['ID']] = $ar;
2058 }
2059 }
2060 foreach ($arList as $ar)
2061 {
2062 $arVoteList[$ar['ID']] = $ar;
2063 }
2064
2065 if (
2066 $bExtended
2067 && !empty($arUserID)
2068 )
2069 {
2070 $arUserListParams = [];
2071 $arUsers = [];
2072
2073 $arUserListParams["FIELDS"] = (
2074 array_key_exists("USER_FIELDS", $arParam)
2075 && is_array($arParam["USER_FIELDS"])
2076 ? $arParam["USER_FIELDS"]
2077 : ["NAME", "LAST_NAME", "SECOND_NAME", "LOGIN", "PERSONAL_PHOTO"]
2078 );
2079
2080 $arUserListParams["FIELDS"] = array_unique(array_merge(["ID"], $arUserListParams["FIELDS"]));
2081
2082 if (
2083 array_key_exists("USER_SELECT", $arParam)
2084 && is_array($arParam["USER_SELECT"])
2085 )
2086 {
2087 $arUserListParams["SELECT"] = $arParam["USER_SELECT"];
2088 }
2089
2090 $rsUser = CUser::GetList(
2091 "ID",
2092 "ASC",
2093 ["ID" => implode("|", $arUserID)],
2094 $arUserListParams
2095 );
2096
2097 while ($arUser = $rsUser->Fetch())
2098 {
2099 $arUser["PHOTO"] = $arUser["PHOTO_SRC"] = '';
2100 if (array_key_exists("PERSONAL_PHOTO", $arUser))
2101 {
2102 $arFileTmp = CFile::ResizeImageGet(
2103 $arUser["PERSONAL_PHOTO"],
2104 ["width" => 58, "height" => 58],
2106 false
2107 );
2108 $arUser["PHOTO_SRC"] = $arFileTmp["src"];
2109 $arUser["PHOTO"] = CFile::ShowImage($arFileTmp["src"], 21, 21, "border=0");
2110 }
2111 $arUser["FULL_NAME"] = CUser::FormatName(CSite::GetNameFormat(false), $arUser, true);
2112 $arUsers[$arUser["ID"]] = $arUser;
2113 }
2114
2115 foreach ($arVoteList as $i => $arVoteUser)
2116 {
2117 if (array_key_exists($arVoteUser["ID"], $arUsers))
2118 {
2119 foreach ($arUsers[$arVoteUser["ID"]] as $key => $value)
2120 {
2121 $arVoteList[$i][$key] = $value;
2122 }
2123 }
2124 }
2125 }
2126 }
2127
2128 return [
2129 'items_all' => $cnt,
2130 'items_page' => count($arVoteList),
2131 'items' => $arVoteList,
2132 'reactions' => $cntReactions,
2133 'list_page' => isset($arParam['LIST_PAGE']) ? (int)$arParam['LIST_PAGE'] : 0,
2134 ];
2135 }
2136
2137 public static function getUserWeight($userId = 0)
2138 {
2139 $result = 0;
2140
2141 if (!\Bitrix\Main\ModuleManager::isModuleInstalled('intranet'))
2142 {
2143 return $result;
2144 }
2145
2146 $userId = (
2147 !empty($userId)
2148 ? (int)$userId
2149 : 0
2150 );
2151
2152 if ($userId <= 0)
2153 {
2154 return $result;
2155 }
2156
2157 $ratingId = \CRatings::getAuthorityRating();
2158 if ((int)$ratingId <= 0)
2159 {
2160 return $result;
2161 }
2162
2163 $res = \Bitrix\Main\Application::getConnection()->query('SELECT MAX(VOTES) AS VOTES FROM b_rating_subordinate WHERE RATING_ID = ' . $ratingId . ' AND ENTITY_ID = ' . $userId);
2164 if ($record = $res->fetch())
2165 {
2166 $result = (float)$record['VOTES'];
2167 }
2168
2169 return $result;
2170 }
2171
2172 public static function getUserData($userId = 0, $value = 0)
2173 {
2174 $result = [];
2175
2176 $userId = (
2177 !empty($userId)
2178 ? (int)$userId
2179 : 0
2180 );
2181
2182 if ($userId <= 0)
2183 {
2184 return $result;
2185 }
2186
2187 $res = \CUser::getById($userId);
2188 if ($userFields = $res->fetch())
2189 {
2190 $result = [
2191 'NAME_FORMATTED' => \CUser::formatName(
2192 \CSite::getNameFormat(false),
2193 [
2194 'NAME' => $userFields["NAME"],
2195 'LAST_NAME' => $userFields["LAST_NAME"],
2196 'SECOND_NAME' => $userFields["SECOND_NAME"],
2197 'LOGIN' => $userFields["LOGIN"],
2198 ],
2199 true
2200 ),
2201 'PERSONAL_PHOTO' => [
2202 'ID' => $userFields["PERSONAL_PHOTO"],
2203 'SRC' => false,
2204 ],
2205 "WEIGHT" => (
2208 : $value
2209 ),
2210 ];
2211
2212 if ((int)$userFields['PERSONAL_PHOTO'] > 0)
2213 {
2214 $imageFile = \CFile::getFileArray($userFields["PERSONAL_PHOTO"]);
2215 if ($imageFile !== false)
2216 {
2217 $file = \CFile::resizeImageGet(
2218 $imageFile,
2219 ["width" => 100, "height" => 100],
2221 false
2222 );
2223 $result['PERSONAL_PHOTO']['SRC'] = $file['src'];
2224 }
2225 }
2226 }
2227
2228 return $result;
2229 }
2230
2231 public static function getEntityRatingData($params = [])
2232 {
2233 global $USER;
2235 $helper = $connection->getSqlHelper();
2236
2237 $result = [];
2238
2239 $entityTypeId = (
2240 !empty($params['entityTypeId'])
2241 ? $params['entityTypeId']
2242 : ''
2243 );
2244
2245 $entityIdList = (
2246 !empty($params['entityId'])
2247 ? $params['entityId']
2248 : []
2249 );
2250
2251 if (!is_array($entityIdList))
2252 {
2253 $entityIdList = [$entityIdList];
2254 }
2255
2256 if (empty($entityIdList))
2257 {
2258 return $result;
2259 }
2260
2261 $ratingId = \CRatings::getAuthorityRating();
2262 if ((int)$ratingId <= 0)
2263 {
2264 return $result;
2265 }
2266
2267 $topCount = (
2268 isset($params['topCount'])
2269 ? (int)$params['topCount']
2270 : 0
2271 );
2272
2273 if ($topCount <= 0)
2274 {
2275 $topCount = 2;
2276 }
2277
2278 if ($topCount > 5)
2279 {
2280 $topCount = 5;
2281 }
2282
2283 $avatarSize = (
2284 isset($params['avatarSize'])
2285 ? (int)$params['avatarSize']
2286 : 100
2287 );
2288
2289 if (\Bitrix\Main\ModuleManager::isModuleInstalled('intranet'))
2290 {
2291 $res = $connection->query("
2292 SELECT
2293 RS1.ENTITY_ID as USER_ID,
2294 RV1.ENTITY_ID as ENTITY_ID,
2295 MAX(RS1.VOTES) as WEIGHT
2296 FROM
2297 b_rating_subordinate RS1,
2298 b_rating_vote RV1
2299 WHERE
2300 RS1.ENTITY_ID = RV1.USER_ID
2301 AND RS1.RATING_ID = " . (int)$ratingId . "
2302 AND RV1.ENTITY_TYPE_ID = '" . $helper->forSQL($entityTypeId) . "'
2303 AND RV1.ENTITY_ID IN (" . implode(',', $entityIdList) . ")
2304 GROUP BY
2305 RV1.ENTITY_ID, RS1.ENTITY_ID
2306 ORDER BY
2307 RV1.ENTITY_ID,
2308 WEIGHT DESC
2309 ");
2310 }
2311 else
2312 {
2313 $res = $connection->query("
2314 SELECT
2315 RV1.USER_ID as USER_ID,
2316 RV1.ENTITY_ID as ENTITY_ID,
2317 RV1.VALUE as WEIGHT
2318 FROM
2319 b_rating_vote RV1
2320 WHERE
2321 RV1.ENTITY_TYPE_ID = '" . $helper->forSQL($entityTypeId) . "'
2322 AND RV1.ENTITY_ID IN (" . implode(',', $entityIdList) . ")
2323 ORDER BY
2324 RV1.ENTITY_ID,
2325 WEIGHT DESC
2326 ");
2327 }
2328
2329 $userWeightData = $entityUserData = [];
2330
2331 $currentEntityId = false;
2332 $hasMine = false;
2333
2334 while ($voteFields = $res->fetch())
2335 {
2336 if (
2337 !$hasMine
2338 && $voteFields['USER_ID'] == $USER->getId()
2339 )
2340 {
2341 $hasMine = true;
2342 }
2343
2344 if ($voteFields['ENTITY_ID'] != $currentEntityId)
2345 {
2346 $cnt = 0;
2347 $hasMine = false;
2348 $entityUserData[$voteFields['ENTITY_ID']] = [];
2349 }
2350
2351 $currentEntityId = $voteFields['ENTITY_ID'];
2352 $cnt++;
2353
2354 if ($cnt > ($hasMine ? $topCount + 1 : $topCount))
2355 {
2356 continue;
2357 }
2358
2359 $entityUserData[$voteFields['ENTITY_ID']][] = $voteFields['USER_ID'];
2360 if (!isset($userWeightData[$voteFields['USER_ID']]))
2361 {
2362 $userWeightData[$voteFields['USER_ID']] = (float)$voteFields['WEIGHT'];
2363 }
2364 }
2365
2366 $userData = [];
2367
2368 if (!empty($userWeightData))
2369 {
2371 'filter' => [
2372 '@ID' => array_keys($userWeightData),
2373 ],
2374 'select' => ['ID', 'NAME', 'LAST_NAME', 'SECOND_NAME', 'LOGIN', 'PERSONAL_PHOTO', 'PERSONAL_GENDER'],
2375 ]);
2376
2377 while ($userFields = $res->fetch())
2378 {
2379 $userData[$userFields["ID"]] = [
2380 'NAME_FORMATTED' => \CUser::formatName(
2381 \CSite::getNameFormat(false),
2382 $userFields,
2383 true
2384 ),
2385 'PERSONAL_PHOTO' => [
2386 'ID' => $userFields['PERSONAL_PHOTO'],
2387 'SRC' => false,
2388 ],
2389 'PERSONAL_GENDER' => $userFields['PERSONAL_GENDER'],
2390 ];
2391
2392 if ((int)$userFields['PERSONAL_PHOTO'] > 0)
2393 {
2394 $imageFile = \CFile::getFileArray($userFields["PERSONAL_PHOTO"]);
2395 if ($imageFile !== false)
2396 {
2397 $file = \CFile::resizeImageGet(
2398 $imageFile,
2399 ["width" => $avatarSize, "height" => $avatarSize],
2401 false
2402 );
2403 $userData[$userFields["ID"]]['PERSONAL_PHOTO']['SRC'] = $file['src'];
2404 }
2405 }
2406 }
2407 }
2408
2409 foreach ($entityUserData as $entityId => $userIdList)
2410 {
2411 $result[$entityId] = [];
2412
2413 foreach ($userIdList as $userId)
2414 {
2415 $result[$entityId][] = [
2416 'ID' => $userId,
2417 'NAME_FORMATTED' => $userData[$userId]['NAME_FORMATTED'],
2418 'PERSONAL_PHOTO' => $userData[$userId]['PERSONAL_PHOTO']['ID'],
2419 'PERSONAL_PHOTO_SRC' => $userData[$userId]['PERSONAL_PHOTO']['SRC'],
2420 'PERSONAL_GENDER' => $userData[$userId]['PERSONAL_GENDER'],
2421 'WEIGHT' => $userWeightData[$userId],
2422 ];
2423 }
2424 }
2425
2426 foreach ($result as $entityId => $data)
2427 {
2428 usort(
2429 $data,
2430 function ($a, $b) {
2431 if ($a['WEIGHT'] == $b['WEIGHT'])
2432 {
2433 return 0;
2434 }
2435 return ($a['WEIGHT'] > $b['WEIGHT']) ? -1 : 1;
2436 }
2437 );
2439 }
2440
2441 return $result;
2442 }
2443
2444 public static function deleteRatingVoting(array $params = [])
2445 {
2446 global $DB;
2447
2448 $entityTypeId = (
2449 isset($params['ENTITY_TYPE_ID'])
2450 && $params['ENTITY_TYPE_ID'] <> ''
2451 ? $params['ENTITY_TYPE_ID']
2452 : ''
2453 );
2454 $entityId = (
2455 isset($params['ENTITY_ID'])
2456 && (int)$params['ENTITY_ID'] > 0
2457 ? (int)$params['ENTITY_ID']
2458 : 0
2459 );
2460 if (
2461 $entityTypeId == ''
2462 || $entityId <= 0
2463 )
2464 {
2465 return;
2466 }
2467
2468 $DB->query("DELETE FROM b_rating_vote WHERE ENTITY_TYPE_ID='" . $DB->forSql($entityTypeId) . "' AND ENTITY_ID=" . $entityId, true);
2469 $DB->query("DELETE FROM b_rating_voting WHERE ENTITY_TYPE_ID='" . $DB->forSql($entityTypeId) . "' AND ENTITY_ID=" . $entityId, true);
2470 $DB->query("DELETE FROM b_rating_voting_reaction WHERE ENTITY_TYPE_ID='" . $DB->forSql($entityTypeId) . "' AND ENTITY_ID=" . $entityId, true);
2471 }
2472
2473 // building rating on computed components
2474 public static function BuildRating($ID)
2475 {
2476 global $DB;
2478 $helper = $connection->getSqlHelper();
2479
2480 $ID = intval($ID);
2481
2482 $resRating = CRatings::GetByID($ID);
2483 $arRating = $resRating->Fetch();
2484 if ($arRating && $arRating['ACTIVE'] == 'Y')
2485 {
2486 $DB->Query("UPDATE b_rating SET CALCULATED = 'C' WHERE id = " . $ID);
2487
2488 // Insert new results
2489 $sqlFunc = ($arRating['CALCULATION_METHOD'] == 'SUM') ? 'SUM' : 'AVG';
2490 $strSql = "
2491 INSERT INTO b_rating_results
2492 (RATING_ID, ENTITY_TYPE_ID, ENTITY_ID, CURRENT_VALUE, PREVIOUS_VALUE)
2493 SELECT
2494 " . $ID . " RATING_ID,
2495 '" . $arRating['ENTITY_ID'] . "' ENTITY_TYPE_ID,
2496 RC.ENTITY_ID,
2497 " . $sqlFunc . "(RC.CURRENT_VALUE) CURRENT_VALUE,
2498 0 PREVIOUS_VALUE
2499 FROM
2500 b_rating_component_results RC LEFT JOIN b_rating_results RR ON RR.RATING_ID = RC.RATING_ID and RR.ENTITY_ID = RC.ENTITY_ID
2501 WHERE
2502 RC.RATING_ID = " . $ID . " and RR.ID IS NULL
2503 GROUP BY RC.ENTITY_ID";
2504 $DB->Query($strSql);
2505
2506 // Update current results
2507 $strSql = $helper->prepareCorrelatedUpdate("b_rating_results", "RR", [
2508 'PREVIOUS_VALUE' => 'case when RR.CURRENT_VALUE = RCR.CURRENT_VALUE then RR.PREVIOUS_VALUE else RR.CURRENT_VALUE end',
2509 'CURRENT_VALUE' => 'RCR.CURRENT_VALUE',
2510 ], "
2511 (SELECT '" . $arRating['ENTITY_ID'] . "' ENTITY_TYPE_ID, RC.ENTITY_ID, " . $sqlFunc . "(RC.CURRENT_VALUE) CURRENT_VALUE
2512 FROM b_rating_component_results RC INNER JOIN b_rating_results RR on RR.RATING_ID = RC.RATING_ID and RR.ENTITY_ID = RC.ENTITY_ID
2513 WHERE RC.RATING_ID = " . $ID . "
2514 GROUP BY RC.ENTITY_ID
2515 ) as RCR
2516 ", "
2517 RR.RATING_ID=" . $ID . "
2518 and RR.ENTITY_TYPE_ID = RCR.ENTITY_TYPE_ID
2519 and RR.ENTITY_ID = RCR.ENTITY_ID
2520 "
2521 );
2522 $DB->Query($strSql);
2523
2524 // Calculation position in rating
2525 if ($arRating['POSITION'] == 'Y')
2526 {
2527 $strSql = $helper->initRowNumber('nPos');
2528 if ($strSql)
2529 {
2530 $DB->Query($strSql);
2531 }
2532 $strSql = $helper->prepareCorrelatedUpdate("b_rating_results", "RR", [
2533 'PREVIOUS_POSITION' => 'case when RR.CURRENT_POSITION = RP.POSITION then RR.PREVIOUS_POSITION else RR.CURRENT_POSITION end',
2534 'CURRENT_POSITION' => 'RP.POSITION',
2535 ], "
2536 (SELECT ENTITY_TYPE_ID, ENTITY_ID, CURRENT_VALUE, " . $helper->getRowNumber('nPos') . " as POSITION
2537 FROM b_rating_results
2538 WHERE RATING_ID = " . $ID . "
2539 ORDER BY CURRENT_VALUE DESC
2540 ) as RP
2541 ", "
2542 RR.RATING_ID=" . $ID . "
2543 and RR.ENTITY_TYPE_ID = RP.ENTITY_TYPE_ID
2544 and RR.ENTITY_ID = RP.ENTITY_ID
2545 "
2546 );
2547 $DB->Query($strSql);
2548 }
2549
2550 // Insert new user rating prop
2551 $strSql = "
2552 INSERT INTO b_rating_user
2553 (RATING_ID, ENTITY_ID)
2554 SELECT
2555 " . $ID . " RATING_ID,
2556 U.ID as ENTITY_ID
2557 FROM
2558 b_user U
2559 LEFT JOIN b_rating_user RU ON RU.RATING_ID = " . $ID . " and RU.ENTITY_ID = U.ID
2560 WHERE
2561 U.ACTIVE = 'Y'
2562 AND (CASE WHEN U.EXTERNAL_AUTH_ID IN ('" . join("', '", \Bitrix\Main\UserTable::getExternalUserTypes()) . "') THEN 'Y' ELSE 'N' END) = 'N'
2563 AND RU.ID IS NULL ";
2564 $DB->Query($strSql);
2565 // authority calc
2566 if ($arRating['AUTHORITY'] == 'Y')
2567 {
2568 $sRatingAssignType = COption::GetOptionString("main", "rating_assign_type", "manual");
2569 if ($sRatingAssignType == 'auto')
2570 {
2571 // auto assign for rating group
2572 $assignRatingGroup = COption::GetOptionString("main", "rating_assign_rating_group", 0);
2573 $assignRatingValueAdd = COption::GetOptionString("main", "rating_assign_rating_group_add", 1);
2574 $assignRatingValueDelete = COption::GetOptionString("main", "rating_assign_rating_group_delete", 1);
2575
2576 CRatings::AutoAssignGroup($assignRatingGroup, $assignRatingValueAdd, $assignRatingValueDelete);
2577
2578 // auto assign for authority group
2579 $assignAuthorityGroup = COption::GetOptionString("main", "rating_assign_authority_group", 0);
2580 $assignAuthorityValueAdd = COption::GetOptionString("main", "rating_assign_authority_group_add", 2);
2581 $assignAuthorityValueDelete = COption::GetOptionString("main", "rating_assign_authority_group_delete", 2);
2582
2583 CRatings::AutoAssignGroup($assignAuthorityGroup, $assignAuthorityValueAdd, $assignAuthorityValueDelete);
2584 }
2585
2586 $sRatingWeightType = COption::GetOptionString("main", "rating_weight_type", "auto");
2587 if ($sRatingWeightType == 'auto')
2588 {
2590 $communitySize = $arCI['COMMUNITY_SIZE'];
2591 $communityAuthority = $arCI['COMMUNITY_AUTHORITY'];
2592
2593 $sRatingNormalizationType = COption::GetOptionString("main", "rating_normalization_type", "auto");
2594 if ($sRatingNormalizationType == 'manual')
2595 {
2596 $ratingNormalization = COption::GetOptionString("main", "rating_normalization", 1000);
2597 }
2598 else
2599 {
2600 if ($communitySize <= 10)
2601 {
2602 $ratingNormalization = 10;
2603 }
2604 elseif ($communitySize <= 1000)
2605 {
2606 $ratingNormalization = 100;
2607 }
2608 else
2609 {
2610 $ratingNormalization = 1000;
2611 }
2612 COption::SetOptionString("main", "rating_normalization", $ratingNormalization);
2613 }
2614
2615 $voteWeight = 1;
2616 if ($communitySize > 0)
2617 {
2618 $voteWeight = $ratingNormalization / $communitySize;
2619 }
2620
2621 COption::SetOptionString("main", "rating_community_size", $communitySize);
2622 COption::SetOptionString("main", "rating_community_authority", $communityAuthority);
2623 COption::SetOptionString("main", "rating_vote_weight", $voteWeight);
2624
2625 $ratingCountVote = COption::GetOptionString("main", "rating_count_vote", 10);
2626 $strSql = "UPDATE b_rating_user SET VOTE_COUNT = 0, VOTE_WEIGHT =0 WHERE RATING_ID=" . $ID;
2627 $DB->Query($strSql);
2628 // default vote count + user authority
2629 $strSql = $helper->prepareCorrelatedUpdate("b_rating_user", "RU", [
2630 'VOTE_COUNT' => intval($ratingCountVote) . " + RP.CURRENT_VALUE",
2631 'VOTE_WEIGHT' => "RP.CURRENT_VALUE * " . $voteWeight,
2632 ], "
2633 (SELECT ENTITY_ID, CURRENT_VALUE
2634 FROM b_rating_results
2635 WHERE RATING_ID = " . $ID . "
2636 ) as RP
2637 ", "
2638 RU.RATING_ID=" . $ID . "
2639 and RU.ENTITY_ID = RP.ENTITY_ID
2640 "
2641 );
2642 $DB->Query($strSql);
2643 }
2644 else
2645 {
2646 // Depending on current authority set correct weight votes
2647 // Depending on current authority set correct vote count
2648 $strSql = "UPDATE b_rating_user SET VOTE_COUNT = 0, VOTE_WEIGHT =0 WHERE RATING_ID=" . $ID;
2649 $DB->Query($strSql);
2650
2651 $strSql = $helper->prepareCorrelatedUpdate("b_rating_user", "RU", [
2652 'VOTE_COUNT' => 'RP.COUNT',
2653 'VOTE_WEIGHT' => 'RP.WEIGHT',
2654 ], "
2655 (SELECT
2656 RW.RATING_FROM, RW.RATING_TO, RW.WEIGHT, RW.COUNT, RR.ENTITY_ID
2657 FROM
2658 b_rating_weight RW,
2659 b_rating_results RR
2660 WHERE
2661 RR.RATING_ID = " . $ID . "
2662 and RR.CURRENT_VALUE BETWEEN RW.RATING_FROM AND RW.RATING_TO
2663 ) as RP
2664 ", "
2665 RU.RATING_ID=" . $ID . "
2666 and RU.ENTITY_ID = RP.ENTITY_ID
2667 "
2668 );
2669 $DB->Query($strSql);
2670 }
2671 }
2672 global $CACHE_MANAGER;
2673 $CACHE_MANAGER->CleanDir("b_rating_user");
2674
2675 $DB->Query("UPDATE b_rating SET CALCULATED = 'Y', LAST_CALCULATED = " . $DB->GetNowFunction() . " WHERE id = " . $ID);
2676 }
2677 return true;
2678 }
2679
2680 public static function DeleteByUser($ID)
2681 {
2682 global $CACHE_MANAGER;
2684 $helper = $connection->getSqlHelper();
2685
2686 $ID = intval($ID);
2687
2688 $strSql = $helper->prepareCorrelatedUpdate("b_rating_voting_reaction", "RVR", [
2689 'TOTAL_VOTES' => 'RP.TOTAL_POSITIVE_VOTES',
2690 ], "
2691 (SELECT
2692 ENTITY_TYPE_ID,
2693 ENTITY_ID,
2694 SUM(case when VALUE > 0 AND USER_ID <> $ID then 1 else 0 end) as TOTAL_POSITIVE_VOTES
2695 FROM b_rating_vote
2696 WHERE RATING_VOTING_ID IN (
2697 SELECT DISTINCT RV0.RATING_VOTING_ID FROM b_rating_vote RV0 WHERE RV0.USER_ID=$ID
2698 )
2699 GROUP BY RATING_VOTING_ID, ENTITY_TYPE_ID, ENTITY_ID
2700 ) as RP
2701 ", "
2702 RVR.ENTITY_TYPE_ID = RP.ENTITY_TYPE_ID
2703 AND RVR.ENTITY_ID = RP.ENTITY_ID
2704 "
2705 );
2706 $connection->query($strSql);
2707
2708 $strSql = $helper->prepareCorrelatedUpdate("b_rating_voting", "RV", [
2709 'TOTAL_VALUE' => 'RP.TOTAL_VALUE',
2710 'TOTAL_VOTES' => 'RP.TOTAL_VOTES',
2711 'TOTAL_POSITIVE_VOTES' => 'RP.TOTAL_POSITIVE_VOTES',
2712 'TOTAL_NEGATIVE_VOTES' => 'RP.TOTAL_NEGATIVE_VOTES',
2713 ], "
2714 (SELECT
2715 RATING_VOTING_ID,
2716 SUM(case when USER_ID <> $ID then VALUE else 0 end) as TOTAL_VALUE,
2717 SUM(case when USER_ID <> $ID then 1 else 0 end) as TOTAL_VOTES,
2718 SUM(case when VALUE > 0 AND USER_ID <> $ID then 1 else 0 end) as TOTAL_POSITIVE_VOTES,
2719 SUM(case when VALUE < 0 AND USER_ID <> $ID then 1 else 0 end) as TOTAL_NEGATIVE_VOTES
2720 FROM b_rating_vote
2721 WHERE RATING_VOTING_ID IN (
2722 SELECT DISTINCT RV0.RATING_VOTING_ID FROM b_rating_vote RV0 WHERE RV0.USER_ID=$ID
2723 )
2724 GROUP BY RATING_VOTING_ID
2725 ) as RP
2726 ", "
2727 RV.ID = RP.RATING_VOTING_ID
2728 "
2729 );
2730
2731 $connection->query($strSql);
2732
2733 $connection->query("DELETE FROM b_rating_vote WHERE USER_ID = $ID");
2734 $connection->query("DELETE FROM b_rating_user WHERE ENTITY_ID = $ID");
2735 $CACHE_MANAGER->ClearByTag('RV_CACHE');
2736
2737 return true;
2738 }
2739
2740 // insert result calculate rating
2741 public static function AddResults($arResults)
2742 {
2743 global $DB;
2744
2745 // Only Mysql
2746 $strSqlPrefix = "
2747 INSERT INTO b_rating_results
2748 (RATING_ID, ENTITY_TYPE_ID, ENTITY_ID, CURRENT_VALUE, PREVIOUS_VALUE)
2749 VALUES
2750 ";
2751 $maxValuesLen = 2048;
2752 $strSqlValues = "";
2753
2754 foreach ($arResults as $arResult)
2755 {
2756 $strSqlValues .= ",\n(" . intval($arResult['RATING_ID']) . ", '" . $DB->ForSql($arResult['ENTITY_TYPE_ID']) . "', '" . $DB->ForSql($arResult['ENTITY_ID']) . "', '" . $DB->ForSql($arResult['CURRENT_VALUE']) . "', '" . $DB->ForSql($arResult['PREVIOUS_VALUE']) . "')";
2757 if (mb_strlen($strSqlValues) > $maxValuesLen)
2758 {
2759 $DB->Query($strSqlPrefix . mb_substr($strSqlValues, 2));
2760 $strSqlValues = "";
2761 }
2762 }
2763 if ($strSqlValues <> '')
2764 {
2765 $DB->Query($strSqlPrefix . mb_substr($strSqlValues, 2));
2766 }
2767
2768 return true;
2769 }
2770
2771 // insert result calculate rating-components
2772 public static function AddComponentResults($arComponentConfigs)
2773 {
2774 global $DB;
2775
2776 if (!is_array($arComponentConfigs))
2777 {
2778 return false;
2779 }
2780
2781 $strSql = "
2782 UPDATE b_rating_component
2783 SET LAST_CALCULATED = " . $DB->GetNowFunction() . ",
2784 NEXT_CALCULATION = '" . date('Y-m-d H:i:s', time() + $arComponentConfigs['REFRESH_INTERVAL']) . "'
2785 WHERE RATING_ID = " . intval($arComponentConfigs['RATING_ID']) . " AND COMPLEX_NAME = '" . $DB->ForSql($arComponentConfigs['COMPLEX_NAME']) . "'";
2786 $DB->Query($strSql);
2787
2788 return true;
2789 }
2790
2791 public static function SetAuthorityRating($ratingId)
2792 {
2793 global $DB, $stackCacheManager;
2794
2795 $ratingId = intval($ratingId);
2796
2797 $DB->Query("UPDATE b_rating SET AUTHORITY = CASE WHEN ID <> $ratingId THEN 'N' ELSE 'Y' END");
2798
2799 COption::SetOptionString("main", "rating_authority_rating", $ratingId);
2800
2801 $stackCacheManager->Clear("b_rating");
2802
2803 return true;
2804 }
2805
2806 public static function GetCommunityInfo($ratingId)
2807 {
2808 global $DB;
2810 $helper = $connection->getSqlHelper();
2811
2812 $bAllGroups = false;
2813 $arGroups = [];
2814 $communityLastVisit = COption::GetOptionString("main", "rating_community_last_visit", '90');
2816 while ($arVoteGroup = $res->Fetch())
2817 {
2818 if ($arVoteGroup['GROUP_ID'] == 2)
2819 {
2820 $bAllGroups = true;
2821 break;
2822 }
2823 $arGroups[] = $arVoteGroup['GROUP_ID'];
2824 }
2825
2826 $strModulesSql = '';
2827 if (IsModuleInstalled("forum"))
2828 {
2829 $strModulesSql .= "
2830 SELECT USER_START_ID as ENTITY_ID
2831 FROM b_forum_topic
2832 WHERE START_DATE > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2833 GROUP BY USER_START_ID
2834 UNION ALL
2835 SELECT AUTHOR_ID as ENTITY_ID
2836 FROM b_forum_message
2837 WHERE POST_DATE > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2838 GROUP BY AUTHOR_ID
2839 UNION ALL
2840 ";
2841 }
2842 if (IsModuleInstalled("blog"))
2843 {
2844 $strModulesSql .= "
2845 SELECT AUTHOR_ID as ENTITY_ID
2846 FROM b_blog_post
2847 WHERE DATE_PUBLISH > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2848 GROUP BY AUTHOR_ID
2849 UNION ALL
2850 SELECT AUTHOR_ID as ENTITY_ID
2851 FROM b_blog_comment
2852 WHERE DATE_CREATE > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2853 GROUP BY AUTHOR_ID
2854 UNION ALL";
2855 }
2856 if (IsModuleInstalled("intranet"))
2857 {
2858 $ratingId = COption::GetOptionString("main", "rating_authority_rating", 0);
2859 $strModulesSql .= "
2860 SELECT ENTITY_ID
2861 FROM b_rating_subordinate
2862 WHERE RATING_ID = $ratingId
2863 UNION ALL";
2864 }
2865 if (!empty($strModulesSql))
2866 {
2867 $strModulesSql = "
2868 (
2869 " . $strModulesSql . "
2870 SELECT USER_ID as ENTITY_ID
2871 FROM b_rating_vote
2872 WHERE CREATED > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2873 GROUP BY USER_ID
2874 ) MS,
2875 ";
2876 }
2877
2878// $DB->Query("TRUNCATE TABLE b_rating_prepare");
2879 $DB->Query("DELETE FROM b_rating_prepare");
2880
2881 $strSql = '';
2882 if ($bAllGroups || empty($arGroups))
2883 {
2884 $strSql .= "
2885 INSERT INTO b_rating_prepare (ID)
2886 SELECT DISTINCT U.ID
2887 FROM " . $strModulesSql . "
2888 b_user U
2889 WHERE " . (!empty($strModulesSql) ? "U.ID = MS.ENTITY_ID AND" : "") . "
2890 U.ACTIVE = 'Y'
2891 AND (CASE WHEN U.EXTERNAL_AUTH_ID IN ('" . join("', '", \Bitrix\Main\UserTable::getExternalUserTypes()) . "') THEN 'Y' ELSE 'N' END) = 'N'
2892 AND U.LAST_LOGIN >" . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2893 ";
2894 }
2895 else
2896 {
2897 $strSql .= "
2898 INSERT INTO b_rating_prepare (ID)
2899 SELECT DISTINCT U.ID
2900 FROM " . $strModulesSql . "
2901 b_user U
2902 WHERE " . (!empty($strModulesSql) ? "U.ID = MS.ENTITY_ID AND" : "") . "
2903 U.ACTIVE = 'Y'
2904 AND (CASE WHEN U.EXTERNAL_AUTH_ID IN ('" . join("', '", \Bitrix\Main\UserTable::getExternalUserTypes()) . "') THEN 'Y' ELSE 'N' END) = 'N'
2905 AND U.LAST_LOGIN > " . $helper->addDaysToDateTime(-intval($communityLastVisit)) . "
2906 ";
2907 }
2908 $DB->Query($strSql);
2909
2910 $strSql = 'SELECT COUNT(*) as COMMUNITY_SIZE, SUM(CURRENT_VALUE) COMMUNITY_AUTHORITY
2911 FROM b_rating_results RC LEFT JOIN b_rating_prepare TT ON RC.ENTITY_ID = TT.ID
2912 WHERE RATING_ID = ' . intval($ratingId) . ' AND TT.ID IS NOT NULL';
2913 $res = $DB->Query($strSql);
2914
2915 return $res->Fetch();
2916 }
2917
2918 public static function CheckAllowVote($arVoteParam)
2919 {
2920 global $USER;
2921
2922 if (
2923 isset($arVoteParam['CURRENT_USER_ID'])
2924 && (int)$arVoteParam['CURRENT_USER_ID'] > 0
2925 )
2926 {
2927 $userId = (int)$arVoteParam['CURRENT_USER_ID'];
2928 $bUserAuth = ($userId > 0);
2929 }
2930 else
2931 {
2932 $userId = (int)$USER?->GetId();
2933 $bUserAuth = (bool)$USER?->IsAuthorized();
2934 }
2935
2936 $arInfo = [
2937 'RESULT' => true,
2938 'ERROR_TYPE' => '',
2939 'ERROR_MSG' => '',
2940 ];
2941
2942 $bSelfVote = COption::GetOptionString("main", "rating_self_vote", 'N');
2943 if ($bSelfVote == 'N' && intval($arVoteParam['OWNER_ID']) == $userId)
2944 {
2945 $arInfo = [
2946 'RESULT' => false,
2947 'ERROR_TYPE' => 'SELF',
2948 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_SELF'),
2949 ];
2950 }
2951 elseif (!$bUserAuth)
2952 {
2953 $arInfo = [
2954 'RESULT' => false,
2955 'ERROR_TYPE' => 'GUEST',
2956 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_GUEST'),
2957 ];
2958 }
2959 else
2960 {
2961 static $cacheAllowVote = [];
2962 static $cacheUserVote = [];
2963 static $cacheVoteSize = 0;
2964 if (!array_key_exists($userId, $cacheAllowVote))
2965 {
2966 global $DB;
2968 $helper = $connection->getSqlHelper();
2969
2970 $sVoteType = $arVoteParam['ENTITY_TYPE_ID'] == 'USER' ? 'A' : 'R';
2971
2972 $userVoteGroup = [];
2974 foreach ($ar as $group)
2975 {
2976 if ($sVoteType == $group['TYPE'])
2977 {
2978 $userVoteGroup[] = $group['GROUP_ID'];
2979 }
2980 }
2981
2982 $userGroup = $USER->GetUserGroupArray();
2983
2984 $result = array_intersect($userGroup, $userVoteGroup);
2985 if (empty($result))
2986 {
2987 $arInfo = $cacheAllowVote[$userId] = [
2988 'RESULT' => false,
2989 'ERROR_TYPE' => 'ACCESS',
2990 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_ACCESS'),
2991 ];
2992 }
2993
2994 $authorityRatingId = CRatings::GetAuthorityRating();
2995 $arAuthorityUserProp = CRatings::GetRatingUserPropEx($authorityRatingId, $userId);
2996 if (
2997 $arAuthorityUserProp['VOTE_WEIGHT'] < 0
2998 || (
2999 $arAuthorityUserProp['VOTE_WEIGHT'] == 0
3000 && !IsModuleInstalled('intranet')
3001 )
3002 )
3003 {
3004 $arInfo = $cacheAllowVote[$userId] = [
3005 'RESULT' => false,
3006 'ERROR_TYPE' => 'ACCESS',
3007 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_LOW_WEIGHT'),
3008 ];
3009 }
3010
3011 if ($arInfo['RESULT'] && $sVoteType == 'A')
3012 {
3013 $strSql = '
3014 SELECT COUNT(*) as VOTE
3015 FROM b_rating_vote RV
3016 WHERE RV.USER_ID = ' . $userId . '
3017 AND RV.CREATED > ' . $helper->addDaysToDateTime(-1);
3018 $res = $DB->Query($strSql);
3019 $countVote = $res->Fetch();
3020 $cacheVoteSize = \Bitrix\Main\Application::getInstance()->getSession()['RATING_VOTE_COUNT'] = $countVote['VOTE'];
3021
3022 $cacheUserVote[$userId] = \Bitrix\Main\Application::getInstance()->getSession()['RATING_USER_VOTE_COUNT'] = $arAuthorityUserProp['VOTE_COUNT'];
3023 if ($cacheVoteSize >= $cacheUserVote[$userId])
3024 {
3025 $arInfo = $cacheAllowVote[$userId] = [
3026 'RESULT' => false,
3027 'ERROR_TYPE' => 'COUNT_VOTE',
3028 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_COUNT_VOTE'),
3029 ];
3030 }
3031 }
3032 }
3033 else
3034 {
3035 if ($cacheAllowVote[$userId]['RESULT'])
3036 {
3037 if ($cacheVoteSize >= $cacheUserVote[$userId])
3038 {
3039 $cacheAllowVote[$userId] = [
3040 'RESULT' => false,
3041 'ERROR_TYPE' => 'COUNT_VOTE',
3042 'ERROR_MSG' => GetMessage('RATING_ALLOW_VOTE_COUNT_VOTE'),
3043 ];
3044 }
3045 }
3046 $arInfo = $cacheAllowVote[$userId];
3047 }
3048 }
3049
3050 static $handlers;
3051 if (!isset($handlers))
3052 {
3053 $handlers = GetModuleEvents("main", "OnAfterCheckAllowVote", true);
3054 }
3055
3056 foreach ($handlers as $arEvent)
3057 {
3058 $arEventResult = ExecuteModuleEventEx($arEvent, [$arVoteParam]);
3059 if (is_array($arEventResult) && isset($arEventResult['RESULT']) && $arEventResult['RESULT'] === false
3060 && isset($arEventResult['ERROR_TYPE']) && $arEventResult['ERROR_TYPE'] <> ''
3061 && isset($arEventResult['ERROR_MSG']) && $arEventResult['ERROR_MSG'] <> '')
3062 {
3063 $arInfo = [
3064 'RESULT' => false,
3065 'ERROR_TYPE' => $arEventResult['ERROR_TYPE'],
3066 'ERROR_MSG' => $arEventResult['ERROR_MSG'],
3067 ];
3068 }
3069 }
3070 return $arInfo;
3071 }
3072
3073 public static function SetAuthorityDefaultValue($arParams)
3074 {
3075 global $DB;
3076
3077 $rsRatings = CRatings::GetList(['ID' => 'ASC'], ['ENTITY_ID' => 'USER']);
3078 $arRatingList = [];
3079 while ($arRatingsTmp = $rsRatings->GetNext())
3080 {
3081 $arRatingList[] = $arRatingsTmp['ID'];
3082 }
3083
3084 if (isset($arParams['DEFAULT_USER_ACTIVE']) && $arParams['DEFAULT_USER_ACTIVE'] == 'Y' && IsModuleInstalled("forum") && !empty($arRatingList))
3085 {
3086 $ratingStartValue = 0;
3087 if (isset($arParams['DEFAULT_CONFIG_NEW_USER']) && $arParams['DEFAULT_CONFIG_NEW_USER'] == 'Y')
3088 {
3089 $ratingStartValue = COption::GetOptionString("main", "rating_start_authority", 3);
3090 }
3091
3092 $strSql = "UPDATE b_rating_user SET BONUS = $ratingStartValue WHERE RATING_ID IN (" . implode(',', $arRatingList) . ")";
3093 $DB->Query($strSql);
3094 $strSql = "
3095 UPDATE
3096 b_rating_user RU,
3097 ( SELECT
3098 TO_USER_ID as ENTITY_ID, COUNT(*) as CNT
3099 FROM
3100 b_forum_user_points FUP
3101 GROUP BY TO_USER_ID
3102 ) as RP
3103 SET
3104 RU.BONUS = " . $DB->IsNull('RP.CNT', '0') . "+" . $ratingStartValue . "
3105 WHERE
3106 RU.RATING_ID IN (" . implode(',', $arRatingList) . ")
3107 and RU.ENTITY_ID = RP.ENTITY_ID
3108 ";
3109 $DB->Query($strSql);
3110 }
3111 else
3112 {
3113 if (isset($arParams['DEFAULT_CONFIG_NEW_USER']) && $arParams['DEFAULT_CONFIG_NEW_USER'] == 'Y' && !empty($arRatingList))
3114 {
3115 $ratingStartValue = COption::GetOptionString("main", "rating_start_authority", 3);
3116 $strSql = "UPDATE b_rating_user SET BONUS = " . $ratingStartValue . " WHERE RATING_ID IN (" . implode(',', $arRatingList) . ")";
3117 $DB->Query($strSql);
3118 }
3119 }
3120
3121 return true;
3122 }
3123
3124 public static function AutoAssignGroup($groupId, $authorityValueAdd, $authorityValueDelete)
3125 {
3126 global $DB;
3127
3128 $groupId = intval($groupId);
3129 if ($groupId == 0)
3130 {
3131 return false;
3132 }
3133
3134 $ratingId = CRatings::GetAuthorityRating();
3135 $ratingValueAdd = intval($authorityValueAdd);
3136 $ratingValueDelete = intval($authorityValueDelete);
3137 $sRatingWeightType = COption::GetOptionString("main", "rating_weight_type", "auto");
3138 if ($sRatingWeightType == 'auto')
3139 {
3140 $ratingValueAdd = $ratingValueAdd * COption::GetOptionString("main", "rating_vote_weight", 1);
3141 $ratingValueDelete = $ratingValueDelete * COption::GetOptionString("main", "rating_vote_weight", 1);
3142 }
3143
3144 // remove the group from all users who it is, but you need to remove it
3145 $strSql = "
3146 SELECT rr.ENTITY_ID
3147 FROM b_rating_results rr
3148 WHERE rr.RATING_ID = $ratingId
3149 AND rr.CURRENT_VALUE < $ratingValueDelete
3150 GROUP BY rr.ENTITY_ID
3151 ";
3152 $res = $DB->Query($strSql);
3153 while ($row = $res->Fetch())
3154 {
3155 CUser::RemoveUserGroup($row['ENTITY_ID'], [$groupId]);
3156 }
3157
3158 // add a group to all users who do not, but you need to add it
3159 $strSql = "
3160 SELECT rr.ENTITY_ID
3161 FROM b_rating_results rr
3162 LEFT JOIN b_user_group ug ON ug.GROUP_ID = $groupId AND ug.USER_ID = rr.ENTITY_ID
3163 WHERE rr.RATING_ID = $ratingId
3164 and rr.CURRENT_VALUE >= $ratingValueAdd
3165 and ug.USER_ID IS NULL
3166 GROUP BY rr.ENTITY_ID
3167 ";
3168 $res = $DB->Query($strSql);
3169 while ($row = $res->Fetch())
3170 {
3171 CUser::AppendUserGroup($row['ENTITY_ID'], [$groupId]);
3172 }
3173
3174 return true;
3175 }
3176
3177 public static function GetRatingVoteListSQL($arParam, $bplus, $bIntranetInstalled, $includeReaction = false)
3178 {
3179 global $DB, $USER;
3180
3181 $externalAuthTypes = array_diff(\Bitrix\Main\UserTable::getExternalUserTypes(), ['email', 'replica']);
3182
3183 $reactionField = $includeReaction ? "RV.REACTION," : "";
3184
3185 $groupBy = "U.ID, U.NAME, U.LAST_NAME, U.SECOND_NAME, U.LOGIN, U.PERSONAL_PHOTO, RV.VALUE, RV.USER_ID";
3186 if ($includeReaction)
3187 {
3188 $groupBy .= ", RV.REACTION";
3189 }
3190
3191 return "
3192 SELECT
3193 U.ID,
3194 U.NAME,
3195 U.LAST_NAME,
3196 U.SECOND_NAME,
3197 U.LOGIN,
3198 U.PERSONAL_PHOTO,
3199 $reactionField
3200 RV.VALUE AS VOTE_VALUE,
3201 RV.USER_ID,
3202 SUM(case when RV0.ID is not null then 1 else 0 end) " . $DB->quote("RANK") . ",
3203 MIN(RV.ID) RV_ID
3204 FROM
3205 b_rating_vote RV LEFT JOIN b_rating_vote RV0 ON RV0.USER_ID = " . intval($USER->GetId()) . " and RV0.OWNER_ID = RV.USER_ID
3206 INNER JOIN b_user U ON RV.USER_ID = U.ID
3207 WHERE
3208 (CASE WHEN U.EXTERNAL_AUTH_ID IN ('" . join("', '", $externalAuthTypes) . "') THEN 'Y' ELSE 'N' END) = 'N'
3209 AND RV.ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "'
3210 and RV.ENTITY_ID = " . intval($arParam['ENTITY_ID']) . "
3211 " . self::getReactionFilterSQL($arParam, $bplus) . "
3212 GROUP BY $groupBy
3213 ORDER BY " . ($bIntranetInstalled ? "RV.VALUE DESC, " . $DB->quote("RANK") . " DESC, RV_ID DESC" : $DB->quote("RANK") . " DESC, RV.VALUE DESC, RV_ID DESC");
3214 }
3215
3216 public static function GetRatingVoteListSQLExtended($arParam, $bplus, $bIntranetInstalled, $includeReaction = false)
3217 {
3218 global $DB, $USER;
3219
3220 $externalAuthTypes = array_diff(\Bitrix\Main\UserTable::getExternalUserTypes(), ['email', 'replica']);
3221
3222 $reactionField = $includeReaction ? "RV.REACTION," : "";
3223
3224 $groupBy = "U.ID, RV.VALUE, RV.USER_ID";
3225 if ($includeReaction)
3226 {
3227 $groupBy .= ", RV.REACTION";
3228 }
3229
3230 return "
3231 SELECT
3232 U.ID,
3233 RV.VALUE AS VOTE_VALUE,
3234 RV.USER_ID,
3235 $reactionField
3236 SUM(case when RV0.ID is not null then 1 else 0 end) " . $DB->quote("RANK") . ",
3237 MIN(RV.ID) RV_ID
3238 FROM
3239 b_rating_vote RV
3240 LEFT JOIN b_rating_vote RV0 ON RV0.USER_ID = " . intval($USER->GetId()) . " and RV0.OWNER_ID = RV.USER_ID
3241 INNER JOIN b_user U ON RV.USER_ID = U.ID
3242 WHERE
3243 (CASE WHEN U.EXTERNAL_AUTH_ID IN ('" . join("', '", $externalAuthTypes) . "') THEN 'Y' ELSE 'N' END) = 'N'
3244 AND RV.ENTITY_TYPE_ID = '" . $DB->ForSql($arParam['ENTITY_TYPE_ID']) . "'
3245 and RV.ENTITY_ID = " . intval($arParam['ENTITY_ID']) . "
3246 " . self::getReactionFilterSQL($arParam, $bplus) . "
3247 GROUP BY $groupBy
3248 ORDER BY " . ($bIntranetInstalled ? "RV.VALUE DESC, " . $DB->quote("RANK") . " DESC, RV_ID DESC" : $DB->quote("RANK") . " DESC, RV.VALUE DESC, RV_ID DESC");
3249 }
3250
3251 private static function getReactionFilterSQL($arParam, $bplus)
3252 {
3253 global $DB;
3254
3255 $result = (
3256 $bplus
3257 && !empty($arParam["REACTION"])
3258 ? (
3259 $arParam["REACTION"] == self::REACTION_DEFAULT
3260 ? " and (RV.REACTION IS NULL OR RV.REACTION = '" . $DB->ForSql($arParam["REACTION"]) . "') "
3261 : " and RV.REACTION = '" . $DB->ForSql($arParam["REACTION"]) . "' "
3262 )
3263 : ""
3264 );
3265
3266 return $result;
3267 }
3268}
$arParams
Определения access_dialog.php:21
$connection
Определения actionsdefinitions.php:38
$count
Определения admin_tab.php:4
$type
Определения options.php:106
$db_res
Определения options_user_settings.php:8
$arResult
Определения generate_coupon.php:16
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
static isModuleInstalled($moduleName)
Определения modulemanager.php:125
static getList(array $parameters=array())
Определения datamanager.php:431
Определения ratings.php:6
static GetRatingVoteListSQL($arParam, $bplus, $bIntranetInstalled, $includeReaction=false)
Определения ratings.php:3177
static SetWeight($arConfigs)
Определения ratings.php:1577
static __UpdateComponents($ID, $arFields)
Определения ratings.php:1909
static SetAuthorityDefaultValue($arParams)
Определения ratings.php:3073
static OnAfterUserRegister($arFields)
Определения ratings.php:1736
static AddResults($arResults)
Определения ratings.php:2741
const REACTION_KISS
Определения ratings.php:8
static CheckAllowVote($arVoteParam)
Определения ratings.php:2918
static SetVoteGroup($arGroupId, $type)
Определения ratings.php:1621
static AddRatingVote($arParam)
Определения ratings.php:817
static GetRatingConfigs($objectType=null, $withRatingType=true)
Определения ratings.php:498
static getEntityRatingData($params=[])
Определения ratings.php:2231
const REACTION_LAUGH
Определения ratings.php:9
static Delete($ID)
Определения ratings.php:360
static GetRatingEntityTypes($objectType=null)
Определения ratings.php:463
static GetAuthorityRating()
Определения ratings.php:1475
const REACTION_WONDER
Определения ratings.php:11
static SetAuthorityRating($ratingId)
Определения ratings.php:2791
static Add($arFields)
Определения ratings.php:232
static GetByID($ID)
Определения ratings.php:15
static GetList($arSort=[], $arFilter=[])
Определения ratings.php:94
static GetRatingObjects()
Определения ratings.php:444
static getRatingVoteList($arParam)
Определения ratings.php:1984
static BuildRating($ID)
Определения ratings.php:2474
static getRatingVoteReaction($arParam)
Определения ratings.php:1930
static GetRatingUserProp($ratingId, $entityId)
Определения ratings.php:1352
static OnUserDelete($ID)
Определения ratings.php:1730
static UpdateRatingUserBonus($arParam)
Определения ratings.php:1305
static GetWeightList($arSort=[], $arFilter=[])
Определения ratings.php:1492
static __AddComponents($ID, $arFields)
Определения ratings.php:1854
static GetVoteGroupEx($type='')
Определения ratings.php:1676
static GetRatingVoteListSQLExtended($arParam, $bplus, $bIntranetInstalled, $includeReaction=false)
Определения ratings.php:3216
static ClearData()
Определения ratings.php:1708
static DeleteByUser($ID)
Определения ratings.php:2680
static getUserWeight($userId=0)
Определения ratings.php:2137
static GetArrayByID($ID)
Определения ratings.php:39
static ChangeRatingVote($arParam)
Определения ratings.php:1028
const REACTION_CRY
Определения ratings.php:12
static getUserData($userId=0, $value=0)
Определения ratings.php:2172
static GetRatingVoteResultCache($entityTypeId, $entityId, $user_id=0)
Определения ratings.php:580
const REACTION_DEFAULT
Определения ratings.php:7
static err_mess()
Определения ratings.php:1925
static __CheckFields($arFields)
Определения ratings.php:1818
static GetRatingResult($ID, $entityId)
Определения ratings.php:729
static GetVoteGroup($type='')
Определения ratings.php:1656
static AddComponentResults($arComponentConfigs)
Определения ratings.php:2772
static deleteRatingVoting(array $params=[])
Определения ratings.php:2444
const REACTION_ANGRY
Определения ratings.php:10
static Calculate($ID, $bForceRecalc=false)
Определения ratings.php:385
static GetRatingVoteResult($entityTypeId, $entityId, $user_id=0)
Определения ratings.php:549
static GetRatingUserPropEx($ratingId, $entityId)
Определения ratings.php:1424
static Update($ID, $arFields)
Определения ratings.php:281
static __SortWeight($a, $b)
Определения ratings.php:1807
static GetCommunityInfo($ratingId)
Определения ratings.php:2806
static GetRatingValueInfo($ratingId)
Определения ratings.php:214
static CancelRatingVote($arParam)
Определения ratings.php:1183
static AutoAssignGroup($groupId, $authorityValueAdd, $authorityValueDelete)
Определения ratings.php:3124
global $CACHE_MANAGER
Определения clear_component_cache.php:7
$arFields
Определения dblapprove.php:5
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$arGroups
Определения options.php:1766
$res
Определения filter_act.php:7
GetFilterSqlSearch($arSqlSearch=array(), $FilterLogic="FILTER_logic")
Определения filter_tools.php:397
GetFilterQuery($field, $val, $procent="Y", $ex_sep=array(), $clob="N", $div_fields="Y", $clob_upper="N")
Определения filter_tools.php:383
$result
Определения get_property_values.php:14
if($ajaxMode) $ID
Определения get_user.php:27
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
const BX_RESIZE_IMAGE_EXACT
Определения constants.php:12
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
IsModuleInstalled($module_id)
Определения tools.php:5301
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
is_set($a, $k=false)
Определения tools.php:2133
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$entityId
Определения payment.php:4
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
else $a
Определения template.php:137
$val
Определения options.php:1793
$arRes
Определения options.php:104
$rows
Определения options.php:264
$GLOBALS['_____370096793']
Определения update_client.php:1
$arFilter
Определения user_search.php:106