1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
iblockelement.php
См. документацию.
1<?php
2
12
13IncludeModuleLangFile(__FILE__);
14
18$BX_IBLOCK_PROP_CACHE = Array();
21
23{
24 public const WORKFLOW_STATUS_UNLOCK = 'green';
25 public const WORKFLOW_STATUS_CURRENT_LOCK = 'yellow';
26 public const WORKFLOW_STATUS_LOCK = 'red';
27
28 private const PROPERTY_LINK_ELEMENT_MASK = '/^([^.]+)\\.([^.]+)$/';
29
30 private const JOIN_TYPE_SELECT = 0x01;
31 private const JOIN_TYPE_WHERE = 0x02;
32 private const JOIN_TYPE_GROUP = 0x04;
33 private const JOIN_TYPE_ORDER = 0x08;
34
35 public string $LAST_ERROR = '';
36 protected $bWF_SetMove = true;
37
38 public $strField;
39 protected $subQueryProp;
40 public $arFilter;
41
43 public $bDistinct;
45
52
53 public $sSelect;
54 public $sFrom;
55 public $sWhere;
56 public $sGroupBy;
57 public $sOrderBy;
58 public ?string $countFrom = null;
59
60 protected static $elementIblock = array();
61
65 protected $searchIncluded;
66
67 protected $userExists;
68 protected $userId;
69 protected bool $isAdmin;
70
71 protected $iblock;
72 protected $iblockLanguage;
73
75
76 protected $offerProperties = array();
77
78 private static array $propertyIdentifierMasks = [
79 '/^[0-9]+([A-Z_]*)$/',
80 '/^[A-Z_][A-Z0-9_]*$/',
81 ];
82
83 private static array $propertyLinkFieldIdentifierMasks = [
84 '/^[A-Z][A-Z_]*$/',
85 '/^PROPERTY_[0-9]+$/',
86 '/^PROPERTY_[A-Z_][A-Z0-9_]*$/',
87 ];
88
89 public function __construct()
90 {
91 global $USER;
92
93 $this->catalogIncluded = Loader::includeModule('catalog');
94 $this->workflowIncluded = Loader::includeModule('workflow');
95 $this->bizprocInstalled = ModuleManager::isModuleInstalled('bizproc');
96 $this->searchIncluded = Loader::includeModule('search');
97 $this->userExists = isset($USER) && $USER instanceof \CUser;
98 $this->userId = ($this->userExists ? (int)$USER->GetID() : 0);
99 $this->isAdmin = $this->userExists && $USER->IsAdmin();
100 $this->iblock = null;
101 $this->iblockLanguage = null;
102 }
103
104 public function setIblock(?int $iblockId): void
105 {
106 $iblock = null;
107 $language = null;
108 if ($iblockId !== null)
109 {
110 $iblock = CIBlock::GetArrayByID($iblockId);
111 if (!is_array($iblock))
112 {
113 $iblock = null;
114 }
115 else
116 {
117 $iblock['ID'] = (int)$iblock['ID'];
118 $language = static::getIblockLanguage($iblock['ID']);
119 }
120 }
121 $this->iblock = $iblock;
122 $this->iblockLanguage = $language;
123 }
124
130 public static function SubQuery($strField, $arFilter)
131 {
132 if(mb_substr($strField, 0, 9) == "PROPERTY_")
133 {
134 if (!is_array($arFilter))
135 {
136 return null;
137 }
138 $iblockId = null;
139 if (isset($arFilter['IBLOCK_ID']))
140 {
141 $iblockId = $arFilter['IBLOCK_ID'];
142 }
143 elseif (isset($arFilter['=IBLOCK_ID']))
144 {
145 $iblockId = $arFilter['=IBLOCK_ID'];
146 }
147 if ($iblockId === null)
148 {
149 return null;
150 }
151
152 $db_prop = CIBlockProperty::GetPropertyArray(
153 mb_substr($strField, 9),
154 CIBlock::_MergeIBArrays(
155 $iblockId,
156 $arFilter["IBLOCK_CODE"] ?? false,
157 $arFilter["~IBLOCK_ID"] ?? false,
158 $arFilter["~IBLOCK_CODE"] ?? false
159 )
160 );
161 if ($db_prop && $db_prop["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_ELEMENT)
162 {
163 $ob = new CIBlockElement;
164 $ob->subQueryProp = $db_prop;
165 $ob->strField = $strField;
166 $ob->arFilter = $arFilter;
167 return $ob;
168 }
169 }
170 elseif($strField == "ID")
171 {
172 $ob = new CIBlockElement;
173 $ob->strField = $strField;
174 $ob->arFilter = $arFilter;
175 return $ob;
176 }
177
178 return null;
179 }
180
181 public function CancelWFSetMove()
182 {
183 $this->bWF_SetMove = false;
184 }
185
186 public static function WF_Restore($ID)
187 {
188 $obElement = new CIBlockElement;
189 $rsElement = $obElement->GetByID($ID);
190 if($arElement = $rsElement->Fetch())
191 {
192 if($arElement["WF_PARENT_ELEMENT_ID"] <> '')
193 {
194 $arElement["PROPERTY_VALUES"] = array();
195 $rsProperties = $obElement->GetProperty($arElement["IBLOCK_ID"], $arElement["WF_PARENT_ELEMENT_ID"], "sort", "asc", array("PROPERTY_TYPE"=>"F"));
196 while($arProperty = $rsProperties->Fetch())
197 {
198 if(!array_key_exists($arProperty["ID"], $arElement["PROPERTY_VALUES"]))
199 {
200 $arElement["PROPERTY_VALUES"][$arProperty["ID"]] = array();
201 }
202 $arElement["PROPERTY_VALUES"][$arProperty["ID"]][$arProperty["PROPERTY_VALUE_ID"]] = array(
203 "del" => "Y",
204 );
205 }
206 $n = 1;
207 $rsProperties = $obElement->GetProperty($arElement["IBLOCK_ID"], $arElement["ID"]);
208 while($arProperty = $rsProperties->Fetch())
209 {
210 if(!array_key_exists($arProperty["ID"], $arElement["PROPERTY_VALUES"]))
211 {
212 $arElement["PROPERTY_VALUES"][$arProperty["ID"]] = array();
213 }
214 if($arProperty["PROPERTY_TYPE"] == "F")
215 {
216 $arElement["PROPERTY_VALUES"][$arProperty["ID"]]["n".$n] = array(
217 "VALUE" => $arProperty["VALUE"],
218 "DESCRIPTION" => $arProperty["DESCRIPTION"],
219 );
220 $n++;
221 }
222 else
223 {
224 $arElement["PROPERTY_VALUES"][$arProperty["ID"]][$arProperty["PROPERTY_VALUE_ID"]] = array(
225 "VALUE" => $arProperty["VALUE"],
226 "DESCRIPTION" => $arProperty["DESCRIPTION"],
227 );
228 }
229 }
230
231 return $obElement->Update($arElement["WF_PARENT_ELEMENT_ID"], $arElement, true);
232 }
233 }
234 return false;
235 }
236
238 // Clear history
240 public static function WF_CleanUpHistory()
241 {
242 if (CModule::IncludeModule("workflow"))
243 {
244 global $DB;
245
246 $HISTORY_DAYS = COption::GetOptionInt("workflow", "HISTORY_DAYS", -1);
247 if($HISTORY_DAYS >= 0)
248 {
249 $arDate = localtime(time());
250 $date = mktime(0, 0, 0, $arDate[4]+1, $arDate[3]-$HISTORY_DAYS, 1900+$arDate[5]);
251
252 CTimeZone::Disable();
253 $strSql = "
254 SELECT ID, WF_PARENT_ELEMENT_ID
255 FROM b_iblock_element
256 WHERE TIMESTAMP_X <= ".$DB->CharToDateFunction(ConvertTimeStamp($date, "FULL"))."
257 AND WF_PARENT_ELEMENT_ID is not null
258 ORDER BY ID DESC
259 ";
260 $rsElements = $DB->Query($strSql);
261 CTimeZone::Enable();
262
263 //This Fetch will keep at least one history copy
264 //in order to prevent files being deleted
265 //before they copied into working copy
266 if($rsElements->Fetch())
267 {
268 while($arElement = $rsElements->Fetch())
269 {
270 $LAST_ID = CIBlockElement::WF_GetLast($arElement["WF_PARENT_ELEMENT_ID"]);
271 if($LAST_ID != $arElement["ID"])
272 {
273 CIBlockElement::Delete($arElement["ID"]);
274 }
275 }
276 }
277 }
278 }
279 }
280
281 // Send changing status message
283 public function WF_SetMove($NEW_ID, $OLD_ID = 0)
284 {
285 if(CModule::IncludeModule("workflow"))
286 {
287 global $DB, $USER;
288
289 $USER_ID = is_object($USER)? (int)$USER->GetID(): 0;
290 $NEW = "Y";
291 $OLD_ID = (int)$OLD_ID;
292 $NEW_ID = (int)$NEW_ID;
293 $oldStatusId = 0;
294 if($OLD_ID>0)
295 {
296 $old = $DB->Query("SELECT WF_STATUS_ID FROM b_iblock_element WHERE ID = ".$OLD_ID);
297 if($old_r=$old->Fetch())
298 {
299 $NEW = "N";
300 $oldStatusId = (int)$old_r["WF_STATUS_ID"];
301 }
302 }
303 CTimeZone::Disable();
304 $new = CIBlockElement::GetByID($NEW_ID);
305 CTimeZone::Enable();
306
307 if($new_r=$new->Fetch())
308 {
309 $NEW_STATUS_ID = (int)$new_r["WF_STATUS_ID"];
310 $OLD_STATUS_ID = $oldStatusId;
311 $PARENT_ID = (int)$new_r["WF_PARENT_ELEMENT_ID"];
312
313 CTimeZone::Disable();
314 $parent = CIBlockElement::GetByID($PARENT_ID);
315 CTimeZone::Enable();
316
317 if($parent_r = $parent->Fetch())
318 {
320 "TIMESTAMP_X" => $DB->GetNowFunction(),
321 "IBLOCK_ELEMENT_ID" => $PARENT_ID,
322 "OLD_STATUS_ID" => $OLD_STATUS_ID,
323 "STATUS_ID" => $NEW_STATUS_ID,
324 "USER_ID" => $USER_ID,
325 );
326 $DB->Insert("b_workflow_move", $arFields);
327 if($NEW_STATUS_ID != $OLD_STATUS_ID)
328 {
329 // Get creator Email
330 $strSql = "SELECT EMAIL FROM b_user WHERE ID = ".(int)$parent_r["CREATED_BY"];
331 $rs = $DB->Query($strSql);
332 if($ar = $rs->Fetch())
333 $parent_r["CREATED_BY_EMAIL"] = $ar["EMAIL"];
334 else
335 $parent_r["CREATED_BY_EMAIL"] = "";
336
337 // gather email of the workflow admins
338 $WORKFLOW_ADMIN_GROUP_ID = (int)Main\Config\Option::get("workflow", "WORKFLOW_ADMIN_GROUP_ID");
339 $strSql = "
340 SELECT U.ID, U.EMAIL
341 FROM b_user U, b_user_group UG
342 WHERE
343 UG.GROUP_ID=".$WORKFLOW_ADMIN_GROUP_ID."
344 AND U.ID = UG.USER_ID
345 AND U.ACTIVE='Y'
346 ";
347 $rs = $DB->Query($strSql);
348 $arAdmin = Array();
349 while($ar = $rs->Fetch())
350 {
351 $arAdmin[$ar["ID"]] = $ar["EMAIL"];
352 }
353
354 // gather email for BCC
355 $arBCC = array();
356
357 // gather all who changed doc in its current status
358 $strSql = "
359 SELECT U.EMAIL
360 FROM
361 b_workflow_move WM
362 INNER JOIN b_user U on U.ID = WM.USER_ID
363 WHERE
364 IBLOCK_ELEMENT_ID = ".$PARENT_ID."
365 AND OLD_STATUS_ID = ".$NEW_STATUS_ID."
366 ";
367 $rs = $DB->Query($strSql);
368 while($ar = $rs->Fetch())
369 {
370 $arBCC[$ar["EMAIL"]] = $ar["EMAIL"];
371 }
372
373 // gather all editors
374 // in case status have notifier flag
375
376 //First those who have write permissions on iblock
377 $strSql = "
378 SELECT U.EMAIL
379 FROM
380 b_workflow_status S
381 INNER JOIN b_workflow_status2group SG on SG.STATUS_ID = S.ID
382 INNER JOIN b_iblock_group IG on IG.GROUP_ID = SG.GROUP_ID
383 INNER JOIN b_user_group UG on UG.GROUP_ID = IG.GROUP_ID
384 INNER JOIN b_user U on U.ID = UG.USER_ID
385 WHERE
386 S.ID = ".$NEW_STATUS_ID."
387 AND S.NOTIFY = 'Y'
388 AND IG.IBLOCK_ID = ".intval($new_r["IBLOCK_ID"])."
389 AND IG.PERMISSION >= 'U'
390 AND SG.PERMISSION_TYPE = '2'
391 AND U.ACTIVE = 'Y'
392 ";
393 $rs = $DB->Query($strSql);
394 while($ar = $rs->Fetch())
395 {
396 $arBCC[$ar["EMAIL"]] = $ar["EMAIL"];
397 }
398
399 //Second admins if they in PERMISSION_TYPE = 2 list
400 //because they have all the rights
401 $strSql = "
402 SELECT U.EMAIL
403 FROM
404 b_workflow_status S
405 INNER JOIN b_workflow_status2group SG on SG.STATUS_ID = S.ID
406 INNER JOIN b_user_group UG on UG.GROUP_ID = SG.GROUP_ID
407 INNER JOIN b_user U on U.ID = UG.USER_ID
408 WHERE
409 S.ID = ".$NEW_STATUS_ID."
410 AND S.NOTIFY = 'Y'
411 AND SG.GROUP_ID = 1
412 AND SG.PERMISSION_TYPE = '2'
413 AND U.ACTIVE = 'Y'
414 ";
415 $rs = $DB->Query($strSql);
416 while($ar = $rs->Fetch())
417 {
418 $arBCC[$ar["EMAIL"]] = $ar["EMAIL"];
419 }
420
421 $iblock_r = CIBlock::GetArrayByID($new_r["IBLOCK_ID"]);
422 $iblock_r["LID"] = array();
423 $rsIBlockSite = $DB->Query("SELECT SITE_ID FROM b_iblock_site WHERE IBLOCK_ID= ".(int)$new_r["IBLOCK_ID"]);
424 while($arIBlockSite = $rsIBlockSite->Fetch())
425 $iblock_r["LID"][] = $arIBlockSite["SITE_ID"];
426
427 if(array_key_exists($new_r["MODIFIED_BY"], $arAdmin))
428 $new_r["USER_NAME"] .= " (Admin)";
429 // it is not new doc
430 if($NEW!="Y")
431 {
432 if(array_key_exists($parent_r["CREATED_BY"], $arAdmin))
433 $parent_r["CREATED_USER_NAME"] .= " (Admin)";
434
435 // send change notification
436 $arEventFields = array(
437 "ID" => $PARENT_ID,
438 "IBLOCK_ID" => $new_r["IBLOCK_ID"],
439 "IBLOCK_TYPE" => $iblock_r["IBLOCK_TYPE_ID"],
440 "ADMIN_EMAIL" => implode(",", $arAdmin),
441 "BCC" => implode(",", $arBCC),
442 "PREV_STATUS_ID" => $OLD_STATUS_ID,
443 "PREV_STATUS_TITLE" => CIblockElement::WF_GetStatusTitle($OLD_STATUS_ID),
444 "STATUS_ID" => $NEW_STATUS_ID,
445 "STATUS_TITLE" => CIblockElement::WF_GetStatusTitle($NEW_STATUS_ID),
446 "DATE_CREATE" => $parent_r["DATE_CREATE"],
447 "CREATED_BY_ID" => $parent_r["CREATED_BY"],
448 "CREATED_BY_NAME" => $parent_r["CREATED_USER_NAME"],
449 "CREATED_BY_EMAIL" => $parent_r["CREATED_BY_EMAIL"],
450 "DATE_MODIFY" => $new_r["TIMESTAMP_X"],
451 "MODIFIED_BY_ID" => $new_r["MODIFIED_BY"],
452 "MODIFIED_BY_NAME" => $new_r["USER_NAME"],
453 "NAME" => $new_r["NAME"],
454 "SECTION_ID" => $new_r["IBLOCK_SECTION_ID"],
455 "PREVIEW_HTML" => ($new_r["PREVIEW_TEXT_TYPE"]=="html" ?$new_r["PREVIEW_TEXT"]:TxtToHtml($new_r["PREVIEW_TEXT"])),
456 "PREVIEW_TEXT" => ($new_r["PREVIEW_TEXT_TYPE"]=="text"? $new_r["PREVIEW_TEXT"]:HtmlToTxt($new_r["PREVIEW_TEXT"])),
457 "PREVIEW" => $new_r["PREVIEW_TEXT"],
458 "PREVIEW_TYPE" => $new_r["PREVIEW_TEXT_TYPE"],
459 "DETAIL_HTML" => ($new_r["DETAIL_TEXT_TYPE"]=="html" ?$new_r["DETAIL_TEXT"]:TxtToHtml($new_r["DETAIL_TEXT"])),
460 "DETAIL_TEXT" => ($new_r["DETAIL_TEXT_TYPE"]=="text"? $new_r["DETAIL_TEXT"]:HtmlToTxt($new_r["DETAIL_TEXT"])),
461 "DETAIL" => $new_r["DETAIL_TEXT"],
462 "DETAIL_TYPE" => $new_r["DETAIL_TEXT_TYPE"],
463 "COMMENTS" => $new_r["WF_COMMENTS"]
464 );
465 CEvent::Send("WF_IBLOCK_STATUS_CHANGE", $iblock_r["LID"], $arEventFields);
466 }
467 else // otherwise
468 {
469 // it was new one
470
471 $arEventFields = array(
472 "ID" => $PARENT_ID,
473 "IBLOCK_ID" => $new_r["IBLOCK_ID"],
474 "IBLOCK_TYPE" => $iblock_r["IBLOCK_TYPE_ID"],
475 "ADMIN_EMAIL" => implode(",", $arAdmin),
476 "BCC" => implode(",", $arBCC),
477 "STATUS_ID" => $NEW_STATUS_ID,
478 "STATUS_TITLE" => CIblockElement::WF_GetStatusTitle($NEW_STATUS_ID),
479 "DATE_CREATE" => $parent_r["DATE_CREATE"],
480 "CREATED_BY_ID" => $parent_r["CREATED_BY"],
481 "CREATED_BY_NAME" => $parent_r["CREATED_USER_NAME"],
482 "CREATED_BY_EMAIL" => $parent_r["CREATED_BY_EMAIL"],
483 "NAME" => $new_r["NAME"],
484 "PREVIEW_HTML" => ($new_r["PREVIEW_TEXT_TYPE"]=="html" ?$new_r["PREVIEW_TEXT"]:TxtToHtml($new_r["PREVIEW_TEXT"])),
485 "PREVIEW_TEXT" => ($new_r["PREVIEW_TEXT_TYPE"]=="text"? $new_r["PREVIEW_TEXT"]:HtmlToTxt($new_r["PREVIEW_TEXT"])),
486 "PREVIEW" => $new_r["PREVIEW_TEXT"],
487 "PREVIEW_TYPE" => $new_r["PREVIEW_TEXT_TYPE"],
488 "SECTION_ID" => $new_r["IBLOCK_SECTION_ID"],
489 "DETAIL_HTML" => ($new_r["DETAIL_TEXT_TYPE"]=="html" ?$new_r["DETAIL_TEXT"]:TxtToHtml($new_r["DETAIL_TEXT"])),
490 "DETAIL_TEXT" => ($new_r["DETAIL_TEXT_TYPE"]=="text"? $new_r["DETAIL_TEXT"]:HtmlToTxt($new_r["DETAIL_TEXT"])),
491 "DETAIL" => $new_r["DETAIL_TEXT"],
492 "DETAIL_TYPE" => $new_r["DETAIL_TEXT_TYPE"],
493 "COMMENTS" => $new_r["WF_COMMENTS"]
494 );
495 CEvent::Send("WF_NEW_IBLOCK_ELEMENT",$iblock_r["LID"], $arEventFields);
496 }
497 }
498 }
499 }
500 }
501 }
502
504 // Clears the last or old records in history using parameters from workflow module
506 public static function WF_CleanUpHistoryCopies($ELEMENT_ID=false, $HISTORY_COPIES=false)
507 {
508 if(CModule::IncludeModule("workflow"))
509 {
510 global $DB;
511 if($HISTORY_COPIES===false)
512 $HISTORY_COPIES = intval(COption::GetOptionString("workflow","HISTORY_COPIES","10"));
513
514 $strSqlSearch = '';
515 $ELEMENT_ID = (int)$ELEMENT_ID;
516 if($ELEMENT_ID>0)
517 $strSqlSearch = " AND ID = $ELEMENT_ID ";
518 $strSql = "SELECT ID FROM b_iblock_element ".
519 "WHERE (ID=WF_PARENT_ELEMENT_ID or (WF_PARENT_ELEMENT_ID IS NULL AND WF_STATUS_ID=1)) ".
520 $strSqlSearch;
521 $z = $DB->Query($strSql);
522 while ($zr=$z->Fetch())
523 {
524 $DID = $zr["ID"];
525 $strSql =
526 "SELECT ID, WF_NEW, WF_PARENT_ELEMENT_ID ".
527 "FROM b_iblock_element ".
528 "WHERE WF_PARENT_ELEMENT_ID = ".$DID." ".
529 " AND WF_PARENT_ELEMENT_ID<>ID ".
530 " AND (WF_NEW<>'Y' or WF_NEW is null) ".
531 "ORDER BY ID desc";
532 $t = $DB->Query($strSql);
533 $i = 0;
534 while ($tr = $t->Fetch())
535 {
536 $i++;
537 if($i>$HISTORY_COPIES)
538 {
539 $LAST_ID = CIBlockElement::WF_GetLast($DID);
540 if($LAST_ID!=$tr["ID"])
541 {
542 CIBlockElement::Delete($tr["ID"]);
543 }
544 }
545 }
546 }
547 }
548 }
549
550 public static function WF_GetSqlLimit($PS="BE.", $SHOW_NEW="N")
551 {
552 if(CModule::IncludeModule("workflow"))
553 {
554 $limit = " and ((".$PS."WF_STATUS_ID=1 and ".$PS."WF_PARENT_ELEMENT_ID is null)";
555 if($SHOW_NEW=="Y") $limit .= " or ".$PS."WF_NEW='Y' ";
556 $limit .= " ) ";
557 }
558 else
559 {
560 $limit = " AND ".$PS."WF_STATUS_ID=1 and ".$PS."WF_PARENT_ELEMENT_ID is null ";
561 }
562 return $limit;
563 }
564
566 // Returns last ID of element in the history
568 public static function WF_GetLast($ID)
569 {
570 global $DB;
571 $ID = (int)$ID;
572
573 $z = $DB->Query("SELECT ID, WF_PARENT_ELEMENT_ID FROM b_iblock_element WHERE ID = ".$ID);
574 $zr = $z->Fetch();
575 $WF_PARENT_ELEMENT_ID = (int)$zr["WF_PARENT_ELEMENT_ID"];
576 if ($WF_PARENT_ELEMENT_ID > 0)
577 {
578 $strSql = "SELECT ID FROM b_iblock_element WHERE WF_PARENT_ELEMENT_ID='".$WF_PARENT_ELEMENT_ID."' ORDER BY ID desc";
579 $s = $DB->Query($strSql);
580 $sr = $s->Fetch();
581 if ($sr && $sr["ID"] > 0)
582 {
583 $ID = $sr["ID"];
584 }
585 }
586 else
587 {
588 $strSql = "SELECT ID, WF_STATUS_ID FROM b_iblock_element WHERE WF_PARENT_ELEMENT_ID='$ID' ORDER BY ID desc";
589 $s = $DB->Query($strSql);
590 $sr = $s->Fetch();
591 if ($sr && $sr['WF_STATUS_ID'] > 1 && $sr["ID"] > 0)
592 {
593 $ID = $sr["ID"];
594 }
595 }
596 return $ID;
597 }
598
603 public static function GetRealElement($ID): int
604 {
605 global $DB;
606 $ID = (int)$ID;
607 if ($ID <= 0)
608 {
609 return $ID;
610 }
611
612 $PARENT_ID = 0;
613 $z = $DB->Query("SELECT WF_PARENT_ELEMENT_ID FROM b_iblock_element WHERE ID='$ID'");
614 $zr = $z->Fetch();
615 unset($z);
616 if (!empty($zr))
617 {
618 $PARENT_ID = (int)$zr["WF_PARENT_ELEMENT_ID"];
619 }
620 unset($zr);
621
622 return ($PARENT_ID > 0 ? $PARENT_ID : $ID);
623 }
624
625 public static function WF_GetStatusTitle($STATUS_ID)
626 {
627 global $DB;
628
629 $zr = array(
630 'TITLE' => null
631 );
632 if(CModule::IncludeModule("workflow"))
633 {
634 $STATUS_ID = (int)$STATUS_ID;
635 if($STATUS_ID>0)
636 {
637 $strSql = "SELECT * FROM b_workflow_status WHERE ID='$STATUS_ID'";
638 $z = $DB->Query($strSql);
639 $zr = $z->Fetch();
640 }
641 }
642 return $zr["TITLE"];
643 }
644
645 public static function WF_GetCurrentStatus($ELEMENT_ID, &$STATUS_TITLE)
646 {
647 global $DB;
648 $STATUS_ID = 0;
649
650 if(CModule::IncludeModule("workflow"))
651 {
652 $ELEMENT_ID = (int)$ELEMENT_ID;
653
654 $WF_ID = (int)CIBlockElement::WF_GetLast($ELEMENT_ID);
655 if ($WF_ID <= 0)
656 $WF_ID = $ELEMENT_ID;
657
658 if ($WF_ID > 0)
659 {
660 $strSql =
661 "SELECT E.WF_STATUS_ID, S.TITLE ".
662 "FROM b_iblock_element E, b_workflow_status S ".
663 "WHERE E.ID = ".$WF_ID." ".
664 " AND S.ID = E.WF_STATUS_ID";
665 $z = $DB->Query($strSql);
666 $zr = $z->Fetch();
667 $STATUS_ID = $zr["WF_STATUS_ID"];
668 $STATUS_TITLE = $zr["TITLE"];
669 }
670 }
671 return (int)$STATUS_ID;
672 }
673
675 // Returns permission status
677 public static function WF_GetStatusPermission($STATUS_ID, $ID = false)
678 {
679 global $DB, $USER;
680 $result = false;
681 if(CModule::IncludeModule("workflow"))
682 {
684 return 2;
685 else
686 {
687 $ID = (int)$ID;
688 if($ID)
689 {
690 $arStatus = array();
691 $arSql = Array("ID='".$ID."'", "WF_PARENT_ELEMENT_ID='".$ID."'");
692 foreach($arSql as $where)
693 {
694 $strSql = "SELECT ID, WF_STATUS_ID FROM b_iblock_element WHERE ".$where;
695 $rs = $DB->Query($strSql);
696 while($ar = $rs->Fetch())
697 $arStatus[$ar["WF_STATUS_ID"]] = $ar["WF_STATUS_ID"];
698 }
699 }
700 else
701 {
702 $arStatus = array((int)($STATUS_ID)=>(int)($STATUS_ID));
703 }
704 $arGroups = $USER->GetUserGroupArray();
705 if (!is_array($arGroups))
706 {
707 $arGroups = [2];
708 }
709 $groups = implode(",",$arGroups);
710 foreach($arStatus as $STATUS_ID)
711 {
712 $strSql =
713 "SELECT max(G.PERMISSION_TYPE) as MAX_PERMISSION ".
714 "FROM b_workflow_status2group G ".
715 "WHERE G.STATUS_ID = ".$STATUS_ID." ".
716 " AND G.GROUP_ID in (".$groups.") ";
717 $rs = $DB->Query($strSql);
718 $ar = $rs->Fetch();
719 $ar["MAX_PERMISSION"] = (int)$ar["MAX_PERMISSION"];
720 if($result===false || ($result > $ar["MAX_PERMISSION"]))
721 $result = $ar["MAX_PERMISSION"];
722 }
723 }
724 }
725 return $result;
726 }
727
728 public static function WF_IsLocked($ID, &$locked_by, &$date_lock)
729 {
730 return static::WF_GetLockStatus($ID, $locked_by, $date_lock) === self::WORKFLOW_STATUS_LOCK;
731 }
732
741 public static function WF_GetLockStatus($ID, &$locked_by, &$date_lock)
742 {
743 global $USER;
744
746 $helper = $connection->getSqlHelper();
747
748 $ID = (int)$ID;
749 if ($ID <= 0)
750 {
751 return self::WORKFLOW_STATUS_UNLOCK;
752 }
753
754 $MAX_LOCK = (int)Main\Config\Option::get('workflow','MAX_LOCK_TIME','60');
755 $uid = is_object($USER)? (int)$USER->GetID(): 0;
756
757 $strSql = "
758 SELECT WF_LOCKED_BY,
759 WF_DATE_LOCK,
760 case
761 when WF_DATE_LOCK is null then '" . self::WORKFLOW_STATUS_UNLOCK . "'
762 when " . $helper->addSecondsToDateTime($MAX_LOCK * 60, 'WF_DATE_LOCK') . " < " . $helper->getCurrentDateTimeFunction() . " then '" . self::WORKFLOW_STATUS_UNLOCK . "'
763 when WF_LOCKED_BY = " . $uid . " then '" . self::WORKFLOW_STATUS_CURRENT_LOCK . "'
764 else '" . self::WORKFLOW_STATUS_LOCK . "'
765 end LOCK_STATUS
766 FROM b_iblock_element
767 WHERE ID = " . $ID . "
768 ";
769 unset($helper);
770
771 $iterator = $connection->query($strSql);
772 unset($connection);
773 $row = $iterator->fetch();
774 unset($iterator);
775
776 if (empty($row))
777 {
778 return self::WORKFLOW_STATUS_UNLOCK;
779 }
780
781 $locked_by = $row['WF_LOCKED_BY'];
782 $date_lock = $row['WF_DATE_LOCK'] instanceof Main\Type\DateTime ? $row['WF_DATE_LOCK']->toString() : $row['WF_DATE_LOCK'];
783
784 return $row['LOCK_STATUS'];
785 }
786
794 public static function WF_Lock($lastId, $bWorkFlow = true)
795 {
796 global $USER;
797 $lastId = (int)$lastId;
798 if ($lastId <= 0)
799 {
800 return;
801 }
802 $userId = $USER instanceof CUser ? (int)$USER->GetID(): 0;
803
804 $updateIds = [];
805 if ($bWorkFlow === true)
806 {
807 $row = ElementTable::getRow([
808 'select' => [
809 'WF_PARENT_ELEMENT_ID',
810 ],
811 'filter' => [
812 '=ID' => $lastId,
813 ],
814 ]);
815 if ($row)
816 {
817 $updateIds[] = $lastId;
818 $parentId = (int)$row['WF_PARENT_ELEMENT_ID'];
819 if ($parentId > 0)
820 {
821 $updateIds[] = $parentId;
822 }
823 }
824 }
825 else
826 {
827 $updateIds[] = $lastId;
828 }
829 if (!empty($updateIds))
830 {
832 $helper = $connection->getSqlHelper();
833
834 $query =
835 'update ' . $helper->quote(ElementTable::getTableName()) .
836 ' set'
837 . ' ' . $helper->quote('WF_DATE_LOCK') . ' = ' . $helper->getCurrentDateTimeFunction() . ','
838 . ' ' . $helper->quote('WF_LOCKED_BY') . ' = ' . $userId
839 . ' where ' . $helper->quote('ID') . ' in (' . implode(',', $updateIds) . ')'
840 ;
841 $connection->queryExecute($query);
842
843 unset($helper, $connection);
844 }
845 }
846
854 public static function WF_UnLock($lastId, $bWorkFlow = true)
855 {
856 global $USER;
857 $lastId = (int)$lastId;
858 if ($lastId <= 0)
859 {
860 return;
861 }
862 $userId = $USER instanceof CUser ? (int)$USER->GetID(): 0;
863
865 $helper = $connection->getSqlHelper();
866
867 if ($bWorkFlow === true)
868 {
869 $row = ElementTable::getRow([
870 'select' => [
871 'WF_PARENT_ELEMENT_ID',
872 'WF_LOCKED_BY',
873 ],
874 'filter' => [
875 '=ID' => $lastId,
876 ],
877 ]);
878 if ($row)
879 {
880 if (
881 (int)$row['WF_LOCKED_BY'] === $userId
882 || (
884 )
885 )
886 {
887 $updateIds = [
888 $lastId,
889 ];
890 $parentId = (int)$row['WF_PARENT_ELEMENT_ID'];
891 if ($parentId > 0)
892 {
893 $updateIds[] = $parentId;
894 }
895 $query =
896 'update ' . $helper->quote(ElementTable::getTableName())
897 . ' set'
898 . ' ' . $helper->quote('WF_DATE_LOCK') . ' = null, '
899 . ' ' . $helper->quote('WF_LOCKED_BY') . ' = null'
900 . ' where'
901 . ' ' . $helper->quote('ID' ). ' in (' . implode(',', $updateIds) . ')'
902 ;
903 if ($parentId > 0)
904 {
905 $query .= ' or ' . $helper->quote('WF_PARENT_ELEMENT_ID') . ' = ' . $parentId;
906 }
907 $connection->queryExecute($query);
908 }
909 }
910 }
911 else
912 {
913 $query =
914 'update ' . $helper->quote(ElementTable::getTableName())
915 . ' set'
916 . ' ' . $helper->quote('WF_DATE_LOCK') . ' = null, '
917 . ' ' . $helper->quote('WF_LOCKED_BY') . ' = null'
918 . ' where'
919 . ' ' . $helper->quote('ID') . ' = ' . $lastId
920 ;
921 $connection->queryExecute($query);
922 }
923
924 unset($helper, $connection);
925 }
926
936 public static function WF_GetHistoryList($ELEMENT_ID, $by = 's_id', $order = 'desc', $arFilter = [])
937 {
938 global $DB;
939
940 $ELEMENT_ID = (int)$ELEMENT_ID;
941 $strSqlSearch = "";
942 if(is_array($arFilter))
943 {
944 foreach ($arFilter as $key => $val)
945 {
946 if ((string)$val == '' || $val == "NOT_REF")
947 continue;
948 $val = $DB->ForSql($val);
949 $key = strtoupper($key);
950 switch($key)
951 {
952 case "ID":
953 $arr = explode(",", $val);
954 if (!empty($arr))
955 {
956 $arr = array_map("intval", $arr);
957 $str = implode(", ", $arr);
958 $strSqlSearch .= " and E.ID in (".$str.")";
959 }
960 break;
961 case "TIMESTAMP_FROM":
962 $strSqlSearch .= " and E.TIMESTAMP_X>=FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y"),"d.m.Y")."')";
963 break;
964 case "TIMESTAMP_TO":
965 $strSqlSearch .= " and E.TIMESTAMP_X<=FROM_UNIXTIME('".MkDateTime(FmtDate($val,"D.M.Y")." 23:59:59","d.m.Y H:i:s")."')";
966 break;
967 case "MODIFIED_BY":
968 case "MODIFIED_USER_ID":
969 $strSqlSearch .= " and E.MODIFIED_BY='" . (int)$val . "'";
970 break;
971 case "IBLOCK_ID":
972 $strSqlSearch .= " and E.IBLOCK_ID='" . (int)$val . "'";
973 break;
974 case "NAME":
975 if($val!="%%")
976 $strSqlSearch .= " and upper(E.NAME) like upper('".$DB->ForSQL($val,255)."')";
977 break;
978 case "STATUS":
979 case "STATUS_ID":
980 $strSqlSearch .= " and E.WF_STATUS_ID='" . (int)$val . "'";
981 break;
982 }
983 }
984 }
985
986 if($by == "s_id")
987 $strSqlOrder = "ORDER BY E.ID";
988 elseif($by == "s_timestamp")
989 $strSqlOrder = "ORDER BY E.TIMESTAMP_X";
990 elseif($by == "s_modified_by")
991 $strSqlOrder = "ORDER BY E.MODIFIED_BY";
992 elseif($by == "s_name")
993 $strSqlOrder = "ORDER BY E.NAME";
994 elseif($by == "s_status")
995 $strSqlOrder = "ORDER BY E.WF_STATUS_ID";
996 else
997 {
998 $strSqlOrder = "ORDER BY E.ID";
999 }
1000
1001 if($order != "asc")
1002 {
1003 $strSqlOrder .= " desc ";
1004 }
1005
1006 $strSql = "
1007 SELECT
1008 E.*,
1009 ".$DB->DateToCharFunction("E.TIMESTAMP_X")." TIMESTAMP_X,
1010 " . self::getUserNameSql('U') . " USER_NAME,
1011 S.TITLE STATUS_TITLE
1012 FROM
1013 b_iblock_element E
1014 INNER JOIN b_workflow_status S on S.ID = E.WF_STATUS_ID
1015 LEFT JOIN b_user U ON U.ID = E.MODIFIED_BY
1016 WHERE
1017 E.WF_PARENT_ELEMENT_ID = ".$ELEMENT_ID."
1018 ".$strSqlSearch."
1019 ".$strSqlOrder."
1020 ";
1021
1022 return $DB->Query($strSql);
1023 }
1024
1025 protected static function getSingleIblockIdFromFilter(array $filter): ?int
1026 {
1027 $iblockId = null;
1028 $list = [
1029 'IBLOCK_ID',
1030 '=IBLOCK_ID',
1031 ];
1032 foreach ($list as $index)
1033 {
1034 if (isset($filter[$index]) && is_numeric($filter[$index]))
1035 {
1036 $iblockId = (int)$filter[$index];
1037 if ($iblockId > 0)
1038 {
1039 break;
1040 }
1041 else
1042 {
1043 $iblockId = null;
1044 }
1045 }
1046 }
1047
1048 if ($iblockId === null)
1049 {
1050 return null;
1051 }
1052
1053 return
1054 CIBlock::GetArrayByID($iblockId, 'ID') === null
1055 ? null
1056 : $iblockId
1057 ;
1058 }
1059
1060 public function MkFilter($arFilter, &$arJoinProps, &$arAddWhereFields, $level = 0, $bPropertyLeftJoin = false)
1061 {
1062 global $DB, $USER;
1064 $helper = $connection->getSqlHelper();
1065
1066 $catalogIncluded = Loader::includeModule('catalog');
1067 $catalogFields = [];
1068
1069 $arSqlSearch = [];
1070 $permSQL = '';
1071
1072 $arSectionFilter = [
1073 'LOGIC' => '',
1074 'BE' => [],
1075 'BS' => [],
1076 ];
1077
1078 $specialFilterKeys = [
1079 'MIN_PERMISSION' => true,
1080 'PERMISSIONS_BY' => true,
1081 'INCLUDE_SUBSECTIONS' => true,
1082 'SECTION_SCOPE' => true,
1083 'SHOW_NEW' => true,
1084 'SHOW_BP_NEW' => true,
1085 'SHOW_HISTORY' => true,
1086 ];
1087
1088 if (!is_array($arFilter))
1089 {
1090 $arFilter = [];
1091 }
1092
1093 foreach ($arFilter as $key => $val)
1094 {
1095 $origKey = $key;
1096 $key = mb_strtoupper($key);
1097 if (str_ends_with($key, 'PROPERTY') && is_array($val))
1098 {
1099 unset($arFilter[$origKey]);
1100 $arFilter[$key] = array_change_key_case($val, CASE_UPPER);
1101 }
1102 }
1103
1104 foreach ($arFilter as $key => $val)
1105 {
1106 $origKey = $key;
1107 $key = mb_strtoupper($key);
1108 $p = mb_strpos($key, 'PROPERTY_');
1109 if ($p !== false && $p < 4)
1110 {
1111 $newIndex = mb_substr($key, 0, $p) . 'PROPERTY';
1112 $arFilter[$newIndex] ??= [];
1113 $arFilter[$newIndex][mb_substr($key, $p + 9)] = $val;
1114 unset($newIndex);
1115 unset($arFilter[$origKey]);
1116 }
1117 else
1118 {
1119 $p = strpos($key, 'SUBQUERY');
1120 if ($p !== false && $p < 4)
1121 {
1122 if (!empty($val) && is_array($val))
1123 {
1124 $arFilter[substr($key, 0, $p).'ID'] = static::SubQuery(
1125 $val['FIELD'],
1126 $val['FILTER']
1127 );
1128 }
1129 unset($arFilter[$origKey]);
1130 }
1131 }
1132 }
1133
1134 if (isset($arFilter['LOGIC']) && $arFilter['LOGIC'] === 'OR')
1135 {
1136 $Logic = 'OR';
1137 unset($arFilter['LOGIC']);
1138 $bPropertyLeftJoin = true;
1139 }
1140 else
1141 {
1142 $Logic = 'AND';
1143 }
1144
1145 if ($Logic === "AND" && $level === 0 && isset($arFilter['IBLOCK_ID']))
1146 {
1147 $f = new \Bitrix\Iblock\PropertyIndex\QueryBuilder($arFilter['IBLOCK_ID']);
1148 if ($f->isValid())
1149 {
1150 $arJoinProps['FC'] = $f->getFilterSql($arFilter, $arSqlSearch);
1151 $arJoinProps['FC_DISTINCT'] = $f->getDistinct();
1152 }
1153 unset($f);
1154 }
1155
1156 foreach ($arFilter as $orig_key => $val)
1157 {
1158 $res = CIBlock::MkOperationFilter($orig_key);
1159 $key = $res['FIELD'];
1160 $cOperationType = $res['OPERATION'];
1161
1162 //it was done before $key = strtoupper($key);
1163
1164 switch ($key)
1165 {
1166 case "ACTIVE":
1167 case "DETAIL_TEXT_TYPE":
1168 case "PREVIEW_TEXT_TYPE":
1169 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "string_equal", $bFullJoinTmp, $cOperationType);
1170 break;
1171 case "NAME":
1172 case "XML_ID":
1173 case "TMP_ID":
1174 case "DETAIL_TEXT":
1175 case "PREVIEW_TEXT":
1176 case "CODE":
1177 case "TAGS":
1178 case "WF_COMMENTS":
1179 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "string", $bFullJoinTmp, $cOperationType);
1180 break;
1181 case "SEARCHABLE_CONTENT":
1182 $iblockId = 0;
1183
1184 if (
1185 !empty($arFilter['IBLOCK_ID'])
1186 && is_scalar($arFilter['IBLOCK_ID'])
1187 )
1188 {
1189 $iblockId = (int)$arFilter['IBLOCK_ID'];
1190 }
1191 elseif (
1192 !empty($arFilter['~IBLOCK_ID'])
1193 && is_scalar($arFilter['~IBLOCK_ID'])
1194 )
1195 {
1196 $iblockId = (int)$arFilter['~IBLOCK_ID'];
1197 }
1198
1199 // TODO: temporary shutdown until request is corrected
1200 if (false && !empty($iblockId) && FullText::canUseFulltextSearch($iblockId))
1201 {
1202 $tableName = FullText::getTableName($iblockId);
1203 $alias = "BESI" . $iblockId;
1204
1205 if (!is_scalar($val))
1206 {
1207 break;
1208 }
1209
1210 $val = (string)$val;
1211
1212 if (mb_strlen($val) < Helper::getMinTokenSize())
1213 {
1214 break;
1215 }
1216
1217 $where = CIBlock::FilterCreateEx($alias . ".SEARCH_CONTENT", $val, "fulltext", $bFullJoinTmp, 'FT');
1218
1219 if (!empty($where))
1220 {
1221 $arSqlSearch[] = $where;
1222 $arJoinProps["BESI"] = " INNER JOIN " . $tableName . " " . $alias . " ON " . $alias . ".ELEMENT_ID = BE.ID ";
1223 }
1224 }
1225 else
1226 {
1227 if ($DB->IndexExists("b_iblock_element", array("SEARCHABLE_CONTENT")))
1228 {
1229 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "fulltext", $bFullJoinTmp, $cOperationType);
1230 }
1231 else
1232 {
1233 if ($cOperationType == "FT")
1234 $cOperationType = "FTL";
1235 elseif ($cOperationType == "FTI")
1236 $cOperationType = "E";
1237 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "string", $bFullJoinTmp, $cOperationType);
1238 }
1239 }
1240
1241 break;
1242 case "ID":
1243 if(is_object($val))
1244 {
1246 $val->prepareSql(array($val->strField), $val->arFilter, false, false);
1247 $arSqlSearch[] = 'BE.'.$key.(mb_substr($cOperationType, 0, 1) == "N"? ' NOT': '').' IN (
1248 SELECT '.$val->sSelect.'
1249 FROM '.$val->sFrom.'
1250 WHERE 1=1
1251 '.$val->sWhere.'
1252 )'
1253 ;
1254 }
1255 else
1256 {
1257 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "number", $bFullJoinTmp, $cOperationType);
1258 }
1259 break;
1260 case "SHOW_COUNTER":
1261 case "WF_PARENT_ELEMENT_ID":
1262 case "WF_STATUS_ID":
1263 case "SORT":
1264 case "CREATED_BY":
1265 case "MODIFIED_BY":
1266 case "PREVIEW_PICTURE":
1267 case "DETAIL_PICTURE":
1268 case "IBLOCK_ID":
1269 case "IBLOCK_SECTION_ID":
1270 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.".$key, $val, "number", $bFullJoinTmp, $cOperationType);
1271 break;
1272 case "TIMESTAMP_X":
1273 case "DATE_CREATE":
1274 case "SHOW_COUNTER_START":
1275 $sqlSearch = CIBlock::FilterCreateEx("BE.".$key, $val, "date", $bFullJoinTmp, $cOperationType);
1276 if($sqlSearch <> '')
1277 {
1278 $arSqlSearch[] = $sqlSearch;
1279 }
1280 break;
1281 case "EXTERNAL_ID":
1282 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.XML_ID", $val, "string", $bFullJoinTmp, $cOperationType);
1283 break;
1284 case "IBLOCK_TYPE":
1285 $arSqlSearch[] = CIBlock::FilterCreateEx("B.IBLOCK_TYPE_ID", $val, "string", $bFullJoinTmp, $cOperationType);
1286 break;
1287 case "CHECK_PERMISSIONS":
1288 if ($val === 'Y')
1289 {
1290 $minPermission = (string)($arFilter['MIN_PERMISSION'] ?? CIBlockRights::PUBLIC_READ);
1291 if (strlen($minPermission) !== 1)
1292 {
1293 $minPermission = CIBlockRights::PUBLIC_READ;
1294 }
1295
1296 $permissionsBy = null;
1297 if (isset($arFilter['PERMISSIONS_BY']))
1298 {
1299 $permissionsBy = (int)$arFilter['PERMISSIONS_BY'];
1300 if ($permissionsBy < 0)
1301 {
1302 $permissionsBy = null;
1303 }
1304 }
1305
1306 $iblockId = static::getSingleIblockIdFromFilter($arFilter);
1307
1308 if ($permissionsBy !== null)
1309 {
1310 $permSQL = self::getCheckRightsSql($iblockId, $minPermission, $permissionsBy);
1311 }
1312 elseif (!$this->isAdmin)
1313 {
1314 $permSQL = self::getCheckRightsSql($iblockId, $minPermission);
1315 }
1316
1317 unset(
1318 $iblockId,
1319 $permissionsBy,
1320 $minPermission,
1321 );
1322 }
1323 break;
1324 case "CHECK_BP_PERMISSIONS":
1325 if (IsModuleInstalled('bizproc') && !$this->isAdmin)
1326 {
1327 if(is_array($val))
1328 {
1329 $MODULE_ID = $DB->ForSQL($val["MODULE_ID"]);
1330 $ENTITY = $DB->ForSQL($val["ENTITY"]);
1331 $PERMISSION = $DB->ForSQL($val["PERMISSION"]);
1332 $arUserGroups = array();
1333 if(is_array($val["GROUPS"]))
1334 {
1335 $USER_ID = intval($val["USER_ID"]);
1336 foreach($val["GROUPS"] as $GROUP_ID)
1337 {
1338 $GROUP_ID = intval($GROUP_ID);
1339 if($GROUP_ID)
1340 $arUserGroups[$GROUP_ID] = $GROUP_ID;
1341 }
1342 }
1343 else
1344 {
1345 $USER_ID = 0;
1346 }
1347 }
1348 else
1349 {
1350 $MODULE_ID = "iblock";
1351 $ENTITY = "CIBlockDocument";
1352 $PERMISSION = $val;
1353 $arUserGroups = false;
1354 $USER_ID = 0;
1355 }
1356
1357 if($PERMISSION == "read" || $PERMISSION == "write")
1358 {
1359 if(!is_array($arUserGroups) && is_object($USER))
1360 {
1361 $USER_ID = intval($USER->GetID());
1362 $arUserGroups = $USER->GetUserGroupArray();
1363 }
1364
1365 if(!is_array($arUserGroups) || count($arUserGroups) <= 0)
1366 $arUserGroups = array(2);
1367
1368 $arSqlSearch[] = "EXISTS (
1369 SELECT S.DOCUMENT_ID_INT
1370 FROM
1371 b_bp_workflow_state S
1372 INNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID
1373 WHERE
1374 S.DOCUMENT_ID_INT = BE.ID
1375 AND S.MODULE_ID = '$MODULE_ID'
1376 AND S.ENTITY = '$ENTITY'
1377 AND P.PERMISSION = '$PERMISSION'
1378 AND (
1379 P.OBJECT_ID IN ('".implode("', '", $arUserGroups)."')
1380 OR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = $USER_ID)
1381 OR (P.OBJECT_ID = ".$DB->Concat("'USER_'", "'$USER_ID'").")
1382 )
1383 )";
1384 }
1385 }
1386 break;
1387 case "CHECK_BP_VIRTUAL_PERMISSIONS":
1388 if (
1389 IsModuleInstalled('bizproc')
1390 && !$this->isAdmin
1391 )
1392 {
1393 if (!in_array($val, array("read", "create", "admin")))
1394 $val = "admin";
1395
1396 $userId = is_object($USER)? (int)$USER->GetID(): 0;
1397 $arUserGroups = is_object($USER)? $USER->GetUserGroupArray(): false;
1398
1399 if (!is_array($arUserGroups) || empty($arUserGroups))
1400 $arUserGroups = array(2);
1401
1402 $arSqlSearch[] = "EXISTS (
1403 SELECT S.DOCUMENT_ID_INT
1404 FROM b_bp_workflow_state S
1405 INNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID
1406 WHERE S.DOCUMENT_ID_INT = BE.ID
1407 AND S.MODULE_ID = 'bizproc'
1408 AND S.ENTITY = 'CBPVirtualDocument'
1409 AND
1410 (P.PERMISSION = '".$val."'
1411 AND (
1412 P.OBJECT_ID IN ('".implode("', '", $arUserGroups)."')
1413 OR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = ".$userId.")
1414 OR (P.OBJECT_ID = ".$DB->Concat("'USER_'", "'".$userId."'").")
1415 )
1416 )
1417 )";
1418 }
1419 break;
1420 case "LID":
1421 case "SITE_ID":
1422 case "IBLOCK_LID":
1423 case "IBLOCK_SITE_ID":
1424 $flt = CIBlock::FilterCreateEx("SITE_ID", $val, "string_equal", $bFullJoinTmp, $cOperationType);
1425 if ($flt !== '')
1426 $arSqlSearch[] = ($cOperationType == "N" ? "NOT " : "")."EXISTS (
1427 SELECT IBLOCK_ID FROM b_iblock_site WHERE IBLOCK_ID = B.ID
1428 AND ".$flt."
1429 )";
1430 break;
1431 case "DATE_ACTIVE_FROM":
1432 $sqlSearch = CIBlock::FilterCreateEx("BE.ACTIVE_FROM", $val, "date", $bFullJoinTmp, $cOperationType);
1433 if ($sqlSearch <> '')
1434 {
1435 $arSqlSearch[] = $sqlSearch;
1436 }
1437 break;
1438 case "DATE_ACTIVE_TO":
1439 $sqlSearch = CIBlock::FilterCreateEx("BE.ACTIVE_TO", $val, "date", $bFullJoinTmp, $cOperationType);
1440 if ($sqlSearch <> '')
1441 {
1442 $arSqlSearch[] = $sqlSearch;
1443 }
1444 break;
1445 case "IBLOCK_ACTIVE":
1446 $arSqlSearch[] = CIBlock::FilterCreateEx("B.ACTIVE", $val, "string_equal", $bFullJoinTmp, $cOperationType);
1447 break;
1448 case "IBLOCK_CODE":
1449 $arSqlSearch[] = CIBlock::FilterCreateEx("B.CODE", $val, "string", $bFullJoinTmp, $cOperationType);
1450 break;
1451 case "ID_ABOVE":
1452 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ID", $val, "number_above", $bFullJoinTmp, $cOperationType);
1453 break;
1454 case "ID_LESS":
1455 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ID", $val, "number_less", $bFullJoinTmp, $cOperationType);
1456 break;
1457 case "ACTIVE_FROM":
1458 $val = (string)$val;
1459 if ($val !== '')
1460 {
1461 $isCorrect = \CIBlock::isCorrectFullFormatDate($DB->ForSql($val));
1462 if ($isCorrect)
1463 {
1464 $arSqlSearch[] = "(BE.ACTIVE_FROM "
1465 . ($cOperationType == "N" ? "<" : ">=")
1466 . $DB->CharToDateFunction($DB->ForSql($val), "FULL")
1467 . ($cOperationType == "N" ? "" : " OR BE.ACTIVE_FROM IS NULL")
1468 . ")";
1469 }
1470 }
1471 break;
1472 case "ACTIVE_TO":
1473 $val = (string)$val;
1474 if ($val !== '')
1475 {
1476 $isCorrect = \CIBlock::isCorrectFullFormatDate($DB->ForSql($val));
1477 if ($isCorrect)
1478 {
1479 $arSqlSearch[] = "(BE.ACTIVE_TO "
1480 . ($cOperationType == "N" ? ">" : "<=")
1481 . $DB->CharToDateFunction($DB->ForSql($val), "FULL")
1482 . ($cOperationType == "N" ? "" : " OR BE.ACTIVE_TO IS NULL")
1483 . ")";
1484 }
1485 }
1486 break;
1487 case "ACTIVE_DATE":
1488 $val = (string)$val;
1489 if($val !== '')
1490 $arSqlSearch[] = ($cOperationType=="N"?" NOT":"")."((BE.ACTIVE_TO >= ".$DB->GetNowFunction()." OR BE.ACTIVE_TO IS NULL) AND (BE.ACTIVE_FROM <= ".$DB->GetNowFunction()." OR BE.ACTIVE_FROM IS NULL))";
1491 break;
1492 case "DATE_MODIFY_FROM":
1493 $val = (string)$val;
1494 if ($val !== '')
1495 {
1496 $isCorrect = \CIBlock::isCorrectFullFormatDate($DB->ForSql($val));
1497 if ($isCorrect)
1498 {
1499 $arSqlSearch[] = "(BE.TIMESTAMP_X " .
1500 ($cOperationType == "N" ? "<" : ">=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") .
1501 ($cOperationType == "N" ? "" : " OR BE.TIMESTAMP_X IS NULL") . ")";
1502 }
1503 }
1504 break;
1505 case "DATE_MODIFY_TO":
1506 $val = (string)$val;
1507 if ($val !== '')
1508 {
1509 $isCorrect = \CIBlock::isCorrectFullFormatDate($DB->ForSql($val));
1510 if ($isCorrect)
1511 {
1512 $arSqlSearch[] = "(BE.TIMESTAMP_X " .
1513 ($cOperationType == "N" ? ">" : "<=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") .
1514 ($cOperationType == "N" ? "" : " OR BE.TIMESTAMP_X IS NULL") . ")";
1515 }
1516 }
1517 break;
1518 case "WF_NEW":
1519 if($val=="Y" || $val=="N")
1520 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.WF_NEW", "Y", "string_equal", $bFullJoinTmp, ($val=="Y"?false:true), false);
1521 break;
1522 case "MODIFIED_USER_ID":
1523 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.MODIFIED_BY", $val, "number", $bFullJoinTmp, $cOperationType);
1524 break;
1525 case "CREATED_USER_ID":
1526 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.CREATED_BY", $val, "number", $bFullJoinTmp, $cOperationType);
1527 break;
1528 case "RATING_USER_ID":
1529 $arSqlSearch[] = CIBlock::FilterCreateEx("RVV.USER_ID", $val, "number", $bFullJoinTmp, $cOperationType);
1530 $arJoinProps["RVV"] = self::addJoinTypeWhere([
1531 "bFullJoin" => $bFullJoinTmp,
1532 ]);
1533 break;
1534 case "WF_STATUS":
1535 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.WF_STATUS_ID", $val, "number", $bFullJoinTmp, $cOperationType);
1536 break;
1537 case "WF_LOCK_STATUS":
1538 $val = (string)$val;
1539 if ($val !== '')
1540 {
1541 $lockInterval = (int)Main\Config\Option::get('workflow', 'MAX_LOCK_TIME', 60) * 60;
1542 $arSqlSearch[] =
1543 "(case when BE.WF_DATE_LOCK is null then 'green' when "
1544 . $helper->addSecondsToDateTime($lockInterval, 'BE.WF_DATE_LOCK')
1545 . " < " . $helper->getCurrentDateTimeFunction()
1546 . " then 'green' when BE.WF_LOCKED_BY = " . $this->userId
1547 . " then 'yellow' else 'red' end) = '" . $DB->ForSql($val) . "'"
1548 ;
1549 unset($lockInterval);
1550 }
1551 break;
1552 case "WF_LAST_STATUS_ID":
1553 $arSqlSearch[] = "exists (
1554 select
1555 history.ID
1556 from
1557 b_iblock_element history
1558 where
1559 history.WF_PARENT_ELEMENT_ID = BE.ID
1560 and history.WF_STATUS_ID = ".intval($val)."
1561 and history.ID = (
1562 select max(history0.ID) LAST_ID
1563 from b_iblock_element history0
1564 where history0.WF_PARENT_ELEMENT_ID = BE.ID
1565 )
1566 )
1567 ";
1568 break;
1569 case "SECTION_ACTIVE":
1570 if($arFilter["INCLUDE_SUBSECTIONS"]==="Y")
1571 $arSectionFilter["BS"][] = "BSubS.ACTIVE = 'Y'";
1572 else
1573 $arSectionFilter["BS"][] = "BS.ACTIVE = 'Y'";
1574 break;
1575 case "SECTION_GLOBAL_ACTIVE":
1576 if($arFilter["INCLUDE_SUBSECTIONS"]==="Y")
1577 $arSectionFilter["BS"][] = "BSubS.GLOBAL_ACTIVE = 'Y'";
1578 else
1579 $arSectionFilter["BS"][] = "BS.GLOBAL_ACTIVE = 'Y'";
1580 break;
1581 case "SUBSECTION":
1582 if (!is_array($val))
1583 $val=Array($val);
1584 //Find out margins of sections
1585 $arUnknownMargins = array();
1586 foreach($val as $i=>$section)
1587 {
1588 if(!is_array($section))
1589 $arUnknownMargins[intval($section)] = intval($section);
1590 }
1591 if (!empty($arUnknownMargins))
1592 {
1593 $rs = $DB->Query("SELECT ID, LEFT_MARGIN, RIGHT_MARGIN FROM b_iblock_section WHERE ID in (".implode(", ", $arUnknownMargins).")");
1594 while($ar = $rs->Fetch())
1595 {
1596 $arUnknownMargins[intval($ar["ID"])] = array(
1597 intval($ar["LEFT_MARGIN"]),
1598 intval($ar["RIGHT_MARGIN"]),
1599 );
1600 }
1601 foreach($val as $i=>$section)
1602 {
1603 if(!is_array($section))
1604 $val[$i] = $arUnknownMargins[intval($section)];
1605 }
1606 }
1607 //Now sort them out
1608 $arMargins = array();
1609 foreach($val as $i=>$section)
1610 {
1611 if(is_array($section) && (count($section) == 2))
1612 {
1613 $left = intval($section[0]);
1614 $right = intval($section[1]);
1615 if($left > 0 && $right > 0)
1616 $arMargins[$left] = $right;
1617 }
1618 }
1619 ksort($arMargins);
1620 //Remove subsubsections of the sections
1621 $prev_right = 0;
1622 foreach($arMargins as $left => $right)
1623 {
1624 if($right <= $prev_right)
1625 unset($arMargins[$left]);
1626 else
1627 $prev_right = $right;
1628 }
1629
1630 if(isset($arFilter["INCLUDE_SUBSECTIONS"]) && $arFilter["INCLUDE_SUBSECTIONS"] === "Y")
1631 $bsAlias = "BSubS";
1632 else
1633 $bsAlias = "BS";
1634
1635 $subsectionWhere = '';
1636 foreach ($arMargins as $left => $right)
1637 {
1638 if ($subsectionWhere !== '')
1639 {
1640 $subsectionWhere .= ($cOperationType === 'N' ? ' AND ' : ' OR ');
1641 }
1642 $subsectionWhere .= ($cOperationType == "N"? " NOT ": " ")."($bsAlias.LEFT_MARGIN >= ".$left." AND $bsAlias.RIGHT_MARGIN <= ".$right.")\n";;
1643 }
1644
1645 if ($subsectionWhere !== '')
1646 {
1647 $arSectionFilter["BS"][] = "(".$subsectionWhere.")";
1648 }
1649 unset($subsectionWhere);
1650 break;
1651 case "SECTION_ID":
1652 if(!is_array($val))
1653 $val = array($val);
1654
1655 $arSections = array();
1656 foreach($val as $section_id)
1657 {
1658 $section_id = (int)$section_id;
1659 $arSections[$section_id] = $section_id;
1660 }
1661
1662 if($cOperationType=="N")
1663 {
1664 if (isset($arSections[0]))
1665 {
1666 $arSectionFilter["BE"][] = "BE.IN_SECTIONS<>'N'";
1667 $arSectionFilter["LOGIC"] = "AND";
1668 unset($arSections[0]);
1669 if(!empty($arSections))
1670 $arSectionFilter["BS"][] = "BS.ID NOT IN (".implode(", ", $arSections).")";
1671 }
1672 elseif(!empty($arSections))
1673 {
1674 $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
1675 $arSectionFilter["LOGIC"] = "OR";
1676 $arSectionFilter["BS"][] = "BS.ID NOT IN (".implode(", ", $arSections).")";
1677 }
1678 }
1679 else
1680 {
1681 if (isset($arSections[0]))
1682 {
1683 $allSections = (
1684 isset($arFilter["INCLUDE_SUBSECTIONS"])
1685 && $arFilter["INCLUDE_SUBSECTIONS"] === "Y"
1686 && count($arSections) == 1
1687 );
1688 if (!$allSections)
1689 {
1690 $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
1691 $arSectionFilter["LOGIC"] = "OR";
1692 }
1693 unset($arSections[0]);
1694 }
1695 if(!empty($arSections))
1696 $arSectionFilter["BS"][] = "BS.ID IN (".implode(", ", $arSections).")";
1697 }
1698 break;
1699 case "SECTION_CODE":
1700 if(!is_array($val))
1701 $val = array($val);
1702
1703 $arSections = array();
1704 foreach($val as $section_code)
1705 {
1706 $section_code = $DB->ForSql($section_code);
1707 $arSections[$section_code] = $section_code;
1708 }
1709
1710 if($cOperationType=="N")
1711 {
1712 if(array_key_exists("", $arSections))
1713 {
1714 $arSectionFilter["BE"][] = "BE.IN_SECTIONS<>'N'";
1715 $arSectionFilter["LOGIC"] = "AND";
1716 unset($arSections[""]);
1717 if(!empty($arSections))
1718 $arSectionFilter["BS"][] = "BS.CODE NOT IN ('".implode("', '", $arSections)."')";
1719 }
1720 elseif(!empty($arSections))
1721 {
1722 $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
1723 $arSectionFilter["LOGIC"] = "OR";
1724 $arSectionFilter["BS"][] = "BS.CODE NOT IN ('".implode("', '", $arSections)."')";
1725 }
1726 }
1727 else
1728 {
1729 if(array_key_exists("", $arSections))
1730 {
1731 $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
1732 $arSectionFilter["LOGIC"] = "OR";
1733 unset($arSections[""]);
1734 }
1735 if(!empty($arSections))
1736 $arSectionFilter["BS"][] = "BS.CODE IN ('".implode("', '", $arSections)."')";
1737 }
1738 break;
1739 case "PROPERTY":
1740 $iblockIds = CIBlock::_MergeIBArrays(
1741 $arFilter["IBLOCK_ID"] ?? false,
1742 $arFilter["IBLOCK_CODE"] ?? false,
1743 $arFilter["~IBLOCK_ID"] ?? false,
1744 $arFilter["~IBLOCK_CODE"] ?? false
1745 );
1746 foreach($val as $propID=>$propVAL)
1747 {
1748 $propertyFilter = CIBlock::MkOperationFilter($propID);
1749 $propertyFilter["LOGIC"] = $Logic;
1750 $propertyFilter["LEFT_JOIN"] = $bPropertyLeftJoin;
1751
1752 if(preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $propertyFilter["FIELD"], $arMatch))
1753 {
1754 if (self::checkPropertyLinkIdentifier($propertyFilter['FIELD']))
1755 {
1756 $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
1757 if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
1758 {
1759 $propertyFilter["FIELD"] = $arMatch;
1761 $propertyFilter,
1762 $cOperationType,
1763 $propVAL,
1764 $db_prop,
1765 $arJoinProps,
1766 $arSqlSearch
1767 );
1768 }
1769 }
1770 }
1771 else
1772 {
1773 if (self::checkPropertyIdentifier($propertyFilter['FIELD']))
1774 {
1775 $db_prop = CIBlockProperty::GetPropertyArray($propertyFilter["FIELD"], $iblockIds);
1776 if ($db_prop)
1777 {
1779 $propertyFilter,
1780 $cOperationType,
1781 $propVAL,
1782 $db_prop,
1783 $arJoinProps,
1784 $arSqlSearch
1785 );
1786 }
1787 }
1788 }
1789 unset($propertyFilter);
1790 }
1791 unset($iblockIds);
1792 break;
1793 default:
1794 if(is_numeric($orig_key))
1795 {
1796 if (is_array($val))
1797 {
1798 //Here is hint for better property resolution:
1799 if (!isset($val["~IBLOCK_ID"]))
1800 {
1801 if (isset($arFilter["IBLOCK_ID"]))
1802 $val["~IBLOCK_ID"] = $arFilter["IBLOCK_ID"];
1803 elseif (isset($arFilter["~IBLOCK_ID"]))
1804 $val["~IBLOCK_ID"] = $arFilter["~IBLOCK_ID"];
1805 }
1806 if (!isset($val["~IBLOCK_CODE"]))
1807 {
1808 if (isset($arFilter["IBLOCK_CODE"]))
1809 $val["~IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"];
1810 elseif (isset($arFilter["~IBLOCK_CODE"]))
1811 $val["~IBLOCK_CODE"] = $arFilter["~IBLOCK_CODE"];
1812 }
1813 //Subfilter process
1814 $arSubSqlSearch = CIBlockElement::MkFilter($val, $arJoinProps, $arAddWhereFields, $level + 1, $bPropertyLeftJoin);
1815 if(trim($arSubSqlSearch[0], "\n\t") <> '')
1816 {
1817 $arSqlSearch[] = str_replace("\n\t\t\t", "\n\t\t\t\t", $arSubSqlSearch[0]);
1818 }
1819 }
1820 }
1821 elseif ($catalogIncluded && !isset($specialFilterKeys[$key]))
1822 {
1824 {
1825 $catalogFields[$orig_key] = $val;
1826 $arAddWhereFields[$orig_key] = $val;
1827 }
1828 }
1829 break;
1830 }
1831 }
1832 if ($catalogIncluded && !empty($catalogFields))
1833 {
1834 $catalogQueryResult = \CProductQueryBuilder::makeFilter($catalogFields);
1835 // catalog join set in \CIBlockElement::prepareSql
1836 if (!empty($catalogQueryResult) && !empty($catalogQueryResult['filter']))
1837 {
1838 $arSqlSearch = array_merge($arSqlSearch, $catalogQueryResult['filter']);
1839 }
1840 unset($catalogQueryResult);
1841 }
1842 unset($catalogFields);
1843
1844 //SECTION sub filter
1845 $sWhere = "";
1846 foreach($arSectionFilter["BS"] as $strFilter)
1847 {
1848 if ($strFilter !== '')
1849 {
1850 if ($sWhere !== '')
1851 $sWhere .= " ".$Logic." ";
1852 $sWhere .= "(".$strFilter.")";
1853 }
1854 }
1855
1856 $bINCLUDE_SUBSECTIONS = isset($arFilter["INCLUDE_SUBSECTIONS"]) && $arFilter["INCLUDE_SUBSECTIONS"] === "Y";
1857
1858 if($sWhere !== '')
1859 {
1860 $sectionScope = "";
1861 if (isset($arFilter["SECTION_SCOPE"]))
1862 {
1863 if ($arFilter["SECTION_SCOPE"] == "IBLOCK")
1864 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID IS NULL";
1865 elseif ($arFilter["SECTION_SCOPE"] == "PROPERTY")
1866 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID IS NOT NULL";
1867 elseif (preg_match("/^PROPERTY_(\\d+)\$/", $arFilter["SECTION_SCOPE"], $match))
1868 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID = ".$match[1];
1869 }
1870
1871 //Try to convert correlated subquery to join subquery
1872 if($level == 0 && $Logic == "AND" && !count($arSectionFilter["BE"]))
1873 {
1874 $arJoinProps["BES"] .= " INNER JOIN (
1875 SELECT DISTINCT BSE.IBLOCK_ELEMENT_ID
1876 FROM b_iblock_section_element BSE
1877 ".($bINCLUDE_SUBSECTIONS? "
1878 INNER JOIN b_iblock_section BSubS ON BSE.IBLOCK_SECTION_ID = BSubS.ID
1879 INNER JOIN b_iblock_section BS ON (BSubS.IBLOCK_ID=BS.IBLOCK_ID
1880 AND BSubS.LEFT_MARGIN>=BS.LEFT_MARGIN
1881 AND BSubS.RIGHT_MARGIN<=BS.RIGHT_MARGIN)
1882 " : "
1883 INNER JOIN b_iblock_section BS ON BSE.IBLOCK_SECTION_ID = BS.ID
1884 ")."
1885 WHERE (".$sWhere.")$sectionScope
1886 ) BES ON BES.IBLOCK_ELEMENT_ID = BE.ID\n";
1887 }
1888 else
1889 {
1890 $arSqlSearch[] = "(".(count($arSectionFilter["BE"])? implode(" ".$arSectionFilter["LOGIC"]." ", $arSectionFilter["BE"])." ".$arSectionFilter["LOGIC"]: "")." EXISTS (
1891 SELECT BSE.IBLOCK_ELEMENT_ID
1892 FROM b_iblock_section_element BSE
1893 ".($bINCLUDE_SUBSECTIONS? "
1894 INNER JOIN b_iblock_section BSubS ON BSE.IBLOCK_SECTION_ID = BSubS.ID
1895 INNER JOIN b_iblock_section BS ON (BSubS.IBLOCK_ID=BS.IBLOCK_ID
1896 AND BSubS.LEFT_MARGIN>=BS.LEFT_MARGIN
1897 AND BSubS.RIGHT_MARGIN<=BS.RIGHT_MARGIN)
1898 " : "
1899 INNER JOIN b_iblock_section BS ON BSE.IBLOCK_SECTION_ID = BS.ID
1900 ")."
1901 WHERE BSE.IBLOCK_ELEMENT_ID = BE.ID
1902 AND (".$sWhere.")$sectionScope
1903 ))";
1904 }
1905 }
1906 elseif(!empty($arSectionFilter["BE"]))
1907 {
1908 foreach($arSectionFilter["BE"] as $strFilter)
1909 $arSqlSearch[] = $strFilter;
1910 }
1911
1912 $sWhere = "";
1913 foreach($arSqlSearch as $strFilter)
1914 {
1915 if(trim($strFilter, "\n\t") !== '')
1916 {
1917 if ($sWhere !== '')
1918 $sWhere .= "\n\t\t\t\t".$Logic." ";
1919 else
1920 $sWhere .= "\n\t\t\t\t";
1921 $sWhere .= "(".$strFilter.")";
1922 }
1923 }
1924
1925 $arSqlSearch = array("\n\t\t\t".$sWhere."\n\t\t\t");
1926
1927 $SHOW_BP_NEW = "";
1928 $SHOW_NEW = isset($arFilter["SHOW_NEW"]) && $arFilter["SHOW_NEW"]=="Y"? "Y": "N";
1929
1930 if(
1931 $SHOW_NEW == "Y"
1932 && isset($arFilter["SHOW_BP_NEW"])
1933 && is_array($arFilter["SHOW_BP_NEW"])
1934 && IsModuleInstalled('bizproc')
1935 && !$this->isAdmin
1936 )
1937 {
1938
1939 $MODULE_ID = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["MODULE_ID"]);
1940 $ENTITY = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["ENTITY"]);
1941 $PERMISSION = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["PERMISSION"]);
1942 $arUserGroups = array();
1943 if(is_array($arFilter["SHOW_BP_NEW"]["GROUPS"]))
1944 {
1945 $USER_ID = intval($arFilter["SHOW_BP_NEW"]["USER_ID"]);
1946 foreach($arFilter["SHOW_BP_NEW"]["GROUPS"] as $GROUP_ID)
1947 {
1948 $GROUP_ID = intval($GROUP_ID);
1949 if($GROUP_ID)
1950 $arUserGroups[$GROUP_ID] = $GROUP_ID;
1951 }
1952 }
1953 else
1954 {
1955 $USER_ID = false;
1956 $arUserGroups = false;
1957 }
1958
1959 if($PERMISSION == "read" || $PERMISSION == "write")
1960 {
1961 if(!is_array($arUserGroups))
1962 {
1963 $USER_ID = is_object($USER)? (int)$USER->GetID(): 0;
1964 if(is_object($USER))
1965 $arUserGroups = $USER->GetUserGroupArray();
1966 }
1967 if(!is_array($arUserGroups) || empty($arUserGroups))
1968 $arUserGroups = array(2);
1969
1970 $SHOW_BP_NEW = " AND EXISTS (
1971 SELECT S.DOCUMENT_ID_INT
1972 FROM
1973 b_bp_workflow_state S
1974 INNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID
1975 WHERE
1976 S.DOCUMENT_ID_INT = BE.ID
1977 AND S.MODULE_ID = '$MODULE_ID'
1978 AND S.ENTITY = '$ENTITY'
1979 AND P.PERMISSION = '$PERMISSION'
1980 AND (
1981 P.OBJECT_ID IN ('".implode("', '", $arUserGroups)."')
1982 OR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = $USER_ID)
1983 OR (P.OBJECT_ID = ".$DB->Concat("'USER_'", "'$USER_ID'").")
1984 )
1985 )";
1986 }
1987 }
1988
1989 if(!isset($arFilter["SHOW_HISTORY"]) || $arFilter["SHOW_HISTORY"] != "Y")
1990 $arSqlSearch[] = "((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL)".($SHOW_NEW == "Y"? " OR (BE.WF_NEW='Y'".$SHOW_BP_NEW.")": "").")";
1991
1992 if($permSQL)
1993 $arSqlSearch[] = $permSQL;
1994
1995 if(isset($this) && is_object($this) && isset($this->subQueryProp))
1996 {
1997 //Subquery list value should not be null
1998 $this->MkPropertyFilter(
1999 CIBlock::MkOperationFilter("!".mb_substr($this->strField, 9))
2000 ,"NE"
2001 ,false
2002 ,$this->subQueryProp, $arJoinProps, $arSqlSearch
2003 );
2004 }
2005
2006 return $arSqlSearch;
2007 }
2008
2009 public function MkPropertyFilter($res, $cOperationType, $propVAL, $db_prop, &$arJoinProps, &$arSqlSearch)
2010 {
2011 global $DB;
2012
2013 $propertyId = $db_prop['ID'];
2014
2015 if($res["OPERATION"]!="E")
2016 $cOperationType = $res["OPERATION"];
2017
2018 //Tables counters
2019 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
2020 {
2021 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2022 $iPropCnt = count($arJoinProps["FPS"]);
2023 else
2024 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
2025 }
2026 else
2027 {
2028 if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
2029 $iPropCnt = count($arJoinProps["FPV"]);
2030 else
2031 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
2032 }
2033
2034 if(!is_array($res["FIELD"]) && (mb_substr(mb_strtoupper($res["FIELD"]), -6) == '_VALUE'))
2035 $bValueEnum = true;
2036 else
2037 $bValueEnum = false;
2038
2039 if($db_prop["PROPERTY_TYPE"] == "L" && $bValueEnum)
2040 {
2041 if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
2042 $iFpenCnt = count($arJoinProps["FPEN"]);
2043 else
2044 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
2045 }
2046 else
2047 {
2048 $iFpenCnt = false;
2049 }
2050
2051 if(is_array($res["FIELD"]))
2052 {
2053 if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
2054 $iElCnt = count($arJoinProps["BE"]);
2055 else
2056 $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
2057 }
2058 else
2059 {
2060 $iElCnt = false;
2061 }
2062
2063 $bFullJoin = false;
2064 $r = "";
2065
2066 if(is_array($res["FIELD"]))
2067 {
2068 switch($res["FIELD"][2]."")
2069 {
2070 case "ACTIVE":
2071 case "DETAIL_TEXT_TYPE":
2072 case "PREVIEW_TEXT_TYPE":
2073 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "string_equal", $bFullJoinTmp, $cOperationType);
2074 break;
2075 case "EXTERNAL_ID":
2076 $res["FIELD"][2] = "XML_ID";
2077 case "NAME":
2078 case "XML_ID":
2079 case "TMP_ID":
2080 case "DETAIL_TEXT":
2081 case "SEARCHABLE_CONTENT":
2082 case "PREVIEW_TEXT":
2083 case "CODE":
2084 case "TAGS":
2085 case "WF_COMMENTS":
2086 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "string", $bFullJoinTmp, $cOperationType);
2087 break;
2088 case "ID":
2089 case "SHOW_COUNTER":
2090 case "WF_PARENT_ELEMENT_ID":
2091 case "WF_STATUS_ID":
2092 case "SORT":
2093 case "CREATED_BY":
2094 case "MODIFIED_BY":
2095 case "PREVIEW_PICTURE":
2096 case "DETAIL_PICTURE":
2097 case "IBLOCK_ID":
2098 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "number", $bFullJoinTmp, $cOperationType);
2099 break;
2100 case "TIMESTAMP_X":
2101 case "DATE_CREATE":
2102 case "SHOW_COUNTER_START":
2103 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "date", $bFullJoinTmp, $cOperationType);
2104 break;
2105 case "DATE_ACTIVE_FROM":
2106 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".ACTIVE_FROM", $propVAL, "date", $bFullJoinTmp, $cOperationType);
2107 break;
2108 case "DATE_ACTIVE_TO":
2109 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".ACTIVE_TO", $propVAL, "date", $bFullJoinTmp, $cOperationType);
2110 break;
2111 case "ACTIVE_FROM":
2112 if($propVAL <> '')
2113 $r = "(BE".$iElCnt.".ACTIVE_FROM ".($cOperationType=="N"?"<":">=").$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").($cOperationType=="N"?"":" OR BE".$iElCnt.".ACTIVE_FROM IS NULL").")";
2114 break;
2115 case "ACTIVE_TO":
2116 if($propVAL <> '')
2117 $r = "(BE".$iElCnt.".ACTIVE_TO ".($cOperationType=="N"?">":"<=").$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").($cOperationType=="N"?"":" OR BE".$iElCnt.".ACTIVE_TO IS NULL").")";
2118 break;
2119 case "ACTIVE_DATE":
2120 if($propVAL <> '')
2121 $r = ($cOperationType=="N"?" NOT":"")."((BE".$iElCnt.".ACTIVE_TO >= ".$DB->GetNowFunction()." OR BE".$iElCnt.".ACTIVE_TO IS NULL) AND (BE".$iElCnt.".ACTIVE_FROM <= ".$DB->GetNowFunction()." OR BE".$iElCnt.".ACTIVE_FROM IS NULL))";
2122 break;
2123 case "DATE_MODIFY_FROM":
2124 if($propVAL <> '')
2125 $r = "(BE".$iElCnt.".TIMESTAMP_X ".
2126 ( $cOperationType=="N" ? "<" : ">=" ).$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").
2127 ( $cOperationType=="N" ? "" : " OR BE".$iElCnt.".TIMESTAMP_X IS NULL").")";
2128 break;
2129 case "DATE_MODIFY_TO":
2130 if($propVAL <> '')
2131 $r = "(BE".$iElCnt.".TIMESTAMP_X ".
2132 ( $cOperationType=="N" ? ">" : "<=" ).$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").
2133 ( $cOperationType=="N" ? "" : " OR BE".$iElCnt.".TIMESTAMP_X IS NULL").")";
2134 break;
2135 case "MODIFIED_USER_ID":
2136 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".MODIFIED_BY", $propVAL, "number", $bFullJoinTmp, $cOperationType);
2137 break;
2138 case "CREATED_USER_ID":
2139 $r = CIBlock::FilterCreateEx("BE".$iElCnt.".CREATED_BY", $propVAL, "number", $bFullJoinTmp, $cOperationType);
2140 break;
2141 }
2142 }
2143 else
2144 {
2145 if(!is_array($propVAL))
2146 $propVAL = array($propVAL);
2147
2148 if($db_prop["PROPERTY_TYPE"]=="L")
2149 {
2150 if($bValueEnum)
2151 $r = CIBlock::FilterCreateEx("FPEN".$iFpenCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
2152 elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
2153 $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
2154 else
2155 $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE_ENUM", $propVAL, "number", $bFullJoin, $cOperationType);
2156 }
2157 elseif($db_prop["PROPERTY_TYPE"]=="N" || $db_prop["PROPERTY_TYPE"]=="G" || $db_prop["PROPERTY_TYPE"]=="E")
2158 {
2159 if($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
2160 $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
2161 else
2162 $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE_NUM", $propVAL, "number", $bFullJoin, $cOperationType);
2163 }
2164 else
2165 {
2166 if($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
2167 $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "string", $bFullJoin, $cOperationType);
2168 else
2169 $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
2170 }
2171 }
2172
2173 if($r <> '')
2174 {
2175 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
2176 {
2177 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2178 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = $iPropCnt;
2179 }
2180 else
2181 {
2182 $arJoinProps['FP'][$propertyId] ??= [
2183 'CNT' => count($arJoinProps['FP']),
2184 'bFullJoin' => false,
2185 ];
2186 $arJoinProps['FP'][$propertyId] = self::addJoinTypeWhere($arJoinProps['FP'][$propertyId]);
2187
2188 if (isset($res["LEFT_JOIN"]) && $res["LEFT_JOIN"])
2189 {
2190 $arJoinProps["FP"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
2191 }
2192 else
2193 {
2194 $arJoinProps["FP"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;
2195 }
2196
2197 $arJoinProps['FPV'][$propertyId] ??= [
2198 'CNT' => $iPropCnt,
2199 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
2200 'MULTIPLE' => $db_prop['MULTIPLE'],
2201 'VERSION' => $db_prop['VERSION'],
2202 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
2203 'bFullJoin' => false,
2204 ];
2205 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeWhere($arJoinProps['FPV'][$propertyId]);
2206
2207 if(isset($res["LEFT_JOIN"]) && $res["LEFT_JOIN"])
2208 {
2209 $arJoinProps["FPV"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
2210 }
2211 else
2212 {
2213 $arJoinProps["FPV"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;
2214 }
2215 }
2216
2217 if($db_prop["PROPERTY_TYPE"]=="L" && $bValueEnum)
2218 {
2219 $arJoinProps['FPEN'][$propertyId] ??= [
2220 'CNT' => $iFpenCnt,
2221 'MULTIPLE' => $db_prop['MULTIPLE'],
2222 'VERSION' => $db_prop['VERSION'],
2223 'ORIG_ID' => $db_prop['ORIG_ID'],
2224 'JOIN' => $iPropCnt,
2225 'bFullJoin' => false,
2226 ];
2227 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeWhere($arJoinProps['FPEN'][$propertyId]);
2228
2229 if(isset($res["LEFT_JOIN"]) && $res["LEFT_JOIN"])
2230 {
2231 $arJoinProps["FPEN"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
2232 }
2233 else
2234 {
2235 $arJoinProps["FPEN"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;
2236 }
2237 }
2238
2239 if(is_array($res["FIELD"]))
2240 {
2241 $arJoinProps['BE'][$propertyId] ??= [
2242 'CNT' => $iElCnt,
2243 'MULTIPLE' => $db_prop['MULTIPLE'],
2244 'VERSION' => $db_prop['VERSION'],
2245 'ORIG_ID' => $db_prop['ORIG_ID'],
2246 'JOIN' => $iPropCnt,
2247 'bJoinIBlock' => false,
2248 'bJoinSection' => false,
2249 ];
2250 $arJoinProps['BE'][$propertyId] = self::addJoinTypeWhere($arJoinProps['BE'][$propertyId]);
2251 }
2252
2253 $arSqlSearch[] = $r;
2254 }
2255 }
2256
2257 public function MkPropertyOrder($by, $order, $bSort, $db_prop, &$arJoinProps, &$arSqlOrder)
2258 {
2259 global $DB;
2260 static $arJoinEFields = false;
2261
2262 $propertyId = $db_prop['ID'];
2263
2264 //Tables counters
2265 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
2266 {
2267 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2268 $iPropCnt = count($arJoinProps["FPS"]);
2269 else
2270 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
2271 }
2272 else
2273 {
2274 if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
2275 $iPropCnt = count($arJoinProps["FPV"]);
2276 else
2277 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
2278 }
2279
2280 if($db_prop["PROPERTY_TYPE"] == "L")
2281 {
2282 if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
2283 $iFpenCnt = count($arJoinProps["FPEN"]);
2284 else
2285 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
2286 }
2287 else
2288 {
2289 $iFpenCnt = -1;
2290 }
2291
2292 $iElCnt = -1;
2293 $db_jprop = false;
2294 $ijPropCnt = -1;
2295 $ijFpenCnt = -1;
2296
2297 if(is_array($by))
2298 {
2299 if(!$arJoinEFields) $arJoinEFields = array(
2300 "ID" => "BE#i#.ID",
2301 "TIMESTAMP_X" => "BE#i#.TIMESTAMP_X",
2302 "MODIFIED_BY" => "BE#i#.MODIFIED_BY",
2303 "CREATED" => "BE#i#.DATE_CREATE",
2304 "CREATED_DATE" => $DB->DateFormatToDB("YYYY.MM.DD", "BE#i#.DATE_CREATE"),
2305 "CREATED_BY" => "BE#i#.CREATED_BY",
2306 "IBLOCK_ID" => "BE#i#.IBLOCK_ID",
2307 "ACTIVE" => "BE#i#.ACTIVE",
2308 "ACTIVE_FROM" => "BE#i#.ACTIVE_FROM",
2309 "ACTIVE_TO" => "BE#i#.ACTIVE_TO",
2310 "SORT" => "BE#i#.SORT",
2311 "NAME" => "BE#i#.NAME",
2312 "SHOW_COUNTER" => "BE#i#.SHOW_COUNTER",
2313 "SHOW_COUNTER_START" => "BE#i#.SHOW_COUNTER_START",
2314 "CODE" => "BE#i#.CODE",
2315 "TAGS" => "BE#i#.TAGS",
2316 "XML_ID" => "BE#i#.XML_ID",
2317 "STATUS" => "BE#i#.WF_STATUS_ID",
2318 );
2319
2320 $jProp_ID = mb_substr($by[2], 9);
2321 $db_jprop = CIBlockProperty::GetPropertyArray($jProp_ID, CIBlock::_MergeIBArrays($db_prop["LINK_IBLOCK_ID"]));
2322 if ($bSort && $db_jprop["PROPERTY_TYPE"] != "L")
2323 return;
2324
2325 //Joined Elements Field
2326 if(array_key_exists($by[2], $arJoinEFields))
2327 {
2328 //Then join elements
2329 if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
2330 $iElCnt = count($arJoinProps["BE"]);
2331 else
2332 $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
2333
2334 $arSqlOrder[$by[0]] = CIBlock::_Order(str_replace("#i#", $iElCnt, $arJoinEFields[$by[2]]), $order, "desc");
2335 }
2336 elseif(mb_substr($by[2], 0, 9) == "PROPERTY_")
2337 {
2338 if(is_array($db_jprop))
2339 {
2340 //join elements
2341 if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
2342 $iElCnt = count($arJoinProps["BE"]);
2343 else
2344 $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
2345
2346 if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
2347 {
2348 if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
2349 $ijPropCnt = count($arJoinProps["BE_FPS"]);
2350 else
2351 $ijPropCnt = $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]]["CNT"];
2352 }
2353 else
2354 {
2355 if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
2356 $ijPropCnt = count($arJoinProps["BE_FPV"]);
2357 else
2358 $ijPropCnt = $arJoinProps["BE_FPV"][$db_jprop["ID"]]["CNT"];
2359 }
2360
2361 if($db_jprop["PROPERTY_TYPE"] == "L")
2362 {
2363 if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
2364 $ijFpenCnt = count($arJoinProps["BE_FPEN"]);
2365 else
2366 $ijFpenCnt = $arJoinProps["BE_FPEN"][$db_jprop["ID"]]["CNT"];
2367 }
2368
2369 if($db_jprop["PROPERTY_TYPE"]=="L" && $bSort)
2370 $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBlock::_Order("JFPEN".$ijFpenCnt.".SORT", $order, "desc");
2371 elseif($db_jprop["PROPERTY_TYPE"]=="L")
2372 $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBlock::_Order("JFPEN".$ijFpenCnt.".VALUE", $order, "desc");
2373 elseif($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
2374 $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBlock::_Order("JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"], $order, "desc");
2375 elseif($db_jprop["PROPERTY_TYPE"]=="N")
2376 $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBlock::_Order("JFPV".$ijPropCnt.".VALUE_NUM", $order, "desc");
2377 else
2378 $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBlock::_Order("JFPV".$ijPropCnt.".VALUE", $order, "desc");
2379
2380 }
2381 }
2382 }
2383 else
2384 {
2385 if ($bSort && $db_prop["PROPERTY_TYPE"] != "L")
2386 return;
2387
2388 if($db_prop["PROPERTY_TYPE"]=="L" && $bSort)
2389 $arSqlOrder[$by] = CIBlock::_Order("FPEN".$iFpenCnt.".SORT", $order, "desc");
2390 elseif($db_prop["PROPERTY_TYPE"]=="L")
2391 $arSqlOrder[$by] = CIBlock::_Order("FPEN".$iFpenCnt.".VALUE", $order, "desc");
2392 elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
2393 $arSqlOrder[$by] = CIBlock::_Order("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $order, "desc");
2394 elseif($db_prop["PROPERTY_TYPE"]=="N")
2395 $arSqlOrder[$by] = CIBlock::_Order("FPV".$iPropCnt.".VALUE_NUM", $order, "desc");
2396 else
2397 $arSqlOrder[$by] = CIBlock::_Order("FPV".$iPropCnt.".VALUE", $order, "desc");
2398 }
2399
2400 //Pass join "commands" up there
2401 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
2402 {
2403 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2404 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = $iPropCnt;
2405 }
2406 else
2407 {
2408 $arJoinProps['FP'][$propertyId] ??= [
2409 'CNT' => count($arJoinProps['FP']),
2410 'bFullJoin' => false,
2411 ];
2412 $arJoinProps['FP'][$propertyId] = self::addJoinTypeOrder($arJoinProps['FP'][$propertyId]);
2413
2414 $arJoinProps['FPV'][$propertyId] ??= [
2415 'CNT' => $iPropCnt,
2416 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
2417 'MULTIPLE' => $db_prop['MULTIPLE'],
2418 'VERSION' => $db_prop['VERSION'],
2419 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
2420 'bFullJoin' => false,
2421 ];
2422 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeOrder($arJoinProps['FPV'][$propertyId]);
2423 }
2424
2425 if ($iFpenCnt >= 0)
2426 {
2427 $arJoinProps['FPEN'][$propertyId] ??= [
2428 'CNT' => $iFpenCnt,
2429 'MULTIPLE' => $db_prop['MULTIPLE'],
2430 'VERSION' => $db_prop['VERSION'],
2431 'ORIG_ID' => $db_prop['ORIG_ID'],
2432 'JOIN' => $iPropCnt,
2433 'bFullJoin' => false,
2434 ];
2435 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeOrder($arJoinProps['FPEN'][$propertyId]);
2436 }
2437
2438 if($iElCnt >= 0)
2439 {
2440 $arJoinProps['BE'][$propertyId] ??= [
2441 'CNT' => $iElCnt,
2442 'MULTIPLE' => $db_prop['MULTIPLE'],
2443 'VERSION' => $db_prop['VERSION'],
2444 'ORIG_ID' => $db_prop['ORIG_ID'],
2445 'JOIN' => $iPropCnt,
2446 'bJoinIBlock' => false,
2447 'bJoinSection' => false,
2448 ];
2449 $arJoinProps['BE'][$propertyId] = self::addJoinTypeOrder($arJoinProps['BE'][$propertyId]);
2450
2451 if(is_array($db_jprop))
2452 {
2453 if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
2454 {
2455 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']] ??= [
2456 'CNT' => $ijPropCnt,
2457 'JOIN' => $iElCnt,
2458 ];
2459 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']] = self::addJoinTypeOrder(
2460 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']]
2461 );
2462 }
2463 else
2464 {
2465 $arJoinProps['BE_FP'][$db_jprop['ID']] ??= [
2466 "CNT" => count($arJoinProps["BE_FP"]),
2467 "JOIN" => $iElCnt,
2468 "bFullJoin" => false,
2469 ];
2470 $arJoinProps['BE_FP'][$db_jprop['ID']] = self::addJoinTypeOrder($arJoinProps['BE_FP'][$db_jprop['ID']]);
2471
2472 $arJoinProps['BE_FPV'][$db_jprop['ID']] ??= [
2473 'CNT' => $ijPropCnt,
2474 'IBLOCK_ID' => $db_jprop['IBLOCK_ID'],
2475 'MULTIPLE' => $db_jprop['MULTIPLE'],
2476 'VERSION' => $db_jprop['VERSION'],
2477 'JOIN' => $arJoinProps['BE_FP'][$db_jprop['ID']]['CNT'],
2478 'BE_JOIN' => $iElCnt,
2479 'bFullJoin' => false,
2480 ];
2481 $arJoinProps['BE_FPV'][$db_jprop['ID']] = self::addJoinTypeOrder(
2482 $arJoinProps['BE_FPV'][$db_jprop['ID']]
2483 );
2484 }
2485
2486 if ($ijFpenCnt >= 0)
2487 {
2488 $arJoinProps['BE_FPEN'][$db_jprop['ID']] ??= [
2489 'CNT' => $ijFpenCnt,
2490 'MULTIPLE' => $db_jprop['MULTIPLE'],
2491 'VERSION' => $db_jprop['VERSION'],
2492 'ORIG_ID' => $db_jprop['ORIG_ID'],
2493 'JOIN' => $ijPropCnt,
2494 'bFullJoin' => false,
2495 ];
2496 $arJoinProps['BE_FPEN'][$db_jprop['ID']] = self::addJoinTypeOrder(
2497 $arJoinProps['BE_FPEN'][$db_jprop['ID']]
2498 );
2499 }
2500 }
2501 }
2502 }
2503
2504 public function MkPropertyGroup($db_prop, &$arJoinProps, $bSort = false)
2505 {
2506 $propertyId = $db_prop['ID'];
2507
2508 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
2509 {
2510 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2511 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
2512 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
2513 }
2514 else
2515 {
2516 //Join property metadata table
2517 $arJoinProps['FP'][$propertyId] ??= [
2518 'CNT' => count($arJoinProps['FP']),
2519 'bFullJoin' => false,
2520 ];
2521 $arJoinProps['FP'][$propertyId] = self::addJoinTypeGroup($arJoinProps['FP'][$propertyId]);
2522
2523 $arJoinProps['FPV'][$propertyId] ??= [
2524 'CNT' => count($arJoinProps['FPV']),
2525 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
2526 'MULTIPLE' => $db_prop['MULTIPLE'],
2527 'VERSION' => $db_prop['VERSION'],
2528 'ORIG_ID' => $db_prop['ORIG_ID'],
2529 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
2530 'bFullJoin' => false,
2531 ];
2532 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeGroup($arJoinProps['FPV'][$propertyId]);
2533
2534 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
2535 }
2536
2537 if($db_prop["PROPERTY_TYPE"]=="L")
2538 {
2539 $arJoinProps['FPEN'][$propertyId] ??= [
2540 'CNT' => count($arJoinProps['FPEN']),
2541 'MULTIPLE' => $db_prop['MULTIPLE'],
2542 'VERSION' => $db_prop['VERSION'],
2543 'ORIG_ID' => $db_prop['ORIG_ID'],
2544 'JOIN' => $iPropCnt,
2545 'bFullJoin' => false,
2546 ];
2547 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeGroup($arJoinProps['FPEN'][$propertyId]);
2548
2549 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
2550
2551 return ($bSort? ", FPEN".$iFpenCnt.".SORT": ", FPEN".$iFpenCnt.".VALUE, FPEN".$iFpenCnt.".ID");
2552 }
2553 elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
2554 {
2555 return ", FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"];
2556 }
2557 elseif($db_prop["PROPERTY_TYPE"]=="N")
2558 {
2559 return ", FPV".$iPropCnt.".VALUE, FPV".$iPropCnt.".VALUE_NUM";
2560 }
2561 else
2562 {
2563 return ", FPV".$iPropCnt.".VALUE";
2564 }
2565 }
2566
2567 public function MkPropertySelect($PR_ID, $db_prop, &$arJoinProps, $bWasGroup, $sGroupBy, &$sSelect, $bSort = false)
2568 {
2569 global $DB;
2570
2571 if($bSort && $db_prop["PROPERTY_TYPE"] != "L")
2572 return;
2573
2574 static $arJoinEFields = false;
2575
2576 $propertyId = $db_prop['ID'];
2577
2578 //define maximum alias length
2579 $mal = false;
2580
2581 $bSubQuery = isset($this) && is_object($this) && isset($this->subQueryProp);
2582
2583 $arSelect = array();
2584
2585 //Joined elements
2586 if(is_array($PR_ID))
2587 {
2588 if(!$arJoinEFields) $arJoinEFields = array(
2589 "ID" => "BE#i#.ID",
2590 "TIMESTAMP_X" => $DB->DateToCharFunction("BE#i#.TIMESTAMP_X"),
2591 "MODIFIED_BY" => "BE#i#.MODIFIED_BY",
2592 "DATE_CREATE" => $DB->DateToCharFunction("BE#i#.DATE_CREATE"),
2593 "CREATED_BY" => "BE#i#.CREATED_BY",
2594 "IBLOCK_ID" => "BE#i#.IBLOCK_ID",
2595 "ACTIVE" => "BE#i#.ACTIVE",
2596 "ACTIVE_FROM" => $DB->DateToCharFunction("BE#i#.ACTIVE_FROM"),
2597 "ACTIVE_TO" => $DB->DateToCharFunction("BE#i#.ACTIVE_TO"),
2598 "SORT" => "BE#i#.SORT",
2599 "NAME" => "BE#i#.NAME",
2600 "PREVIEW_PICTURE" => "BE#i#.PREVIEW_PICTURE",
2601 "PREVIEW_TEXT" => "BE#i#.PREVIEW_TEXT",
2602 "PREVIEW_TEXT_TYPE" => "BE#i#.PREVIEW_TEXT_TYPE",
2603 "DETAIL_PICTURE" => "BE#i#.DETAIL_PICTURE",
2604 "DETAIL_TEXT" => "BE#i#.DETAIL_TEXT",
2605 "DETAIL_TEXT_TYPE" => "BE#i#.DETAIL_TEXT_TYPE",
2606 "SHOW_COUNTER" => "BE#i#.SHOW_COUNTER",
2607 "SHOW_COUNTER_START" => $DB->DateToCharFunction("BE#i#.SHOW_COUNTER_START"),
2608 "CODE" => "BE#i#.CODE",
2609 "TAGS" => "BE#i#.TAGS",
2610 "XML_ID" => "BE#i#.XML_ID",
2611 "IBLOCK_SECTION_ID" => "BE#i#.IBLOCK_SECTION_ID",
2612 "IBLOCK_TYPE_ID"=>"B#i#.IBLOCK_TYPE_ID",
2613 "IBLOCK_CODE"=>"B#i#.CODE",
2614 "IBLOCK_NAME"=>"B#i#.NAME",
2615 "IBLOCK_EXTERNAL_ID"=>"B#i#.XML_ID",
2616 "DETAIL_PAGE_URL" => "
2617 replace(
2618 replace(
2619 replace(
2620 replace(
2621 replace(
2622 replace(
2623 replace(
2624 replace(
2625 replace(
2626 replace(
2627 replace(
2628 replace(
2629 replace(B#i#.DETAIL_PAGE_URL, '#ID#', BE#i#.ID)
2630 , '#ELEMENT_ID#', BE#i#.ID)
2631 , '#CODE#', ".$DB->IsNull("BE#i#.CODE", "''").")
2632 , '#ELEMENT_CODE#', ".$DB->IsNull("BE#i#.CODE", "''").")
2633 , '#EXTERNAL_ID#', ".$DB->IsNull("BE#i#.XML_ID", "''").")
2634 , '#IBLOCK_TYPE_ID#', B#i#.IBLOCK_TYPE_ID)
2635 , '#IBLOCK_ID#', BE#i#.IBLOCK_ID)
2636 , '#IBLOCK_CODE#', ".$DB->IsNull("B#i#.CODE", "''").")
2637 , '#IBLOCK_EXTERNAL_ID#', ".$DB->IsNull("B#i#.XML_ID", "''").")
2638 , '#SITE_DIR#', '".$DB->ForSQL(SITE_DIR)."')
2639 , '#SERVER_NAME#', '".$DB->ForSQL(SITE_SERVER_NAME)."')
2640 , '#SECTION_ID#', ".$DB->IsNull("BE#i#.IBLOCK_SECTION_ID", "''").")
2641 , '#SECTION_CODE#', ".$DB->IsNull("BS#i#.CODE", "''").")
2642 ",
2643 "LIST_PAGE_URL" => "
2644 replace(
2645 replace(
2646 replace(
2647 replace(
2648 replace(
2649 replace(B#i#.LIST_PAGE_URL, '#IBLOCK_TYPE_ID#', B#i#.IBLOCK_TYPE_ID)
2650 , '#IBLOCK_ID#', BE#i#.IBLOCK_ID)
2651 , '#IBLOCK_CODE#', ".$DB->IsNull("B#i#.CODE", "''").")
2652 , '#IBLOCK_EXTERNAL_ID#', ".$DB->IsNull("B#i#.XML_ID", "''").")
2653 , '#SITE_DIR#', '".$DB->ForSQL(SITE_DIR)."')
2654 , '#SERVER_NAME#', '".$DB->ForSQL(SITE_SERVER_NAME)."')
2655 ",
2656 );
2657
2658 //Joined Elements Fields
2659 if(array_key_exists($PR_ID[2], $arJoinEFields))
2660 {
2661
2662 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"] == "N")
2663 {
2664 //Join properties table if needed
2665 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2666 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
2667 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
2668 }
2669 else
2670 {
2671 //Join property metadata table
2672 $arJoinProps['FP'][$propertyId] ??= [
2673 'CNT' => count($arJoinProps['FP']),
2674 'bFullJoin' => false,
2675 ];
2676 $arJoinProps['FP'][$propertyId] = self::addJoinTypeSelect($arJoinProps['FP'][$propertyId]);
2677
2678 //Join multiple values properties table if needed
2679 $arJoinProps['FPV'][$propertyId] ??= [
2680 'CNT' => count($arJoinProps['FPV']),
2681 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
2682 'MULTIPLE' => $db_prop['MULTIPLE'],
2683 'VERSION' => $db_prop['VERSION'],
2684 'ORIG_ID' => $db_prop['ORIG_ID'],
2685 'JOIN' => $arJoinProps['FP'][$db_prop['ID']]['CNT'],
2686 'bFullJoin' => false,
2687 ];
2688 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeSelect($arJoinProps['FPV'][$propertyId]);
2689
2690 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
2691 }
2692 //Then join elements
2693 $arJoinProps['BE'][$propertyId] ??= [
2694 'CNT' => count($arJoinProps['BE']),
2695 'MULTIPLE' => $db_prop['MULTIPLE'],
2696 'VERSION' => $db_prop['VERSION'],
2697 'ORIG_ID' => $db_prop['ORIG_ID'],
2698 'JOIN' => $iPropCnt,
2699 'bJoinIBlock' => false,
2700 'bJoinSection' => false,
2701 ];
2702 $arJoinProps['BE'][$propertyId] = self::addJoinTypeSelect($arJoinProps['BE'][$propertyId]);
2703
2704 $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
2705
2706 //Check if b_iblock have to be joined also
2707 if(
2708 $PR_ID[2] == "LIST_PAGE_URL"
2709 || $PR_ID[2] == "IBLOCK_TYPE_ID"
2710 || $PR_ID[2] == "IBLOCK_CODE"
2711 || $PR_ID[2] == "IBLOCK_NAME"
2712 || $PR_ID[2] == "IBLOCK_EXTERNAL_ID"
2713 )
2714 $arJoinProps["BE"][$db_prop["ID"]]["bJoinIBlock"] = true;
2715
2716 //Check if b_iblock_section have to be joined also
2717 if($PR_ID[2] == "DETAIL_PAGE_URL")
2718 {
2719 $arJoinProps["BE"][$db_prop["ID"]]["bJoinIBlock"] = true;
2720 $arJoinProps["BE"][$db_prop["ID"]]["bJoinSection"] = true;
2721 }
2722
2723 $arSelect[str_replace("#i#", $iElCnt, $arJoinEFields[$PR_ID[2]])] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2], $this->arIBlockLongProps);
2724 }
2725 //Joined elements properties
2726 elseif(mb_substr($PR_ID[2], 0, 9) == "PROPERTY_")
2727 {
2728 $jProp_ID = mb_substr($PR_ID[2], 9);
2729 $db_jprop = CIBlockProperty::GetPropertyArray($jProp_ID, CIBlock::_MergeIBArrays($db_prop["LINK_IBLOCK_ID"]));
2730 if(is_array($db_jprop))
2731 {
2732 if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"] == "N")
2733 {
2734 //Join properties table if needed
2735 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
2736 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
2737 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
2738 }
2739 else
2740 {
2741 //Join property metadata table
2742 $arJoinProps['FP'][$propertyId] ??= [
2743 'CNT' => count($arJoinProps['FP']),
2744 'bFullJoin' => false,
2745 ];
2746 $arJoinProps['FP'][$propertyId] = self::addJoinTypeSelect($arJoinProps['FP'][$propertyId]);
2747
2748 //Join multiple values properties table if needed
2749 $arJoinProps['FPV'][$propertyId] ??= [
2750 'CNT' => count($arJoinProps['FPV']),
2751 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
2752 'MULTIPLE' => $db_prop['MULTIPLE'],
2753 'VERSION' => $db_prop['VERSION'],
2754 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
2755 'bFullJoin' => false,
2756 ];
2757 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeSelect($arJoinProps['FPV'][$propertyId]);
2758
2759 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
2760 }
2761 //Then join elements
2762 $arJoinProps['BE'][$propertyId] ??= [
2763 'CNT' => count($arJoinProps['BE']),
2764 'MULTIPLE' => $db_prop['MULTIPLE'],
2765 'VERSION' => $db_prop['VERSION'],
2766 'ORIG_ID' => $db_prop['ORIG_ID'],
2767 'JOIN' => $iPropCnt,
2768 'bJoinIBlock' => false,
2769 'bJoinSection' => false,
2770 ];
2771 $arJoinProps['BE'][$propertyId] = self::addJoinTypeSelect($arJoinProps['BE'][$propertyId]);
2772
2773 $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
2774
2775 if($db_jprop["USER_TYPE"]!="")
2776 {
2777 $arUserType = CIBlockProperty::GetUserType($db_jprop["USER_TYPE"]);
2778 if(array_key_exists("ConvertFromDB", $arUserType))
2779 $this->arIBlockConvProps["PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE"] = array(
2780 "ConvertFromDB" => $arUserType["ConvertFromDB"],
2781 "PROPERTY" => $db_jprop,
2782 );
2783 }
2784
2785 $comp_prop_id = $db_jprop["ID"]."~".$db_prop["ID"];
2786
2787 //Infoblock+ (property stored in separate table)
2788 if($db_jprop["VERSION"] == 2)
2789 {
2790 //This is single value property
2791 if($db_jprop["MULTIPLE"] == "N")
2792 {
2793 //For numbers we will need special processing in CIBlockResult::Fetch
2794 if($db_jprop["PROPERTY_TYPE"]=="N")
2795 $this->arIBlockNumProps["PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE"] = $db_prop;
2796
2797 //Enum single property
2798 if($db_jprop["PROPERTY_TYPE"]=="L")
2799 {
2800 //Join properties table if needed
2801 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']] ??= [
2802 'CNT' => count($arJoinProps['BE_FPS']),
2803 'JOIN' => $iElCnt,
2804 ];
2805 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']] = self::addJoinTypeSelect(
2806 $arJoinProps['BE_FPS'][$db_jprop['IBLOCK_ID']]
2807 );
2808
2809 $ijPropCnt = $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]]["CNT"];
2810 //Then join list values table
2811 $arJoinProps['BE_FPEN'][$comp_prop_id] ??= [
2812 "CNT" => count($arJoinProps["BE_FPEN"]),
2813 "MULTIPLE" => "N",
2814 "VERSION" => 2,
2815 "ORIG_ID" => $db_jprop["ORIG_ID"],
2816 "JOIN" => $ijPropCnt,
2817 "bFullJoin" => false,
2818 ];
2819 $arJoinProps['BE_FPEN'][$comp_prop_id] = self::addJoinTypeSelect(
2820 $arJoinProps['BE_FPEN'][$comp_prop_id]
2821 );
2822
2823 $ijFpenCnt = $arJoinProps["BE_FPEN"][$comp_prop_id]["CNT"];
2824
2825 $arSelect["JFPEN".$ijFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2826 $arSelect["JFPEN".$ijFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_ENUM_ID", $this->arIBlockLongProps);
2827 }
2828 else //Just single value property for Infoblock+
2829 {
2830 //Join properties table if needed
2831 $singleValueKey = $db_jprop['IBLOCK_ID'] . '~' . $db_prop['ID'];
2832
2833 $arJoinProps['BE_FPS'][$singleValueKey] ??= [
2834 'CNT' => count($arJoinProps['BE_FPS']),
2835 'JOIN' => $iElCnt,
2836 ];
2837 $arJoinProps['BE_FPS'][$singleValueKey] = self::addJoinTypeSelect(
2838 $arJoinProps['BE_FPS'][$singleValueKey]
2839 );
2840
2841 $ijPropCnt = $arJoinProps["BE_FPS"][$singleValueKey]["CNT"];
2842 unset($singleValueKey);
2843
2844 $arSelect["JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2845 if($sGroupBy=="" && $db_jprop["WITH_DESCRIPTION"] == "Y")
2846 $arSelect["JFPS".$ijPropCnt.".DESCRIPTION_".$db_jprop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_DESCRIPTION", $this->arIBlockLongProps);
2847 }
2848
2849 //When there is no grouping and this is single value property for Infoblock+
2850 if($sGroupBy == "")
2851 {
2852 $arSelect[$DB->Concat("BE".$iElCnt.".ID","':'",$db_jprop["ORIG_ID"])] = CIBlockElement::MkAlias($mal, $PR_ID[2]."_".$PR_ID[1]."_VALUE_ID", $this->arIBlockLongProps);
2853 }
2854 }
2855 else //This is multiple value property for Infoblock+
2856 {
2857 //Join property metadata table
2858 $arJoinProps['BE_FP'][$comp_prop_id] ??= [
2859 'CNT' => count($arJoinProps['BE_FP']),
2860 'JOIN' => $iElCnt,
2861 'bFullJoin' => false,
2862 ];
2863 $arJoinProps['BE_FP'][$comp_prop_id] = self::addJoinTypeSelect(
2864 $arJoinProps['BE_FP'][$comp_prop_id]
2865 );
2866
2867 //Join multiple values properties table if needed
2868 $arJoinProps['BE_FPV'][$comp_prop_id] ??= [
2869 'CNT' => count($arJoinProps['BE_FPV']),
2870 'MULTIPLE' => 'Y',
2871 'VERSION' => 2,
2872 'IBLOCK_ID' => $db_jprop['IBLOCK_ID'],
2873 'JOIN' => $arJoinProps['BE_FP'][$comp_prop_id]['CNT'],
2874 'BE_JOIN' => $iElCnt,
2875 'bFullJoin' => false,
2876 ];
2877 $arJoinProps['BE_FPV'][$comp_prop_id] = self::addJoinTypeSelect(
2878 $arJoinProps['BE_FPV'][$comp_prop_id]
2879 );
2880
2881 $ijPropCnt = $arJoinProps["BE_FPV"][$comp_prop_id]["CNT"];
2882
2883 //For enum properties
2884 if($db_jprop["PROPERTY_TYPE"]=="L")
2885 {
2886 //Then join list values table
2887 $arJoinProps['BE_FPEN'][$comp_prop_id] ??= [
2888 'CNT' => count($arJoinProps['BE_FPEN']),
2889 'MULTIPLE' => 'Y',
2890 'VERSION' => 2,
2891 'ORIG_ID' => $db_jprop['ORIG_ID'],
2892 'JOIN' => $ijPropCnt,
2893 'bFullJoin' => false,
2894 ];
2895 $arJoinProps['BE_FPEN'][$comp_prop_id] = self::addJoinTypeSelect(
2896 $arJoinProps['BE_FPEN'][$comp_prop_id]
2897 );
2898
2899 $ijFpenCnt = $arJoinProps["BE_FPEN"][$comp_prop_id]["CNT"];
2900
2901 $arSelect["JFPEN".$ijFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2902 $arSelect["JFPEN".$ijFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_ENUM_ID", $this->arIBlockLongProps);
2903 }
2904 else
2905 {
2906 $arSelect["JFPV".$ijPropCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2907 }
2908 }
2909 }//Infoblocks with common values table (VERSION==1)
2910 else
2911 {
2912 //Join property metadata table
2913 $arJoinProps['BE_FP'][$comp_prop_id] ??= [
2914 'CNT' => count($arJoinProps['BE_FP']),
2915 'JOIN' => $iElCnt,
2916 'bFullJoin' => false,
2917 ];
2918 $arJoinProps['BE_FP'][$comp_prop_id] = self::addJoinTypeSelect(
2919 $arJoinProps['BE_FP'][$comp_prop_id]
2920 );
2921
2922 //Join multiple values properties table if needed
2923 $arJoinProps['BE_FPV'][$comp_prop_id] ??= [
2924 'CNT' => count($arJoinProps['BE_FPV']),
2925 'MULTIPLE' => $db_jprop['MULTIPLE'],
2926 'VERSION' => 1,
2927 'IBLOCK_ID' => $db_jprop['IBLOCK_ID'],
2928 'JOIN' => $arJoinProps['BE_FP'][$comp_prop_id]['CNT'],
2929 'BE_JOIN' => $iElCnt,
2930 'bFullJoin' => false,
2931 ];
2932 $arJoinProps['BE_FPV'][$comp_prop_id] = self::addJoinTypeSelect(
2933 $arJoinProps['BE_FPV'][$comp_prop_id]
2934 );
2935
2936 $ijPropCnt = $arJoinProps["BE_FPV"][$comp_prop_id]["CNT"];
2937
2938 //For enum properties
2939 if($db_jprop["PROPERTY_TYPE"]=="L")
2940 {
2941 //Then join list values table
2942 $arJoinProps['BE_FPEN'][$comp_prop_id] ??= [
2943 'CNT' => count($arJoinProps['BE_FPEN']),
2944 'MULTIPLE' => $db_jprop['MULTIPLE'],
2945 'VERSION' => 1,
2946 'ORIG_ID' => $db_jprop['ORIG_ID'],
2947 'JOIN' => $ijPropCnt,
2948 'bFullJoin' => false,
2949 ];
2950 $arJoinProps['BE_FPEN'][$comp_prop_id] = self::addJoinTypeSelect(
2951 $arJoinProps['BE_FPEN'][$comp_prop_id]
2952 );
2953
2954 $ijFpenCnt = $arJoinProps["BE_FPEN"][$comp_prop_id]["CNT"];
2955
2956 $arSelect["JFPEN".$ijFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2957 $arSelect["JFPEN".$ijFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_ENUM_ID", $this->arIBlockLongProps);
2958 }
2959 else
2960 {
2961 $arSelect["JFPV".$ijPropCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE", $this->arIBlockLongProps);
2962 }
2963
2964 //When there is no grouping select property value id also
2965 if($sGroupBy == "")
2966 $arSelect["JFPV".$ijPropCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID[1]."_".$PR_ID[2]."_VALUE_ID", $this->arIBlockLongProps);
2967 }
2968 }
2969
2970 }
2971 }
2972 else
2973 {
2974 //Define special processing for CIBlockResult::Fetch
2975 if($db_prop["USER_TYPE"]!="")
2976 {
2977 $arUserType = CIBlockProperty::GetUserType($db_prop["USER_TYPE"]);
2978 if(array_key_exists("ConvertFromDB", $arUserType))
2979 $this->arIBlockConvProps["PROPERTY_".$PR_ID."_VALUE"] = array(
2980 "ConvertFromDB" => $arUserType["ConvertFromDB"],
2981 "PROPERTY" => $db_prop,
2982 );
2983 }
2984
2985 //Infoblock+ (property stored in separate table)
2986 if($db_prop["VERSION"] == 2)
2987 {
2988 //This is single value property
2989 if($db_prop["MULTIPLE"] == "N")
2990 {
2991 //For numbers we will need special processing in CIBlockResult::Fetch
2992 if($db_prop["PROPERTY_TYPE"]=="N")
2993 $this->arIBlockNumProps["PROPERTY_".$PR_ID."_VALUE"] = $db_prop;
2994
2995 //Enum single property
2996 if($db_prop["PROPERTY_TYPE"]=="L")
2997 {
2998 //Join properties table if needed
2999 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
3000 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
3001 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
3002 //Then join list values table
3003 if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
3004 {
3005 $arJoinProps['FPEN'][$propertyId] ??= [
3006 'CNT' => count($arJoinProps['FPEN']),
3007 'MULTIPLE' => 'N',
3008 'VERSION' => 2,
3009 'ORIG_ID' => $db_prop['ORIG_ID'],
3010 'JOIN' => $iPropCnt,
3011 'bFullJoin' => false,
3012 ];
3013 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeSelect(
3014 $arJoinProps['FPEN'][$propertyId]
3015 );
3016 }
3017 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
3018
3019 if($bSort)
3020 $arSelect["FPEN".$iFpenCnt.".SORT"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_SORT", $this->arIBlockLongProps);
3021 $arSelect["FPEN".$iFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3022 $arSelect["FPEN".$iFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_ENUM_ID", $this->arIBlockLongProps);
3023 }
3024 else //Just single value property for Infoblock+
3025 {
3026 //Join properties table if needed
3027 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
3028 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
3029 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
3030
3031 $arSelect["FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3032 if($sGroupBy=="" && $db_prop["WITH_DESCRIPTION"] == "Y")
3033 $arSelect["FPS".$iPropCnt.".DESCRIPTION_".$db_prop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_DESCRIPTION", $arIBlockLongProps);
3034 }
3035
3036 //When there is no grouping and this is single value property for Infoblock+
3037 if($sGroupBy == "")
3038 {
3039 $arSelect[$DB->Concat("BE.ID","':'",$db_prop["ORIG_ID"])] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE_ID", $this->arIBlockLongProps);
3040 }
3041 }
3042 else //This is multiple value property for Infoblock+
3043 {
3044 //There was no grouping so we can join FPS and constuct an array on CIBlockPropertyResult::Fetch
3045 if(!$bWasGroup && !$bSubQuery)
3046 {
3047 //Join single value properties table if needed
3048 if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
3049 $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
3050 $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
3051
3052 $arSelect["FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3053 if($sGroupBy=="" && $db_prop["WITH_DESCRIPTION"] == "Y")
3054 $arSelect["FPS".$iPropCnt.".DESCRIPTION_".$db_prop["ORIG_ID"]] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_DESCRIPTION", $this->arIBlockLongProps);
3055
3056 //And we will need extra processing in CIBlockPropertyResult::Fetch
3057 $this->arIBlockMultProps["PROPERTY_".$PR_ID."_VALUE"] = $db_prop;
3058 }
3059 //This is multiple value property for Infoblock+ with gouping used
3060 else
3061 {
3062 //Join property metadata table
3063 $arJoinProps['FP'][$propertyId] ??= [
3064 'CNT' => count($arJoinProps['FP']),
3065 'bFullJoin' => false,
3066 ];
3067 $arJoinProps['FP'][$propertyId] = self::addJoinTypeSelect(
3068 $arJoinProps['FP'][$propertyId]
3069 );
3070
3071 //Join multiple values properties table if needed
3072 $arJoinProps['FPV'][$propertyId] ??= [
3073 'CNT' => count($arJoinProps['FPV']),
3074 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
3075 'MULTIPLE' => 'Y',
3076 'VERSION' => 2,
3077 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
3078 'bFullJoin' => false,
3079 ];
3080 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeSelect(
3081 $arJoinProps['FPV'][$propertyId]
3082 );
3083
3084 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
3085
3086 //For enum properties
3087 if($db_prop["PROPERTY_TYPE"]=="L")
3088 {
3089 //Then join list values table
3090 $arJoinProps['FPEN'][$propertyId] ??= [
3091 'CNT' => count($arJoinProps['FPEN']),
3092 'MULTIPLE' => 'Y',
3093 'VERSION' => 2,
3094 'ORIG_ID' => $db_prop['ORIG_ID'],
3095 'JOIN' => $iPropCnt,
3096 'bFullJoin' => false,
3097 ];
3098 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeSelect(
3099 $arJoinProps['FPEN'][$propertyId]
3100 );
3101
3102 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
3103
3104 if($bSort)
3105 $arSelect["FPEN".$iFpenCnt.".SORT"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_SORT", $this->arIBlockLongProps);
3106 $arSelect["FPEN".$iFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3107 $arSelect["FPEN".$iFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_ENUM_ID", $this->arIBlockLongProps);
3108 }
3109 else
3110 {
3111 $arSelect["FPV".$iPropCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3112 }
3113 }
3114 }
3115 }//Infoblocks with common values table (VERSION==1)
3116 else
3117 {
3118 //Join property metadata table
3119 $arJoinProps['FP'][$propertyId] ??= [
3120 'CNT' => count($arJoinProps['FP']),
3121 'bFullJoin' => false,
3122 ];
3123 $arJoinProps['FP'][$propertyId] = self::addJoinTypeSelect(
3124 $arJoinProps['FP'][$propertyId]
3125 );
3126
3127 //Join multiple values properties table if needed
3128 $arJoinProps['FPV'][$propertyId] ??= [
3129 'CNT' => count($arJoinProps['FPV']),
3130 'IBLOCK_ID' => $db_prop['IBLOCK_ID'],
3131 'MULTIPLE' => $db_prop['MULTIPLE'],
3132 'VERSION' => 1,
3133 'JOIN' => $arJoinProps['FP'][$propertyId]['CNT'],
3134 'bFullJoin' => false,
3135 ];
3136 $arJoinProps['FPV'][$propertyId] = self::addJoinTypeSelect(
3137 $arJoinProps['FPV'][$propertyId]
3138 );
3139 $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
3140
3141 //For enum properties
3142 if($db_prop["PROPERTY_TYPE"]=="L")
3143 {
3144 //Then join list values table
3145 $arJoinProps['FPEN'][$propertyId] ??= [
3146 'CNT' => count($arJoinProps['FPEN']),
3147 'MULTIPLE' => $db_prop['MULTIPLE'],
3148 'VERSION' => 1,
3149 'ORIG_ID' => $db_prop['ORIG_ID'],
3150 'JOIN' => $iPropCnt,
3151 'bFullJoin' => false,
3152 ];
3153 $arJoinProps['FPEN'][$propertyId] = self::addJoinTypeSelect(
3154 $arJoinProps['FPEN'][$propertyId]
3155 );
3156
3157 $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
3158
3159 if($bSort)
3160 $arSelect["FPEN".$iFpenCnt.".SORT"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_SORT", $this->arIBlockLongProps);
3161 $arSelect["FPEN".$iFpenCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3162 $arSelect["FPEN".$iFpenCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_ENUM_ID", $this->arIBlockLongProps);
3163 }
3164 else
3165 {
3166 if ($db_prop['PROPERTY_TYPE'] === Iblock\PropertyTable::TYPE_NUMBER)
3167 {
3168 $arSelect['FPV' . $iPropCnt . '.VALUE_NUM'] = CIBlockElement::MkAlias(
3169 $mal,
3170 'PROPERTY_' . $PR_ID . '_VALUE_NUM',
3171 $this->arIBlockLongProps
3172 );
3173 }
3174 $arSelect["FPV".$iPropCnt.".VALUE"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE", $this->arIBlockLongProps);
3175 }
3176
3177 //When there is no grouping select property value id also
3178 if($sGroupBy == "")
3179 $arSelect["FPV".$iPropCnt.".ID"] = CIBlockElement::MkAlias($mal, "PROPERTY_".$PR_ID."_VALUE_ID", $this->arIBlockLongProps);
3180 }
3181 }
3182
3183 //If this is subquery we do not need alias and any othe columns
3184 if($bSubQuery)
3185 {
3186 foreach($arSelect as $column => $alias)
3187 {
3188 if(preg_match('/^(FPV\\d+)\\.VALUE/', $column, $match))
3189 {
3190 $sSelect .= ", ".$match[1].".VALUE_NUM";
3191 break;
3192 }
3193 elseif(preg_match('/^(FPS\\d+)\\.PROPERTY_/', $column))
3194 {
3195 $sSelect .= ", ".$column;
3196 break;
3197 }
3198 }
3199 }
3200 else
3201 {
3202 foreach($arSelect as $column => $alias)
3203 $sSelect .= ", ".$column." as ".$alias;
3204 }
3205 }
3206
3207 public function MkAlias($max_alias_len, $alias, &$arIBlockLongProps)
3208 {
3209 if($max_alias_len && mb_strlen($alias) > $max_alias_len)
3210 {
3211 $alias_index = count($arIBlockLongProps);
3212 $arIBlockLongProps[$alias_index] = $alias;
3213 $alias = "ALIAS_".$alias_index."_";
3214 }
3215 return $alias;
3216 }
3217
3224 private static function checkPropertyIdentifier(int|string $identifier): bool
3225 {
3226 $identifier = (string)$identifier;
3227 if ($identifier === '')
3228 {
3229 return false;
3230 }
3231
3232 $prepared = [];
3233 $result = false;
3234 foreach (self::$propertyIdentifierMasks as $mask)
3235 {
3236 if (preg_match($mask, $identifier, $prepared))
3237 {
3238 $result = true;
3239 break;
3240 }
3241 }
3242
3243 return $result;
3244 }
3245
3252 private static function checkPropertyLinkIdentifier(string $identifier): bool
3253 {
3254 if ($identifier === '')
3255 {
3256 return false;
3257 }
3258
3259 $prepared = [];
3260 if (!preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $identifier, $prepared))
3261 {
3262 return false;
3263 }
3264
3265 if (!static::checkPropertyIdentifier($prepared[1]))
3266 {
3267 return false;
3268 }
3269
3270 $result = false;
3271 $subprepared = [];
3272 foreach (self::$propertyLinkFieldIdentifierMasks as $mask)
3273 {
3274 if (preg_match($mask, $prepared[2], $subprepared))
3275 {
3276 $result = true;
3277 break;
3278 }
3279 }
3280
3281 return $result;
3282 }
3283
3284 public function PrepareGetList(
3285 &$arIblockElementFields,
3286 &$arJoinProps,
3287
3288 &$arSelectFields,
3289 &$sSelect,
3290 &$arAddSelectFields,
3291
3292 &$arFilter,
3293 &$sWhere,
3294 &$sSectionWhere,
3295 &$arAddWhereFields,
3296
3297 &$arGroupBy,
3298 &$sGroupBy,
3299
3300 &$arOrder,
3301 &$arSqlOrder,
3302 &$arAddOrderByFields
3303 )
3304 {
3305 if(
3306 is_array($arSelectFields)
3307 && (in_array("DETAIL_PAGE_URL", $arSelectFields) || in_array("CANONICAL_PAGE_URL", $arSelectFields))
3308 && !in_array("LANG_DIR", $arSelectFields)
3309 )
3310 {
3311 $arSelectFields[] = "LANG_DIR";
3312 }
3313
3314 global $DB;
3315
3316 if (empty($arSelectFields))
3317 {
3318 $arSelectFields = ['*'];
3319 }
3320
3321 if ($arGroupBy === true)
3322 {
3323 $arGroupBy = [];
3324 }
3325
3326 if (empty($arGroupBy) && is_array($arGroupBy))
3327 {
3328 $this->bOnlyCount = true;
3329 }
3330
3331 $iPropCnt = 0;
3332 $arJoinProps = [
3333 'FP' => [
3334 //CNT
3335 //bFullJoin
3336 ],
3337 'FPV' => [
3338 //CNT
3339 //IBLOCK_ID
3340 //MULTIPLE
3341 //VERSION
3342 //JOIN
3343 //bFullJoin
3344 ],
3345 'FPS' => [ // property values for iblock 2.0
3346 //
3347 ],
3348 'FPEN' => [
3349 //CNT
3350 //MULTIPLE
3351 //VERSION
3352 //ORIG_ID
3353 //JOIN
3354 //bFullJoin
3355 ],
3356 'BE' => [
3357 //CNT
3358 //MULTIPLE
3359 //VERSION
3360 //ORIG_ID
3361 //JOIN
3362 //bJoinIBlock
3363 //bJoinSection
3364 ],
3365 'BE_FP' => [
3366 //CNT
3367 //JOIN
3368 //bFullJoin
3369 ],
3370 'BE_FPV' => [
3371 //CNT
3372 //IBLOCK_ID
3373 //MULTIPLE
3374 //VERSION
3375 //JOIN
3376 //BE_JOIN
3377 //bFullJoin
3378 ],
3379 'BE_FPS' => [
3380 //CNT
3381 //JOIN
3382 ],
3383 'BE_FPEN' => [
3384 //CNT
3385 //MULTIPLE
3386 //VERSION
3387 //ORIG_ID
3388 //JOIN
3389 //bFullJoin
3390 ],
3391 'BES' => '',
3392 'RV' => false, // order by RATING_TOTAL_VALUE
3393 'RVU' => false,
3394 'RVV' => false,
3395 'FC' => '',
3396 'BESI' => false,
3397 ];
3398
3399 $this->arIBlockMultProps = [];
3400 $this->arIBlockAllProps = [];
3401 $this->arIBlockNumProps = [];
3402 $bWasGroup = false;
3403
3404 //********************************ORDER BY PART***********************************************
3405
3406 $iblockIds = CIBlock::_MergeIBArrays(
3407 $arFilter["IBLOCK_ID"] ?? false,
3408 $arFilter["IBLOCK_CODE"] ?? false,
3409 );
3410 $orderAlias = array(
3411 'EXTERNAL_ID' => 'XML_ID',
3412 'DATE_ACTIVE_FROM' => 'ACTIVE_FROM',
3413 'DATE_ACTIVE_TO' => 'ACTIVE_TO'
3414 );
3415 $arSqlOrder = [];
3416 $arAddOrderByFields = [];
3417 $iOrdNum = -1;
3418 if (!is_array($arOrder))
3419 {
3420 $arOrder = [];
3421 }
3422 foreach($arOrder as $by=>$order)
3423 {
3424 $by_orig = $by;
3425 $by = mb_strtoupper($by);
3426 //Remove aliases
3427 if (isset($orderAlias[$by]))
3428 $by = $orderAlias[$by];
3429
3430 if (isset($arSqlOrder[$by]))
3431 continue;
3432
3433 if ($this->catalogIncluded && \CProductQueryBuilder::isValidField($by))
3434 {
3435 $iOrdNum++;
3436 $arAddOrderByFields[$iOrdNum] = Array($by=>$order);
3437 //Reserve for future fill
3438 $arSqlOrder[$iOrdNum] = false;
3439 }
3440 else
3441 {
3442 if($by == "ID") $arSqlOrder[$by] = $this->getIdOrder($order);
3443 elseif($by == "NAME") $arSqlOrder[$by] = CIBlock::_Order("BE.NAME", $order, "desc", false);
3444 elseif($by == "STATUS") $arSqlOrder[$by] = CIBlock::_Order("BE.WF_STATUS_ID", $order, "desc");
3445 elseif($by == "XML_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.XML_ID", $order, "desc");
3446 elseif($by == "CODE") $arSqlOrder[$by] = CIBlock::_Order("BE.CODE", $order, "desc");
3447 elseif($by == "TAGS") $arSqlOrder[$by] = CIBlock::_Order("BE.TAGS", $order, "desc");
3448 elseif($by == "TIMESTAMP_X") $arSqlOrder[$by] = CIBlock::_Order("BE.TIMESTAMP_X", $order, "desc");
3449 elseif($by == "CREATED") $arSqlOrder[$by] = CIBlock::_Order("BE.DATE_CREATE", $order, "desc");
3450 elseif($by == "CREATED_DATE") $arSqlOrder[$by] = CIBlock::_Order($DB->DateFormatToDB("YYYY.MM.DD", "BE.DATE_CREATE"), $order, "desc");
3451 elseif($by == "IBLOCK_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_ID", $order, "desc");
3452 elseif($by == "MODIFIED_BY") $arSqlOrder[$by] = CIBlock::_Order("BE.MODIFIED_BY", $order, "desc");
3453 elseif($by == "CREATED_BY") $arSqlOrder[$by] = CIBlock::_Order("BE.CREATED_BY", $order, "desc");
3454 elseif($by == "ACTIVE") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE", $order, "desc");
3455 elseif($by == "ACTIVE_FROM") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_FROM", $order, "desc");
3456 elseif($by == "ACTIVE_TO") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_TO", $order, "desc");
3457 elseif($by == "SORT") $arSqlOrder[$by] = CIBlock::_Order("BE.SORT", $order, "desc");
3458 elseif($by == "IBLOCK_SECTION_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_SECTION_ID", $order, "desc");
3459 elseif($by == "SHOW_COUNTER") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER", $order, "desc");
3460 elseif($by == "SHOW_COUNTER_START") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER_START", $order, "desc");
3461 elseif($by == "RAND") $arSqlOrder[$by] = CIBlockElement::GetRandFunction();
3462 elseif($by == "SHOWS") $arSqlOrder[$by] = CIBlock::_Order('SHOWS', $order, "desc", false);
3463 elseif($by == "HAS_PREVIEW_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.PREVIEW_PICTURE"), $order, "desc", false);
3464 elseif($by == "HAS_DETAIL_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.DETAIL_PICTURE"), $order, "desc", false);
3465 elseif($by == "RATING_TOTAL_VALUE")
3466 {
3467 $arSqlOrder[$by] = CIBlock::_Order("RV.TOTAL_VALUE", $order, "desc");
3468 $arJoinProps["RV"] = true;
3469 }
3470 elseif($by == "CNT")
3471 {
3472 if (!empty($arGroupBy) && is_array($arGroupBy))
3473 {
3474 $arSqlOrder[$by] = ' '.CIBlock::_Order('CNT', $order, 'desc', false).' ';
3475 }
3476 }
3477 elseif(mb_substr($by, 0, 9) == "PROPERTY_")
3478 {
3479 $propID = mb_strtoupper(mb_substr($by_orig, 9));
3480 if (preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $propID, $arMatch))
3481 {
3482 if (self::checkPropertyLinkIdentifier($propID))
3483 {
3484 $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
3485 if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_ELEMENT)
3486 {
3487 CIBlockElement::MkPropertyOrder($arMatch, $order, false, $db_prop, $arJoinProps, $arSqlOrder);
3488 }
3489 }
3490 }
3491 else
3492 {
3493 if (self::checkPropertyIdentifier($propID))
3494 {
3495 $db_prop = CIBlockProperty::GetPropertyArray($propID, $iblockIds);
3496 if ($db_prop)
3497 {
3498 CIBlockElement::MkPropertyOrder($by, $order, false, $db_prop, $arJoinProps, $arSqlOrder);
3499 }
3500 }
3501 }
3502 }
3503 elseif(mb_substr($by, 0, 13) == "PROPERTYSORT_")
3504 {
3505 $propID = mb_strtoupper(mb_substr($by_orig, 13));
3506 if (preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $propID, $arMatch))
3507 {
3508 if (self::checkPropertyLinkIdentifier($propID))
3509 {
3510 $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
3511 if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_ELEMENT)
3512 {
3513 CIBlockElement::MkPropertyOrder($arMatch, $order, true, $db_prop, $arJoinProps, $arSqlOrder);
3514 }
3515 }
3516 }
3517 else
3518 {
3519 if (self::checkPropertyIdentifier($propID))
3520 {
3521 $db_prop = CIBlockProperty::GetPropertyArray($propID, $iblockIds);
3522 if ($db_prop)
3523 {
3524 CIBlockElement::MkPropertyOrder($by, $order, true, $db_prop, $arJoinProps, $arSqlOrder);
3525 }
3526 }
3527 }
3528 }
3529 else
3530 {
3531 $by = "ID";
3532 if (!isset($arSqlOrder[$by]))
3533 {
3534 $arSqlOrder[$by] = CIBlock::_Order("BE.ID", $order, "desc");
3535 }
3536 }
3537
3538 //Check if have to add select field in order to correctly sort
3539 if (isset($arSqlOrder[$by]) && is_array($arSqlOrder[$by]))
3540 {
3541 if (!empty($arGroupBy) && is_array($arGroupBy))
3542 $arGroupBy[] = $arSqlOrder[$by][1];
3543 else
3544 $arSelectFields[] = $arSqlOrder[$by][1];
3545 // COLUMN ALIAS COLUMN EXPRESSION
3546 $arIblockElementFields[$arSqlOrder[$by][1]] = $arSqlOrder[$by][0];
3547 // ORDER EXPRESSION
3548 $arSqlOrder[$by] = $arSqlOrder[$by][2];
3549 }
3550 }
3551
3552 //Add order by fields to the select list
3553 //in order to avoid sql errors
3554 if (!empty($arGroupBy) && is_array($arGroupBy))
3555 {
3556 if ($by == "STATUS")
3557 {
3558 $arGroupBy[] = "WF_STATUS_ID";
3559 }
3560 elseif ($by == "CREATED")
3561 {
3562 $arGroupBy[] = "DATE_CREATE";
3563 }
3564 elseif ($by == "SHOWS")
3565 {
3566 $arGroupBy[] = "SHOW_COUNTER";
3567 $arGroupBy[] = "SHOW_COUNTER_START_X";
3568 }
3569 else
3570 {
3571 $arGroupBy[] = $by;
3572 }
3573 }
3574 else
3575 {
3576 if ($by == "STATUS")
3577 {
3578 $arSelectFields[] = "WF_STATUS_ID";
3579 }
3580 elseif ($by == "CREATED")
3581 {
3582 $arSelectFields[] = "DATE_CREATE";
3583 }
3584 elseif ($by == "SHOWS")
3585 {
3586 $arSelectFields[] = 'SHOWS';
3587 $arSelectFields[] = "SHOW_COUNTER";
3588 $arSelectFields[] = "SHOW_COUNTER_START_X";
3589 }
3590 else
3591 {
3592 $arSelectFields[] = $by;
3593 }
3594 }
3595 }
3596
3597 //*************************GROUP BY PART****************************
3598 $sGroupBy = "";
3599 if(!empty($arGroupBy) && is_array($arGroupBy))
3600 {
3601 $arSelectFields = $arGroupBy;
3602 $bWasGroup = true;
3603 foreach($arSelectFields as $key=>$val)
3604 {
3605 $val = mb_strtoupper($val);
3606 if(array_key_exists($val, $arIblockElementFields))
3607 {
3608 $sGroupBy.=",".preg_replace("/(\s+AS\s+[A-Z_]+)/i", "", $arIblockElementFields[$val]);
3609 }
3610 elseif(mb_substr($val, 0, 9) == "PROPERTY_")
3611 {
3612 $PR_ID = mb_strtoupper(mb_substr($val, 9));
3613 if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
3614 $sGroupBy .= CIBlockElement::MkPropertyGroup($db_prop, $arJoinProps);
3615 }
3616 elseif(mb_substr($val, 0, 13) == "PROPERTYSORT_")
3617 {
3618 $PR_ID = mb_strtoupper(mb_substr($val, 13));
3619 if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
3620 $sGroupBy .= CIBlockElement::MkPropertyGroup($db_prop, $arJoinProps, true);
3621 }
3622 }
3623 if ($sGroupBy !== '')
3624 {
3625 $sGroupBy = " GROUP BY " . mb_substr($sGroupBy, 1 ). " ";
3626 }
3627 }
3628
3629 //*************************SELECT PART****************************
3630 $arAddSelectFields = [];
3631 if($this->bOnlyCount)
3632 {
3633 $sSelect = "COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
3634 }
3635 else
3636 {
3637 $sSelect = "";
3638 $arDisplayedColumns = array();
3639 $bStar = false;
3640 foreach($arSelectFields as $key=>$val)
3641 {
3642 $val = mb_strtoupper($val);
3643 if(array_key_exists($val, $arIblockElementFields))
3644 {
3645 if(isset($arDisplayedColumns[$val]))
3646 continue;
3647 $arDisplayedColumns[$val] = true;
3648 $arSelectFields[$key] = $val;
3649 $sSelect.=",".$arIblockElementFields[$val]." as ".$val;
3650 }
3651 elseif($val == "PROPERTY_*" && !$bWasGroup)
3652 {
3653 //We have to analyze arFilter IBLOCK_ID and IBLOCK_CODE
3654 //in a way to be shure we will get properties of the ONE IBLOCK ONLY!
3655 $arPropertyFilter = array(
3656 "ACTIVE"=>"Y",
3657 "VERSION"=>2,
3658 );
3659 if(array_key_exists("IBLOCK_ID", $arFilter))
3660 {
3661 if(is_array($arFilter["IBLOCK_ID"]) && count($arFilter["IBLOCK_ID"])==1)
3662 $arPropertyFilter["IBLOCK_ID"] = $arFilter["IBLOCK_ID"][0];
3663 elseif(!is_array($arFilter["IBLOCK_ID"]) && intval($arFilter["IBLOCK_ID"])>0)
3664 $arPropertyFilter["IBLOCK_ID"] = $arFilter["IBLOCK_ID"];
3665 }
3666 if(!array_key_exists("IBLOCK_ID", $arPropertyFilter))
3667 {
3668 if(array_key_exists("IBLOCK_CODE", $arFilter))
3669 {
3670 if(is_array($arFilter["IBLOCK_CODE"]) && count($arFilter["IBLOCK_CODE"])==1)
3671 $arPropertyFilter["IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"][0];
3672 elseif(!is_array($arFilter["IBLOCK_CODE"]) && $arFilter["IBLOCK_CODE"] <> '')
3673 $arPropertyFilter["IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"];
3674 else
3675 continue;
3676 }
3677 else
3678 continue;
3679 }
3680
3681 $rs_prop = CIBlockProperty::GetList(array("sort"=>"asc"), $arPropertyFilter);
3682 while($db_prop = $rs_prop->Fetch())
3683 $this->arIBlockAllProps[]=$db_prop;
3684 $iblock_id = false;
3685 foreach($this->arIBlockAllProps as $db_prop)
3686 {
3687 if($db_prop["USER_TYPE"]!="")
3688 {
3689 $arUserType = CIBlockProperty::GetUserType($db_prop["USER_TYPE"]);
3690 if(array_key_exists("ConvertFromDB", $arUserType))
3691 $this->arIBlockConvProps["PROPERTY_".$db_prop["ID"]] = array(
3692 "ConvertFromDB"=>$arUserType["ConvertFromDB"],
3693 "PROPERTY"=>$db_prop,
3694 );
3695 }
3696 $db_prop["ORIG_ID"] = $db_prop["ID"];
3697 if($db_prop["MULTIPLE"]=="Y")
3698 $this->arIBlockMultProps["PROPERTY_".$db_prop["ID"]] = $db_prop;
3699 $iblock_id = $db_prop["IBLOCK_ID"];
3700 }
3701 if($iblock_id!==false)
3702 {
3703 if(!array_key_exists($iblock_id, $arJoinProps["FPS"]))
3704 $arJoinProps["FPS"][$iblock_id] = count($arJoinProps["FPS"]);
3705 $iPropCnt = $arJoinProps["FPS"][$iblock_id];
3706
3707 $sSelect .= ", FPS".$iPropCnt.".*";
3708 }
3709 }
3710 elseif(mb_substr($val, 0, 9) == "PROPERTY_")
3711 {
3712 $PR_ID = mb_strtoupper($val);
3713 if(isset($arDisplayedColumns[$PR_ID]))
3714 continue;
3715 $arDisplayedColumns[$PR_ID] = true;
3716 $PR_ID = mb_substr($PR_ID, 9);
3717
3718 $iblockIds = CIBlock::_MergeIBArrays(
3719 $arFilter["IBLOCK_ID"] ?? false,
3720 $arFilter["IBLOCK_CODE"] ?? false
3721 );
3722
3723 if(preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $PR_ID, $arMatch))
3724 {
3725 if (self::checkPropertyLinkIdentifier($PR_ID))
3726 {
3727 $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
3728 if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
3729 {
3730 $this->MkPropertySelect($arMatch, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect);
3731 }
3732 }
3733 }
3734 else
3735 {
3736 if (self::checkPropertyIdentifier($PR_ID))
3737 {
3738 $db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds);
3739 if ($db_prop)
3740 {
3741 $this->MkPropertySelect($PR_ID, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect);
3742 }
3743 }
3744 }
3745 }
3746 elseif(mb_substr($val, 0, 13) == "PROPERTYSORT_")
3747 {
3748 $PR_ID = mb_strtoupper($val);
3749 if(isset($arDisplayedColumns[$PR_ID]))
3750 continue;
3751 $arDisplayedColumns[$PR_ID] = true;
3752 $PR_ID = mb_substr($PR_ID, 13);
3753
3754 if(preg_match(self::PROPERTY_LINK_ELEMENT_MASK, $PR_ID, $arMatch))
3755 {
3756 if (self::checkPropertyLinkIdentifier($PR_ID))
3757 {
3758 $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
3759 if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
3760 $this->MkPropertySelect($arMatch, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect, true);
3761 }
3762 }
3763 else
3764 {
3765 if (self::checkPropertyIdentifier($PR_ID))
3766 {
3767 if ($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
3768 $this->MkPropertySelect($PR_ID, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect, true);
3769 }
3770 }
3771 }
3772 elseif($val == "*")
3773 {
3774 $bStar = true;
3775 }
3776 elseif ($this->catalogIncluded && \CProductQueryBuilder::isValidField($val))
3777 {
3778 $arAddSelectFields[] = $val;
3779 }
3780 elseif(
3781 $val == "RATING_TOTAL_VALUE"
3782 || $val == "RATING_TOTAL_VOTES"
3783 || $val == "RATING_TOTAL_POSITIVE_VOTES"
3784 || $val == "RATING_TOTAL_NEGATIVE_VOTES"
3785 )
3786 {
3787 if(isset($arDisplayedColumns[$val]))
3788 continue;
3789 $arDisplayedColumns[$val] = true;
3790 $arSelectFields[$key] = $val;
3791 $sSelect.=",".preg_replace("/^RATING_/", "RV.", $val)." as ".$val;
3792 $arJoinProps["RV"] = true;
3793 }
3794 elseif($val == "RATING_USER_VOTE_VALUE")
3795 {
3796 if(isset($arDisplayedColumns[$val]))
3797 continue;
3798 $arDisplayedColumns[$val] = true;
3799 $arSelectFields[$key] = $val;
3800
3801 //if(isset($USER) && is_object($USER))
3802 if ($this->userExists)
3803 {
3804 $sSelect.=",".$DB->IsNull('RVU.VALUE', '0')." as ".$val;
3805 $arJoinProps["RVU"] = true;
3806 }
3807 else
3808 {
3809 $sSelect.=",0 as ".$val;
3810 }
3811 }
3812 elseif ($val === 'SHOWS')
3813 {
3814 $arSelectFields[$key] = $val;
3815 $sSelect .= ',' . CIBlockElement::GetShowedFunction() . ' as ' . $val;
3816 }
3817 }
3818
3819 if($bStar)
3820 {
3821 foreach($arIblockElementFields as $key=>$val)
3822 {
3823 if(isset($arDisplayedColumns[$key]))
3824 continue;
3825 $arDisplayedColumns[$key] = true;
3826 $arSelectFields[]=$key;
3827 $sSelect.=",".$val." as ".$key;
3828 }
3829 }
3830 elseif ($sGroupBy === '')
3831 {
3832 //Try to add missing fields for correct URL translation (only then no grouping)
3833 if(isset($arDisplayedColumns["DETAIL_PAGE_URL"]))
3834 $arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
3835 elseif(isset($arDisplayedColumns["CANONICAL_PAGE_URL"]))
3836 $arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
3837 elseif(isset($arDisplayedColumns["SECTION_PAGE_URL"]))
3838 $arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
3839 elseif(isset($arDisplayedColumns["LIST_PAGE_URL"]))
3840 $arAddFields = array("LANG_DIR", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
3841 else
3842 $arAddFields = array();
3843
3844 //Try to add missing fields for correct PREVIEW and DETAIL text formatting
3845 if(isset($arDisplayedColumns["DETAIL_TEXT"]))
3846 $arAddFields[] = "DETAIL_TEXT_TYPE";
3847 if(isset($arDisplayedColumns["PREVIEW_TEXT"]))
3848 $arAddFields[] = "PREVIEW_TEXT_TYPE";
3849
3850 foreach($arAddFields as $key)
3851 {
3852 if(isset($arDisplayedColumns[$key]))
3853 continue;
3854 $arDisplayedColumns[$key] = true;
3855 $arSelectFields[]=$key;
3856 $sSelect.=",".$arIblockElementFields[$key]." as ".$key;
3857 }
3858 }
3859
3860 if ($sGroupBy !== '')
3861 {
3862 $sSelect = mb_substr($sSelect, 1). ", COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
3863 }
3864 elseif ($sSelect !== '')
3865 {
3866 $sSelect = "%%_DISTINCT_%% " . mb_substr($sSelect, 1) . " ";
3867 }
3868 }
3869
3870 //*********************WHERE PART*********************
3871 $arAddWhereFields = [];
3872 if (is_array($arFilter) && isset($arFilter["CATALOG"]))
3873 {
3874 $arAddWhereFields = $arFilter["CATALOG"];
3875 unset($arFilter["CATALOG"]);
3876 }
3877
3878 $arSqlSearch = CIBlockElement::MkFilter($arFilter, $arJoinProps, $arAddWhereFields);
3879 $this->bDistinct = false;
3880 $sSectionWhere = "";
3881
3882 $sWhere = "";
3883 foreach ($arSqlSearch as $condition)
3884 {
3885 if (trim($condition, "\n\t") !== '')
3886 {
3887 $sWhere .= "\n\t\t\tAND (" . $condition . ")";
3888 }
3889 }
3890 }
3891
3893 // Add function
3895 public function Add($arFields, $bWorkFlow=false, $bUpdateSearch=true, $bResizePictures=false)
3896 {
3897 global $DB;
3898
3899 if ($this->iblock !== null && $this->iblock['ID'] === (int)$arFields["IBLOCK_ID"])
3900 {
3902 }
3903 else
3904 {
3905 $arIBlock = CIBlock::GetArrayByID($arFields["IBLOCK_ID"]);
3906 }
3907
3908 $existIblock = !empty($arIBlock) && is_array($arIBlock);
3909 $bWorkFlow = $bWorkFlow && $existIblock && ($arIBlock["WORKFLOW"] != "N") && $this->workflowIncluded;
3910 $bBizProc = $existIblock && ($arIBlock["BIZPROC"] == "Y") && $this->bizprocInstalled;
3911
3912 if(isset($arFields["BP_PUBLISHED"]))
3913 {
3914 if($bBizProc)
3915 {
3916 if($arFields["BP_PUBLISHED"] == "Y")
3917 {
3918 $arFields["WF_STATUS_ID"] = 1;
3919 $arFields["WF_NEW"] = false;
3920 }
3921 else
3922 {
3923 $arFields["WF_STATUS_ID"] = 2;
3924 $arFields["WF_NEW"] = "Y";
3925 $arFields["BP_PUBLISHED"] = "N";
3926 }
3927 }
3928 else
3929 {
3930 unset($arFields["BP_PUBLISHED"]);
3931 }
3932 }
3933
3934 if(array_key_exists("IBLOCK_SECTION_ID", $arFields))
3935 {
3936 if (!isset($arFields["IBLOCK_SECTION"]))
3937 {
3938 $arFields["IBLOCK_SECTION"] = array($arFields["IBLOCK_SECTION_ID"]);
3939 }
3940 elseif (is_array($arFields["IBLOCK_SECTION"]) && !in_array($arFields["IBLOCK_SECTION_ID"], $arFields["IBLOCK_SECTION"]))
3941 {
3942 unset($arFields["IBLOCK_SECTION_ID"]);
3943 }
3944 }
3945
3946 $strWarning = "";
3947 if($bResizePictures)
3948 {
3949 $arDef = $arIBlock["FIELDS"]["PREVIEW_PICTURE"]["DEFAULT_VALUE"];
3950
3951 if(
3952 $arDef["FROM_DETAIL"] === "Y"
3953 && isset($arFields["DETAIL_PICTURE"])
3954 && is_array($arFields["DETAIL_PICTURE"])
3955 && $arFields["DETAIL_PICTURE"]["size"] > 0
3956 && (
3957 $arDef["UPDATE_WITH_DETAIL"] === "Y"
3958 || $arFields["PREVIEW_PICTURE"]["size"] <= 0
3959 )
3960 )
3961 {
3962 $arNewPreview = $arFields["DETAIL_PICTURE"];
3963 $arNewPreview["COPY_FILE"] = "Y";
3964 if (
3965 isset($arFields["PREVIEW_PICTURE"])
3966 && is_array($arFields["PREVIEW_PICTURE"])
3967 && isset($arFields["PREVIEW_PICTURE"]["description"])
3968 )
3969 {
3970 $arNewPreview["description"] = $arFields["PREVIEW_PICTURE"]["description"];
3971 }
3972
3973 $arFields["PREVIEW_PICTURE"] = $arNewPreview;
3974 }
3975
3976 if(
3977 isset($arFields["PREVIEW_PICTURE"])
3978 && is_array($arFields["PREVIEW_PICTURE"])
3979 && $arDef["SCALE"] === "Y"
3980 )
3981 {
3982 $arNewPicture = CIBlock::ResizePicture($arFields["PREVIEW_PICTURE"], $arDef);
3983 if(is_array($arNewPicture))
3984 {
3985 $arNewPicture["description"] = $arFields["PREVIEW_PICTURE"]["description"];
3986 $arFields["PREVIEW_PICTURE"] = $arNewPicture;
3987 }
3988 elseif($arDef["IGNORE_ERRORS"] !== "Y")
3989 {
3990 unset($arFields["PREVIEW_PICTURE"]);
3991 $strWarning .= GetMessage("IBLOCK_FIELD_PREVIEW_PICTURE").": ".$arNewPicture."<br>";
3992 }
3993 }
3994
3995 if(
3996 isset($arFields["PREVIEW_PICTURE"])
3997 && is_array($arFields["PREVIEW_PICTURE"])
3998 && $arDef["USE_WATERMARK_FILE"] === "Y"
3999 )
4000 {
4001 $arFields["PREVIEW_PICTURE"]["copy"] ??= null;
4002 if(
4003 $arFields["PREVIEW_PICTURE"]["tmp_name"] <> ''
4004 && (
4005 $arFields["PREVIEW_PICTURE"]["tmp_name"] === $arFields["DETAIL_PICTURE"]["tmp_name"]
4006 || ($arFields["PREVIEW_PICTURE"]["COPY_FILE"] == "Y" && !$arFields["PREVIEW_PICTURE"]["copy"])
4007 )
4008 )
4009 {
4010 $tmp_name = CTempFile::GetFileName(basename($arFields["PREVIEW_PICTURE"]["tmp_name"]));
4011 CheckDirPath($tmp_name);
4012 copy($arFields["PREVIEW_PICTURE"]["tmp_name"], $tmp_name);
4013 $arFields["PREVIEW_PICTURE"]["copy"] = true;
4014 $arFields["PREVIEW_PICTURE"]["tmp_name"] = $tmp_name;
4015 }
4016
4017 CIBlock::FilterPicture($arFields["PREVIEW_PICTURE"]["tmp_name"], array(
4018 "name" => "watermark",
4019 "position" => $arDef["WATERMARK_FILE_POSITION"],
4020 "type" => "file",
4021 "size" => "real",
4022 "alpha_level" => 100 - min(max($arDef["WATERMARK_FILE_ALPHA"], 0), 100),
4023 "file" => $_SERVER["DOCUMENT_ROOT"].Rel2Abs("/", $arDef["WATERMARK_FILE"]),
4024 ));
4025 }
4026
4027 if(
4028 isset($arFields["PREVIEW_PICTURE"])
4029 && is_array($arFields["PREVIEW_PICTURE"])
4030 && $arDef["USE_WATERMARK_TEXT"] === "Y"
4031 )
4032 {
4033 $arFields["PREVIEW_PICTURE"]["copy"] ??= null;
4034 if(
4035 $arFields["PREVIEW_PICTURE"]["tmp_name"] <> ''
4036 && (
4037 $arFields["PREVIEW_PICTURE"]["tmp_name"] === $arFields["DETAIL_PICTURE"]["tmp_name"]
4038 || ($arFields["PREVIEW_PICTURE"]["COPY_FILE"] == "Y" && !$arFields["PREVIEW_PICTURE"]["copy"])
4039 )
4040 )
4041 {
4042 $tmp_name = CTempFile::GetFileName(basename($arFields["PREVIEW_PICTURE"]["tmp_name"]));
4043 CheckDirPath($tmp_name);
4044 copy($arFields["PREVIEW_PICTURE"]["tmp_name"], $tmp_name);
4045 $arFields["PREVIEW_PICTURE"]["copy"] = true;
4046 $arFields["PREVIEW_PICTURE"]["tmp_name"] = $tmp_name;
4047 }
4048
4049 CIBlock::FilterPicture($arFields["PREVIEW_PICTURE"]["tmp_name"], array(
4050 "name" => "watermark",
4051 "position" => $arDef["WATERMARK_TEXT_POSITION"],
4052 "type" => "text",
4053 "coefficient" => $arDef["WATERMARK_TEXT_SIZE"],
4054 "text" => $arDef["WATERMARK_TEXT"],
4055 "font" => $_SERVER["DOCUMENT_ROOT"].Rel2Abs("/", $arDef["WATERMARK_TEXT_FONT"]),
4056 "color" => $arDef["WATERMARK_TEXT_COLOR"],
4057 ));
4058 }
4059
4060 $arDef = $arIBlock["FIELDS"]["DETAIL_PICTURE"]["DEFAULT_VALUE"];
4061
4062 if(
4063 isset($arFields["DETAIL_PICTURE"])
4064 && is_array($arFields["DETAIL_PICTURE"])
4065 && $arDef["SCALE"] === "Y"
4066 )
4067 {
4068 $arNewPicture = CIBlock::ResizePicture($arFields["DETAIL_PICTURE"], $arDef);
4069 if(is_array($arNewPicture))
4070 {
4071 $arNewPicture["description"] = $arFields["DETAIL_PICTURE"]["description"];
4072 $arFields["DETAIL_PICTURE"] = $arNewPicture;
4073 }
4074 elseif($arDef["IGNORE_ERRORS"] !== "Y")
4075 {
4076 unset($arFields["DETAIL_PICTURE"]);
4077 $strWarning .= GetMessage("IBLOCK_FIELD_DETAIL_PICTURE").": ".$arNewPicture."<br>";
4078 }
4079 }
4080
4081 if(
4082 isset($arFields["DETAIL_PICTURE"])
4083 && is_array($arFields["DETAIL_PICTURE"])
4084 && $arDef["USE_WATERMARK_FILE"] === "Y"
4085 )
4086 {
4087 $arFields["DETAIL_PICTURE"]["copy"] ??= null;
4088 if(
4089 $arFields["DETAIL_PICTURE"]["tmp_name"] <> ''
4090 && (
4091 $arFields["DETAIL_PICTURE"]["tmp_name"] === $arFields["PREVIEW_PICTURE"]["tmp_name"]
4092 || ($arFields["DETAIL_PICTURE"]["COPY_FILE"] == "Y" && !$arFields["DETAIL_PICTURE"]["copy"])
4093 )
4094 )
4095 {
4096 $tmp_name = CTempFile::GetFileName(basename($arFields["DETAIL_PICTURE"]["tmp_name"]));
4097 CheckDirPath($tmp_name);
4098 copy($arFields["DETAIL_PICTURE"]["tmp_name"], $tmp_name);
4099 $arFields["DETAIL_PICTURE"]["copy"] = true;
4100 $arFields["DETAIL_PICTURE"]["tmp_name"] = $tmp_name;
4101 }
4102
4103 CIBlock::FilterPicture($arFields["DETAIL_PICTURE"]["tmp_name"], array(
4104 "name" => "watermark",
4105 "position" => $arDef["WATERMARK_FILE_POSITION"],
4106 "type" => "file",
4107 "size" => "real",
4108 "alpha_level" => 100 - min(max($arDef["WATERMARK_FILE_ALPHA"], 0), 100),
4109 "file" => $_SERVER["DOCUMENT_ROOT"].Rel2Abs("/", $arDef["WATERMARK_FILE"]),
4110 ));
4111 }
4112
4113 if(
4114 isset($arFields["DETAIL_PICTURE"])
4115 && is_array($arFields["DETAIL_PICTURE"])
4116 && $arDef["USE_WATERMARK_TEXT"] === "Y"
4117 )
4118 {
4119 $arFields["DETAIL_PICTURE"]["copy"] ??= null;
4120 if(
4121 $arFields["DETAIL_PICTURE"]["tmp_name"] <> ''
4122 && (
4123 $arFields["DETAIL_PICTURE"]["tmp_name"] === $arFields["PREVIEW_PICTURE"]["tmp_name"]
4124 || ($arFields["DETAIL_PICTURE"]["COPY_FILE"] == "Y" && !$arFields["DETAIL_PICTURE"]["copy"])
4125 )
4126 )
4127 {
4128 $tmp_name = CTempFile::GetFileName(basename($arFields["DETAIL_PICTURE"]["tmp_name"]));
4129 CheckDirPath($tmp_name);
4130 copy($arFields["DETAIL_PICTURE"]["tmp_name"], $tmp_name);
4131 $arFields["DETAIL_PICTURE"]["copy"] = true;
4132 $arFields["DETAIL_PICTURE"]["tmp_name"] = $tmp_name;
4133 }
4134
4135 CIBlock::FilterPicture($arFields["DETAIL_PICTURE"]["tmp_name"], array(
4136 "name" => "watermark",
4137 "position" => $arDef["WATERMARK_TEXT_POSITION"],
4138 "type" => "text",
4139 "coefficient" => $arDef["WATERMARK_TEXT_SIZE"],
4140 "text" => $arDef["WATERMARK_TEXT"],
4141 "font" => $_SERVER["DOCUMENT_ROOT"].Rel2Abs("/", $arDef["WATERMARK_TEXT_FONT"]),
4142 "color" => $arDef["WATERMARK_TEXT_COLOR"],
4143 ));
4144 }
4145 }
4146
4147 $ipropTemplates = new \Bitrix\Iblock\InheritedProperty\ElementTemplates($arFields["IBLOCK_ID"], 0);
4148 if(array_key_exists("PREVIEW_PICTURE", $arFields))
4149 {
4150 if (is_array($arFields["PREVIEW_PICTURE"]))
4151 {
4152 if (
4153 ($arFields["PREVIEW_PICTURE"]["name"] ?? '') === ''
4154 && ($arFields["PREVIEW_PICTURE"]["del"] ?? '') === ''
4155 )
4156 {
4157 unset($arFields["PREVIEW_PICTURE"]);
4158 }
4159 else
4160 {
4161 $arFields["PREVIEW_PICTURE"]["MODULE_ID"] = "iblock";
4162 $arFields["PREVIEW_PICTURE"]["name"] = \Bitrix\Iblock\Template\Helper::makeFileName(
4163 $ipropTemplates
4164 ,"ELEMENT_PREVIEW_PICTURE_FILE_NAME"
4165 ,$arFields
4166 ,$arFields["PREVIEW_PICTURE"]
4167 );
4168 }
4169 }
4170 else
4171 {
4172 if((int)$arFields["PREVIEW_PICTURE"] <= 0)
4173 unset($arFields["PREVIEW_PICTURE"]);
4174 }
4175 }
4176
4177 if(array_key_exists("DETAIL_PICTURE", $arFields))
4178 {
4179 if (is_array($arFields["DETAIL_PICTURE"]))
4180 {
4181 if (
4182 ($arFields["DETAIL_PICTURE"]["name"] ?? '') === ''
4183 && ($arFields["DETAIL_PICTURE"]["del"] ?? '') === ''
4184 )
4185 {
4186 unset($arFields["DETAIL_PICTURE"]);
4187 }
4188 else
4189 {
4190 $arFields["DETAIL_PICTURE"]["MODULE_ID"] = "iblock";
4191 $arFields["DETAIL_PICTURE"]["name"] = \Bitrix\Iblock\Template\Helper::makeFileName(
4192 $ipropTemplates
4193 ,"ELEMENT_DETAIL_PICTURE_FILE_NAME"
4194 ,$arFields
4195 ,$arFields["DETAIL_PICTURE"]
4196 );
4197 }
4198 }
4199 else
4200 {
4201 if((int)$arFields["DETAIL_PICTURE"] <= 0)
4202 unset($arFields["DETAIL_PICTURE"]);
4203 }
4204 }
4205
4206 if(isset($arFields["ACTIVE"]) && $arFields["ACTIVE"]!="Y")
4207 $arFields["ACTIVE"]="N";
4208
4209 if(isset($arFields["PREVIEW_TEXT_TYPE"]) && $arFields["PREVIEW_TEXT_TYPE"]!="html")
4210 $arFields["PREVIEW_TEXT_TYPE"]="text";
4211
4212 if(isset($arFields["DETAIL_TEXT_TYPE"]) && $arFields["DETAIL_TEXT_TYPE"]!="html")
4213 $arFields["DETAIL_TEXT_TYPE"]="text";
4214
4215 if(is_set($arFields, "DATE_ACTIVE_FROM"))
4216 $arFields["ACTIVE_FROM"] = $arFields["DATE_ACTIVE_FROM"];
4217 if(is_set($arFields, "DATE_ACTIVE_TO"))
4218 $arFields["ACTIVE_TO"] = $arFields["DATE_ACTIVE_TO"];
4219 if(is_set($arFields, "EXTERNAL_ID"))
4220 $arFields["XML_ID"] = $arFields["EXTERNAL_ID"];
4221
4222 if($bWorkFlow)
4223 {
4224 $arFields["WF"] = "Y";
4225 if($arFields["WF_STATUS_ID"] != 1)
4226 $arFields["WF_NEW"] = "Y";
4227 else
4228 $arFields["WF_NEW"] = "";
4229 }
4230
4231 $arFields["NAME"] = (string)$arFields["NAME"];
4232 $arFields["SEARCHABLE_CONTENT"] = false;
4233 if ($this->searchIncluded)
4234 {
4235 $arFields["SEARCHABLE_CONTENT"] = $arFields["NAME"];
4236 if (isset($arFields["PREVIEW_TEXT"]))
4237 {
4238 if (isset($arFields["PREVIEW_TEXT_TYPE"]) && $arFields["PREVIEW_TEXT_TYPE"] == "html")
4239 {
4240 $arFields["SEARCHABLE_CONTENT"] .= "\r\n".HTMLToTxt($arFields["PREVIEW_TEXT"]);
4241 }
4242 else
4243 {
4244 $arFields["SEARCHABLE_CONTENT"] .= "\r\n".$arFields["PREVIEW_TEXT"];
4245 }
4246 }
4247
4248 if (isset($arFields["DETAIL_TEXT"]))
4249 {
4250 if (isset($arFields["DETAIL_TEXT_TYPE"]) && $arFields["DETAIL_TEXT_TYPE"] == "html")
4251 {
4252 $arFields["SEARCHABLE_CONTENT"] .= "\r\n".HTMLToTxt($arFields["DETAIL_TEXT"]);
4253 }
4254 else
4255 {
4256 $arFields["SEARCHABLE_CONTENT"] .= "\r\n".$arFields["DETAIL_TEXT"];
4257 }
4258 }
4259 $arFields["SEARCHABLE_CONTENT"] = mb_strtoupper($arFields["SEARCHABLE_CONTENT"]);
4260 }
4261
4262 if(!$this->CheckFields($arFields) || $strWarning != '')
4263 {
4264 $this->LAST_ERROR .= $strWarning;
4265 $Result = false;
4266 $arFields["RESULT_MESSAGE"] = &$this->LAST_ERROR;
4267 }
4268 else
4269 {
4270 if(array_key_exists("PREVIEW_PICTURE", $arFields))
4271 {
4272 $SAVED_PREVIEW_PICTURE = $arFields["PREVIEW_PICTURE"];
4273 if(is_array($arFields["PREVIEW_PICTURE"]))
4274 CFile::SaveForDB($arFields, "PREVIEW_PICTURE", "iblock");
4275 if($bWorkFlow)
4276 $COPY_PREVIEW_PICTURE = $arFields["PREVIEW_PICTURE"];
4277 }
4278
4279 if(array_key_exists("DETAIL_PICTURE", $arFields))
4280 {
4281 $SAVED_DETAIL_PICTURE = $arFields["DETAIL_PICTURE"];
4282 if(is_array($arFields["DETAIL_PICTURE"]))
4283 CFile::SaveForDB($arFields, "DETAIL_PICTURE", "iblock");
4284 if($bWorkFlow)
4285 $COPY_DETAIL_PICTURE = $arFields["DETAIL_PICTURE"];
4286 }
4287
4288 unset($arFields["ID"]);
4289 if ($this->userExists)
4290 {
4291 if(!isset($arFields["CREATED_BY"]) || (int)$arFields["CREATED_BY"] <= 0)
4292 $arFields["CREATED_BY"] = $this->userId;
4293 if(!isset($arFields["MODIFIED_BY"]) || (int)$arFields["MODIFIED_BY"] <= 0)
4294 $arFields["MODIFIED_BY"] = $this->userId;
4295 }
4296 $arFields["~TIMESTAMP_X"] = $arFields["~DATE_CREATE"] = $DB->CurrentTimeFunction();
4297
4298 foreach (GetModuleEvents("iblock", "OnIBlockElementAdd", true) as $arEvent)
4300
4301 $IBLOCK_SECTION_ID = $arFields["IBLOCK_SECTION_ID"] ?? null;
4302 unset($arFields["IBLOCK_SECTION_ID"]);
4303
4304 $ID = $DB->Add("b_iblock_element", $arFields, array("DETAIL_TEXT", "SEARCHABLE_CONTENT"), "iblock");
4305
4306 if(array_key_exists("PREVIEW_PICTURE", $arFields))
4307 {
4308 $arFields["PREVIEW_PICTURE_ID"] = $arFields["PREVIEW_PICTURE"];
4309 $arFields["PREVIEW_PICTURE"] = $SAVED_PREVIEW_PICTURE;
4310 }
4311
4312 if(array_key_exists("DETAIL_PICTURE", $arFields))
4313 {
4314 $arFields["DETAIL_PICTURE_ID"] = $arFields["DETAIL_PICTURE"];
4315 $arFields["DETAIL_PICTURE"] = $SAVED_DETAIL_PICTURE;
4316 }
4317
4319 {
4320 $DB->Query("INSERT INTO b_iblock_element_prop_s".$arFields["IBLOCK_ID"]."(IBLOCK_ELEMENT_ID)VALUES(".$ID.")");
4321 }
4322
4323 if (!empty($arFields["PROPERTY_VALUES"]) && is_array($arFields["PROPERTY_VALUES"]))
4324 {
4325 CIBlockElement::SetPropertyValues($ID, $arFields["IBLOCK_ID"], $arFields["PROPERTY_VALUES"]);
4326 }
4327
4328 $updateFields = array();
4329 if(!isset($arFields["XML_ID"]) || $arFields["XML_ID"] == '')
4330 {
4331 $arFields["XML_ID"] = $ID;
4332 $updateFields["XML_ID"] = $ID;
4333 }
4334 if (!$this->searchIncluded)
4335 {
4336 $arFields['SEARCHABLE_CONTENT'] = $this->getSearchableContent($ID, $arFields, $arIBlock);
4337
4338 if (FullText::doesIblockSupportByData($arIBlock))
4339 {
4340 $searchIndexParams = [
4341 'ELEMENT_ID' => $ID,
4342 'SEARCH_CONTENT' => $arFields['SEARCHABLE_CONTENT'],
4343 ];
4344
4345 FullText::add($arIBlock['ID'], $searchIndexParams);
4346 }
4347
4348 $updateFields['SEARCHABLE_CONTENT'] = $arFields['SEARCHABLE_CONTENT'];
4349 }
4350
4351 if (!empty($updateFields))
4352 {
4353 $updateQuery = $DB->PrepareUpdate("b_iblock_element", $updateFields, "iblock");
4354 if ($updateQuery != "")
4355 {
4356 $updateQuery .= ', TIMESTAMP_X = TIMESTAMP_X';
4357 $DB->Query("UPDATE b_iblock_element SET ".$updateQuery." WHERE ID = ".$ID);
4358 }
4359 }
4360 unset($updateFields);
4361
4362 if(is_set($arFields, "IBLOCK_SECTION"))
4363 CIBlockElement::SetElementSection($ID, $arFields["IBLOCK_SECTION"], true, $arIBlock["RIGHTS_MODE"] === "E"? $arIBlock["ID"]: 0, $IBLOCK_SECTION_ID);
4364
4365 if ($arIBlock["RIGHTS_MODE"] === Iblock\IblockTable::RIGHTS_EXTENDED)
4366 {
4367 $obElementRights = new CIBlockElementRights($arIBlock["ID"], $ID);
4368 if(!is_set($arFields, "IBLOCK_SECTION") || empty($arFields["IBLOCK_SECTION"]))
4369 $obElementRights->ChangeParents(array(), array(0));
4370 if(array_key_exists("RIGHTS", $arFields) && is_array($arFields["RIGHTS"]))
4371 $obElementRights->SetRights($arFields["RIGHTS"]);
4372 }
4373
4374 if (array_key_exists("IPROPERTY_TEMPLATES", $arFields))
4375 {
4376 $ipropTemplates = new \Bitrix\Iblock\InheritedProperty\ElementTemplates($arIBlock["ID"], $ID);
4377 $ipropTemplates->set($arFields["IPROPERTY_TEMPLATES"]);
4378 }
4379
4380 if ($bUpdateSearch && $this->searchIncluded)
4381 {
4383 }
4384
4386
4387 if(
4388 !isset($arFields["WF_PARENT_ELEMENT_ID"])
4389 && $arIBlock["FIELDS"]["LOG_ELEMENT_ADD"]["IS_REQUIRED"] == "Y"
4390 )
4391 {
4392 $arEvents = GetModuleEvents("main", "OnBeforeEventLog", true);
4393 if(
4394 empty($arEvents)
4395 || ExecuteModuleEventEx($arEvents[0], array($this->userId))===false
4396 )
4397 {
4398 $rsElement = CIBlockElement::GetList(array(), array("=ID"=>$ID), false, false, array("LIST_PAGE_URL", "NAME", "CODE"));
4399 $arElement = $rsElement->GetNext();
4400 $res = array(
4401 "ID" => $ID,
4402 "CODE" => $arElement["CODE"],
4403 "NAME" => $arElement["NAME"],
4404 "ELEMENT_NAME" => $arIBlock["ELEMENT_NAME"],
4405 "USER_ID" => $this->userId,
4406 "IBLOCK_PAGE_URL" => $arElement["LIST_PAGE_URL"],
4407 );
4409 "IBLOCK",
4410 "IBLOCK_ELEMENT_ADD",
4411 "iblock",
4412 $arIBlock["ID"],
4413 serialize($res)
4414 );
4415 }
4416 }
4417 if($bWorkFlow && (int)($arFields["WF_PARENT_ELEMENT_ID"] ?? null) <= 0)
4418 {
4419 // It is completly new element - so make it copy
4420 unset($arFields["WF_NEW"]);
4421 $arFields["WF_PARENT_ELEMENT_ID"] = $ID;
4422 $arNewFields = $arFields;
4423 $arNewFields["PREVIEW_PICTURE"] = $COPY_PREVIEW_PICTURE ?? null;
4424 $arNewFields["DETAIL_PICTURE"] = $COPY_DETAIL_PICTURE ?? null;
4425
4426 if (isset($arNewFields['PROPERTY_VALUES']) && is_array($arNewFields['PROPERTY_VALUES']))
4427 {
4428 $i = 0;
4429 $db_prop = CIBlockProperty::GetList(array(), array(
4430 "IBLOCK_ID" => $arFields["IBLOCK_ID"],
4431 "CHECK_PERMISSIONS" => "N",
4432 "PROPERTY_TYPE" => "F",
4433 ));
4434 while($arProp = $db_prop->Fetch())
4435 {
4436 $i++;
4437 unset($arNewFields["PROPERTY_VALUES"][$arProp["CODE"]]);
4438 unset($arNewFields["PROPERTY_VALUES"][$arProp["ID"]]);
4439 $arNewFields["PROPERTY_VALUES"][$arProp["ID"]] = array();
4440 }
4441
4442 if($i > 0)
4443 {
4444 $props = CIBlockElement::GetProperty($arFields["IBLOCK_ID"], $ID, "sort", "asc", array("PROPERTY_TYPE" => "F", "EMPTY" => "N"));
4445 while($arProp = $props->Fetch())
4446 {
4447 $arNewFields["PROPERTY_VALUES"][$arProp["ID"]][$arProp['PROPERTY_VALUE_ID']] = array(
4448 "VALUE" => $arProp["VALUE"],
4449 "DESCRIPTION" => $arProp["DESCRIPTION"],
4450 );
4451 }
4452 }
4453 }
4454
4455 $WF_ID = $this->Add($arNewFields);
4456 if($this->bWF_SetMove)
4458 }
4459
4460 $Result = $ID;
4461 $arFields["ID"] = &$ID;
4463 self::$elementIblock[$ID] = $arIBlock['ID'];
4464 }
4465
4466 if(
4467 isset($arFields["PREVIEW_PICTURE"])
4468 && is_array($arFields["PREVIEW_PICTURE"])
4469 && ($arFields["PREVIEW_PICTURE"]["COPY_FILE"] ?? '') === "Y"
4470 && ($arFields["PREVIEW_PICTURE"]["copy"] ?? null)
4471 )
4472 {
4473 @unlink($arFields["PREVIEW_PICTURE"]["tmp_name"]);
4474 @rmdir(dirname($arFields["PREVIEW_PICTURE"]["tmp_name"]));
4475 }
4476
4477 if(
4478 isset($arFields["DETAIL_PICTURE"])
4479 && is_array($arFields["DETAIL_PICTURE"])
4480 && ($arFields["DETAIL_PICTURE"]["COPY_FILE"] ?? '') === "Y"
4481 && ($arFields["DETAIL_PICTURE"]["copy"] ?? null)
4482 )
4483 {
4484 @unlink($arFields["DETAIL_PICTURE"]["tmp_name"]);
4485 @rmdir(dirname($arFields["DETAIL_PICTURE"]["tmp_name"]));
4486 }
4487
4488 $arFields["RESULT"] = &$Result;
4489
4490 foreach (GetModuleEvents("iblock", "OnAfterIBlockElementAdd", true) as $arEvent)
4492
4493 CIBlock::clearIblockTagCache($arIBlock['ID']);
4494
4496
4497 return $Result;
4498 }
4499
4500 public static function DeleteFile($FILE_ID, $ELEMENT_ID, $TYPE = false, $PARENT_ID = -1, $IBLOCK_ID = false, $bCheckOnly = false)
4501 {
4502 global $DB;
4503
4504 $FILE_ID = (int)$FILE_ID;
4505 if($FILE_ID <= 0)
4506 return;
4507
4508 if($ELEMENT_ID !== false)
4509 {//ELEMENT_ID may be false when we are going to check for a valid file from CheckFields
4510 $ELEMENT_ID = (int)$ELEMENT_ID;
4511 if($ELEMENT_ID <= 0)
4512 return;
4513 }
4514
4515 $IBLOCK_ID = (int)$IBLOCK_ID;
4516 if($IBLOCK_ID <= 0 || $PARENT_ID===-1)
4517 {
4518 if($ELEMENT_ID===false)
4519 return; //This is an error in API call
4520 $rsElement = $DB->Query("SELECT IBLOCK_ID, WF_PARENT_ELEMENT_ID from b_iblock_element WHERE ID = ".$ELEMENT_ID);
4521 $arElement = $rsElement->Fetch();
4522 if(!$arElement)
4523 return;
4524 $IBLOCK_ID = $arElement["IBLOCK_ID"];
4525 $PARENT_ID = $arElement["WF_PARENT_ELEMENT_ID"];
4526 }
4527
4528 if($TYPE === false)
4529 {
4530 $CNT = CIBlockElement::DeleteFile($FILE_ID, $ELEMENT_ID, "PREVIEW", $PARENT_ID, $IBLOCK_ID);
4531 $CNT += CIBlockElement::DeleteFile($FILE_ID, $ELEMENT_ID, "DETAIL", $PARENT_ID, $IBLOCK_ID);
4532 $CNT += CIBlockElement::DeleteFile($FILE_ID, $ELEMENT_ID, "PROPERTY", $PARENT_ID, $IBLOCK_ID);
4533 return $CNT;
4534 }
4535
4537
4538 $arProps = array();
4539 if($TYPE === "PROPERTY" && $VERSION==2)
4540 {
4541 $strSQL = "
4542 SELECT P.ID
4543 FROM
4544 b_iblock_property P
4545 WHERE P.IBLOCK_ID = ".$IBLOCK_ID."
4546 AND P.PROPERTY_TYPE = 'F'
4547 AND P.MULTIPLE = 'N'
4548 ";
4549 $rs = $DB->Query($strSQL);
4550 while($ar = $rs->Fetch())
4551 $arProps[] = " V.PROPERTY_".(int)$ar["ID"]." = ".$FILE_ID;
4552 }
4553
4554 if($ELEMENT_ID === false)
4555 {
4556 //It is new historical record so we'' check original
4557 //and all over history already there
4558 $arWhere = array(
4559 "E.ID=".(int)$PARENT_ID,
4560 "E.WF_PARENT_ELEMENT_ID=".(int)$PARENT_ID
4561 );
4562 }
4563 elseif((int)$PARENT_ID)
4564 {
4565 //It's an historical record so we will check original
4566 // and all history except deleted one
4567 $arWhere = array(
4568 "E.ID=".(int)$PARENT_ID,
4569 "E.WF_PARENT_ELEMENT_ID=".(int)$PARENT_ID." AND E.ID <> ".$ELEMENT_ID
4570 );
4571 }
4572 else
4573 {
4574 //It is an original so we have to check only history
4575 //all history copies
4576 $arWhere = array(
4577 "E.WF_PARENT_ELEMENT_ID=".$ELEMENT_ID
4578 );
4579 }
4580
4581 $CNT = 0;
4582 foreach($arWhere as $strWhere)
4583 {
4584 if($TYPE === "PREVIEW")
4585 {
4586 $strSQL = "
4587 SELECT COUNT(1) CNT
4588 from b_iblock_element E
4589 WHERE ".$strWhere."
4590 AND PREVIEW_PICTURE = ".$FILE_ID."
4591 ";
4592
4593 }
4594 elseif($TYPE === "DETAIL")
4595 {
4596 $strSQL = "
4597 SELECT COUNT(1) CNT
4598 from b_iblock_element E
4599 WHERE ".$strWhere."
4600 AND DETAIL_PICTURE = ".$FILE_ID."
4601 ";
4602 }
4603 elseif($TYPE === "PROPERTY")
4604 {
4605 if($VERSION==2)
4606 {
4607 $strSQL = "
4608 SELECT COUNT(1) CNT
4609 FROM
4610 b_iblock_element E
4611 ,b_iblock_property P
4612 ,b_iblock_element_prop_m".$IBLOCK_ID." V
4613 WHERE ".$strWhere."
4614 AND E.IBLOCK_ID = ".$IBLOCK_ID."
4615 AND P.IBLOCK_ID = E.IBLOCK_ID
4616 AND P.PROPERTY_TYPE = 'F'
4617 AND V.IBLOCK_ELEMENT_ID = E.ID
4618 AND V.IBLOCK_PROPERTY_ID = P.ID
4619 AND V.VALUE_NUM = ".$FILE_ID."
4620 ";
4621 }
4622 else
4623 {
4624 $strSQL = "
4625 SELECT COUNT(1) CNT
4626 FROM
4627 b_iblock_element E
4628 ,b_iblock_property P
4629 ,b_iblock_element_property V
4630 WHERE ".$strWhere."
4631 AND E.IBLOCK_ID = ".$IBLOCK_ID."
4632 AND P.IBLOCK_ID = E.IBLOCK_ID
4633 AND P.PROPERTY_TYPE = 'F'
4634 AND V.IBLOCK_ELEMENT_ID = E.ID
4635 AND V.IBLOCK_PROPERTY_ID = P.ID
4636 AND V.VALUE_NUM = ".$FILE_ID."
4637 ";
4638 }
4639 }
4640
4641 $rs = $DB->Query($strSQL);
4642 $ar = $rs->Fetch();
4643
4644 $CNT += (int)$ar["CNT"];
4645 if($CNT > 0)
4646 return $CNT;
4647
4648 //Check VERSION 2 SINGLE PROPERTIES
4649 if(!empty($arProps))
4650 {
4651 //This SQL potentially wrong
4652 //in case when file may be saved in
4653 //different properties
4654 $strSQL = "
4655 SELECT COUNT(1) CNT
4656 FROM
4657 b_iblock_element E
4658 ,b_iblock_property P
4659 ,b_iblock_element_prop_s".$IBLOCK_ID." V
4660 WHERE ".$strWhere."
4661 AND E.IBLOCK_ID = ".$IBLOCK_ID."
4662 AND P.IBLOCK_ID = E.IBLOCK_ID
4663 AND P.PROPERTY_TYPE = 'F'
4664 AND V.IBLOCK_ELEMENT_ID = E.ID
4665 AND (".implode(" OR ", $arProps).")
4666 ";
4667 $rs = $DB->Query($strSQL);
4668 $ar = $rs->Fetch();
4669 $CNT += (int)$ar["CNT"];
4670 if($CNT > 0)
4671 return $CNT;
4672 }
4673 }
4674
4675 if($bCheckOnly)
4676 return $CNT;
4677 elseif($CNT === 0)
4678 CFile::Delete($FILE_ID);
4679 }
4680
4682 // Removes element
4684 public static function Delete($ID)
4685 {
4686 global $DB, $APPLICATION, $USER;
4687 $USER_ID = is_object($USER)? (int)$USER->GetID() : 0;
4688 $ID = (int)$ID;
4689 if ($ID <= 0)
4690 {
4691 return false;
4692 }
4693
4694 $APPLICATION->ResetException();
4695 foreach (GetModuleEvents("iblock", "OnBeforeIBlockElementDelete", true) as $arEvent)
4696 {
4697 if(ExecuteModuleEventEx($arEvent, array($ID))===false)
4698 {
4699 $err = "";
4700 $err_id = false;
4701 $ex = $APPLICATION->GetException();
4702 if (is_object($ex))
4703 {
4704 $err = $ex->GetString();
4705 $err_id = $ex->GetID();
4706 }
4707 $APPLICATION->throwException($err, $err_id);
4708 return false;
4709 }
4710 }
4711
4712 $arSql = array(
4713 "ID='".$ID."'",
4714 "WF_PARENT_ELEMENT_ID='".$ID."'",
4715 );
4716 foreach($arSql as $strWhere)
4717 {
4718 $strSql = "
4719 SELECT
4720 ID
4721 ,IBLOCK_ID
4722 ,WF_PARENT_ELEMENT_ID
4723 ,WF_STATUS_ID
4724 ,PREVIEW_PICTURE
4725 ,DETAIL_PICTURE
4726 ,XML_ID as EXTERNAL_ID
4727 ,CODE
4728 ,NAME
4729 FROM b_iblock_element
4730 WHERE ".$strWhere."
4731 ORDER BY ID DESC
4732 ";
4733 $z = $DB->Query($strSql);
4734 while ($zr = $z->Fetch())
4735 {
4736 $elementId = (int)$zr["ID"];
4737 $VERSION = CIBlockElement::GetIBVersion($zr["IBLOCK_ID"]);
4738 $db_res = CIBlockElement::GetProperty($zr["IBLOCK_ID"], $zr["ID"], "sort", "asc", array("PROPERTY_TYPE"=>"F"));
4739
4740 $arIblock = CIBlock::GetArrayByID($zr['IBLOCK_ID']);
4741 $arIBlockFields = $arIblock["FIELDS"];
4742 if(
4743 (int)$zr["WF_PARENT_ELEMENT_ID"]<=0
4744 && $arIBlockFields["LOG_ELEMENT_DELETE"]["IS_REQUIRED"] == "Y"
4745 )
4746 {
4747 $arEvents = GetModuleEvents("main", "OnBeforeEventLog", true);
4748
4749 if(empty($arEvents) || ExecuteModuleEventEx($arEvents[0], array($USER_ID))===false)
4750 {
4751 $rsElement = CIBlockElement::GetList(array(), array("=ID"=>$ID), false, false, array("LIST_PAGE_URL", "NAME", "CODE"));
4752 $arElement = $rsElement->GetNext();
4753 $res_log = array(
4754 "ID" => $ID,
4755 "CODE" => $arElement["CODE"],
4756 "NAME" => $arElement["NAME"],
4757 "ELEMENT_NAME" => $arIblock["ELEMENT_NAME"],
4758 "USER_ID" => $USER_ID,
4759 "IBLOCK_PAGE_URL" => $arElement["LIST_PAGE_URL"],
4760 );
4762 "IBLOCK",
4763 "IBLOCK_ELEMENT_DELETE",
4764 "iblock",
4765 $zr["IBLOCK_ID"],
4766 serialize($res_log)
4767 );
4768 }
4769 }
4770
4772
4773 foreach (GetModuleEvents("iblock", "OnIBlockElementDelete", true) as $arEvent)
4774 ExecuteModuleEventEx($arEvent, array($elementId, $zr));
4775
4776 while($res = $db_res->Fetch())
4777 CIBlockElement::DeleteFile($res["VALUE"], $zr["ID"], "PROPERTY", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]);
4778
4779 if($VERSION==2)
4780 {
4781 if(!$DB->Query("DELETE FROM b_iblock_element_prop_m".$zr["IBLOCK_ID"]." WHERE IBLOCK_ELEMENT_ID = ".$elementId))
4782 return false;
4783 if(!$DB->Query("DELETE FROM b_iblock_element_prop_s".$zr["IBLOCK_ID"]." WHERE IBLOCK_ELEMENT_ID = ".$elementId))
4784 return false;
4785 }
4786 else
4787 {
4788 if(!$DB->Query("DELETE FROM b_iblock_element_property WHERE IBLOCK_ELEMENT_ID = ".$elementId))
4789 return false;
4790 }
4791
4792 static $arDelCache = array();
4793 if(!is_set($arDelCache, $zr["IBLOCK_ID"]))
4794 {
4795 $arDelCache[$zr["IBLOCK_ID"]] = [];
4796 $db_ps = $DB->Query("SELECT ID,IBLOCK_ID,VERSION,MULTIPLE FROM b_iblock_property WHERE PROPERTY_TYPE='E' AND (LINK_IBLOCK_ID=".$zr["IBLOCK_ID"]." OR LINK_IBLOCK_ID=0 OR LINK_IBLOCK_ID IS NULL)");
4797 while($ar_ps = $db_ps->Fetch())
4798 {
4799 if($ar_ps["VERSION"]==2)
4800 {
4801 if($ar_ps["MULTIPLE"]=="Y")
4802 $strTable = "b_iblock_element_prop_m".$ar_ps["IBLOCK_ID"];
4803 else
4804 $strTable = "b_iblock_element_prop_s".$ar_ps["IBLOCK_ID"];
4805 }
4806 else
4807 {
4808 $strTable = "b_iblock_element_property";
4809 }
4810 $arDelCache[$zr["IBLOCK_ID"]][$strTable][] = $ar_ps["ID"];
4811 }
4812 }
4813
4814 if($arDelCache[$zr["IBLOCK_ID"]])
4815 {
4816 foreach($arDelCache[$zr["IBLOCK_ID"]] as $strTable=>$arProps)
4817 {
4818 if(strncmp("b_iblock_element_prop_s", $strTable, 23)==0)
4819 {
4820 $tableFields = $DB->GetTableFields($strTable);
4821 foreach($arProps as $prop_id)
4822 {
4823 $strSql = "UPDATE ".$strTable." SET PROPERTY_".$prop_id."=null";
4824 if (isset($tableFields["DESCRIPTION_".$prop_id]))
4825 $strSql .= ",DESCRIPTION_".$prop_id."=null";
4826 $strSql .= " WHERE PROPERTY_".$prop_id."=".$zr["ID"];
4827 if(!$DB->Query($strSql))
4828 return false;
4829 }
4830 }
4831 elseif(strncmp("b_iblock_element_prop_m", $strTable, 23)==0)
4832 {
4833 $tableFields = $DB->GetTableFields(str_replace("prop_m", "prop_s", $strTable));
4834 $strSql = "SELECT IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID FROM ".$strTable." WHERE IBLOCK_PROPERTY_ID IN (".implode(", ", $arProps).") AND VALUE_NUM=".$zr["ID"];
4835 $rs = $DB->Query($strSql);
4836 while($ar = $rs->Fetch())
4837 {
4838 $strSql = "
4839 UPDATE ".str_replace("prop_m", "prop_s", $strTable)."
4840 SET PROPERTY_".$ar["IBLOCK_PROPERTY_ID"]."=null
4841 ".(isset($tableFields["DESCRIPTION_".$ar["IBLOCK_PROPERTY_ID"]])? ",DESCRIPTION_".$ar["IBLOCK_PROPERTY_ID"]."=null": "")."
4842 WHERE IBLOCK_ELEMENT_ID = ".$ar["IBLOCK_ELEMENT_ID"]."
4843 ";
4844 if(!$DB->Query($strSql))
4845 return false;
4846 }
4847 $strSql = "DELETE FROM ".$strTable." WHERE IBLOCK_PROPERTY_ID IN (".implode(", ", $arProps).") AND VALUE_NUM=".$zr["ID"];
4848 if(!$DB->Query($strSql))
4849 return false;
4850 }
4851 else
4852 {
4853 $strSql = "DELETE FROM ".$strTable." WHERE IBLOCK_PROPERTY_ID IN (".implode(", ", $arProps).") AND VALUE_NUM=".$zr["ID"];
4854 if(!$DB->Query($strSql))
4855 return false;
4856 }
4857 }
4858 }
4859
4860 if(!$DB->Query("DELETE FROM b_iblock_section_element WHERE IBLOCK_ELEMENT_ID = ".$elementId))
4861 return false;
4862
4863 $obIBlockElementRights = new CIBlockElementRights($zr["IBLOCK_ID"], $zr["ID"]);
4864 $obIBlockElementRights->DeleteAllRights();
4865
4866 $ipropTemplates = new \Bitrix\Iblock\InheritedProperty\ElementTemplates($zr["IBLOCK_ID"], $zr["ID"]);
4867 $ipropTemplates->delete();
4868
4869 if((int)$zr["WF_PARENT_ELEMENT_ID"]<=0 && $zr["WF_STATUS_ID"]==1 && CModule::IncludeModule("search"))
4870 {
4871 CSearch::DeleteIndex("iblock", $elementId);
4872 }
4873
4874 CIBlockElement::DeleteFile($zr["PREVIEW_PICTURE"], $zr["ID"], "PREVIEW", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]);
4875 CIBlockElement::DeleteFile($zr["DETAIL_PICTURE"], $zr["ID"], "DETAIL", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]);
4876
4877 if(CModule::IncludeModule("workflow"))
4878 $DB->Query("DELETE FROM b_workflow_move WHERE IBLOCK_ELEMENT_ID=".$elementId);
4879
4880 $DB->Query("DELETE FROM b_iblock_element_lock WHERE IBLOCK_ELEMENT_ID=".$elementId);
4881 $DB->Query("DELETE FROM b_rating_vote WHERE ENTITY_TYPE_ID = 'IBLOCK_ELEMENT' AND ENTITY_ID = ".$elementId);
4882 $DB->Query("DELETE FROM b_rating_voting WHERE ENTITY_TYPE_ID = 'IBLOCK_ELEMENT' AND ENTITY_ID = ".$elementId);
4883
4884 if (FullText::doesIblockSupportByData($arIblock))
4885 {
4886 FullText::delete($arIblock["ID"], $elementId);
4887 }
4888
4889 if(!$DB->Query("DELETE FROM b_iblock_element WHERE ID=".$elementId))
4890 return false;
4891
4892 if (isset(self::$elementIblock[$elementId]))
4893 unset(self::$elementIblock[$elementId]);
4894
4896
4897 if(CModule::IncludeModule("bizproc"))
4898 {
4899 $arErrorsTmp = [];
4900 CBPDocument::OnDocumentDelete(["iblock", "CIBlockDocument", $zr["ID"]], $arErrorsTmp);
4901 }
4902
4903 foreach (GetModuleEvents("iblock", "OnAfterIBlockElementDelete", true) as $arEvent)
4904 ExecuteModuleEventEx($arEvent, array($zr));
4905
4906 CIBlock::clearIblockTagCache($zr['IBLOCK_ID']);
4907
4909
4910 unset($elementId);
4911 }
4912 }
4913 /************* QUOTA *************/
4915 /************* QUOTA *************/
4916 return true;
4917 }
4918
4919 public static function GetByID($ID)
4920 {
4921 return CIBlockElement::GetList(array(), array("ID"=>(int)$ID, "SHOW_HISTORY"=>"Y"));
4922 }
4923
4930 public static function GetIBlockByID($ID)
4931 {
4932 global $DB;
4933 $ID = (int)$ID;
4934 if ($ID <= 0)
4935 return false;
4936 if (!isset(self::$elementIblock[$ID]))
4937 {
4938 self::$elementIblock[$ID] = false;
4939 $strSql = "select IBLOCK_ID from b_iblock_element where ID=".$ID;
4940 $rsItems = $DB->Query($strSql);
4941 if ($arItem = $rsItems->Fetch())
4942 self::$elementIblock[$ID] = (int)$arItem['IBLOCK_ID'];
4943 unset($arItem, $rsItems);
4944 }
4945 return self::$elementIblock[$ID];
4946 }
4947
4954 public static function GetIBlockByIDList(array $list)
4955 {
4956 global $DB;
4957 $output = array();
4959 if (empty($list))
4960 return $output;
4961 foreach ($list as $index => $id)
4962 {
4963 if (!empty(self::$elementIblock[$id]))
4964 {
4965 $output[$id] = self::$elementIblock[$id];
4966 unset($list[$index]);
4967 }
4968 }
4969
4970 if (!empty($list))
4971 {
4972 foreach (array_chunk($list, 500) as $pageIds)
4973 {
4974 $strSql = "select IBLOCK_ID,ID from b_iblock_element where ID in (".join(', ', $pageIds).")";
4975 $rsItems = $DB->Query($strSql);
4976 while ($itemData = $rsItems->Fetch())
4977 {
4978 $output[$itemData['ID']] = self::$elementIblock[$itemData['ID']] = (int)$itemData['IBLOCK_ID'];
4979 }
4980 unset($itemData, $rsItems);
4981 }
4982 unset($pageIds);
4983 }
4984
4985 return $output;
4986 }
4987
4989 // Checks fields before update or insert
4991 public function CheckFields(&$arFields, $ID=false, $bCheckDiskQuota=true)
4992 {
4993 global $DB, $APPLICATION, $USER;
4994 $this->LAST_ERROR = "";
4995
4996 $APPLICATION->ResetException();
4997 if($ID===false)
4998 {
4999 $db_events = GetModuleEvents("iblock", "OnStartIBlockElementAdd", true);
5000 }
5001 else
5002 {
5003 $arFields["ID"] = $ID;
5004 $db_events = GetModuleEvents("iblock", "OnStartIBlockElementUpdate", true);
5005 }
5006
5007 foreach ($db_events as $arEvent)
5008 {
5009 $bEventRes = ExecuteModuleEventEx($arEvent, array(&$arFields));
5010 if($bEventRes===false)
5011 break;
5012 }
5013
5014 if(($ID===false || array_key_exists("NAME", $arFields)) && (string)$arFields["NAME"] === '')
5015 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ELEMENT_NAME")."<br>";
5016
5017 if(
5018 isset($arFields["ACTIVE_FROM"])
5019 && $arFields["ACTIVE_FROM"] != ''
5020 && !$DB->IsDate($arFields["ACTIVE_FROM"], false, LANG, "FULL")
5021 )
5022 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ACTIVE_FROM")."<br>";
5023
5024 if(
5025 isset($arFields["ACTIVE_TO"])
5026 && $arFields["ACTIVE_TO"] != ''
5027 && !$DB->IsDate($arFields["ACTIVE_TO"], false, LANG, "FULL")
5028 )
5029 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ACTIVE_TO")."<br>";
5030
5031 if(is_set($arFields, "PREVIEW_PICTURE"))
5032 {
5033 if(
5034 is_array($arFields["PREVIEW_PICTURE"])
5035 && array_key_exists("bucket", $arFields["PREVIEW_PICTURE"])
5036 && is_object($arFields["PREVIEW_PICTURE"]["bucket"])
5037 )
5038 {
5039 //This is trusted image from xml import
5040 }
5041 elseif(is_array($arFields["PREVIEW_PICTURE"]))
5042 {
5043 $error = CFile::CheckImageFile($arFields["PREVIEW_PICTURE"]);
5044 if($error <> '')
5045 $this->LAST_ERROR .= $error."<br>";
5046 elseif(($error = CFile::checkForDb($arFields, "PREVIEW_PICTURE")) !== "")
5047 $this->LAST_ERROR .= GetMessage("IBLOCK_ERR_PREVIEW_PICTURE")."<br>".$error."<br>";
5048 }
5049 elseif((int)$arFields["PREVIEW_PICTURE"] > 0)
5050 {
5051 if(
5052 (int)$arFields["WF_PARENT_ELEMENT_ID"] <= 0
5054 $arFields["PREVIEW_PICTURE"],
5055 $ID,
5056 "PREVIEW",
5057 (int)$arFields["WF_PARENT_ELEMENT_ID"],
5058 $arFields["IBLOCK_ID"],
5059 true
5060 ) <= 0
5061 )
5062 {
5063 $this->LAST_ERROR .= GetMessage("IBLOCK_ERR_PREVIEW_PICTURE")."<br>";
5064 }
5065 }
5066 }
5067
5068 if(is_set($arFields, "DETAIL_PICTURE"))
5069 {
5070 if(
5071 is_array($arFields["DETAIL_PICTURE"])
5072 && array_key_exists("bucket", $arFields["DETAIL_PICTURE"])
5073 && is_object($arFields["DETAIL_PICTURE"]["bucket"])
5074 )
5075 {
5076 //This is trusted image from xml import
5077 }
5078 elseif(is_array($arFields["DETAIL_PICTURE"]))
5079 {
5080 $error = CFile::CheckImageFile($arFields["DETAIL_PICTURE"]);
5081 if($error <> '')
5082 $this->LAST_ERROR .= $error."<br>";
5083 elseif(($error = CFile::checkForDb($arFields, "DETAIL_PICTURE")) !== "")
5084 $this->LAST_ERROR .= GetMessage("IBLOCK_ERR_DETAIL_PICTURE")."<br>".$error."<br>";
5085 }
5086 elseif((int)$arFields["DETAIL_PICTURE"] > 0)
5087 {
5088 if(
5089 (int)($arFields["WF_PARENT_ELEMENT_ID"]) <= 0
5091 $arFields["DETAIL_PICTURE"],
5092 $ID,
5093 "DETAIL",
5094 (int)$arFields["WF_PARENT_ELEMENT_ID"],
5095 $arFields["IBLOCK_ID"],
5096 true
5097 ) <= 0
5098 )
5099 {
5100 $this->LAST_ERROR .= GetMessage("IBLOCK_ERR_DETAIL_PICTURE")."<br>";
5101 }
5102 }
5103 }
5104
5105 if(array_key_exists("TAGS", $arFields) && CModule::IncludeModule('search'))
5106 {
5107 $arFields["TAGS"] = implode(", ", tags_prepare($arFields["TAGS"]));
5108 }
5109
5110 if($ID===false && !is_set($arFields, "IBLOCK_ID"))
5111 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_BLOCK_ID")."<br>";
5112
5113 //Find out IBLOCK_ID from fields or from element
5114 $IBLOCK_ID = (int)($arFields["IBLOCK_ID"] ?? 0);
5115 if($IBLOCK_ID <= 0)
5116 {
5117 $IBLOCK_ID = 0;
5118 $res = $DB->Query("SELECT IBLOCK_ID FROM b_iblock_element WHERE ID=".intval($ID));
5119 if($ar = $res->Fetch())
5120 $IBLOCK_ID = (int)$ar["IBLOCK_ID"];
5121 }
5122
5123 //Read iblock metadata
5124 static $IBLOCK_CACHE = array();
5125 if(!isset($IBLOCK_CACHE[$IBLOCK_ID]))
5126 {
5127 if($IBLOCK_ID > 0)
5128 $IBLOCK_CACHE[$IBLOCK_ID] = CIBlock::GetArrayByID($IBLOCK_ID);
5129 else
5130 $IBLOCK_CACHE[$IBLOCK_ID] = false;
5131 }
5132
5133 if($IBLOCK_CACHE[$IBLOCK_ID])
5134 $arFields["IBLOCK_ID"] = $IBLOCK_ID;
5135 else
5136 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_BLOCK_ID")."<br>";
5137
5138 if (is_set($arFields,'IBLOCK_SECTION') && !empty($arFields['IBLOCK_SECTION']))
5139 {
5140 if (!is_array($arFields['IBLOCK_SECTION']))
5141 $arFields['IBLOCK_SECTION'] = array($arFields['IBLOCK_SECTION']);
5142 $arFields['IBLOCK_SECTION'] = array_filter($arFields['IBLOCK_SECTION']);
5143 }
5144
5145 if($IBLOCK_CACHE[$IBLOCK_ID])
5146 {
5147 $ar = $IBLOCK_CACHE[$IBLOCK_ID]["FIELDS"];
5148 if(is_array($ar))
5149 {
5150 $WF_PARENT_ELEMENT_ID = (int)($arFields["WF_PARENT_ELEMENT_ID"] ?? 0);
5151 if(
5152 (
5153 $WF_PARENT_ELEMENT_ID == 0
5154 || $WF_PARENT_ELEMENT_ID == (int)$ID
5155 )
5156 && array_key_exists("CODE", $arFields)
5157 && $arFields["CODE"] <> ''
5158 && is_array($ar["CODE"]["DEFAULT_VALUE"])
5159 && $ar["CODE"]["DEFAULT_VALUE"]["UNIQUE"] == "Y"
5160 )
5161 {
5162 $res = $DB->Query("
5163 SELECT ID
5164 FROM b_iblock_element
5165 WHERE IBLOCK_ID = ".$IBLOCK_ID."
5166 AND CODE = '".$DB->ForSQL($arFields["CODE"])."'
5167 AND WF_PARENT_ELEMENT_ID IS NULL
5168 AND ID <> ".(int)$ID
5169 );
5170 if($res->Fetch())
5171 $this->LAST_ERROR .= GetMessage("IBLOCK_DUP_ELEMENT_CODE")."<br>";
5172 }
5173
5174
5175 $arOldElement = false;
5176 foreach($ar as $FIELD_ID => $field)
5177 {
5178 if(preg_match("/^(SECTION_|LOG_)/", $FIELD_ID))
5179 continue;
5180
5181 if($field["IS_REQUIRED"] === "Y")
5182 {
5183 switch($FIELD_ID)
5184 {
5185 case "NAME":
5186 case "ACTIVE":
5187 case "PREVIEW_TEXT_TYPE":
5188 case "DETAIL_TEXT_TYPE":
5189 case "SORT":
5190 //We should never check for this fields
5191 break;
5192 case "IBLOCK_SECTION":
5193 if($ID===false || array_key_exists($FIELD_ID, $arFields))
5194 {
5195 $sum = 0;
5196 if(is_array($arFields[$FIELD_ID]))
5197 {
5198 foreach($arFields[$FIELD_ID] as $k => $v)
5199 if(intval($v) > 0)
5200 $sum += intval($v);
5201 }
5202 else
5203 {
5204 $sum = intval($arFields[$FIELD_ID]);
5205 }
5206 if($sum <= 0)
5207 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5208 }
5209 break;
5210 case "PREVIEW_PICTURE":
5211 case "DETAIL_PICTURE":
5212 if($ID !== false && !$arOldElement)
5213 {
5214 $rs = $DB->Query("SELECT PREVIEW_PICTURE, DETAIL_PICTURE from b_iblock_element WHERE ID = ".intval($ID));
5215 $arOldElement = $rs->Fetch();
5216 }
5217 if($arOldElement && $arOldElement[$FIELD_ID] > 0)
5218 {//There was an picture so just check that it is not deleted
5219 if(
5220 array_key_exists($FIELD_ID, $arFields)
5221 && is_array($arFields[$FIELD_ID])
5222 && $arFields[$FIELD_ID]["del"] === "Y"
5223 )
5224 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5225 }
5226 else
5227 {//There was NO picture so it MUST be present
5228 if(!array_key_exists($FIELD_ID, $arFields))
5229 {
5230 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5231 }
5232 elseif(is_array($arFields[$FIELD_ID]))
5233 {
5234 if(
5235 $arFields[$FIELD_ID]["del"] === "Y"
5236 || (array_key_exists("error", $arFields[$FIELD_ID]) && $arFields[$FIELD_ID]["error"] !== 0)
5237 || $arFields[$FIELD_ID]["size"] <= 0
5238 )
5239 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5240 }
5241 else
5242 {
5243 if(intval($arFields[$FIELD_ID]) <= 0)
5244 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5245 }
5246 }
5247 break;
5248 case "XML_ID":
5249 if ($ID !== false && array_key_exists($FIELD_ID, $arFields))
5250 {
5251 $val = $arFields[$FIELD_ID];
5252 if($val == '')
5253 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5254 }
5255 break;
5256 default:
5257 if($ID===false || array_key_exists($FIELD_ID, $arFields))
5258 {
5259 if(is_array($arFields[$FIELD_ID]))
5260 $val = implode("", $arFields[$FIELD_ID]);
5261 else
5262 $val = $arFields[$FIELD_ID];
5263 if($val == '')
5264 $this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."<br>";
5265 }
5266 break;
5267 }
5268 }
5269 }
5270 }
5271 }
5272
5273 if(
5274 array_key_exists("PROPERTY_VALUES", $arFields)
5275 && is_array($arFields["PROPERTY_VALUES"])
5276 //&& intval($arFields["WF_PARENT_ELEMENT_ID"]) <= 0 //
5277 )
5278 {
5279 //First "normalize" properties to form:
5280 //$arFields["PROPERTY_VALUES"][<PROPERTY_ID>][<PROPERTY_VALUE_ID>] => $value
5281 $arProperties = array();
5282 foreach($arFields["PROPERTY_VALUES"] as $key => $property_values)
5283 {
5285 if(is_array($property_values)) //This is multiple values
5286 {
5287 if(array_key_exists("VALUE", $property_values)) //Or single "complex" value
5288 {
5289 $arProperties[$key][] = $property_values["VALUE"];
5290 }
5291 elseif(array_key_exists("tmp_name", $property_values)) //Or single file value
5292 {
5293 $arProperties[$key][] = $property_values;
5294 }
5295 else //true multiple
5296 {
5297 foreach($property_values as $key2 => $property_value)
5298 {
5299 if(is_array($property_value) && array_key_exists("VALUE", $property_value)) //each of these may be "complex"
5300 $arProperties[$key][] = $property_value["VALUE"];
5301 else //or simple
5302 $arProperties[$key][] = $property_value;
5303 }
5304 }
5305 }
5306 else //just one simple value
5307 {
5308 $arProperties[$key][] = $property_values;
5309 }
5310 }
5311
5312 foreach($arProperties as $key => $property_values)
5313 {
5314 $arProperty = CIBlockProperty::GetPropertyArray($key, $IBLOCK_ID);
5315
5316 if($arProperty["USER_TYPE"] != "")
5317 $arUserType = CIBlockProperty::GetUserType($arProperty["USER_TYPE"]);
5318 else
5319 $arUserType = array();
5320
5321 if (isset($arUserType['CheckFields']))
5322 {
5323 foreach ($property_values as $singleValue)
5324 {
5325 $arError = call_user_func_array(
5326 $arUserType['CheckFields'],
5327 [
5328 $arProperty,
5329 ['VALUE' => $singleValue],
5330 ]
5331 );
5332 if (is_array($arError))
5333 {
5334 foreach ($arError as $err_mess)
5335 {
5336 $this->LAST_ERROR .= $err_mess . '<br>';
5337 }
5338 }
5339 }
5340 unset($singleValue);
5341 }
5342
5343 //Files check
5344 $bError = false;
5345
5346 if(
5347 $arProperty["IS_REQUIRED"] == "Y"
5348 && $arProperty['PROPERTY_TYPE'] == 'F'
5349 )
5350 {
5351 //New element
5352 if($ID===false)
5353 {
5354 $bError = true;
5355 foreach($property_values as $key2 => $property_value)
5356 {
5357 if(
5358 is_array($property_value)
5359 && array_key_exists("tmp_name", $property_value)
5360 && array_key_exists("size", $property_value)
5361 )
5362 {
5363 if($property_value['size'] > 0)
5364 {
5365 $bError = false;
5366 break;
5367 }
5368 }
5369 elseif(intval($property_value) > 0)
5370 {//This is history copy of the file
5371 $bError = false;
5372 break;
5373 }
5374 }
5375 }
5376 else
5377 {
5378 $dbProperty = CIBlockElement::GetProperty(
5379 $arProperty["IBLOCK_ID"],
5380 $ID,
5381 "sort", "asc",
5382 array(
5383 "ID" => $arProperty["ORIG_ID"],
5384 "EMPTY" => "N",
5385 )
5386 );
5387
5388 $bCount = 0;
5389 while ($a=$dbProperty->Fetch())
5390 {
5391 if ($a["VALUE"] > 0)
5392 $bCount++;
5393 }
5394
5395 foreach ($property_values as $key2 => $property_value)
5396 {
5397 if (is_array($property_value))
5398 {
5399 if ((int)($property_value['size'] ?? null) > 0)
5400 {
5401 $bCount++;
5402 break;
5403 }
5404 elseif (($property_value['del'] ?? null) === 'Y')
5405 {
5406 $bCount--;
5407 }
5408 }
5409 elseif ((int)$property_value > 0)
5410 {//This is history copy of the file
5411 $bCount++;
5412 break;
5413 }
5414 }
5415 $bError = $bCount <= 0;
5416 }
5417 }
5418
5419 $correctValue = true;
5420 if (
5421 $arProperty["IS_REQUIRED"] == "Y"
5422 && $arProperty['PROPERTY_TYPE'] != 'F'
5423 )
5424 {
5425 $len = 0;
5426 foreach ($property_values as $singleValue)
5427 {
5428 if (isset($arUserType['GetLength']))
5429 {
5430 $len += call_user_func_array(
5431 $arUserType['GetLength'],
5432 [
5433 $arProperty,
5434 ['VALUE' => $singleValue],
5435 ]
5436 );
5437 }
5438 else
5439 {
5440 if ($singleValue === null)
5441 {
5442 continue;
5443 }
5444 if (is_scalar($singleValue))
5445 {
5446 if ((string)$singleValue !== '')
5447 {
5448 $len++;
5449 }
5450 }
5451 else
5452 {
5453 $correctValue = false;
5454 }
5455 }
5456 if ($len > 0)
5457 {
5458 break;
5459 }
5460 }
5461 unset($singleValue);
5462
5463 $bError = $len <= 0;
5464 }
5465
5466 if ($bError)
5467 {
5468 $this->LAST_ERROR .=
5469 GetMessage(
5470 'IBLOCK_BAD_PROPERTY',
5471 array('#PROPERTY#' => $arProperty['NAME'])
5472 )
5473 . '<br>'
5474 ;
5475 }
5476 if (!$correctValue)
5477 {
5478 $this->LAST_ERROR .=
5479 GetMessage(
5480 'IBLOCK_BAD_REQUIRED_PROPERTY_VALUE',
5481 array('#PROPERTY#' => $arProperty['NAME'])
5482 )
5483 . '<br>'
5484 ;
5485 }
5486
5487 // check file properties for correctness
5488 if($arProperty['PROPERTY_TYPE'] == 'F')
5489 {
5490 $bImageOnly = False;
5491 $arImageExtentions = explode(",", mb_strtoupper(CFile::GetImageExtensions()));
5492 if($arProperty["FILE_TYPE"] <> '')
5493 {
5494 $bImageOnly = True;
5495 $arAvailTypes = explode(",", mb_strtoupper($arProperty["FILE_TYPE"]));
5496 foreach($arAvailTypes as $avail_type)
5497 {
5498 if(!in_array(trim($avail_type), $arImageExtentions))
5499 {
5500 $bImageOnly = False;
5501 break;
5502 }
5503 }
5504 }
5505
5506 foreach($property_values as $key2 => $property_value)
5507 {
5508 if(
5509 !is_array($property_value)
5510 && (int)$property_value > 0
5511 && isset($arFields['WF_PARENT_ELEMENT_ID'])
5512 && (int)$arFields['WF_PARENT_ELEMENT_ID'] > 0
5513 )
5514 {
5515 if (CIBlockElement::DeleteFile($property_value, $ID, "PROPERTY",
5516 (int)$arFields["WF_PARENT_ELEMENT_ID"], $arFields["IBLOCK_ID"], true) <= 0)
5517 {
5518 $this->LAST_ERROR .= GetMessage("IBLOCK_ERR_FILE_PROPERTY")."<br>";
5519 }
5520 }
5521 elseif(is_array($property_value))
5522 {
5523 if (
5524 array_key_exists('bucket', $property_value)
5525 && is_object($property_value["bucket"])
5526 )
5527 {
5528 //This is trusted image from xml import
5529 $error = "";
5530 }
5531 else
5532 {
5533 if($bImageOnly)
5534 $error = CFile::CheckImageFile($property_value);
5535 else
5536 $error = CFile::CheckFile($property_value, 0, false, $arProperty["FILE_TYPE"]);
5537 }
5538
5539 //For user without edit php permissions
5540 //we allow only pictures upload
5541 if (!$this->isAdmin)
5542 {
5543 if(HasScriptExtension($property_value["name"]))
5544 {
5545 $error = GetMessage("FILE_BAD_TYPE")." (".$property_value["name"].").";
5546 }
5547 }
5548
5549 if ($error <> '')
5550 $this->LAST_ERROR .= $error."<br>";
5551 }
5552 }
5553 }
5554 }
5555 }
5556
5557 $APPLICATION->ResetException();
5558 if($ID===false)
5559 $db_events = GetModuleEvents("iblock", "OnBeforeIBlockElementAdd", true);
5560 else
5561 {
5562 $arFields["ID"] = $ID;
5563 $db_events = GetModuleEvents("iblock", "OnBeforeIBlockElementUpdate", true);
5564 }
5565
5566 foreach($db_events as $arEvent)
5567 {
5568 $bEventRes = ExecuteModuleEventEx($arEvent, array(&$arFields));
5569 if($bEventRes===false)
5570 {
5571 if($err = $APPLICATION->GetException())
5572 $this->LAST_ERROR .= $err->GetString()."<br>";
5573 else
5574 {
5575 $APPLICATION->ThrowException("Unknown error");
5576 $this->LAST_ERROR .= "Unknown error.<br>";
5577 }
5578 break;
5579 }
5580 }
5581
5582 /****************************** QUOTA ******************************/
5583 if(
5584 $bCheckDiskQuota
5585 && empty($this->LAST_ERROR)
5586 && (COption::GetOptionInt("main", "disk_space") > 0)
5587 )
5588 {
5589 $quota = new CDiskQuota();
5590 if(!$quota->checkDiskQuota($arFields))
5591 $this->LAST_ERROR = $quota->LAST_ERROR;
5592 }
5593 /****************************** QUOTA ******************************/
5594
5595 if(!empty($this->LAST_ERROR))
5596 return false;
5597
5598 return true;
5599 }
5600
5607 public static function SetPropertyValueCode($ELEMENT_ID, $PROPERTY_CODE, $PROPERTY_VALUE)
5608 {
5610 if (!$IBLOCK_ID)
5611 return false;
5612
5613 CIBlockElement::SetPropertyValues($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUE, $PROPERTY_CODE);
5614
5615 return true;
5616 }
5617
5618 public static function GetElementGroups($ID, $bElementOnly = false, $arSelect = array())
5619 {
5620 global $DB;
5621
5622 $arFields = array(
5623 "ID" => "BS.ID",
5624 "TIMESTAMP_X" => "BS.TIMESTAMP_X",
5625 "MODIFIED_BY" => "BS.MODIFIED_BY",
5626 "DATE_CREATE" => "BS.DATE_CREATE",
5627 "CREATED_BY" => "BS.CREATED_BY",
5628 "IBLOCK_ID" => "BS.IBLOCK_ID",
5629 "IBLOCK_SECTION_ID" => "BS.IBLOCK_SECTION_ID",
5630 "ACTIVE" => "BS.ACTIVE",
5631 "GLOBAL_ACTIVE" => "BS.GLOBAL_ACTIVE",
5632 "SORT" => "BS.SORT",
5633 "NAME" => "BS.NAME",
5634 "PICTURE" => "BS.PICTURE",
5635 "LEFT_MARGIN" => "BS.LEFT_MARGIN",
5636 "RIGHT_MARGIN" => "BS.RIGHT_MARGIN",
5637 "DEPTH_LEVEL" => "BS.DEPTH_LEVEL",
5638 "DESCRIPTION" => "BS.DESCRIPTION",
5639 "DESCRIPTION_TYPE" => "BS.DESCRIPTION_TYPE",
5640 "SEARCHABLE_CONTENT" => "BS.SEARCHABLE_CONTENT",
5641 "CODE" => "BS.CODE",
5642 "XML_ID" => "BS.XML_ID",
5643 "EXTERNAL_ID" => "BS.XML_ID",
5644 "TMP_ID" => "BS.TMP_ID",
5645 "DETAIL_PICTURE" => "BS.DETAIL_PICTURE",
5646 "SOCNET_GROUP_ID" => "BS.SOCNET_GROUP_ID",
5647
5648 "LIST_PAGE_URL" => "B.LIST_PAGE_URL",
5649 "SECTION_PAGE_URL" => "B.SECTION_PAGE_URL",
5650 "IBLOCK_TYPE_ID" => "B.IBLOCK_TYPE_ID",
5651 "IBLOCK_CODE" => "B.CODE",
5652 "IBLOCK_EXTERNAL_ID" => "B.XML_ID",
5653
5654 "IBLOCK_ELEMENT_ID" => "SE.IBLOCK_ELEMENT_ID",
5655 "ADDITIONAL_PROPERTY_ID" => "SE.ADDITIONAL_PROPERTY_ID",
5656 );
5657
5658 if(is_array($ID))
5659 {
5660 if (!empty($ID))
5661 {
5663 }
5664 $sqlID = !empty($ID) ? $ID : array(0);
5665 }
5666 else
5667 {
5668 $sqlID = array((int)$ID);
5669 }
5670
5671 $arSqlSelect = array();
5672 foreach($arSelect as &$field)
5673 {
5674 $field = mb_strtoupper($field);
5675 if(array_key_exists($field, $arFields))
5676 $arSqlSelect[$field] = $arFields[$field]." AS ".$field;
5677 }
5678 if (isset($field))
5679 unset($field);
5680
5681 if (array_key_exists("DESCRIPTION", $arSqlSelect))
5682 $arSqlSelect["DESCRIPTION_TYPE"] = $arFields["DESCRIPTION_TYPE"]." AS DESCRIPTION_TYPE";
5683
5684 if(array_key_exists("LIST_PAGE_URL", $arSqlSelect) || array_key_exists("SECTION_PAGE_URL", $arSqlSelect))
5685 {
5686 $arSqlSelect["ID"] = $arFields["ID"]." AS ID";
5687 $arSqlSelect["CODE"] = $arFields["CODE"]." AS CODE";
5688 $arSqlSelect["EXTERNAL_ID"] = $arFields["EXTERNAL_ID"]." AS EXTERNAL_ID";
5689 $arSqlSelect["IBLOCK_TYPE_ID"] = $arFields["IBLOCK_TYPE_ID"]." AS IBLOCK_TYPE_ID";
5690 $arSqlSelect["IBLOCK_ID"] = $arFields["IBLOCK_ID"]." AS IBLOCK_ID";
5691 $arSqlSelect["IBLOCK_CODE"] = $arFields["IBLOCK_CODE"]." AS IBLOCK_CODE";
5692 $arSqlSelect["IBLOCK_EXTERNAL_ID"] = $arFields["IBLOCK_EXTERNAL_ID"]." AS IBLOCK_EXTERNAL_ID";
5693 $arSqlSelect["GLOBAL_ACTIVE"] = $arFields["GLOBAL_ACTIVE"]." AS GLOBAL_ACTIVE";
5694 }
5695
5696 if (!empty($arSelect))
5697 {
5698 $strSelect = implode(", ", $arSqlSelect);
5699 }
5700 else
5701 {
5702 $strSelect = "
5703 BS.*
5704 ,B.LIST_PAGE_URL
5705 ,B.SECTION_PAGE_URL
5706 ,B.IBLOCK_TYPE_ID
5707 ,B.CODE as IBLOCK_CODE
5708 ,B.XML_ID as IBLOCK_EXTERNAL_ID
5709 ,BS.XML_ID as EXTERNAL_ID
5710 ,SE.IBLOCK_ELEMENT_ID
5711 ";
5712 }
5713
5714 $dbr = new CIBlockResult($DB->Query("
5715 SELECT
5716 ".$strSelect."
5717 FROM
5718 b_iblock_section_element SE
5719 INNER JOIN b_iblock_section BS ON SE.IBLOCK_SECTION_ID = BS.ID
5720 INNER JOIN b_iblock B ON B.ID = BS.IBLOCK_ID
5721 WHERE
5722 SE.IBLOCK_ELEMENT_ID in (".implode(", ", $sqlID).")
5723 ".($bElementOnly?"AND SE.ADDITIONAL_PROPERTY_ID IS NULL ":"")."
5724 "));
5725 return $dbr;
5726 }
5727
5729 //
5731 public static function RecalcSections($ID, $sectionId = null)
5732 {
5733 global $DB;
5734 $ID = (int)$ID;
5735
5736 $sectionId = (int)$sectionId;
5737 if ($sectionId > 0)
5738 {
5739 $res = $DB->Query("
5740 SELECT
5741 SE.IBLOCK_SECTION_ID as IBLOCK_SECTION_ID_NEW
5742 ,E.IBLOCK_SECTION_ID
5743 ,E.IN_SECTIONS
5744 ,E.IBLOCK_ID
5745 FROM
5746 b_iblock_section_element SE
5747 INNER JOIN b_iblock_element E ON E.ID = SE.IBLOCK_ELEMENT_ID
5748 WHERE
5749 SE.IBLOCK_ELEMENT_ID = ".$ID."
5750 AND SE.IBLOCK_SECTION_ID = ".$sectionId."
5751 AND SE.ADDITIONAL_PROPERTY_ID IS NULL
5752 ");
5753 $res = $res->Fetch();
5754 if ($res)
5755 {
5756 $oldInSections = $res["IN_SECTIONS"];
5757 $newInSections = "Y";
5758 $oldSectionId = (int)$res["IBLOCK_SECTION_ID"];
5759 $newSectionId = (int)$res["IBLOCK_SECTION_ID_NEW"];
5760 }
5761 else
5762 {
5763 //No such section linked to the element
5764 return;
5765 }
5766 }
5767 else
5768 {
5769 $res = $DB->Query("
5770 SELECT
5771 COUNT('x') as C
5772 ,MIN(SE.IBLOCK_SECTION_ID) as MIN_IBLOCK_SECTION_ID
5773 ,E.IBLOCK_SECTION_ID
5774 ,E.IN_SECTIONS
5775 ,E.IBLOCK_ID
5776 FROM
5777 b_iblock_section_element SE
5778 INNER JOIN b_iblock_element E ON E.ID = SE.IBLOCK_ELEMENT_ID
5779 WHERE
5780 SE.IBLOCK_ELEMENT_ID = ".$ID."
5781 AND SE.ADDITIONAL_PROPERTY_ID IS NULL
5782 GROUP BY
5783 E.IBLOCK_SECTION_ID
5784 ,E.IN_SECTIONS
5785 ,E.IBLOCK_ID
5786 ");
5787 $res = $res->Fetch();
5788 if ($res)
5789 {
5790 $oldInSections = $res["IN_SECTIONS"];
5791 $newInSections = ($res["C"] > 0? "Y": "N");
5792 $oldSectionId = (int)$res["IBLOCK_SECTION_ID"];
5793 $newSectionId = (int)$res["MIN_IBLOCK_SECTION_ID"];
5794
5795 $arIBlock = CIBlock::GetArrayByID($res["IBLOCK_ID"]);
5796 if (
5797 $arIBlock["FIELDS"]["IBLOCK_SECTION"]["DEFAULT_VALUE"]["KEEP_IBLOCK_SECTION_ID"] === "Y"
5798 && $oldInSections === $newInSections
5799 )
5800 {
5801 $res2 = $DB->Query("
5802 SELECT
5803 SE.IBLOCK_SECTION_ID
5804 FROM
5805 b_iblock_section_element SE
5806 WHERE
5807 SE.IBLOCK_ELEMENT_ID = ".$ID."
5808 AND SE.IBLOCK_SECTION_ID = ".$oldSectionId."
5809 AND SE.ADDITIONAL_PROPERTY_ID IS NULL
5810 ");
5811 $res2 = $res2->Fetch();
5812 if ($res2)
5813 {
5814 //We'll keep IBLOCK_SECTION_ID
5815 return;
5816 }
5817 }
5818 }
5819 else
5820 {
5821 //No such element
5822 $oldInSections = "";
5823 $newInSections = "N";
5824 $oldSectionId = 0;
5825 $newSectionId = 0;
5826 }
5827 }
5828
5829 if (
5830 $oldInSections != $newInSections
5831 || ($oldSectionId != $newSectionId)
5832 )
5833 {
5834 $DB->Query("
5835 UPDATE b_iblock_element SET
5836 IN_SECTIONS = '".$newInSections."',
5837 IBLOCK_SECTION_ID= ".($newSectionId > 0? $newSectionId: "NULL")."
5838 WHERE
5839 ID = ".$ID."
5840 ");
5841 }
5842 }
5843
5845 //
5847 public static function SetElementSection($ID, $arSections, $bNew = false, $bRightsIBlock = 0, $sectionId = null)
5848 {
5849 global $DB;
5850 $ID = intval($ID);
5851
5852 $min_old_id = null;
5853 $min_new_id = null;
5854
5855 $arToDelete = array();
5856 $arToInsert = array();
5857 if(is_array($arSections))
5858 {
5859 foreach($arSections as $section_id)
5860 {
5861 $section_id = intval($section_id);
5862 if($section_id > 0)
5863 {
5864 if(!isset($min_new_id) || $section_id < $min_new_id)
5865 $min_new_id = $section_id;
5866
5867 $arToInsert[$section_id] = $section_id;
5868 }
5869 }
5870 }
5871 else
5872 {
5873 $section_id = intval($arSections);
5874 if($section_id > 0)
5875 {
5876 $arToInsert[$section_id] = $section_id;
5877 $min_new_id = $section_id;
5878 }
5879 }
5880
5881 $originalInsert = $arToInsert;
5882 $additionalInsert = array();
5883
5884 $arOldParents = array();
5885 $arNewParents = $arToInsert;
5886 $bParentsChanged = false;
5887
5888 //Read database
5889 if(!$bNew)
5890 {
5891 $rs = $DB->Query("
5892 SELECT * FROM b_iblock_section_element
5893 WHERE IBLOCK_ELEMENT_ID = ".$ID."
5894 AND ADDITIONAL_PROPERTY_ID IS NULL
5895 ");
5896
5897 while($ar = $rs->Fetch())
5898 {
5899 $section_id = intval($ar["IBLOCK_SECTION_ID"]);
5900 $arOldParents[] = $section_id;
5901
5902 if(!isset($min_old_id) || $section_id < $min_old_id)
5903 $min_old_id = $section_id;
5904
5905 if(isset($arToInsert[$section_id]))
5906 {
5907 unset($arToInsert[$section_id]); //This already in DB
5908 }
5909 else
5910 {
5911 if (isset($originalInsert[$section_id]))
5912 $additionalInsert[$section_id] = $section_id;
5913 $arToDelete[] = $section_id;
5914 }
5915 }
5916
5917 if(!empty($arToDelete))
5918 {
5919 $bParentsChanged = true;
5920 $DB->Query($s="
5921 DELETE FROM b_iblock_section_element
5922 WHERE IBLOCK_ELEMENT_ID = ".$ID."
5923 AND ADDITIONAL_PROPERTY_ID IS NULL
5924 AND IBLOCK_SECTION_ID in (".implode(", ", $arToDelete).")
5925 "); //And this should be deleted
5926 }
5927
5928 if (!empty($additionalInsert))
5929 {
5930 foreach ($additionalInsert as $index)
5931 $arToInsert[$index] = $index;
5932 }
5933 }
5934
5935 if(!empty($arToInsert))
5936 {
5937 $bParentsChanged = true;
5938 $DB->Query("
5939 INSERT INTO b_iblock_section_element(IBLOCK_SECTION_ID, IBLOCK_ELEMENT_ID)
5940 SELECT S.ID, E.ID
5941 FROM b_iblock_section S, b_iblock_element E
5942 WHERE S.IBLOCK_ID = E.IBLOCK_ID
5943 AND S.ID IN (".implode(", ", $arToInsert).")
5944 AND E.ID = ".$ID."
5945 ");
5946 }
5947
5948 if($bParentsChanged && $bRightsIBlock)
5949 {
5950 $obElementRights = new CIBlockElementRights($bRightsIBlock, $ID);
5951 if(empty($arOldParents))
5952 $arOldParents[] = 0;
5953 if(empty($arNewParents))
5954 $arNewParents[] = 0;
5955
5956 $obElementRights->ChangeParents($arOldParents, $arNewParents);
5957 }
5958
5959 if($sectionId !== null || ($min_old_id !== $min_new_id))
5960 {
5962 }
5963
5964 return !empty($arToDelete) || !empty($arToInsert);
5965 }
5966
5967 function __InitFile($old_id, &$arFields, $fname)
5968 {
5969 if($old_id>0
5970 &&
5971 (
5972 !is_set($arFields, $fname)
5973 ||
5974 (
5975 $arFields[$fname]['name'] == ''
5976 &&
5977 $arFields[$fname]['del']!="Y"
5978 )
5979 )
5980 &&
5981 ($p = CFile::MakeFileArray($old_id))
5982 )
5983 {
5984 if(is_set($arFields[$fname], 'description'))
5985 $p['description'] = $arFields[$fname]['description'];
5986 $p["OLD_VALUE"] = true;
5987 $arFields[$fname] = $p;
5988 }
5989 }
5990
5991 static function __GetFileContent($FILE_ID)
5992 {
5993 static $max_file_size = null;
5994
5995 $arFile = CFile::MakeFileArray($FILE_ID);
5996 if($arFile && $arFile["tmp_name"])
5997 {
5998 if(!isset($max_file_size))
5999 $max_file_size = COption::GetOptionInt("search", "max_file_size", 0)*1024;
6000
6001 if($max_file_size > 0 && $arFile["size"] > $max_file_size)
6002 return "";
6003
6005 $file_abs_path = $io->GetLogicalName($arFile["tmp_name"]);
6006
6007 $arrFile = false;
6008 foreach(GetModuleEvents("search", "OnSearchGetFileContent", true) as $arEvent)
6009 {
6010 if($arrFile = ExecuteModuleEventEx($arEvent, array($file_abs_path)))
6011 break;
6012 }
6013
6014 return $arrFile;
6015 }
6016
6017 return "";
6018 }
6019
6020 public static function UpdateSearch($ID, $bOverWrite=false)
6021 {
6022 if(!Loader::includeModule("search"))
6023 return;
6024
6025 global $DB;
6026 $ID = (int)$ID;
6027
6028 static $strElementSql = false;
6029 if(!$strElementSql)
6030 {
6031 $strElementSql = "
6032 SELECT BE.ID, BE.NAME, BE.XML_ID as EXTERNAL_ID,
6033 BE.PREVIEW_TEXT_TYPE, BE.PREVIEW_TEXT, BE.CODE,
6034 BE.TAGS,
6035 BE.DETAIL_TEXT_TYPE, BE.DETAIL_TEXT, BE.IBLOCK_ID, B.IBLOCK_TYPE_ID,
6036 ".$DB->DateToCharFunction("BE.TIMESTAMP_X")." as LAST_MODIFIED,
6037 ".$DB->DateToCharFunction("BE.ACTIVE_FROM")." as DATE_FROM,
6038 ".$DB->DateToCharFunction("BE.ACTIVE_TO")." as DATE_TO,
6039 BE.IBLOCK_SECTION_ID,
6040 B.CODE as IBLOCK_CODE, B.XML_ID as IBLOCK_EXTERNAL_ID, B.DETAIL_PAGE_URL,
6041 B.VERSION, B.RIGHTS_MODE, B.SOCNET_GROUP_ID
6042 FROM b_iblock_element BE, b_iblock B
6043 WHERE BE.IBLOCK_ID=B.ID
6044 AND B.ACTIVE='Y'
6045 AND BE.ACTIVE='Y'
6046 AND B.INDEX_ELEMENT='Y'
6047 ".CIBlockElement::WF_GetSqlLimit("BE.", "N")."
6048 AND BE.ID=";
6049 }
6050
6051 $dbrIBlockElement = $DB->Query($strElementSql.$ID);
6052
6053 if($arIBlockElement = $dbrIBlockElement->Fetch())
6054 {
6055 $IBLOCK_ID = $arIBlockElement["IBLOCK_ID"];
6056 $DETAIL_URL =
6057 '=ID=' . urlencode($arIBlockElement['ID'])
6058 . '&EXTERNAL_ID=' . urlencode((string)$arIBlockElement['EXTERNAL_ID'])
6059 . '&IBLOCK_SECTION_ID=' . urlencode((string)$arIBlockElement['IBLOCK_SECTION_ID'])
6060 . '&IBLOCK_TYPE_ID=' . urlencode($arIBlockElement['IBLOCK_TYPE_ID'])
6061 . '&IBLOCK_ID=' . urlencode($arIBlockElement['IBLOCK_ID'])
6062 . '&IBLOCK_CODE=' . urlencode((string)$arIBlockElement['IBLOCK_CODE'])
6063 . '&IBLOCK_EXTERNAL_ID=' . urlencode((string)$arIBlockElement['IBLOCK_EXTERNAL_ID'])
6064 . '&CODE=' . urlencode((string)$arIBlockElement['CODE'])
6065 ;
6066
6067 static $arGroups = array();
6068 if(!isset($arGroups[$IBLOCK_ID]))
6069 {
6071 $strSql =
6072 "SELECT GROUP_ID ".
6073 "FROM b_iblock_group ".
6074 "WHERE IBLOCK_ID= ".$IBLOCK_ID." ".
6075 " AND PERMISSION>='R' ".
6076 "ORDER BY GROUP_ID";
6077
6078 $dbrIBlockGroup = $DB->Query($strSql);
6079 while($arIBlockGroup = $dbrIBlockGroup->Fetch())
6080 {
6081 $arGroups[$IBLOCK_ID][] = $arIBlockGroup["GROUP_ID"];
6082 if($arIBlockGroup["GROUP_ID"]==2) break;
6083 }
6084 unset($arIBlockGroup);
6085 unset($dbrIBlockGroup);
6086 }
6087
6088 static $arSITE = array();
6089 if(!isset($arSITE[$IBLOCK_ID]))
6090 {
6091 $arSITE[$IBLOCK_ID] = array();
6092 $strSql =
6093 "SELECT SITE_ID ".
6094 "FROM b_iblock_site ".
6095 "WHERE IBLOCK_ID= ".$IBLOCK_ID;
6096
6097 $dbrIBlockSite = $DB->Query($strSql);
6098 while($arIBlockSite = $dbrIBlockSite->Fetch())
6099 $arSITE[$IBLOCK_ID][] = $arIBlockSite["SITE_ID"];
6100 unset($arIBlockSite);
6101 unset($dbrIBlockSite);
6102 }
6103
6104 $BODY =
6105 ($arIBlockElement["PREVIEW_TEXT_TYPE"]=="html" ?
6106 CSearch::KillTags($arIBlockElement["PREVIEW_TEXT"]) :
6107 $arIBlockElement["PREVIEW_TEXT"]
6108 )."\r\n".
6109 ($arIBlockElement["DETAIL_TEXT_TYPE"]=="html" ?
6110 CSearch::KillTags($arIBlockElement["DETAIL_TEXT"]) :
6111 $arIBlockElement["DETAIL_TEXT"]
6112 );
6113
6114 static $arProperties = array();
6115 if(!isset($arProperties[$IBLOCK_ID]))
6116 {
6118 $rsProperties = CIBlockProperty::GetList(
6119 array("sort"=>"asc","id"=>"asc"),
6120 array(
6121 "IBLOCK_ID"=>$IBLOCK_ID,
6122 "ACTIVE"=>"Y",
6123 "SEARCHABLE"=>"Y",
6124 "CHECK_PERMISSIONS"=>"N",
6125 )
6126 );
6127 while($ar = $rsProperties->Fetch())
6128 {
6129 if($ar["USER_TYPE"] <> '')
6130 {
6131 $arUT = CIBlockProperty::GetUserType($ar["USER_TYPE"]);
6132 if(isset($arUT["GetSearchContent"]))
6133 $ar["GetSearchContent"] = $arUT["GetSearchContent"];
6134 elseif(isset($arUT["GetPublicViewHTML"]))
6135 $ar["GetSearchContent"] = $arUT["GetPublicViewHTML"];
6136 }
6137 $arProperties[$IBLOCK_ID][$ar["ID"]] = $ar;
6138 }
6139 unset($ar);
6140 unset($rsProperties);
6141 }
6142
6143 //Read current property values from database
6144 $strProperties = "";
6145 if(!empty($arProperties[$IBLOCK_ID]))
6146 {
6147 if($arIBlockElement["VERSION"]==1)
6148 {
6149 $rs = $DB->Query("
6150 select *
6151 from b_iblock_element_property
6152 where IBLOCK_ELEMENT_ID=".$arIBlockElement["ID"]."
6153 AND IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($arProperties[$IBLOCK_ID])).")
6154 ");
6155 while($ar=$rs->Fetch())
6156 {
6157 $strProperties .= "\r\n";
6158 $arProperty = $arProperties[$IBLOCK_ID][$ar["IBLOCK_PROPERTY_ID"]];
6159 if (isset($arProperty["GetSearchContent"]) && $arProperty["GetSearchContent"])
6160 {
6161 $strProperties .= CSearch::KillTags(
6162 call_user_func_array($arProperty["GetSearchContent"],
6163 array(
6164 $arProperty,
6165 array("VALUE" => $ar["VALUE"]),
6166 array(),
6167 )
6168 )
6169 );
6170 }
6171 elseif ($arProperty["PROPERTY_TYPE"] == Iblock\PropertyTable::TYPE_LIST)
6172 {
6173 $arEnum = CIBlockPropertyEnum::GetByID($ar["VALUE"]);
6174 if($arEnum!==false)
6175 $strProperties .= $arEnum["VALUE"];
6176 }
6177 elseif ($arProperty["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_FILE)
6178 {
6179 $arFile = CIBlockElement::__GetFileContent($ar["VALUE"]);
6180 if(is_array($arFile))
6181 {
6182 $strProperties .= $arFile["CONTENT"];
6183 $arIBlockElement["TAGS"] .= ",".$arFile["PROPERTIES"][COption::GetOptionString("search", "page_tag_property")];
6184 }
6185 }
6186 else
6187 {
6188 $strProperties .= $ar["VALUE"];
6189 }
6190 }
6191 }
6192 else
6193 {
6194 $rs = $DB->Query("
6195 select *
6196 from b_iblock_element_prop_m".$IBLOCK_ID."
6197 where IBLOCK_ELEMENT_ID=".$arIBlockElement["ID"]."
6198 AND IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($arProperties[$IBLOCK_ID])).")
6199 ");
6200 while($ar=$rs->Fetch())
6201 {
6202 $strProperties .= "\r\n";
6203 $arProperty = $arProperties[$IBLOCK_ID][$ar["IBLOCK_PROPERTY_ID"]];
6204 if($arProperty["GetSearchContent"])
6205 {
6206 $strProperties .= CSearch::KillTags(
6207 call_user_func_array($arProperty["GetSearchContent"],
6208 array(
6209 $arProperty,
6210 array("VALUE" => $ar["VALUE"]),
6211 array(),
6212 )
6213 )
6214 );
6215 }
6216 elseif($arProperty["PROPERTY_TYPE"]=='L')
6217 {
6218 $arEnum = CIBlockPropertyEnum::GetByID($ar["VALUE"]);
6219 if($arEnum!==false)
6220 $strProperties .= $arEnum["VALUE"];
6221 }
6222 elseif($arProperty["PROPERTY_TYPE"]=='F')
6223 {
6224 $arFile = CIBlockElement::__GetFileContent($ar["VALUE"]);
6225 if(is_array($arFile))
6226 {
6227 $strProperties .= $arFile["CONTENT"];
6228 $arIBlockElement["TAGS"] .= ",".$arFile["PROPERTIES"][COption::GetOptionString("search", "page_tag_property")];
6229 }
6230 }
6231 else
6232 {
6233 $strProperties .= $ar["VALUE"];
6234 }
6235 }
6236 $rs = $DB->Query("
6237 select *
6238 from b_iblock_element_prop_s".$IBLOCK_ID."
6239 where IBLOCK_ELEMENT_ID=".$arIBlockElement["ID"]."
6240 ");
6241 if($ar=$rs->Fetch())
6242 {
6243 foreach($arProperties[$IBLOCK_ID] as $property_id=>$property)
6244 {
6245 if( array_key_exists("PROPERTY_".$property_id, $ar)
6246 && $property["MULTIPLE"]=="N"
6247 && $ar["PROPERTY_".$property_id] <> '')
6248 {
6249 $strProperties .= "\r\n";
6250 if($property["GetSearchContent"])
6251 {
6252 $strProperties .= CSearch::KillTags(
6253 call_user_func_array($property["GetSearchContent"],
6254 array(
6255 $property,
6256 array("VALUE" => $ar["PROPERTY_".$property_id]),
6257 array(),
6258 )
6259 )
6260 );
6261 }
6262 elseif($property["PROPERTY_TYPE"]=='L')
6263 {
6264 $arEnum = CIBlockPropertyEnum::GetByID($ar["PROPERTY_".$property_id]);
6265 if($arEnum!==false)
6266 $strProperties .= $arEnum["VALUE"];
6267 }
6268 elseif($property["PROPERTY_TYPE"]=='F')
6269 {
6270 $arFile = CIBlockElement::__GetFileContent($ar["PROPERTY_".$property_id]);
6271 if(is_array($arFile))
6272 {
6273 $strProperties .= $arFile["CONTENT"];
6274 $arIBlockElement["TAGS"] .= ",".$arFile["PROPERTIES"][COption::GetOptionString("search", "page_tag_property")];
6275 }
6276 }
6277 else
6278 {
6279 $strProperties .= $ar["PROPERTY_".$property_id];
6280 }
6281 }
6282 }
6283 }
6284 }
6285 }
6286 $BODY .= $strProperties;
6287
6288 if($arIBlockElement["RIGHTS_MODE"] !== "E")
6289 {
6290 $arPermissions = $arGroups[$IBLOCK_ID];
6291 }
6292 else
6293 {
6294 $obElementRights = new CIBlockElementRights($IBLOCK_ID, $arIBlockElement["ID"]);
6295 $arPermissions = $obElementRights->GetGroups(array("element_read"));
6296 }
6297
6298 $arFields = array(
6299 "LAST_MODIFIED" => ($arIBlockElement["DATE_FROM"] <> ''?$arIBlockElement["DATE_FROM"]:$arIBlockElement["LAST_MODIFIED"]),
6300 "DATE_FROM" => ($arIBlockElement["DATE_FROM"] <> ''? $arIBlockElement["DATE_FROM"] : false),
6301 "DATE_TO" => ($arIBlockElement["DATE_TO"] <> ''? $arIBlockElement["DATE_TO"] : false),
6302 "TITLE" => $arIBlockElement["NAME"],
6303 "PARAM1" => $arIBlockElement["IBLOCK_TYPE_ID"],
6304 "PARAM2" => $IBLOCK_ID,
6305 "SITE_ID" => $arSITE[$IBLOCK_ID],
6306 "PERMISSIONS" => $arPermissions,
6307 "URL" => $DETAIL_URL,
6308 "BODY" => $BODY,
6309 "TAGS" => $arIBlockElement["TAGS"],
6310 );
6311
6312 if ($arIBlockElement["SOCNET_GROUP_ID"] > 0)
6313 $arFields["PARAMS"] = array(
6314 "socnet_group" => $arIBlockElement["SOCNET_GROUP_ID"],
6315 );
6316
6317 CSearch::Index("iblock", $ID, $arFields, $bOverWrite);
6318 }
6319 else
6320 {
6321 CSearch::DeleteIndex("iblock", $ID);
6322 }
6323 }
6324
6325 public static function GetPropertyValues($IBLOCK_ID, $arElementFilter, $extMode = false, $propertyFilter = array())
6326 {
6327 global $DB;
6328 $IBLOCK_ID = (int)$IBLOCK_ID;
6330
6331 $propertyID = array();
6332 if (isset($propertyFilter['ID']))
6333 {
6334 $propertyID = (is_array($propertyFilter['ID']) ? $propertyFilter['ID'] : array($propertyFilter['ID']));
6336 }
6337
6338 $arElementFilter["IBLOCK_ID"] = $IBLOCK_ID;
6339
6340 $element = new CIBlockElement;
6341 $element->strField = "ID";
6342 $element->prepareSql(array("ID"), $arElementFilter, false, false);
6343
6344 if ($VERSION == 2)
6345 $strSql = "
6346 SELECT
6347 BEP.*
6348 FROM
6349 ".$element->sFrom."
6350 INNER JOIN b_iblock_element_prop_s".$IBLOCK_ID." BEP ON BEP.IBLOCK_ELEMENT_ID = BE.ID
6351 WHERE 1=1 ".$element->sWhere."
6352 ORDER BY
6353 BEP.IBLOCK_ELEMENT_ID
6354 ";
6355 else
6356 $strSql = "
6357 SELECT
6358 BE.ID IBLOCK_ELEMENT_ID
6359 ,BEP.IBLOCK_PROPERTY_ID
6360 ,BEP.VALUE
6361 ,BEP.VALUE_NUM
6362 ".($extMode ?
6363 ",BEP.ID PROPERTY_VALUE_ID
6364 ,BEP.DESCRIPTION
6365 " :
6366 ""
6367 )."
6368 FROM
6369 ".$element->sFrom."
6370 LEFT JOIN b_iblock_element_property BEP ON BEP.IBLOCK_ELEMENT_ID = BE.ID ".
6371 (!empty($propertyID) ? "AND BEP.IBLOCK_PROPERTY_ID IN (" . implode(', ', $propertyID) . ")" : "") .
6372 "WHERE 1=1 " . $element->sWhere . "
6373 ORDER BY
6374 BEP.IBLOCK_ELEMENT_ID, BEP.IBLOCK_PROPERTY_ID, BEP.ID
6375 ";
6376 $rs = new CIBlockPropertyResult($DB->Query($strSql));
6377 $rs->setIBlock($IBLOCK_ID, $propertyID);
6378 $rs->setMode($extMode);
6379
6380 return $rs;
6381 }
6382
6383 public static function GetPropertyValuesArray(&$result, $iblockID, $filter, $propertyFilter = array(), $options = array())
6384 {
6385 $iblockExtVersion = (CIBlockElement::GetIBVersion($iblockID) == 2);
6386 $propertiesList = array();
6387 $shortProperties = array();
6388 $userTypesList = array();
6389
6390 $selectListMultiply = array('SORT' => SORT_ASC, 'VALUE' => SORT_STRING);
6391 $selectAllMultiply = array('PROPERTY_VALUE_ID' => SORT_ASC);
6392
6394 'ID', 'IBLOCK_ID', 'NAME', 'ACTIVE', 'SORT', 'CODE', 'DEFAULT_VALUE', 'PROPERTY_TYPE', 'ROW_COUNT', 'COL_COUNT', 'LIST_TYPE',
6395 'MULTIPLE', 'XML_ID', 'FILE_TYPE', 'MULTIPLE_CNT', 'LINK_IBLOCK_ID', 'WITH_DESCRIPTION', 'SEARCHABLE', 'FILTRABLE',
6396 'IS_REQUIRED', 'VERSION', 'USER_TYPE', 'USER_TYPE_SETTINGS', 'HINT'
6397 );
6398
6399 if (!is_array($options))
6400 $options = array();
6401 $usePropertyId = (isset($options['USE_PROPERTY_ID']) && $options['USE_PROPERTY_ID'] == 'Y');
6402 $getRawData = (isset($options['GET_RAW_DATA']) && $options['GET_RAW_DATA'] == 'Y');
6403 $propertyFieldList = array();
6404 if (!empty($options['PROPERTY_FIELDS']) && is_array($options['PROPERTY_FIELDS']))
6405 $propertyFieldList = array_intersect($options['PROPERTY_FIELDS'], $selectFields);
6406 if (!empty($propertyFieldList))
6407 {
6408 if (!in_array('ID', $propertyFieldList))
6409 $propertyFieldList[] = 'ID';
6410 if (!$getRawData)
6411 {
6412 if (in_array('NAME', $propertyFieldList))
6413 $propertyFieldList[] = '~NAME';
6414 if (in_array('DEFAULT_VALUE', $propertyFieldList))
6415 $propertyFieldList[] = '~DEFAULT_VALUE';
6416 }
6417 $propertyFieldList = array_fill_keys($propertyFieldList, true);
6418 }
6419
6420 $propertyListFilter = array(
6421 'IBLOCK_ID' => $iblockID
6422 );
6423 $propertyID = array();
6424 if (isset($propertyFilter['ID']))
6425 {
6426 $propertyID = (is_array($propertyFilter['ID']) ? $propertyFilter['ID'] : array($propertyFilter['ID']));
6428 }
6429 if (!empty($propertyID))
6430 {
6431 $propertyListFilter['@ID'] = $propertyID;
6432 }
6433 elseif (isset($propertyFilter['CODE']))
6434 {
6435 if (!is_array($propertyFilter['CODE']))
6436 $propertyFilter['CODE'] = array($propertyFilter['CODE']);
6437 $propertyCodes = array();
6438 if (!empty($propertyFilter['CODE']))
6439 {
6440 foreach ($propertyFilter['CODE'] as &$code)
6441 {
6442 $code = (string)$code;
6443 if ($code !== '')
6444 $propertyCodes[] = $code;
6445 }
6446 unset($code);
6447 }
6448 if (!empty($propertyCodes))
6449 $propertyListFilter['@CODE'] = $propertyCodes;
6450 unset($propertyCodes);
6451 }
6452 $propertyListFilter['=ACTIVE'] = (
6453 isset($propertyFilter['ACTIVE']) && ($propertyFilter['ACTIVE'] == 'Y' || $propertyFilter['ACTIVE'] == 'N')
6454 ? $propertyFilter['ACTIVE']
6455 : 'Y'
6456 );
6457
6458 $propertyID = array();
6459 $propertyIterator = Iblock\PropertyTable::getList(array(
6460 'select' => $selectFields,
6461 'filter' => $propertyListFilter,
6462 'order' => array('SORT'=>'ASC', 'ID'=>'ASC'),
6463 'cache' => array(
6464 'ttl' => 86400,
6465 ),
6466 ));
6467 while ($property = $propertyIterator->fetch())
6468 {
6469 $propertyID[] = (int)$property['ID'];
6470 $property['CODE'] = trim((string)$property['CODE']);
6471 if ($property['CODE'] === '')
6472 $property['CODE'] = $property['ID'];
6473 $code = ($usePropertyId ? $property['ID'] : $property['CODE']);
6474 if (!$getRawData)
6475 {
6476 $property['~NAME'] = $property['NAME'];
6477 if (preg_match("/[;&<>\"]/", $property['NAME']))
6478 $property['NAME'] = htmlspecialcharsEx($property['NAME']);
6479 }
6480
6481 if ($property['USER_TYPE'])
6482 {
6483 $userType = CIBlockProperty::GetUserType($property['USER_TYPE']);
6484 if (isset($userType['ConvertFromDB']))
6485 {
6486 $userTypesList[$property['ID']] = $userType;
6487 if (array_key_exists('DEFAULT_VALUE', $property))
6488 {
6489 $value = [
6490 'VALUE' => $property['DEFAULT_VALUE'],
6491 'DESCRIPTION' => '',
6492 ];
6493 $value = call_user_func_array(
6494 $userType['ConvertFromDB'],
6495 [$property, $value]
6496 );
6497 $property['DEFAULT_VALUE'] = $value['VALUE'] ?? '';
6498 }
6499 }
6500 }
6501
6502 if (!empty($property['USER_TYPE_SETTINGS']))
6503 {
6504 $property['USER_TYPE_SETTINGS'] = unserialize($property['USER_TYPE_SETTINGS'], ['allowed_classes' => false]);
6505 }
6506
6507 if (!$getRawData)
6508 {
6509 $property['~DEFAULT_VALUE'] = $property['DEFAULT_VALUE'] ?? null;
6510 if (
6511 isset($property['DEFAULT_VALUE'])
6512 && (
6513 is_array($property['DEFAULT_VALUE'])
6514 || preg_match("/[;&<>\"]/", $property['DEFAULT_VALUE'])
6515 )
6516 )
6517 {
6518 $property['DEFAULT_VALUE'] = htmlspecialcharsEx($property['DEFAULT_VALUE']);
6519 }
6520 }
6521
6522 $propertiesList[$code] = $property;
6523 $shortProperties[$code] = (!empty($propertyFieldList)
6524 ? array_intersect_key($property, $propertyFieldList)
6525 : $property
6526 );
6527 }
6528 unset($property, $propertyIterator);
6529
6530 if (empty($propertiesList))
6531 return;
6532
6533 $enumList = array();
6534
6535 $emptyResult = empty($result);
6536
6537 $valuesRes = (
6538 !empty($propertyID)
6539 ? CIBlockElement::GetPropertyValues($iblockID, $filter, true, array('ID' => $propertyID))
6540 : CIBlockElement::GetPropertyValues($iblockID, $filter, true)
6541 );
6542 while ($value = $valuesRes->Fetch())
6543 {
6544 $elementID = (int)$value['IBLOCK_ELEMENT_ID'];
6545 if (!isset($result[$elementID]))
6546 {
6547 if ($emptyResult)
6548 {
6549 $result[$elementID] = [];
6550 }
6551 else
6552 {
6553 continue;
6554 }
6555 }
6556 $elementValues = array();
6557 $existDescription = isset($value['DESCRIPTION']);
6558 foreach ($propertiesList as $code => $property)
6559 {
6560 $existElementDescription = isset($value['DESCRIPTION']) && array_key_exists($property['ID'], $value['DESCRIPTION']);
6561 $existElementPropertyID = isset($value['PROPERTY_VALUE_ID']) && array_key_exists($property['ID'], $value['PROPERTY_VALUE_ID']);
6562 $elementValues[$code] = $shortProperties[$code];
6563
6564 $elementValues[$code]['VALUE_ENUM'] = null;
6565 $elementValues[$code]['VALUE_XML_ID'] = null;
6566 $elementValues[$code]['VALUE_SORT'] = null;
6567 $elementValues[$code]['VALUE'] = null;
6568
6569 if ('Y' === $property['MULTIPLE'])
6570 {
6571 $elementValues[$code]['PROPERTY_VALUE_ID'] = false;
6572 if (!isset($value[$property['ID']]) || empty($value[$property['ID']]))
6573 {
6574 $elementValues[$code]['DESCRIPTION'] = false;
6575 $elementValues[$code]['VALUE'] = false;
6576 if (!$getRawData)
6577 {
6578 $elementValues[$code]['~DESCRIPTION'] = false;
6579 $elementValues[$code]['~VALUE'] = false;
6580 }
6581 if ($property['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_LIST)
6582 {
6583 $elementValues[$code]['VALUE_ENUM_ID'] = false;
6584 $elementValues[$code]['VALUE_ENUM'] = false;
6585 $elementValues[$code]['VALUE_XML_ID'] = false;
6586 $elementValues[$code]['VALUE_SORT'] = false;
6587 }
6588 }
6589 else
6590 {
6591 if ($existElementPropertyID)
6592 {
6593 $elementValues[$code]['PROPERTY_VALUE_ID'] = $value['PROPERTY_VALUE_ID'][$property['ID']];
6594 }
6595 if (isset($userTypesList[$property['ID']]))
6596 {
6597 foreach ($value[$property['ID']] as $valueKey => $oneValue)
6598 {
6599 $raw = call_user_func_array(
6600 $userTypesList[$property['ID']]['ConvertFromDB'],
6601 array(
6602 $property,
6603 array(
6604 'VALUE' => $oneValue,
6605 'DESCRIPTION' => ($existElementDescription ? $value['DESCRIPTION'][$property['ID']][$valueKey] : null),
6606 )
6607 )
6608 );
6609 $value[$property['ID']][$valueKey] = $raw['VALUE'] ?? null;
6610 if (!$existDescription)
6611 {
6612 $value['DESCRIPTION'] = array();
6613 $existDescription = true;
6614 }
6615 if (!$existElementDescription)
6616 {
6617 $value['DESCRIPTION'][$property['ID']] = array();
6618 $existElementDescription = true;
6619 }
6620 $value['DESCRIPTION'][$property['ID']][$valueKey] = (string)$raw['DESCRIPTION'];
6621 }
6622 if (isset($oneValue))
6623 unset($oneValue);
6624 }
6625 if ($property['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_LIST)
6626 {
6627 if (empty($value[$property['ID']]))
6628 {
6629 $elementValues[$code]['VALUE_ENUM_ID'] = $value[$property['ID']];
6630 $elementValues[$code]['DESCRIPTION'] = ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : array());
6631 }
6632 else
6633 {
6634 $selectedValues = array();
6635 foreach ($value[$property['ID']] as $listKey => $listValue)
6636 {
6637 if (!isset($enumList[$property['ID']][$listValue]))
6638 {
6639 if (!isset($enumList[$property['ID']]))
6640 $enumList[$property['ID']] = [];
6641 $enumList[$property['ID']][$listValue] = false;
6642 $enumIterator = Iblock\PropertyEnumerationTable::getList(array(
6643 'select' => array('ID', 'VALUE', 'SORT', 'XML_ID'),
6644 'filter' => array('=ID' => $listValue, '=PROPERTY_ID' => $property['ID'])
6645 ));
6646 $row = $enumIterator->fetch();
6647 unset($enumIterator);
6648 if (!empty($row))
6649 {
6650 $enumList[$property['ID']][$listValue] = array(
6651 'ID' => $row['ID'],
6652 'VALUE' => $row['VALUE'],
6653 'SORT' => $row['SORT'],
6654 'XML_ID' => $row['XML_ID']
6655 );
6656 }
6657 unset($row);
6658 }
6659 if (!empty($enumList[$property['ID']][$listValue]))
6660 {
6661 $selectedValues[$listKey] = $enumList[$property['ID']][$listValue];
6662 $selectedValues[$listKey]['DESCRIPTION'] = (
6663 $existElementDescription && array_key_exists($listKey, $value['DESCRIPTION'][$property['ID']])
6664 ? $value['DESCRIPTION'][$property['ID']][$listKey]
6665 : null
6666 );
6667 $selectedValues[$listKey]['PROPERTY_VALUE_ID'] = (
6668 $existElementPropertyID && array_key_exists($listKey, $value['PROPERTY_VALUE_ID'][$property['ID']])
6669 ? $value['PROPERTY_VALUE_ID'][$property['ID']][$listKey]
6670 : null
6671 );
6672 }
6673 }
6674 if (empty($selectedValues))
6675 {
6676 $elementValues[$code]['VALUE_ENUM_ID'] = $value[$property['ID']];
6677 $elementValues[$code]['DESCRIPTION'] = ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : array());
6678 }
6679 else
6680 {
6681 Main\Type\Collection::sortByColumn($selectedValues, $selectListMultiply);
6682 $elementValues[$code]['VALUE_SORT'] = array();
6683 $elementValues[$code]['VALUE_ENUM_ID'] = array();
6684 $elementValues[$code]['VALUE'] = array();
6685 $elementValues[$code]['VALUE_ENUM'] = array();
6686 $elementValues[$code]['VALUE_XML_ID'] = array();
6687 $elementValues[$code]['DESCRIPTION'] = array();
6688 $elementValues[$code]['PROPERTY_VALUE_ID'] = array();
6689 foreach ($selectedValues as $listValue)
6690 {
6691 $elementValues[$code]['VALUE_SORT'][] = $listValue['SORT'];
6692 $elementValues[$code]['VALUE_ENUM_ID'][] = $listValue['ID'];
6693 $elementValues[$code]['VALUE'][] = $listValue['VALUE'];
6694 $elementValues[$code]['VALUE_ENUM'][] = $listValue['VALUE'];
6695 $elementValues[$code]['VALUE_XML_ID'][] = $listValue['XML_ID'];
6696 $elementValues[$code]['PROPERTY_VALUE_ID'][] = $listValue['PROPERTY_VALUE_ID'];
6697 $elementValues[$code]['DESCRIPTION'][] = $listValue['DESCRIPTION'];
6698 }
6699 unset($selectedValues);
6700 }
6701 }
6702 }
6703 else
6704 {
6705 if (empty($value[$property['ID']]) || !$existElementPropertyID || isset($userTypesList[$property['ID']]))
6706 {
6707 $elementValues[$code]['VALUE'] = $value[$property['ID']];
6708 $elementValues[$code]['DESCRIPTION'] = ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : array());
6709 }
6710 else
6711 {
6712 $selectedValues = array();
6713 foreach ($value['PROPERTY_VALUE_ID'][$property['ID']] as $propKey => $propValueID)
6714 {
6715 $selectedValues[$propKey] = array(
6716 'PROPERTY_VALUE_ID' => $propValueID,
6717 'VALUE' => $value[$property['ID']][$propKey],
6718 );
6719 if ($existElementDescription)
6720 {
6721 $selectedValues[$propKey]['DESCRIPTION'] = $value['DESCRIPTION'][$property['ID']][$propKey];
6722 }
6723 }
6724 unset($propValueID, $propKey);
6725
6726 Main\Type\Collection::sortByColumn($selectedValues, $selectAllMultiply);
6727 $elementValues[$code]['PROPERTY_VALUE_ID'] = array();
6728 $elementValues[$code]['VALUE'] = array();
6729 $elementValues[$code]['DESCRIPTION'] = array();
6730 foreach ($selectedValues as &$propValue)
6731 {
6732 $elementValues[$code]['PROPERTY_VALUE_ID'][] = $propValue['PROPERTY_VALUE_ID'];
6733 $elementValues[$code]['VALUE'][] = $propValue['VALUE'];
6734 if ($existElementDescription)
6735 {
6736 $elementValues[$code]['DESCRIPTION'][] = $propValue['DESCRIPTION'];
6737 }
6738 }
6739 unset($propValue, $selectedValues);
6740 }
6741 }
6742 }
6743
6744 if (!$getRawData)
6745 {
6746 $elementValues[$code]['~VALUE'] = $elementValues[$code]['VALUE'];
6747 if (is_array($elementValues[$code]['VALUE']))
6748 {
6749 foreach ($elementValues[$code]['VALUE'] as &$oneValue)
6750 {
6751 $isArr = is_array($oneValue);
6752 if ($isArr || ('' !== $oneValue && null !== $oneValue))
6753 {
6754 if ($isArr || preg_match("/[;&<>\"]/", $oneValue))
6755 {
6756 $oneValue = htmlspecialcharsEx($oneValue);
6757 }
6758 }
6759 }
6760 if (isset($oneValue))
6761 unset($oneValue);
6762 }
6763 else
6764 {
6765 if ('' !== $elementValues[$code]['VALUE'] && null !== $elementValues[$code]['VALUE'])
6766 {
6767 if (preg_match("/[;&<>\"]/", $elementValues[$code]['VALUE']))
6768 {
6769 $elementValues[$code]['VALUE'] = htmlspecialcharsEx($elementValues[$code]['VALUE']);
6770 }
6771 }
6772 }
6773
6774 $elementValues[$code]['~DESCRIPTION'] = $elementValues[$code]['DESCRIPTION'];
6775 if (is_array($elementValues[$code]['DESCRIPTION']))
6776 {
6777 foreach ($elementValues[$code]['DESCRIPTION'] as &$oneDescr)
6778 {
6779 $isArr = is_array($oneDescr);
6780 if ($isArr || (!$isArr && '' !== $oneDescr && null !== $oneDescr))
6781 {
6782 if ($isArr || preg_match("/[;&<>\"]/", $oneDescr))
6783 {
6784 $oneDescr = htmlspecialcharsEx($oneDescr);
6785 }
6786 }
6787 }
6788 if (isset($oneDescr))
6789 unset($oneDescr);
6790 }
6791 else
6792 {
6793 if ('' !== $elementValues[$code]['DESCRIPTION'] && null !== $elementValues[$code]['DESCRIPTION'])
6794 {
6795 if (preg_match("/[;&<>\"]/", $elementValues[$code]['DESCRIPTION']))
6796 {
6797 $elementValues[$code]['DESCRIPTION'] = htmlspecialcharsEx($elementValues[$code]['DESCRIPTION']);
6798 }
6799 }
6800 }
6801 }
6802 }
6803 else
6804 {
6805 $elementValues[$code]['VALUE_ENUM'] = ($iblockExtVersion ? '' : null);
6806 $elementValues[$code]['PROPERTY_VALUE_ID'] = ($iblockExtVersion ? $elementID.':'.$property['ID'] : null);
6807
6808 if (!isset($value[$property['ID']]) || false === $value[$property['ID']])
6809 {
6810 $elementValues[$code]['DESCRIPTION'] = '';
6811 $elementValues[$code]['VALUE'] = '';
6812 if (!$getRawData)
6813 {
6814 $elementValues[$code]['~DESCRIPTION'] = '';
6815 $elementValues[$code]['~VALUE'] = '';
6816 }
6817 if ($property['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_LIST)
6818 {
6819 $elementValues[$code]['VALUE_ENUM_ID'] = null;
6820 }
6821 }
6822 else
6823 {
6824 if ($existElementPropertyID)
6825 {
6826 $elementValues[$code]['PROPERTY_VALUE_ID'] = $value['PROPERTY_VALUE_ID'][$property['ID']];
6827 }
6828 if (isset($userTypesList[$property['ID']]))
6829 {
6830 $raw = call_user_func_array(
6831 $userTypesList[$property['ID']]['ConvertFromDB'],
6832 array(
6833 $property,
6834 array(
6835 'VALUE' => $value[$property['ID']],
6836 'DESCRIPTION' => ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : null)
6837 )
6838 )
6839 );
6840 $value[$property['ID']] = $raw['VALUE'] ?? null;
6841 if (!$existDescription)
6842 {
6843 $value['DESCRIPTION'] = array();
6844 $existDescription = true;
6845 }
6846 $value['DESCRIPTION'][$property['ID']] = (string)($raw['DESCRIPTION'] ?? null);
6847 $existElementDescription = true;
6848 }
6849 if ($property['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_LIST)
6850 {
6851 $elementValues[$code]['VALUE_ENUM_ID'] = $value[$property['ID']];
6852 if (!isset($enumList[$property['ID']][$value[$property['ID']]]))
6853 {
6854 if (!isset($enumList[$property['ID']]))
6855 $enumList[$property['ID']] = [];
6856 $enumList[$property['ID']][$value[$property['ID']]] = false;
6857 $enumIterator = Iblock\PropertyEnumerationTable::getList(array(
6858 'select' => array('ID', 'VALUE', 'SORT', 'XML_ID'),
6859 'filter' => array('=ID' => $value[$property['ID']], '=PROPERTY_ID' => $property['ID'])
6860 ));
6861 $row = $enumIterator->fetch();
6862 unset($enumIterator);
6863 if (!empty($row))
6864 {
6865 $enumList[$property['ID']][$value[$property['ID']]] = array(
6866 'ID' => $row['ID'],
6867 'VALUE' => $row['VALUE'],
6868 'SORT' => $row['SORT'],
6869 'XML_ID' => $row['XML_ID']
6870 );
6871 }
6872 unset($row);
6873 }
6874 if (!empty($enumList[$property['ID']][$value[$property['ID']]]))
6875 {
6876 $elementValues[$code]['VALUE'] = $enumList[$property['ID']][$value[$property['ID']]]['VALUE'];
6877 $elementValues[$code]['VALUE_ENUM'] = $elementValues[$code]['VALUE'];
6878 $elementValues[$code]['VALUE_XML_ID'] = $enumList[$property['ID']][$value[$property['ID']]]['XML_ID'];
6879 $elementValues[$code]['VALUE_SORT'] = $enumList[$property['ID']][$value[$property['ID']]]['SORT'];
6880 }
6881 $elementValues[$code]['DESCRIPTION'] = ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : null);
6882 }
6883 else
6884 {
6885 $elementValues[$code]['VALUE'] = $value[$property['ID']];
6886 $elementValues[$code]['DESCRIPTION'] = ($existElementDescription ? $value['DESCRIPTION'][$property['ID']] : null);
6887 }
6888 }
6889
6890 if (!$getRawData)
6891 {
6892 $elementValues[$code]['~VALUE'] = $elementValues[$code]['VALUE'];
6893 $isArr = is_array($elementValues[$code]['VALUE']);
6894 if ($isArr || ('' !== $elementValues[$code]['VALUE'] && null !== $elementValues[$code]['VALUE']))
6895 {
6896 if ($isArr || preg_match("/[;&<>\"]/", $elementValues[$code]['VALUE']))
6897 {
6898 $elementValues[$code]['VALUE'] = htmlspecialcharsEx($elementValues[$code]['VALUE']);
6899 }
6900 }
6901
6902 $elementValues[$code]['~DESCRIPTION'] = $elementValues[$code]['DESCRIPTION'];
6903 $isArr = is_array($elementValues[$code]['DESCRIPTION']);
6904 if ($isArr || ('' !== $elementValues[$code]['DESCRIPTION'] && null !== $elementValues[$code]['DESCRIPTION']))
6905 {
6906 if ($isArr || preg_match("/[;&<>\"]/", $elementValues[$code]['DESCRIPTION']))
6907 $elementValues[$code]['DESCRIPTION'] = htmlspecialcharsEx($elementValues[$code]['DESCRIPTION']);
6908 }
6909 }
6910 }
6911 }
6912 if (isset($result[$elementID]['PROPERTIES']))
6913 {
6914 $result[$elementID]['PROPERTIES'] = $elementValues;
6915 }
6916 else
6917 {
6918 $result[$elementID] = $elementValues;
6919 }
6920 unset($elementValues);
6921 }
6922 }
6923
6924 public static function GetProperty($IBLOCK_ID, $ELEMENT_ID, $by="sort", $order="asc", $arFilter = Array())
6925 {
6926 global $DB;
6927 if(is_array($by))
6928 {
6929 if($order!="asc")
6930 $arFilter = $order;
6931 $arOrder = $by;
6932 }
6933 else
6934 {
6935 $arOrder = false;
6936 }
6937
6938 $IBLOCK_ID = (int)$IBLOCK_ID;
6939 $ELEMENT_ID = (int)$ELEMENT_ID;
6941
6942 $strSqlSearch = "";
6943 foreach($arFilter as $key=>$val)
6944 {
6945 switch(mb_strtoupper($key))
6946 {
6947 case "ACTIVE":
6948 if($val == "Y" || $val == "N")
6949 {
6950 $strSqlSearch .= "AND BP.ACTIVE='".$val."'\n";
6951 }
6952 break;
6953 case "SEARCHABLE":
6954 if($val == "Y" || $val == "N")
6955 {
6956 $strSqlSearch .= "AND BP.SEARCHABLE='".$val."'\n";
6957 }
6958 break;
6959 case "NAME":
6960 if($val <> '')
6961 {
6962 $strSqlSearch .= "AND ".CIBlock::_Upper("BP.NAME")." LIKE ".CIBlock::_Upper("'".$DB->ForSql($val)."'")."\n";
6963 }
6964 break;
6965 case "ID":
6966 if(is_array($val))
6967 {
6968 if(!empty($val))
6969 {
6970 $strSqlSearch .= "AND BP.ID in (".implode(", ", array_map("intval", $val)).")\n";
6971 }
6972 }
6973 elseif($val <> '')
6974 {
6975 $strSqlSearch .= "AND BP.ID=".intval($val)."\n";
6976 }
6977 break;
6978 case "PROPERTY_TYPE":
6979 if($val <> '')
6980 {
6981 $strSqlSearch .= "AND BP.PROPERTY_TYPE='".$DB->ForSql($val)."'\n";
6982 }
6983 break;
6984 case "CODE":
6985 if($val <> '')
6986 {
6987 $strSqlSearch .= "AND ".CIBlock::_Upper("BP.CODE")." LIKE ".CIBlock::_Upper("'".$DB->ForSql($val)."'")."\n";
6988 }
6989 break;
6990 case "EMPTY":
6991 if($val <> '')
6992 {
6993 if($val == "Y")
6994 {
6995 $strSqlSearch .= "AND BEP.ID IS NULL\n";
6996 }
6997 elseif($VERSION != 2)
6998 {
6999 $strSqlSearch .= "AND BEP.ID IS NOT NULL\n";
7000 }
7001 }
7002 break;
7003 }
7004 }
7005
7006 $arSqlOrder = array();
7007 if($arOrder)
7008 {
7009 foreach($arOrder as $by=>$order)
7010 {
7011 $order = mb_strtolower($order);
7012 if($order!="desc")
7013 $order = "asc";
7014
7015 $by = mb_strtolower($by);
7016 if($by == "sort") $arSqlOrder["BP.SORT"]=$order;
7017 elseif($by == "id") $arSqlOrder["BP.ID"]=$order;
7018 elseif($by == "name") $arSqlOrder["BP.NAME"]=$order;
7019 elseif($by == "active") $arSqlOrder["BP.ACTIVE"]=$order;
7020 elseif($by == "value_id") $arSqlOrder["BEP.ID"]=$order;
7021 elseif($by == "enum_sort") $arSqlOrder["BEPE.SORT"]=$order;
7022 else
7023 $arSqlOrder["BP.SORT"]=$order;
7024 }
7025 }
7026 else
7027 {
7028 if($by == "id") $arSqlOrder["BP.ID"]="asc";
7029 elseif($by == "name") $arSqlOrder["BP.NAME"]="asc";
7030 elseif($by == "active") $arSqlOrder["BP.ACTIVE"]="asc";
7031 elseif($by == "value_id") $arSqlOrder["BEP.ID"]=$order;
7032 elseif($by == "enum_sort") $arSqlOrder["BEPE.SORT"]=$order;
7033 else
7034 {
7035 $arSqlOrder["BP.SORT"]="asc";
7036 $by = "sort";
7037 }
7038
7039 if ($order!="desc")
7040 {
7041 $arSqlOrder["BP.SORT"]="asc";
7042 $arSqlOrder["BP.ID"]="asc";
7043 $arSqlOrder["BEPE.SORT"]="asc";
7044 $arSqlOrder["BEP.ID"]="asc";
7045 $order = "asc";
7046 }
7047 else
7048 {
7049 $arSqlOrder["BP.SORT"]="desc";
7050 $arSqlOrder["BP.ID"]="desc";
7051 $arSqlOrder["BEPE.SORT"]="desc";
7052 $arSqlOrder["BEP.ID"]="desc";
7053 }
7054 }
7055
7056 $strSqlOrder = "";
7057 foreach($arSqlOrder as $key=>$val)
7058 $strSqlOrder.=", ".$key." ".$val;
7059
7060 if($strSqlOrder!="")
7061 $strSqlOrder = ' ORDER BY '.mb_substr($strSqlOrder, 1);
7062
7063 if($VERSION==2)
7064 $strTable = "b_iblock_element_prop_m".$IBLOCK_ID;
7065 else
7066 $strTable = "b_iblock_element_property";
7067
7068 $strSql = "
7069 SELECT BP.*, BEP.ID as PROPERTY_VALUE_ID, BEP.VALUE, BEP.DESCRIPTION, BEPE.VALUE VALUE_ENUM, BEPE.XML_ID VALUE_XML_ID, BEPE.SORT VALUE_SORT
7070 FROM b_iblock B
7071 INNER JOIN b_iblock_property BP ON B.ID=BP.IBLOCK_ID
7072 LEFT JOIN ".$strTable." BEP ON (BP.ID = BEP.IBLOCK_PROPERTY_ID AND BEP.IBLOCK_ELEMENT_ID = ".$ELEMENT_ID.")
7073 LEFT JOIN b_iblock_property_enum BEPE ON (BP.PROPERTY_TYPE = 'L' AND BEPE.ID=BEP.VALUE_ENUM AND BEPE.PROPERTY_ID=BP.ID)
7074 WHERE B.ID = ".$IBLOCK_ID."
7075 ".$strSqlSearch."
7076 ".$strSqlOrder;
7077
7078 if($VERSION==2)
7079 {
7080 $emptyFilter = !isset($arFilter['EMPTY']) || $arFilter['EMPTY'] === 'Y';
7081 $notEmptyFilter = isset($arFilter['EMPTY']) && $arFilter['EMPTY'] === 'N';
7082 $result = array();
7083 $arElements = array();
7084 $rs = $DB->Query($strSql);
7085 while($ar = $rs->Fetch())
7086 {
7087 if($ar["VERSION"]==2 && $ar["MULTIPLE"]=="N")
7088 {
7089 if (!isset($arElements[$ELEMENT_ID]))
7090 {
7091 $strSql = "
7092 SELECT *
7093 FROM b_iblock_element_prop_s".$ar["IBLOCK_ID"]."
7094 WHERE IBLOCK_ELEMENT_ID = ".$ELEMENT_ID."
7095 ";
7096 $rs2 = $DB->Query($strSql);
7097 $arElements[$ELEMENT_ID] = $rs2->Fetch();
7098 unset($rs2);
7099 }
7100 $notEmptyValue =
7101 is_array($arElements[$ELEMENT_ID])
7102 && isset($arElements[$ELEMENT_ID]["PROPERTY_".$ar["ID"]])
7103 && $arElements[$ELEMENT_ID]["PROPERTY_".$ar["ID"]] !== ''
7104 ;
7105 if ($emptyFilter || $notEmptyValue)
7106 {
7107 $val = $arElements[$ELEMENT_ID]["PROPERTY_".$ar["ID"]] ?? null;
7108 $ar["PROPERTY_VALUE_ID"] = $ELEMENT_ID . ":" . $ar["ID"];
7109 if ($ar["PROPERTY_TYPE"]=="L" && (int)$val > 0)
7110 {
7112 if($arEnum!==false)
7113 {
7114 $ar["VALUE_ENUM"] = $arEnum["VALUE"];
7115 $ar["VALUE_XML_ID"] = $arEnum["XML_ID"];
7116 $ar["VALUE_SORT"] = $arEnum["SORT"];
7117 }
7118 }
7119 else
7120 {
7121 $ar["VALUE_ENUM"] = "";
7122 }
7123 if($ar["PROPERTY_TYPE"]=="N" && $val <> '')
7124 {
7125 $val = CIBlock::NumberFormat($val);
7126 }
7127 $ar["DESCRIPTION"] = $arElements[$ELEMENT_ID]["DESCRIPTION_".$ar["ID"]] ?? null;
7128 $ar["VALUE"] = $val;
7129 }
7130 else
7131 {
7132 continue;
7133 }
7134 }
7135 if ($notEmptyFilter && $ar["PROPERTY_VALUE_ID"] == "")
7136 continue;
7137 $result[]=$ar;
7138 }
7140 $rs->InitFromArray($result);
7141 }
7142 else
7143 {
7144 $rs = new CIBlockPropertyResult($DB->Query($strSql));
7145 }
7146 return $rs;
7147 }
7148
7149 public static function CounterInc($ID)
7150 {
7151 global $DB;
7152 $ID = (int)$ID;
7153 if ($ID <= 0)
7154 return;
7155 if(!isset($_SESSION["IBLOCK_COUNTER"]) || !is_array($_SESSION["IBLOCK_COUNTER"]))
7156 $_SESSION["IBLOCK_COUNTER"] = array();
7157 if(in_array($ID, $_SESSION["IBLOCK_COUNTER"]))
7158 return;
7159 $_SESSION["IBLOCK_COUNTER"][] = $ID;
7160
7161 $DB->StartUsingMasterOnly();
7162 $strSql =
7163 "UPDATE b_iblock_element SET ".
7164 " TIMESTAMP_X = ".($DB->type=="ORACLE"?" NULL":"TIMESTAMP_X").", ".
7165 " SHOW_COUNTER_START = ".$DB->IsNull("SHOW_COUNTER_START", $DB->CurrentTimeFunction()).", ".
7166 " SHOW_COUNTER = ".$DB->IsNull("SHOW_COUNTER", 0)." + 1 ".
7167 "WHERE ID=".$ID;
7168 $DB->Query($strSql, false, "", array("ignore_dml"=>true));
7169 $DB->StopUsingMasterOnly();
7170 }
7171
7172 public static function GetIBVersion($iblock_id)
7173 {
7174 return
7175 (int)CIBlock::GetArrayByID($iblock_id, 'VERSION') === Iblock\IblockTable::PROPERTY_STORAGE_SEPARATE
7178 ;
7179 }
7180
7181 public static function DeletePropertySQL($property, $iblock_element_id)
7182 {
7183 $propertyId = (int)$property['ID'];
7184 $elementId = (int)$iblock_element_id;
7185 if ((int)$property['VERSION'] === IblockTable::PROPERTY_STORAGE_SEPARATE)
7186 {
7187 $iblockId = (int)$property['IBLOCK_ID'];
7188 if ($property['MULTIPLE'] === 'Y')
7189 {
7190 return "
7191 DELETE
7192 FROM b_iblock_element_prop_m" . $iblockId . "
7193 WHERE
7194 IBLOCK_ELEMENT_ID=" . $elementId . "
7195 AND IBLOCK_PROPERTY_ID=" . $propertyId . "
7196 ";
7197 }
7198 else
7199 {
7200 return "
7201 UPDATE
7202 b_iblock_element_prop_s" . $iblockId . "
7203 SET
7204 PROPERTY_" . $propertyId . "=null
7205 " . self::__GetDescriptionUpdateSql($iblockId, $propertyId) . "
7206 WHERE
7207 IBLOCK_ELEMENT_ID=" . $elementId . "
7208 ";
7209 }
7210 }
7211 else
7212 {
7213 return "
7214 DELETE FROM
7215 b_iblock_element_property
7216 WHERE
7217 IBLOCK_ELEMENT_ID=" . $elementId . "
7218 AND IBLOCK_PROPERTY_ID=" . $propertyId . "
7219 ";
7220 }
7221 }
7222
7223 public static function SetPropertyValuesEx($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $FLAGS = [])
7224 {
7225 //Check input parameters
7226 if (!is_array($PROPERTY_VALUES))
7227 {
7228 return;
7229 }
7230
7231 if (!is_array($FLAGS))
7232 {
7233 $FLAGS = [];
7234 }
7235 //FLAGS - modify function behavior
7236 //NewElement - if present no db values select will be issued
7237 //DoNotValidateLists - if present list values do not validates against metadata tables
7238
7239 global $DB;
7240 global $BX_IBLOCK_PROP_CACHE;
7241
7242 $ELEMENT_ID = (int)$ELEMENT_ID;
7243 if ($ELEMENT_ID <= 0)
7244 {
7245 return;
7246 }
7247
7248 $IBLOCK_ID = (int)$IBLOCK_ID;
7249 if ($IBLOCK_ID <= 0)
7250 {
7251 $ar = static::GetIBlockByID($ELEMENT_ID);
7252 if (empty($ar))
7253 {
7254 return;
7255 }
7256 $IBLOCK_ID = $ar;
7257 }
7258
7259 //Get property metadata
7260 $uniq_flt = $IBLOCK_ID."|SetPropertyValuesEx";
7261
7262 if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID]))
7263 {
7265 }
7266
7267 if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt]))
7268 {
7269 $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt] = array(0=>array());
7270 $rs = CIBlockProperty::GetList(array(), array(
7271 "IBLOCK_ID"=>$IBLOCK_ID,
7272 "CHECK_PERMISSIONS"=>"N",
7273 "ACTIVE"=>"Y",
7274 ));
7275 while($ar = $rs->Fetch())
7276 {
7277 $ar["ConvertToDB"] = false;
7278 if($ar["USER_TYPE"]!="")
7279 {
7280 $arUserType = CIBlockProperty::GetUserType($ar["USER_TYPE"]);
7281 if(array_key_exists("ConvertToDB", $arUserType))
7282 $ar["ConvertToDB"] = $arUserType["ConvertToDB"];
7283 }
7284
7285 $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt][$ar["ID"]] = $ar;
7286 //For CODE2ID conversion
7287 $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt][0][$ar["CODE"]] = $ar["ID"];
7288 //VERSION
7289 $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt]["VERSION"] = $ar["VERSION"];
7290 }
7291 }
7292
7293 $PROPS_CACHE = $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt];
7294 //Unify properties values arProps[$property_id]=>array($id=>array("VALUE", "DESCRIPTION"),....)
7295 $arProps = array();
7296 $propertyList = [];
7297 foreach($PROPERTY_VALUES as $key=>$value)
7298 {
7299 //Code2ID
7300 if(array_key_exists($key, $PROPS_CACHE[0]))
7301 {
7302 $key = $PROPS_CACHE[0][$key];
7303 }
7304 //It's not CODE so check if such ID exists
7305 else
7306 {
7307 $key = intval($key);
7308 if($key <= 0 || !array_key_exists($key, $PROPS_CACHE))
7309 continue;
7310 }
7311
7312 $propertyList[$key] = $PROPS_CACHE[$key];
7313 if($PROPS_CACHE[$key]["PROPERTY_TYPE"]=="F")
7314 {
7315 if(is_array($value))
7316 {
7317 $ar = array_keys($value);
7318 if(array_key_exists("tmp_name", $value) || array_key_exists("del", $value))
7319 {
7320 $uni_value = array(array("ID"=>0,"VALUE"=>$value,"DESCRIPTION"=>""));
7321 }
7322 elseif($ar[0]==="VALUE" && $ar[1]==="DESCRIPTION")
7323 {
7324 $uni_value = array(array("ID"=>0,"VALUE"=>$value["VALUE"],"DESCRIPTION"=>$value["DESCRIPTION"]));
7325 }
7326 elseif(count($ar)===1 && $ar[0]==="VALUE")
7327 {
7328 $uni_value = array(array("ID"=>0,"VALUE"=>$value["VALUE"],"DESCRIPTION"=>""));
7329 }
7330 else //multiple values
7331 {
7332 $uni_value = array();
7333 foreach($value as $id=>$val)
7334 {
7335 if(is_array($val))
7336 {
7337 if(array_key_exists("tmp_name", $val) || array_key_exists("del", $val))
7338 {
7339 $uni_value[] = array("ID"=>$id,"VALUE"=>$val,"DESCRIPTION"=>"");
7340 }
7341 else
7342 {
7343 $ar = array_keys($val);
7344 if($ar[0]==="VALUE" && $ar[1]==="DESCRIPTION")
7345 $uni_value[] = array("ID"=>$id,"VALUE"=>$val["VALUE"],"DESCRIPTION"=>$val["DESCRIPTION"]);
7346 elseif(count($ar)===1 && $ar[0]==="VALUE")
7347 $uni_value[] = array("ID"=>$id,"VALUE"=>$val["VALUE"],"DESCRIPTION"=>"");
7348 }
7349 }
7350 }
7351 }
7352 }
7353 else
7354 {
7355 //There was no valid file array found so we'll skip this property
7356 $uni_value = array();
7357 }
7358 }
7359 elseif(!is_array($value))
7360 {
7361 $uni_value = array(array("VALUE"=>$value,"DESCRIPTION"=>""));
7362 }
7363 else
7364 {
7365 $ar = array_keys($value);
7366 if(count($ar)===2 && $ar[0]==="VALUE" && $ar[1]==="DESCRIPTION")
7367 {
7368 $uni_value = array(array("VALUE"=>$value["VALUE"],"DESCRIPTION"=>$value["DESCRIPTION"]));
7369 }
7370 elseif(count($ar)===1 && $ar[0]==="VALUE")
7371 {
7372 $uni_value = array(array("VALUE"=>$value["VALUE"],"DESCRIPTION"=>""));
7373 }
7374 else // multiple values
7375 {
7376 $uni_value = array();
7377 foreach($value as $id=>$val)
7378 {
7379 if(!is_array($val))
7380 $uni_value[] = array("VALUE"=>$val,"DESCRIPTION"=>"");
7381 else
7382 {
7383 $ar = array_keys($val);
7384 if($ar[0]==="VALUE" && $ar[1]==="DESCRIPTION")
7385 $uni_value[] = array("VALUE"=>$val["VALUE"],"DESCRIPTION"=>$val["DESCRIPTION"]);
7386 elseif(count($ar)===1 && $ar[0]==="VALUE")
7387 $uni_value[] = array("VALUE"=>$val["VALUE"],"DESCRIPTION"=>"");
7388 }
7389 }
7390 }
7391 }
7392
7393 $arValueCounters = array();
7394 foreach($uni_value as $val)
7395 {
7396 if(!array_key_exists($key, $arProps))
7397 {
7398 $arProps[$key] = array();
7399 $arValueCounters[$key] = 0;
7400 }
7401
7402 if($PROPS_CACHE[$key]["ConvertToDB"]!==false)
7403 {
7404 $arProperty = $PROPS_CACHE[$key];
7405 $arProperty["ELEMENT_ID"] = $ELEMENT_ID;
7406 $val = call_user_func_array($PROPS_CACHE[$key]["ConvertToDB"], array($arProperty, $val));
7407 }
7408
7409 if(
7410 (!is_array($val["VALUE"]) && (string)$val["VALUE"] <> '')
7411 || (is_array($val["VALUE"]) && !empty($val["VALUE"]))
7412 )
7413 {
7414 if(
7415 $arValueCounters[$key] == 0
7416 || $PROPS_CACHE[$key]["MULTIPLE"]=="Y"
7417 )
7418 {
7419 if(!is_array($val["VALUE"]) || !isset($val["VALUE"]["del"]))
7420 $arValueCounters[$key]++;
7421
7422 $arProps[$key][] = $val;
7423 }
7424 }
7425 }
7426 }
7427
7428 if (empty($arProps))
7429 {
7430 return;
7431 }
7432
7433 //Read current property values from database
7434 $arDBProps = array();
7435 if(!array_key_exists("NewElement", $FLAGS))
7436 {
7437 if($PROPS_CACHE["VERSION"]==1)
7438 {
7439 $rs = $DB->Query("
7440 select *
7441 from b_iblock_element_property
7442 where IBLOCK_ELEMENT_ID=".$ELEMENT_ID."
7443 AND IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($arProps)).")
7444 ");
7445 while($ar=$rs->Fetch())
7446 {
7447 if(!array_key_exists($ar["IBLOCK_PROPERTY_ID"], $arDBProps))
7448 $arDBProps[$ar["IBLOCK_PROPERTY_ID"]] = array();
7449 $arDBProps[$ar["IBLOCK_PROPERTY_ID"]][$ar["ID"]] = $ar;
7450 }
7451 }
7452 else
7453 {
7454 $rs = $DB->Query("
7455 select *
7456 from b_iblock_element_prop_m".$IBLOCK_ID."
7457 where IBLOCK_ELEMENT_ID=".$ELEMENT_ID."
7458 AND IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($arProps)).")
7459 ");
7460 while($ar=$rs->Fetch())
7461 {
7462 if(!array_key_exists($ar["IBLOCK_PROPERTY_ID"], $arDBProps))
7463 $arDBProps[$ar["IBLOCK_PROPERTY_ID"]] = array();
7464 $arDBProps[$ar["IBLOCK_PROPERTY_ID"]][$ar["ID"]] = $ar;
7465 }
7466 $rs = $DB->Query("
7467 select *
7468 from b_iblock_element_prop_s".$IBLOCK_ID."
7469 where IBLOCK_ELEMENT_ID=".$ELEMENT_ID."
7470 ");
7471 if($ar=$rs->Fetch())
7472 {
7473 foreach($PROPS_CACHE as $property_id=>$property)
7474 {
7475 if( array_key_exists($property_id, $arProps)
7476 && array_key_exists("PROPERTY_".$property_id, $ar)
7477 && $property["MULTIPLE"]=="N"
7478 && $ar["PROPERTY_".$property_id] <> '')
7479 {
7480 $pr=array(
7481 "IBLOCK_PROPERTY_ID" => $property_id,
7482 "VALUE" => $ar["PROPERTY_".$property_id],
7483 "DESCRIPTION" => $ar["DESCRIPTION_".$property_id],
7484 );
7485 if(!array_key_exists($pr["IBLOCK_PROPERTY_ID"], $arDBProps))
7486 $arDBProps[$pr["IBLOCK_PROPERTY_ID"]] = array();
7487 $arDBProps[$pr["IBLOCK_PROPERTY_ID"]][$ELEMENT_ID.":".$property_id] = $pr;
7488 }
7489 }
7490 }
7491 else
7492 {
7493 $DB->Query("
7494 insert into b_iblock_element_prop_s".$IBLOCK_ID."
7495 (IBLOCK_ELEMENT_ID) values (".$ELEMENT_ID.")
7496 ");
7497 }
7498 }
7499 }
7500
7501 foreach (GetModuleEvents("iblock", "OnIBlockElementSetPropertyValuesEx", true) as $arEvent)
7502 ExecuteModuleEventEx($arEvent, array($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $propertyList, $arDBProps));
7503 if (isset($arEvent))
7504 unset($arEvent);
7505
7506 $arFilesToDelete = array();
7507 //Handle file properties
7508 foreach($arProps as $property_id=>$values)
7509 {
7510 if($PROPS_CACHE[$property_id]["PROPERTY_TYPE"]=="F")
7511 {
7512 foreach($values as $i=>$value)
7513 {
7514 $val = $value["VALUE"];
7515 if($val["del"] <> '')
7516 {
7517 $val = "NULL";
7518 }
7519 else
7520 {
7521 $val["MODULE_ID"] = "iblock";
7522 unset($val["old_file"]);
7523
7524 if($value["DESCRIPTION"] <> '')
7525 $val["description"] = $value["DESCRIPTION"];
7526
7527 $val = CFile::SaveFile($val, "iblock");
7528 }
7529
7530 if($val=="NULL")
7531 {//Delete it! Actually it will not add an value
7532 unset($arProps[$property_id][$i]);
7533 }
7534 elseif(intval($val)>0)
7535 {
7536 $arProps[$property_id][$i]["VALUE"] = intval($val);
7537 if($value["DESCRIPTION"] == '')
7538 $arProps[$property_id][$i]["DESCRIPTION"]=$arDBProps[$property_id][$value["ID"]]["DESCRIPTION"];
7539 }
7540 elseif($value["DESCRIPTION"] <> '')
7541 {
7542 $arProps[$property_id][$i]["VALUE"] = $arDBProps[$property_id][$value["ID"]]["VALUE"];
7543 //Only needs to update description so CFile::Delete will not called
7544 unset($arDBProps[$property_id][$value["ID"]]);
7545 }
7546 else
7547 {
7548 $arProps[$property_id][$i]["VALUE"] = $arDBProps[$property_id][$value["ID"]]["VALUE"];
7549 //CFile::Delete will not called
7550 unset($arDBProps[$property_id][$value["ID"]]);
7551 }
7552 }
7553
7554 if(array_key_exists($property_id, $arDBProps))
7555 {
7556 foreach($arDBProps[$property_id] as $id=>$value)
7557 $arFilesToDelete[] = array($value["VALUE"], $ELEMENT_ID, "PROPERTY", -1, $IBLOCK_ID);
7558 }
7559 }
7560 }
7561
7562 foreach($arFilesToDelete as $ar)
7563 call_user_func_array(array("CIBlockElement", "DeleteFile"), $ar);
7564
7565 //Now we'll try to find out properties which do not require any update
7566 if(!array_key_exists("NewElement", $FLAGS))
7567 {
7568 foreach($arProps as $property_id=>$values)
7569 {
7570 if($PROPS_CACHE[$property_id]["PROPERTY_TYPE"]!="F")
7571 {
7572 if(array_key_exists($property_id, $arDBProps))
7573 {
7574 $db_values = $arDBProps[$property_id];
7575 if(count($values) == count($db_values))
7576 {
7577 $bEqual = true;
7578 foreach($values as $id=>$value)
7579 {
7580 $bDBFound = false;
7581 foreach($db_values as $db_id=>$db_row)
7582 {
7583 if (
7584 strcmp($value['VALUE'], $db_row['VALUE']) === 0
7585 && strcmp(
7586 (string)($value['DESCRIPTION'] ?? ''),
7587 (string)($db_row['DESCRIPTION'] ?? '')
7588 ) === 0
7589 )
7590 {
7591 unset($db_values[$db_id]);
7592 $bDBFound = true;
7593 break;
7594 }
7595 }
7596 if(!$bDBFound)
7597 {
7598 $bEqual = false;
7599 break;
7600 }
7601 }
7602 if($bEqual)
7603 {
7604 unset($arProps[$property_id]);
7605 unset($arDBProps[$property_id]);
7606 }
7607 }
7608 }
7609 elseif(count($values)==0)
7610 {
7611 //Values was not found in database neither no values input was given
7612 unset($arProps[$property_id]);
7613 }
7614 }
7615 }
7616 }
7617
7618 //Init "commands" arrays
7619 $ar2Delete = array(
7620 "b_iblock_element_property" => array(/*property_id=>true, property_id=>true, ...*/),
7621 "b_iblock_element_prop_m".$IBLOCK_ID => array(/*property_id=>true, property_id=>true, ...*/),
7622 "b_iblock_section_element" => array(/*property_id=>true, property_id=>true, ...*/),
7623 );
7624 $ar2Insert = array(
7625 "values" => array(
7626 "b_iblock_element_property" => array(/*property_id=>value, property_id=>value, ...*/),
7627 "b_iblock_element_prop_m".$IBLOCK_ID => array(/*property_id=>value, property_id=>value, ...*/),
7628 ),
7629 "sqls"=>array(
7630 "b_iblock_element_property" => array(/*property_id=>sql, property_id=>sql, ...*/),
7631 "b_iblock_element_prop_m".$IBLOCK_ID => array(/*property_id=>sql, property_id=>sql, ...*/),
7632 "b_iblock_section_element" => array(/*property_id=>sql, property_id=>sql, ...*/),
7633 ),
7634 );
7635 $ar2Update = array(
7636 //"b_iblock_element_property" => array(/*property_id=>value, property_id=>value, ...*/),
7637 //"b_iblock_element_prop_m".$IBLOCK_ID => array(/*property_id=>value, property_id=>value, ...*/),
7638 //"b_iblock_element_prop_s".$IBLOCK_ID => array(/*property_id=>value, property_id=>value, ...*/),
7639 );
7640
7641 foreach($arDBProps as $property_id=>$values)
7642 {
7643 if($PROPS_CACHE[$property_id]["VERSION"]==1)
7644 {
7645 $ar2Delete["b_iblock_element_property"][$property_id]=true;
7646 }
7647 elseif($PROPS_CACHE[$property_id]["MULTIPLE"]=="Y")
7648 {
7649 $ar2Delete["b_iblock_element_prop_m".$IBLOCK_ID][$property_id]=true;
7650 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=false;//null
7651 }
7652 else
7653 {
7654 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=false;//null
7655 }
7656 if($PROPS_CACHE[$property_id]["PROPERTY_TYPE"]=="G")
7657 $ar2Delete["b_iblock_section_element"][$property_id]=true;
7658 }
7659
7660 foreach($arProps as $property_id=>$values)
7661 {
7662 $db_prop = $PROPS_CACHE[$property_id];
7663 if($db_prop["PROPERTY_TYPE"]=="L" && !array_key_exists("DoNotValidateLists",$FLAGS))
7664 {
7665 $arID=array();
7666 foreach($values as $value)
7667 {
7668 $value["VALUE"] = intval($value["VALUE"]);
7669 if($value["VALUE"]>0)
7670 $arID[]=$value["VALUE"];
7671 }
7672 if(count($arID)>0)
7673 {
7674 if($db_prop["VERSION"]==1)
7675 {
7676 $ar2Insert["sqls"]["b_iblock_element_property"][$property_id] = "
7677 INSERT INTO b_iblock_element_property
7678 (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_ENUM)
7679 SELECT ".$ELEMENT_ID.", P.ID, PEN.ID, PEN.ID
7680 FROM
7681 b_iblock_property P
7682 ,b_iblock_property_enum PEN
7683 WHERE
7684 P.ID=".$property_id."
7685 AND P.ID=PEN.PROPERTY_ID
7686 AND PEN.ID IN (".implode(", ",$arID).")
7687 ";
7688 }
7689 elseif($db_prop["MULTIPLE"]=="Y")
7690 {
7691 $ar2Insert["sqls"]["b_iblock_element_prop_m".$IBLOCK_ID][$property_id] = "
7692 INSERT INTO b_iblock_element_prop_m".$IBLOCK_ID."
7693 (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_ENUM)
7694 SELECT ".$ELEMENT_ID.", P.ID, PEN.ID, PEN.ID
7695 FROM
7696 b_iblock_property P
7697 ,b_iblock_property_enum PEN
7698 WHERE
7699 P.ID=".$property_id."
7700 AND P.ID=PEN.PROPERTY_ID
7701 AND PEN.ID IN (".implode(", ",$arID).")
7702 ";
7703 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=false;//null
7704 }
7705 else
7706 {
7707 $rs = $DB->Query("
7708 SELECT PEN.ID
7709 FROM
7710 b_iblock_property P
7711 ,b_iblock_property_enum PEN
7712 WHERE
7713 P.ID=".$property_id."
7714 AND P.ID=PEN.PROPERTY_ID
7715 AND PEN.ID IN (".implode(", ",$arID).")
7716 ");
7717 if($ar = $rs->Fetch())
7718 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=array("VALUE"=>$ar["ID"],"DESCRIPTION"=>"");
7719 }
7720 }
7721 continue;
7722 }
7723 if($db_prop["PROPERTY_TYPE"]=="G")
7724 {
7725 $arID=array();
7726 foreach($values as $value)
7727 {
7728 $value["VALUE"] = intval($value["VALUE"]);
7729 if($value["VALUE"]>0)
7730 $arID[]=$value["VALUE"];
7731 }
7732 if(count($arID)>0)
7733 {
7734 if($db_prop["VERSION"]==1)
7735 {
7736 $ar2Insert["sqls"]["b_iblock_element_property"][$property_id] = "
7737 INSERT INTO b_iblock_element_property
7738 (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM)
7739 SELECT ".$ELEMENT_ID.", P.ID, S.ID, S.ID
7740 FROM
7741 b_iblock_property P
7742 ,b_iblock_section S
7743 WHERE
7744 P.ID=".$property_id."
7745 AND S.IBLOCK_ID = P.LINK_IBLOCK_ID
7746 AND S.ID IN (".implode(", ",$arID).")
7747 ";
7748 }
7749 elseif($db_prop["MULTIPLE"]=="Y")
7750 {
7751 $ar2Insert["sqls"]["b_iblock_element_prop_m".$IBLOCK_ID][$property_id] = "
7752 INSERT INTO b_iblock_element_prop_m".$IBLOCK_ID."
7753 (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM)
7754 SELECT ".$ELEMENT_ID.", P.ID, S.ID, S.ID
7755 FROM
7756 b_iblock_property P
7757 ,b_iblock_section S
7758 WHERE
7759 P.ID=".$property_id."
7760 AND S.IBLOCK_ID = P.LINK_IBLOCK_ID
7761 AND S.ID IN (".implode(", ",$arID).")
7762 ";
7763 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=false;//null
7764 }
7765 else
7766 {
7767 $rs = $DB->Query("
7768 SELECT S.ID
7769 FROM
7770 b_iblock_property P
7771 ,b_iblock_section S
7772 WHERE
7773 P.ID=".$property_id."
7774 AND S.IBLOCK_ID = P.LINK_IBLOCK_ID
7775 AND S.ID IN (".implode(", ",$arID).")
7776 ");
7777 if($ar = $rs->Fetch())
7778 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=array("VALUE"=>$ar["ID"],"DESCRIPTION"=>"");
7779 }
7780 $ar2Insert["sqls"]["b_iblock_section_element"][$property_id] = "
7781 INSERT INTO b_iblock_section_element
7782 (IBLOCK_ELEMENT_ID, IBLOCK_SECTION_ID, ADDITIONAL_PROPERTY_ID)
7783 SELECT ".$ELEMENT_ID.", S.ID, P.ID
7784 FROM b_iblock_property P, b_iblock_section S
7785 WHERE P.ID=".$property_id."
7786 AND S.IBLOCK_ID = P.LINK_IBLOCK_ID
7787 AND S.ID IN (".implode(", ",$arID).")
7788 ";
7789 }
7790 continue;
7791 }
7792 foreach($values as $value)
7793 {
7794 if($db_prop["VERSION"]==1)
7795 {
7796 $ar2Insert["values"]["b_iblock_element_property"][$property_id][]=$value;
7797 }
7798 elseif($db_prop["MULTIPLE"]=="Y")
7799 {
7800 $ar2Insert["values"]["b_iblock_element_prop_m".$IBLOCK_ID][$property_id][]=$value;
7801 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=false;//null
7802 }
7803 else
7804 {
7805 $ar2Update["b_iblock_element_prop_s".$IBLOCK_ID][$property_id]=$value;
7806 }
7807 }
7808 }
7809
7810 foreach($ar2Delete as $table=>$arID)
7811 {
7812 if(count($arID)>0)
7813 {
7814 if($table=="b_iblock_section_element")
7815 $DB->Query("
7816 delete from ".$table."
7817 where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID."
7818 and ADDITIONAL_PROPERTY_ID in (".implode(", ", array_keys($arID)).")
7819 ");
7820 else
7821 $DB->Query("
7822 delete from ".$table."
7823 where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID."
7824 and IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($arID)).")
7825 ");
7826 }
7827 }
7828
7829 foreach($ar2Insert["values"] as $table=>$properties)
7830 {
7831 $strSqlPrefix = "
7832 insert into ".$table."
7833 (IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID, VALUE, VALUE_ENUM, VALUE_NUM, DESCRIPTION)
7834 values
7835 ";
7836
7837 $maxValuesLen = $DB->type=="MYSQL"?1024:0;
7838 $strSqlValues = "";
7839 foreach ($properties as $property_id=>$values)
7840 {
7841 foreach ($values as $value)
7842 {
7843 if ((string)$value["VALUE"] <> '')
7844 {
7845 $description = (string)($value['DESCRIPTION'] ?? '');
7846 $strSqlValues .= ",\n(".
7847 $property_id.", ".
7848 $ELEMENT_ID.", ".
7849 "'".$DB->ForSQL($value["VALUE"])."', ".
7850 intval($value["VALUE"]).", ".
7851 CIBlock::roundDB($value["VALUE"]).", ".
7852 ($description !== ''? "'".$DB->ForSQL($description)."'" : "null")." ".
7853 ")";
7854 }
7855 if (mb_strlen($strSqlValues) > $maxValuesLen)
7856 {
7857 $DB->Query($strSqlPrefix.mb_substr($strSqlValues, 2));
7858 $strSqlValues = "";
7859 }
7860 }
7861 }
7862 if($strSqlValues <> '')
7863 {
7864 $DB->Query($strSqlPrefix.mb_substr($strSqlValues, 2));
7865 $strSqlValues = "";
7866 }
7867 }
7868
7869 foreach($ar2Insert["sqls"] as $table=>$properties)
7870 {
7871 foreach($properties as $property_id=>$sql)
7872 {
7873 $DB->Query($sql);
7874 }
7875 }
7876
7877 foreach($ar2Update as $table=>$properties)
7878 {
7879 $tableFields = $DB->GetTableFields($table);
7880 if(count($properties)>0)
7881 {
7882 $arFields = array();
7883 foreach($properties as $property_id=>$value)
7884 {
7885 if($value===false || (string)$value["VALUE"] === '')
7886 {
7887 $arFields[] = "PROPERTY_".$property_id." = null";
7888 if (isset($tableFields["DESCRIPTION_".$property_id]))
7889 {
7890 $arFields[] = "DESCRIPTION_".$property_id." = null";
7891 }
7892 }
7893 else
7894 {
7895 $arFields[] = "PROPERTY_".$property_id." = '".$DB->ForSQL($value["VALUE"])."'";
7896 if (isset($tableFields["DESCRIPTION_".$property_id]))
7897 {
7898 if($value["DESCRIPTION"] <> '')
7899 {
7900 $arFields[] = "DESCRIPTION_".$property_id." = '".$DB->ForSQL($value["DESCRIPTION"])."'";
7901 }
7902 else
7903 {
7904 $arFields[] = "DESCRIPTION_".$property_id." = null";
7905 }
7906 }
7907 }
7908 }
7909 $DB->Query("
7910 update ".$table."
7911 set ".implode(",\n", $arFields)."
7912 where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID."
7913 ");
7914 }
7915 }
7916 /****************************** QUOTA ******************************/
7918 /****************************** QUOTA ******************************/
7919
7920 foreach (GetModuleEvents("iblock", "OnAfterIBlockElementSetPropertyValuesEx", true) as $arEvent)
7921 ExecuteModuleEventEx($arEvent, array($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $FLAGS));
7922 }
7923
7924 protected static function getCheckRightsSql(?int $iblockId, string $minPermission, ?int $permissionsBy = null): string
7925 {
7926 global $USER;
7927
7929 $helper = $connection->getSqlHelper();
7930 unset($connection);
7931
7932 $minPermission = (strlen($minPermission) === 1) ? $minPermission : CIBlockRights::PUBLIC_READ;
7933
7934 if ($permissionsBy !== null && $permissionsBy < 0)
7935 {
7936 $permissionsBy = null;
7937 }
7938
7939 if ($permissionsBy !== null)
7940 {
7941 $userId = $permissionsBy;
7942 $groupList = CUser::GetUserGroup($permissionsBy);
7943 $authorized = false;
7944 }
7945 else
7946 {
7947 if (isset($USER) && $USER instanceof CUser)
7948 {
7949 $userId = (int)$USER->GetID();
7950 $groupList = $USER->GetUserGroupArray();
7951 $authorized = $USER->IsAuthorized();
7952 }
7953 else
7954 {
7955 $userId = 0;
7956 $groupList = ['2'];
7957 $authorized = false;
7958 }
7959 }
7960
7961 $simplePermissions = "
7962 SELECT IBLOCK_ID
7963 FROM b_iblock_group IBG
7964 WHERE IBG.GROUP_ID IN (" . implode(',', $groupList) . ")
7965 AND IBG.PERMISSION >= '" . $helper->forSql($minPermission) . "'
7966 ";
7967 if (!defined('ADMIN_SECTION'))
7968 {
7969 $simplePermissions .= "
7970 AND (IBG.PERMISSION='" . CIBlockRights::FULL_ACCESS . "' OR B.ACTIVE='Y')
7971 ";
7972 }
7973 $simplePermissions = "B.ID IN (" . $simplePermissions . ")";
7974
7975 if ($minPermission >= CIBlockRights::FULL_ACCESS)
7976 {
7977 $operation = CIBlockElementRights::OPERATION_RIGHTS_EDIT;
7978 }
7979 elseif ($minPermission >= CIBlockRights::EDIT_ACCESS)
7980 {
7981 $operation = CIBlockElementRights::OPERATION_EDIT;
7982 }
7983 elseif ($minPermission >= CIBlockRights::PUBLIC_READ)
7984 {
7985 $operation = CIBlockElementRights::OPERATION_READ;
7986 }
7987 else
7988 {
7989 $operation = '';
7990 }
7991
7992 if ($operation)
7993 {
7994 $acc = new CAccess;
7995 $acc->UpdateCodes($permissionsBy !== null ? ['USER_ID' => $permissionsBy] : false);
7996 unset($acc);
7997 }
7998
7999 if ($operation === CIBlockElementRights::OPERATION_READ)
8000 {
8001 $extendedPermissions = "
8002 SELECT ER.ELEMENT_ID
8003 FROM b_iblock_element_right ER
8004 INNER JOIN b_iblock_right IBR ON IBR.ID = ER.RIGHT_ID
8005 " . ($userId > 0 ? 'LEFT': 'INNER')
8006 . " JOIN b_user_access UA ON UA.ACCESS_CODE = IBR.GROUP_CODE AND UA.USER_ID = " . $userId . "
8007 WHERE ER.ELEMENT_ID = BE.ID
8008 AND IBR.OP_EREAD = 'Y'
8009 " . ($authorized || $userId > 0
8010 ? "
8011 AND (UA.USER_ID IS NOT NULL
8012 " . ($authorized ? "OR IBR.GROUP_CODE = 'AU'": '') . "
8013 " . ($userId > 0 ? "OR (IBR.GROUP_CODE = 'CR' AND BE.CREATED_BY = " . $userId . ")": '') . "
8014 )"
8015 : ''
8016 ) . "
8017 ";
8018
8019 $full = "(
8020 " . $simplePermissions . "
8021 OR (B.RIGHTS_MODE = '" . Iblock\IblockTable::RIGHTS_EXTENDED . "' AND EXISTS (" . $extendedPermissions . "))
8022 )";
8023 }
8024 elseif ($operation)
8025 {
8026 $extendedPermissions = "
8027 SELECT ER.ELEMENT_ID
8028 FROM b_iblock_element_right ER
8029 INNER JOIN b_iblock_right IBR ON IBR.ID = ER.RIGHT_ID
8030 INNER JOIN b_task_operation T ON T.TASK_ID = IBR.TASK_ID
8031 INNER JOIN b_operation O ON O.ID = T.OPERATION_ID
8032 " . ($userId > 0 ? 'LEFT': 'INNER')
8033 . " JOIN b_user_access UA ON UA.ACCESS_CODE = IBR.GROUP_CODE AND UA.USER_ID = " . $userId . "
8034 WHERE ER.ELEMENT_ID = BE.ID
8035 AND O.NAME = '" . $operation . "'
8036 " . ($authorized || $userId > 0
8037 ? "
8038 AND (UA.USER_ID IS NOT NULL
8039 " . ($authorized ? "OR IBR.GROUP_CODE = 'AU'": '') . "
8040 " . ($userId > 0 ? "OR (IBR.GROUP_CODE = 'CR' AND BE.CREATED_BY = " . $userId . ")": '') . "
8041 )"
8042 : ''
8043 ) . "
8044 ";
8045
8046 $full = "(
8047 " . $simplePermissions . "
8048 OR (B.RIGHTS_MODE = '" . Iblock\IblockTable::RIGHTS_EXTENDED . "' AND EXISTS (" . $extendedPermissions . "))
8049 )";
8050 }
8051 else
8052 {
8053 $extendedPermissions = '';
8054 $full = "(
8055 " . $simplePermissions . "
8056 )";
8057 }
8058
8059 $result = [
8060 'SIMPLE' => $simplePermissions,
8061 'EXTENDED' => 'EXISTS (' . $extendedPermissions .')',
8062 'FULL' => $full,
8063 ];
8064
8065 $mode = 'FULL';
8066 if ($iblockId !== null)
8067 {
8068 $mode = match (CIBlock::GetArrayByID($iblockId, 'RIGHTS_MODE'))
8069 {
8072 default => 'FULL',
8073 };
8074 }
8075
8076 return $result[$mode];
8077 }
8078
8080 protected static function _check_rights_sql($min_permission, $permissionsBy = null)
8081 {
8082 if ($permissionsBy !== null)
8083 {
8084 $permissionsBy = (int)$permissionsBy;
8085 }
8086
8087 return static::getCheckRightsSql(null, (string)$min_permission, $permissionsBy);
8088 }
8089
8090 protected static function __GetDescriptionUpdateSql($iblock_id, $property_id, $description = false)
8091 {
8092 global $DB;
8093 $tableFields = $DB->GetTableFields("b_iblock_element_prop_s".$iblock_id);
8094 if (isset($tableFields["DESCRIPTION_".$property_id]))
8095 {
8096 if ($description !== false)
8097 $sqlValue = "'".$DB->ForSQL($description, 255)."'";
8098 else
8099 $sqlValue = "null";
8100 return ", DESCRIPTION_".$property_id."=".$sqlValue;
8101 }
8102 else
8103 {
8104 return "";
8105 }
8106 }
8107
8112 protected function getIdOrder($order): string
8113 {
8114 if (is_array($order))
8115 {
8117 if (!empty($order))
8118 {
8120 $helper = $connection->getSqlHelper();
8121
8122 return $helper->getOrderByIntField('BE.ID', $order, false);
8123 }
8124 else
8125 {
8126 $order = '';
8127 }
8128 }
8129 if (!is_string($order))
8130 {
8131 $order = '';
8132 }
8133
8134 return CIBlock::_Order('BE.ID', $order, 'desc', false);
8135 }
8136
8137 protected function getSearchableContent(int $id, array $fields, array $iblock): ?string
8138 {
8139 if ($id <= 0 || empty($fields))
8140 {
8141 return null;
8142 }
8143
8144 $result = $fields['NAME'];
8145
8146 $properties = array();
8147 $list = $this->getIndexedProperties($iblock['ID']);
8148 if (!empty($list))
8149 {
8150 $properties = $list;
8151 }
8152 $list = $this->getOfferProperties($iblock['ID']);
8153 if (!empty($list))
8154 {
8155 foreach (array_keys($list) as $index)
8156 {
8157 $properties[$index] = $list[$index];
8158 }
8159 }
8160
8161 if (!empty($properties))
8162 {
8165 {
8166 $iterator = $connection->query("
8167 select *
8168 from b_iblock_element_property
8169 where IBLOCK_ELEMENT_ID=".$id."
8170 and IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($properties)).")
8171 ");
8172 }
8173 else
8174 {
8175 $iterator = $connection->query("
8176 select *
8177 from b_iblock_element_prop_m".$iblock['ID']."
8178 where IBLOCK_ELEMENT_ID=".$id."
8179 and IBLOCK_PROPERTY_ID in (".implode(", ", array_keys($properties)).")
8180 ");
8181 }
8182 while ($row = $iterator->fetch())
8183 {
8184 $result .= "\r\n";
8185 $property = $properties[$row["IBLOCK_PROPERTY_ID"]];
8186 if (isset($property["GetSearchContent"]))
8187 {
8188 $result .= HTMLToTxt(
8189 call_user_func_array($property["GetSearchContent"],
8190 array(
8191 $property,
8192 array("VALUE" => $row["VALUE"]),
8193 array(),
8194 )
8195 )
8196 );
8197 }
8198 elseif ($property["PROPERTY_TYPE"] == Iblock\PropertyTable::TYPE_LIST)
8199 {
8200 $arEnum = CIBlockPropertyEnum::GetByID($row["VALUE"]);
8201 if ($arEnum !== false)
8202 $result .= $arEnum["VALUE"];
8203 }
8204 elseif($property["PROPERTY_TYPE"] == Iblock\PropertyTable::TYPE_FILE)
8205 {
8206 $arFile = CIBlockElement::__GetFileContent($row["VALUE"]);
8207 if(is_array($arFile))
8208 {
8209 $result .= $arFile["CONTENT"];
8210 }
8211 }
8212 else
8213 {
8214 $result .= $row["VALUE"];
8215 }
8216 }
8218 {
8219 $iterator = $connection->query("
8220 select *
8221 from b_iblock_element_prop_s".$iblock['ID']."
8222 where IBLOCK_ELEMENT_ID=".$id."
8223 ");
8224 if ($row = $iterator->fetch())
8225 {
8226 foreach($properties as $propertyId => $item)
8227 {
8228 $fieldId = 'PROPERTY_'.$propertyId;
8229 if (isset($row[$fieldId])
8230 && $item["MULTIPLE"] == "N"
8231 && $row[$fieldId] != '')
8232 {
8233 $result .= "\r\n";
8234 if (isset($item["GetSearchContent"]))
8235 {
8236 $result .= HTMLToTxt(
8237 call_user_func_array($item["GetSearchContent"],
8238 array(
8239 $item,
8240 array("VALUE" => $row[$fieldId]),
8241 array(),
8242 )
8243 )
8244 );
8245 }
8246 elseif ($item["PROPERTY_TYPE"] == Iblock\PropertyTable::TYPE_LIST)
8247 {
8248 $arEnum = CIBlockPropertyEnum::GetByID($row[$fieldId]);
8249 if($arEnum!==false)
8250 $result .= $arEnum["VALUE"];
8251 }
8252 elseif($item["PROPERTY_TYPE"] == Iblock\PropertyTable::TYPE_FILE)
8253 {
8254 $arFile = CIBlockElement::__GetFileContent($row[$fieldId]);
8255 if(is_array($arFile))
8256 {
8257 $result .= $arFile["CONTENT"];
8258 }
8259 }
8260 else
8261 {
8262 $result .= $row[$fieldId];
8263 }
8264 }
8265 }
8266 }
8267 }
8268 }
8269 if (isset($fields["PREVIEW_TEXT"]))
8270 {
8271 if (isset($fields["PREVIEW_TEXT_TYPE"]) && $fields["PREVIEW_TEXT_TYPE"] == "html")
8272 $result .= "\r\n".HTMLToTxt($fields["PREVIEW_TEXT"]);
8273 else
8274 $result .= "\r\n".$fields["PREVIEW_TEXT"];
8275 }
8276 if (isset($fields["DETAIL_TEXT"]))
8277 {
8278 if (isset($fields["DETAIL_TEXT_TYPE"]) && $fields["DETAIL_TEXT_TYPE"] == "html")
8279 $result .= "\r\n".HTMLToTxt($fields["DETAIL_TEXT"]);
8280 else
8281 $result .= "\r\n".$fields["DETAIL_TEXT"];
8282 }
8283
8284 return $result;
8285 }
8286
8288 {
8289 $result = array();
8291 'select' => array(
8292 'ID', 'IBLOCK_ID', 'NAME', 'SORT', 'MULTIPLE', 'WITH_DESCRIPTION',
8293 'PROPERTY_TYPE', 'USER_TYPE', 'USER_TYPE_SETTINGS_LIST', 'LINK_IBLOCK_ID'
8294 ),
8295 'filter' => $filter,
8296 'order' => array('SORT' => 'ASC', 'ID' => 'ASC'),
8297 'cache' => array('ttl' => 86400)
8298 ));
8299 while ($row = $iterator->fetch())
8300 {
8301 $row['USER_TYPE'] = (string)$row['USER_TYPE'];
8302 if (!is_array($row['USER_TYPE_SETTINGS_LIST']))
8303 {
8304 $row['USER_TYPE_SETTINGS_LIST'] = null;
8305 }
8306 $row['USER_TYPE_SETTINGS'] = $row['USER_TYPE_SETTINGS_LIST'];
8307 unset($row['USER_TYPE_SETTINGS_LIST']);
8308 if ($row['USER_TYPE'] != '')
8309 {
8310 $userType = CIBlockProperty::GetUserType($row['USER_TYPE']);
8311 if (isset($userType['GetSearchContent']))
8312 {
8313 $row['GetSearchContent'] = $userType['GetSearchContent'];
8314 }
8315 elseif (isset($userType['GetPublicViewHTML']))
8316 {
8317 $row['GetSearchContent'] = $userType['GetPublicViewHTML'];
8318 }
8319 }
8320 $result[$row['ID']] = $row;
8321 }
8322 return (!empty($result) ? $result : null);
8323 }
8324
8325 protected function getIndexedProperties(int $iblockId): ?array
8326 {
8327 if ($iblockId <= 0)
8328 {
8329 return null;
8330 }
8331 if (!isset($this->indexedProperties[$iblockId]))
8332 {
8333 $this->indexedProperties[$iblockId] = $this->getPropertiesByFilter(array(
8334 '=IBLOCK_ID' => $iblockId,
8335 '=ACTIVE' => 'Y',
8336 '=SEARCHABLE' => 'Y'
8337 ));
8338 if (empty($this->indexedProperties[$iblockId]))
8339 {
8340 $this->indexedProperties[$iblockId] = array();
8341 }
8342 }
8343 return (!empty($this->indexedProperties[$iblockId]) ? $this->indexedProperties[$iblockId] : null);
8344 }
8345
8346 protected function getOfferProperties(int $iblockId): ?array
8347 {
8348 if ($iblockId <= 0)
8349 {
8350 return null;
8351 }
8352 if (!$this->catalogIncluded)
8353 {
8354 return null;
8355 }
8356
8357 if (!isset($this->offerProperties[$iblockId]))
8358 {
8359 $this->offerProperties[$iblockId] = array();
8360 $catalog = CCatalogSku::GetInfoByOfferIBlock($iblockId);
8361 if (!empty($catalog))
8362 {
8363 $ids = Catalog\Product\PropertyCatalogFeature::getOfferTreePropertyCodes($catalog['IBLOCK_ID']);
8364 if (!empty($ids))
8365 {
8366 $this->offerProperties[$iblockId] = $this->getPropertiesByFilter(array(
8367 '=IBLOCK_ID' => $catalog['IBLOCK_ID'],
8368 '=ACTIVE' => 'Y',
8369 '@ID' => $ids
8370 ));
8371 if (empty($this->offerProperties[$iblockId]))
8372 {
8373 $this->offerProperties[$iblockId] = array();
8374 }
8375 }
8376 }
8377 }
8378 return (!empty($this->offerProperties[$iblockId]) ? $this->offerProperties[$iblockId] : null);
8379 }
8380
8381 public function generateMnemonicCode(string $name, int $iblockId, array $options = []): ?string
8382 {
8383 if ($name === '' || $iblockId <= 0)
8384 {
8385 return null;
8386 }
8387
8388 if ($this->iblock !== null && $this->iblock['ID'] === $iblockId)
8389 {
8391 $language = $this->iblockLanguage;
8392 }
8393 else
8394 {
8395 $iblock = CIBlock::GetArrayByID($iblockId);
8396 if (empty($iblock))
8397 {
8398 $iblock = null;
8399 $language = null;
8400 }
8401 else
8402 {
8403 $iblock['ID'] = (int)$iblock['ID'];
8404 $language = static::getIblockLanguage($iblock['ID']);
8405 }
8406 }
8407
8408 if (empty($iblock))
8409 {
8410 return null;
8411 }
8412
8413 $result = null;
8414 if (isset($iblock['FIELDS']['CODE']['DEFAULT_VALUE']))
8415 {
8416 if ($iblock['FIELDS']['CODE']['DEFAULT_VALUE']['TRANSLITERATION'] === 'Y'
8417 && $iblock['FIELDS']['CODE']['DEFAULT_VALUE']['USE_GOOGLE'] === 'N'
8418 )
8419 {
8420 $config = $iblock['FIELDS']['CODE']['DEFAULT_VALUE'];
8421 $config['LANGUAGE_ID'] = $language;
8422 $config = array_merge($config, $options);
8423
8424 if ($config['LANGUAGE_ID'] !== null)
8425 {
8426 $settings = [
8427 'max_len' => $config['TRANS_LEN'],
8428 'change_case' => $config['TRANS_CASE'],
8429 'replace_space' => $config['TRANS_SPACE'],
8430 'replace_other' => $config['TRANS_OTHER'],
8431 'delete_repeat_replace' => ($config['TRANS_EAT'] == 'Y'),
8432 ];
8433
8434 $result = CUtil::translit($name, $config['LANGUAGE_ID'], $settings);
8435 }
8436 }
8437 }
8438
8439 return $result;
8440 }
8441
8442 public function isExistsMnemonicCode(string $code, ?int $elementId, int $iblockId): bool
8443 {
8444 if ($code === '')
8445 {
8446 return false;
8447 }
8448
8449 $filter = static::getPublicElementsOrmFilter([
8450 '=IBLOCK_ID' => $iblockId,
8451 '=CODE' => $code,
8452 ]);
8453 if ($elementId !== null)
8454 {
8455 $filter['!=ID'] = $elementId;
8456 }
8457
8458 return ElementTable::getRow([
8459 'select' => ['ID'],
8460 'filter' => $filter,
8461 ]) !== null;
8462 }
8463
8464 public function getUniqueMnemonicCode(string $code, ?int $elementId, int $iblockId, array $options = []): ?string
8465 {
8466 if ($code === '')
8467 {
8468 return false;
8469 }
8470 if ($iblockId <= 0)
8471 {
8472 return null;
8473 }
8474
8475 if (!$this->isExistsMnemonicCode($code, $elementId, $iblockId))
8476 {
8477 return $code;
8478 }
8479
8480 $checkSimilar = ($options['CHECK_SIMILAR'] ?? 'N') === 'Y';
8481
8482 $list = [];
8484 'select' => [
8485 'ID',
8486 'CODE',
8487 ],
8488 'filter' => static::getPublicElementsOrmFilter([
8489 '=IBLOCK_ID' => $iblockId,
8490 '%=CODE' => $code . '%',
8491 ]),
8492 ]);
8493 while ($row = $iterator->fetch())
8494 {
8495 if ($checkSimilar && $elementId === (int)$row['ID'])
8496 {
8497 return null;
8498 }
8499 $list[$row['CODE']] = true;
8500 }
8501 unset($iterator, $row);
8502
8503 if (isset($list[$code]))
8504 {
8505 $code .= '_';
8506 $i = 1;
8507 while (isset($list[$code . $i]))
8508 {
8509 $i++;
8510 }
8511
8512 $code .= $i;
8513 }
8514 unset($list);
8515
8516 return $code;
8517 }
8518
8519 public function createMnemonicCode(array $element, array $options = []): ?string
8520 {
8521 if (!isset($element['NAME']) || $element['NAME'] === '')
8522 {
8523 return null;
8524 }
8525 $iblockId = $element['IBLOCK_ID'] ?? 0;
8526 if ($iblockId !== null)
8527 {
8528 $iblockId = (int)$iblockId;
8529 }
8530 if ($iblockId <= 0)
8531 {
8532 return null;
8533 }
8534
8535 if ($this->iblock !== null && $this->iblock['ID'] === $iblockId)
8536 {
8538 }
8539 else
8540 {
8541 $iblock = CIBlock::GetArrayByID($iblockId);
8542 }
8543
8544 if (empty($iblock))
8545 {
8546 return null;
8547 }
8548
8549 $code = null;
8550 if (isset($iblock['FIELDS']['CODE']['DEFAULT_VALUE']))
8551 {
8552 $code = $this->generateMnemonicCode($element['NAME'], $iblockId, $options);
8553 if ($code === null)
8554 {
8555 return null;
8556 }
8557
8558 if ($iblock['FIELDS']['CODE']['DEFAULT_VALUE']['TRANSLITERATION'] === 'Y'
8559 && (
8560 $iblock['FIELDS']['CODE']['DEFAULT_VALUE']['UNIQUE'] === 'Y'
8561 || ($options['CHECK_UNIQUE'] ?? 'N') === 'Y'
8562 )
8563 )
8564 {
8565 $id = (int)($element['ID'] ?? null);
8566 if ($id <= 0)
8567 {
8568 $id = null;
8569 }
8570
8572 $code,
8573 $id,
8574 $iblockId,
8575 $options
8576 );
8577 }
8578 }
8579
8580 return $code;
8581 }
8582
8583 protected static function getIblockLanguage(int $iblockId): ?string
8584 {
8585 $result = [];
8586 $iterator = Iblock\IblockSiteTable::getList([
8587 'select' => ['LANGUAGE_ID' => 'SITE.LANGUAGE_ID'],
8588 'filter' => ['=IBLOCK_ID' => $iblockId],
8589 ]);
8590 while ($row = $iterator->fetch())
8591 {
8592 $result[$row['LANGUAGE_ID']] = true;
8593 }
8594 unset($iterator, $row);
8595
8596 return count($result) === 1 ? key($result) : null;
8597 }
8598
8600 {
8601 $filter['=WF_STATUS_ID'] = 1;
8602 $filter['==WF_PARENT_ELEMENT_ID'] = null;
8603
8604 return $filter;
8605 }
8606
8607 public function getLastError(): string
8608 {
8609 return $this->LAST_ERROR;
8610 }
8611
8612 private static function getUserNameSql(string $tableAlias): string
8613 {
8615 $helper = $connection->getSqlHelper();
8616
8617 return $helper->getConcatFunction(
8618 "'('",
8619 $tableAlias . '.LOGIN',
8620 "') '",
8621 $helper->getIsNullFunction($tableAlias . '.NAME', "''"),
8622 "' '",
8623 $helper->getIsNullFunction($tableAlias . '.LAST_NAME', "''")
8624 );
8625 }
8626
8627 private static function isJoinForCount(int $joinType): bool
8628 {
8629 return ($joinType & self::JOIN_TYPE_WHERE) !== 0 || ($joinType & self::JOIN_TYPE_GROUP) !== 0;
8630 }
8631
8632 protected static function useCountJoin(array $row): bool
8633 {
8634 return
8635 (int)($row['bFullJoin'] ?? false) === 1
8636 || self::isJoinForCount($row['JOIN_TYPE'] ?? 0)
8637 ;
8638 }
8639
8640 private static function addJoinType(array $row, int $joinType): array
8641 {
8642 $row['JOIN_TYPE'] ??= 0;
8643 $row['JOIN_TYPE'] |= $joinType;
8644
8645 return $row;
8646 }
8647
8648 private static function addJoinTypeSelect(array $row): array
8649 {
8650 return self::addJoinType($row, self::JOIN_TYPE_SELECT);
8651 }
8652
8653 private static function addJoinTypeWhere(array $row): array
8654 {
8655 return self::addJoinType($row, self::JOIN_TYPE_WHERE);
8656 }
8657
8658 private static function addJoinTypeGroup(array $row): array
8659 {
8660 return self::addJoinType($row, self::JOIN_TYPE_GROUP);
8661 }
8662
8663 private static function addJoinTypeOrder(array $row): array
8664 {
8665 return self::addJoinType($row, self::JOIN_TYPE_ORDER);
8666 }
8667}
$connection
Определения actionsdefinitions.php:38
$sum
Определения checkout.php:6
$db_res
Определения options_user_settings.php:8
global $APPLICATION
Определения include.php:80
if($canUseYandexMarket) $strWarning
Определения options.php:74
static getTableName()
Определения elementtable.php:83
const PROPERTY_STORAGE_COMMON
Определения iblocktable.php:84
const RIGHTS_EXTENDED
Определения iblocktable.php:88
const PROPERTY_STORAGE_SEPARATE
Определения iblocktable.php:85
const RIGHTS_SIMPLE
Определения iblocktable.php:87
static deleteElementIndex($iblockId, $elementId)
Определения manager.php:237
static updateElementIndex($iblockId, $elementId)
Определения manager.php:264
static resolveElement($iblockId, $elementId)
Определения manager.php:60
const TYPE_ELEMENT
Определения propertytable.php:68
const TYPE_FILE
Определения propertytable.php:67
const TYPE_LIST
Определения propertytable.php:70
const TYPE_NUMBER
Определения propertytable.php:66
static makeFileName(\Bitrix\Iblock\InheritedProperty\BaseTemplate $ipropTemplates, string $templateName, array $fields, array $file)
Определения helper.php:136
static getConnection($name="")
Определения application.php:638
static get($moduleId, $name, $default="", $siteId=false)
Определения option.php:30
Определения loader.php:13
static includeModule($moduleName)
Определения loader.php:67
static isModuleInstalled($moduleName)
Определения modulemanager.php:125
static cleanCache()
Определения datamanager.php:1983
static getRow(array $parameters)
Определения datamanager.php:398
static getList(array $parameters=array())
Определения datamanager.php:431
static normalizeArrayValuesByInt(&$map, $sorted=true)
Определения collection.php:150
static sortByColumn(array &$array, $columns, $callbacks='', $defaultValueIfNotSetValue=null, $preserveKeys=false)
Определения collection.php:24
toString(Context\Culture $culture=null)
Определения datetime.php:86
Определения access.php:15
getLastError()
Определения iblockelement.php:8607
static __GetFileContent($FILE_ID)
Определения iblockelement.php:5991
static useCountJoin(array $row)
Определения iblockelement.php:8632
static WF_Lock($lastId, $bWorkFlow=true)
Определения iblockelement.php:794
static __GetDescriptionUpdateSql($iblock_id, $property_id, $description=false)
Определения iblockelement.php:8090
__construct()
Определения iblockelement.php:89
$iblock
Определения iblockelement.php:71
static GetPropertyValues($IBLOCK_ID, $arElementFilter, $extMode=false, $propertyFilter=array())
Определения iblockelement.php:6325
$bDistinct
Определения iblockelement.php:43
$arIBlockMultProps
Определения iblockelement.php:47
static WF_Restore($ID)
Определения iblockelement.php:186
static GetElementGroups($ID, $bElementOnly=false, $arSelect=array())
Определения iblockelement.php:5618
$indexedProperties
Определения iblockelement.php:74
static WF_CleanUpHistoryCopies($ELEMENT_ID=false, $HISTORY_COPIES=false)
Определения iblockelement.php:506
setIblock(?int $iblockId)
Определения iblockelement.php:104
getUniqueMnemonicCode(string $code, ?int $elementId, int $iblockId, array $options=[])
Определения iblockelement.php:8464
static WF_GetLockStatus($ID, &$locked_by, &$date_lock)
Определения iblockelement.php:741
$sGroupBy
Определения iblockelement.php:56
CheckFields(&$arFields, $ID=false, $bCheckDiskQuota=true)
Определения iblockelement.php:4991
$bizprocInstalled
Определения iblockelement.php:64
static Delete($ID)
Определения iblockelement.php:4684
static WF_GetStatusTitle($STATUS_ID)
Определения iblockelement.php:625
$sSelect
Определения iblockelement.php:53
static SetPropertyValueCode($ELEMENT_ID, $PROPERTY_CODE, $PROPERTY_VALUE)
Определения iblockelement.php:5607
WF_SetMove($NEW_ID, $OLD_ID=0)
Определения iblockelement.php:283
static GetRealElement($ID)
Определения iblockelement.php:603
MkPropertySelect($PR_ID, $db_prop, &$arJoinProps, $bWasGroup, $sGroupBy, &$sSelect, $bSort=false)
Определения iblockelement.php:2567
static WF_GetCurrentStatus($ELEMENT_ID, &$STATUS_TITLE)
Определения iblockelement.php:645
static WF_GetLast($ID)
Определения iblockelement.php:568
string $countFrom
Определения iblockelement.php:58
const WORKFLOW_STATUS_CURRENT_LOCK
Определения iblockelement.php:25
static getIblockLanguage(int $iblockId)
Определения iblockelement.php:8583
$searchIncluded
Определения iblockelement.php:65
static DeleteFile($FILE_ID, $ELEMENT_ID, $TYPE=false, $PARENT_ID=-1, $IBLOCK_ID=false, $bCheckOnly=false)
Определения iblockelement.php:4500
static SetPropertyValuesEx($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $FLAGS=[])
Определения iblockelement.php:7223
CancelWFSetMove()
Определения iblockelement.php:181
$arFilterIBlocks
Определения iblockelement.php:46
static GetIBlockByID($ID)
Определения iblockelement.php:4930
static GetIBlockByIDList(array $list)
Определения iblockelement.php:4954
static GetByID($ID)
Определения iblockelement.php:4919
$offerProperties
Определения iblockelement.php:76
$userExists
Определения iblockelement.php:67
MkPropertyFilter($res, $cOperationType, $propVAL, $db_prop, &$arJoinProps, &$arSqlSearch)
Определения iblockelement.php:2009
static WF_IsLocked($ID, &$locked_by, &$date_lock)
Определения iblockelement.php:728
const WORKFLOW_STATUS_LOCK
Определения iblockelement.php:26
$arIBlockLongProps
Определения iblockelement.php:51
getIndexedProperties(int $iblockId)
Определения iblockelement.php:8325
getPropertiesByFilter(array $filter)
Определения iblockelement.php:8287
MkPropertyGroup($db_prop, &$arJoinProps, $bSort=false)
Определения iblockelement.php:2504
static RecalcSections($ID, $sectionId=null)
Определения iblockelement.php:5731
$workflowIncluded
Определения iblockelement.php:63
getSearchableContent(int $id, array $fields, array $iblock)
Определения iblockelement.php:8137
$catalogIncluded
Определения iblockelement.php:62
static GetPropertyValuesArray(&$result, $iblockID, $filter, $propertyFilter=array(), $options=array())
Определения iblockelement.php:6383
$userId
Определения iblockelement.php:68
MkPropertyOrder($by, $order, $bSort, $db_prop, &$arJoinProps, &$arSqlOrder)
Определения iblockelement.php:2257
static getSingleIblockIdFromFilter(array $filter)
Определения iblockelement.php:1025
static WF_CleanUpHistory()
Определения iblockelement.php:240
static SubQuery($strField, $arFilter)
Определения iblockelement.php:130
string $LAST_ERROR
Определения iblockelement.php:35
static WF_GetHistoryList($ELEMENT_ID, $by='s_id', $order='desc', $arFilter=[])
Определения iblockelement.php:936
PrepareGetList(&$arIblockElementFields, &$arJoinProps, &$arSelectFields, &$sSelect, &$arAddSelectFields, &$arFilter, &$sWhere, &$sSectionWhere, &$arAddWhereFields, &$arGroupBy, &$sGroupBy, &$arOrder, &$arSqlOrder, &$arAddOrderByFields)
Определения iblockelement.php:3284
$arFilter
Определения iblockelement.php:40
static WF_GetStatusPermission($STATUS_ID, $ID=false)
Определения iblockelement.php:677
createMnemonicCode(array $element, array $options=[])
Определения iblockelement.php:8519
$bCatalogSort
Определения iblockelement.php:44
$arIBlockConvProps
Определения iblockelement.php:48
isExistsMnemonicCode(string $code, ?int $elementId, int $iblockId)
Определения iblockelement.php:8442
static SetElementSection($ID, $arSections, $bNew=false, $bRightsIBlock=0, $sectionId=null)
Определения iblockelement.php:5847
$bOnlyCount
Определения iblockelement.php:42
Add($arFields, $bWorkFlow=false, $bUpdateSearch=true, $bResizePictures=false)
Определения iblockelement.php:3895
static CounterInc($ID)
Определения iblockelement.php:7149
$iblockLanguage
Определения iblockelement.php:72
$arIBlockNumProps
Определения iblockelement.php:50
$strField
Определения iblockelement.php:38
static WF_GetSqlLimit($PS="BE.", $SHOW_NEW="N")
Определения iblockelement.php:550
static $elementIblock
Определения iblockelement.php:60
getIdOrder($order)
Определения iblockelement.php:8112
$arIBlockAllProps
Определения iblockelement.php:49
static DeletePropertySQL($property, $iblock_element_id)
Определения iblockelement.php:7181
static GetIBVersion($iblock_id)
Определения iblockelement.php:7172
getOfferProperties(int $iblockId)
Определения iblockelement.php:8346
generateMnemonicCode(string $name, int $iblockId, array $options=[])
Определения iblockelement.php:8381
bool $isAdmin
Определения iblockelement.php:69
static getPublicElementsOrmFilter(array $filter)
Определения iblockelement.php:8599
$sOrderBy
Определения iblockelement.php:57
static GetProperty($IBLOCK_ID, $ELEMENT_ID, $by="sort", $order="asc", $arFilter=Array())
Определения iblockelement.php:6924
static _check_rights_sql($min_permission, $permissionsBy=null)
Определения iblockelement.php:8080
static WF_UnLock($lastId, $bWorkFlow=true)
Определения iblockelement.php:854
const WORKFLOW_STATUS_UNLOCK
Определения iblockelement.php:24
static UpdateSearch($ID, $bOverWrite=false)
Определения iblockelement.php:6020
static getCheckRightsSql(?int $iblockId, string $minPermission, ?int $permissionsBy=null)
Определения iblockelement.php:7924
$bWF_SetMove
Определения iblockelement.php:36
__InitFile($old_id, &$arFields, $fname)
Определения iblockelement.php:5967
$subQueryProp
Определения iblockelement.php:39
$sWhere
Определения iblockelement.php:55
MkAlias($max_alias_len, $alias, &$arIBlockLongProps)
Определения iblockelement.php:3207
static MkOperationFilter($key)
Определения iblock.php:2522
static FilterCreateEx($fname, $vals, $type, &$bFullJoin, $cOperationType=false, $bSkipEmpty=true)
Определения iblock.php:2581
static _MergeIBArrays($iblock_id, $iblock_code=false, $iblock_id2=false, $iblock_code2=false)
Определения iblock.php:2929
static GetPropertyArray($ID, $IBLOCK_ID, $bCached=true)
Определения iblockproperty.php:807
static DeleteIndex($MODULE_ID, $ITEM_ID=false, $PARAM1=false, $PARAM2=false, $SITE_ID=false)
Определения search.php:2922
static KillTags($str)
Определения search.php:2092
static Index($MODULE_ID, $ITEM_ID, $arFields, $bOverWrite=false, $SEARCH_SESS_ID='')
Определения search.php:1302
static GetInstance()
Определения virtual_io.php:60
Определения quota.php:6
static recalculateDb(bool $mode=true)
Определения quota.php:29
static Log($SEVERITY, $AUDIT_TYPE_ID, $MODULE_ID, $ITEM_ID, $DESCRIPTION=false, $SITE_ID=false)
Определения event_log.php:32
Определения iblockelement.php:9
prepareSql($arSelectFields=array(), $arFilter=array(), $arGroupBy=false, $arOrder=array("SORT"=>"ASC"))
Определения iblockelement.php:10
static GetByID($ID)
Определения iblockpropertyenum.php:217
Определения iblockresult.php:3
const PUBLIC_READ
Определения iblock_rights.php:17
static isValidField(string $field)
Определения querybuilder.php:95
Определения user.php:6037
static IsAdmin()
Определения workflow.php:455
if(!\Bitrix\Main\Loader::includeModule('clouds')) $lastId
Определения sync.php:68
$right
Определения options.php:8
$options
Определения commerceml2.php:49
$str
Определения commerceml2.php:63
$f
Определения component_props.php:52
$arFields
Определения dblapprove.php:5
$new
Определения file_edit.php:48
$arr
Определения file_new.php:624
</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
$zr
Определения options.php:5
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$getRawData
Определения get_user.php:21
if($ajaxMode) $ID
Определения get_user.php:27
$p
Определения group_list_element_edit.php:23
$elementID
Определения group_wiki_post_comment.php:17
if(Loader::includeModule( 'bitrix24')) elseif(Loader::includeModule('intranet') &&CIntranetUtils::getPortalZone() !=='ru') $description
Определения .description.php:24
$uid
Определения hot_keys_act.php:8
global $BX_IBLOCK_PROP_CACHE
Определения iblockelement.php:17
global $IBLOCK_ACTIVE_DATE_FORMAT
Определения iblockelement.php:15
global $ar_IBLOCK_SITE_FILTER_CACHE
Определения iblockelement.php:19
$iblockId
Определения iblock_catalog_edit.php:30
$catalog
Определения iblock_catalog_edit.php:135
$filter
Определения iblock_catalog_list.php:54
$selectFields
Определения iblock_catalog_list.php:160
$output
Определения options.php:436
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $DB
Определения cron_frame.php:29
$IBLOCK_ID
Определения csv_new_run.php:168
global $USER
Определения csv_new_run.php:40
$io
Определения csv_new_run.php:98
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
const SITE_DIR(!defined('LANG'))
Определения include.php:72
$groups
Определения options.php:30
$z
Определения options.php:31
CheckDirPath($path)
Определения tools.php:2707
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
IsModuleInstalled($module_id)
Определения tools.php:5301
HasScriptExtension($check_name)
Определения tools.php:2956
FmtDate($str_date, $format=false, $site=false, $bSearchInSitesOnly=false)
Определения tools.php:745
htmlspecialcharsEx($str)
Определения tools.php:2685
HTMLToTxt($str, $strSiteUrl="", $aDelete=[], $maxlen=70)
Определения tools.php:2587
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
Rel2Abs($curdir, $relpath)
Определения tools.php:3297
is_set($a, $k=false)
Определения tools.php:2133
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$name
Определения menu_edit.php:35
if(!function_exists(__NAMESPACE__.'\\___972068685'))
Определения license.php:1
$table
Определения mysql_to_pgsql.php:36
$order
Определения payment.php:8
$bError
Определения result_rec.php:46
$settings
Определения product_settings.php:43
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
$config
Определения quickway.php:69
if(empty($signedUserToken)) $key
Определения quickway.php:257
$TYPE
Определения rss.php:27
$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
$props
Определения template.php:269
else $a
Определения template.php:137
$val
Определения options.php:1793
tags_prepare($sText, $site_id=false)
Определения tags.php:4
$error
Определения subscription_card_product.php:20
$rs
Определения action.php:82
$k
Определения template_pdf.php:567
$n
Определения update_log.php:107
$arFilter
Определения user_search.php:106
switch( $_REQUEST[ 'bxsender'])().Authorize(<? break
Определения wrapper_popup.php:7
$arIBlock['PROPERTY']
Определения yandex_detail.php:172
$arSections
Определения yandex_run.php:805
$iterator
Определения yandex_run.php:610
$fields
Определения yandex_run.php:501
if( $site[ 'SERVER_NAME']==='') if($site['SERVER_NAME']==='') $arProperties
Определения yandex_run.php:644