Ejemplo n.º 1
0
 function MkFilter($arFilter, &$arJoinProps, &$arAddWhereFields, $level = 0, $bPropertyLeftJoin = false)
 {
     global $DB, $USER;
     $arSqlSearch = array();
     $permSQL = "";
     $arSectionFilter = array("LOGIC" => "", "BE" => array(), "BS" => array());
     $strSqlSearch = "";
     if (!is_array($arFilter)) {
         $arFilter = array();
     }
     foreach ($arFilter as $key => $val) {
         $key = strtoupper($key);
         $p = strpos($key, "PROPERTY_");
         if ($p !== false && $p < 4) {
             $arFilter[substr($key, 0, $p) . "PROPERTY"][substr($key, $p + 9)] = $val;
             unset($arFilter[$key]);
         }
     }
     if (array_key_exists("LOGIC", $arFilter) && $arFilter["LOGIC"] == "OR") {
         $Logic = "OR";
         unset($arFilter["LOGIC"]);
         $bPropertyLeftJoin = true;
     } else {
         $Logic = "AND";
     }
     if ($Logic === "AND" && $level === 0) {
         $f = new \Bitrix\Iblock\PropertyIndex\QueryBuilder($arFilter["IBLOCK_ID"]);
         if ($f->isValid()) {
             $arJoinProps["FC"] = $f->getFilterSql($arFilter, $arSqlSearch);
             $arJoinProps["FC_DISTINCT"] = $f->getDistinct();
         }
     }
     foreach ($arFilter as $orig_key => $val) {
         $res = CIBlock::MkOperationFilter($orig_key);
         $key = $res["FIELD"];
         $cOperationType = $res["OPERATION"];
         //it was done before $key = strtoupper($key);
         switch ($key . "") {
             case "ACTIVE":
             case "DETAIL_TEXT_TYPE":
             case "PREVIEW_TEXT_TYPE":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "string_equal", $bFullJoinTmp, $cOperationType);
                 break;
             case "NAME":
             case "XML_ID":
             case "TMP_ID":
             case "DETAIL_TEXT":
             case "SEARCHABLE_CONTENT":
             case "PREVIEW_TEXT":
             case "CODE":
             case "TAGS":
             case "WF_COMMENTS":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "string", $bFullJoinTmp, $cOperationType);
                 break;
             case "ID":
                 if (is_object($val)) {
                     $arSqlSearch[] = $val->_sql_in("BE." . $key, $cOperationType);
                 } else {
                     $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "number", $bFullJoinTmp, $cOperationType);
                 }
                 break;
             case "SHOW_COUNTER":
             case "WF_PARENT_ELEMENT_ID":
             case "WF_STATUS_ID":
             case "SORT":
             case "CREATED_BY":
             case "PREVIEW_PICTURE":
             case "DETAIL_PICTURE":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "number", $bFullJoinTmp, $cOperationType);
                 break;
             case "IBLOCK_ID":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "number", $bFullJoinTmp, $cOperationType);
                 break;
             case "TIMESTAMP_X":
             case "DATE_CREATE":
             case "SHOW_COUNTER_START":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE." . $key, $val, "date", $bFullJoinTmp, $cOperationType);
                 break;
             case "EXTERNAL_ID":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.XML_ID", $val, "string", $bFullJoinTmp, $cOperationType);
                 break;
             case "IBLOCK_TYPE":
                 $flt = CIBlock::FilterCreateEx("B.IBLOCK_TYPE_ID", $val, "string", $bFullJoinTmp, $cOperationType);
                 $arSqlSearch[] = $flt;
                 break;
             case "CHECK_PERMISSIONS":
                 if ($val == "Y" && (!is_object($USER) || !$USER->IsAdmin())) {
                     $permSQL = CIBlockElement::_check_rights_sql($arFilter["MIN_PERMISSION"]);
                 }
                 break;
             case "CHECK_BP_PERMISSIONS":
                 if (IsModuleInstalled('bizproc') && (!is_object($USER) || !$USER->IsAdmin())) {
                     if (is_array($val)) {
                         $MODULE_ID = $DB->ForSQL($val["MODULE_ID"]);
                         $ENTITY = $DB->ForSQL($val["ENTITY"]);
                         $PERMISSION = $DB->ForSQL($val["PERMISSION"]);
                         $arUserGroups = array();
                         if (is_array($val["GROUPS"])) {
                             $USER_ID = intval($val["USER_ID"]);
                             foreach ($val["GROUPS"] as $GROUP_ID) {
                                 $GROUP_ID = intval($GROUP_ID);
                                 if ($GROUP_ID) {
                                     $arUserGroups[$GROUP_ID] = $GROUP_ID;
                                 }
                             }
                         } else {
                             $USER_ID = 0;
                         }
                     } else {
                         $MODULE_ID = "iblock";
                         $ENTITY = "CIBlockDocument";
                         $PERMISSION = $val;
                         $arUserGroups = false;
                         $USER_ID = 0;
                     }
                     if ($PERMISSION == "read" || $PERMISSION == "write") {
                         if (!is_array($arUserGroups) && is_object($USER)) {
                             $USER_ID = intval($USER->GetID());
                             $arUserGroups = $USER->GetUserGroupArray();
                         }
                         if (!is_array($arUserGroups) || count($arUserGroups) <= 0) {
                             $arUserGroups = array(2);
                         }
                         $arSqlSearch[] = "EXISTS (\n\t\t\t\t\t\t\tSELECT S.DOCUMENT_ID_INT\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\tb_bp_workflow_state S\n\t\t\t\t\t\t\tINNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\tS.DOCUMENT_ID_INT = BE.ID\n\t\t\t\t\t\t\t\tAND S.MODULE_ID = '{$MODULE_ID}'\n\t\t\t\t\t\t\t\tAND S.ENTITY = '{$ENTITY}'\n\t\t\t\t\t\t\t\tAND P.PERMISSION = '{$PERMISSION}'\n\t\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t\tP.OBJECT_ID IN ('" . implode("', '", $arUserGroups) . "')\n\t\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = {$USER_ID})\n\t\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = " . $DB->Concat("'USER_'", "'{$USER_ID}'") . ")\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)";
                     }
                 }
                 break;
             case "CHECK_BP_TASKS_PERMISSIONS":
                 if (IsModuleInstalled('bizproc') && CModule::IncludeModule("socialnetwork") && (!is_object($USER) || !$USER->IsAdmin())) {
                     $val = explode("_", $val);
                     $taskType = $val[0];
                     if (!in_array($taskType, array("user", "group"))) {
                         $taskType = "user";
                     }
                     $ownerId = intval($val[1]);
                     $val = $val[2];
                     if (!in_array($val, array("read", "write", "comment"))) {
                         $val = "write";
                     }
                     $userId = is_object($USER) ? intval($USER->GetID()) : 0;
                     $arUserGroups = array();
                     if ($taskType == "group") {
                         $r = CSocNetFeaturesPerms::CanPerformOperation($userId, SONET_ENTITY_GROUP, $ownerId, "tasks", $val == "write" ? "edit_tasks" : "view_all");
                         if ($r) {
                             break;
                         }
                         $arUserGroups[] = SONET_ROLES_ALL;
                         $r = CSocNetUserToGroup::GetUserRole($userId, $ownerId);
                         if (strlen($r) > 0) {
                             $arUserGroups[] = $r;
                         }
                     } else {
                         //						$arUserGroups[] = SONET_RELATIONS_TYPE_ALL;
                         //						if (CSocNetUserRelations::IsFriends($userId, $ownerId))
                         //							$arUserGroups[] = SONET_RELATIONS_TYPE_FRIENDS;
                         //						elseif (CSocNetUserRelations::IsFriends2($userId, $ownerId))
                         //							$arUserGroups[] = SONET_RELATIONS_TYPE_FRIENDS2;
                     }
                     $arSqlSearch[] = "EXISTS (\n\t\t\t\t\t\tSELECT S.DOCUMENT_ID_INT\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\tb_bp_workflow_state S\n\t\t\t\t\t\tINNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tS.DOCUMENT_ID_INT = BE.ID\n\t\t\t\t\t\t\tAND S.MODULE_ID = 'intranet'\n\t\t\t\t\t\t\tAND S.ENTITY = 'CIntranetTasksDocument'\n\t\t\t\t\t\t\tAND P.PERMISSION = '" . $val . "'\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t" . ($taskType == "group" ? "P.OBJECT_ID IN ('" . implode("', '", $arUserGroups) . "') OR" : "") . "\n\t\t\t\t\t\t\t\t(P.OBJECT_ID = 'author' AND BE.CREATED_BY = " . $userId . ")\n\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = 'responsible' AND " . $userId . " IN (\n\t\t\t\t\t\t\t\t\tSELECT SFPV0.VALUE_NUM\n\t\t\t\t\t\t\t\t\tFROM b_iblock_element_property SFPV0\n\t\t\t\t\t\t\t\t\t\tINNER JOIN b_iblock_property SFP0 ON (SFPV0.IBLOCK_PROPERTY_ID = SFP0.ID)\n\t\t\t\t\t\t\t\t\tWHERE " . CIBlock::_Upper("SFP0.CODE") . "='TASKASSIGNEDTO'\n\t\t\t\t\t\t\t\t\t\tAND SFP0.IBLOCK_ID = BE.IBLOCK_ID\n\t\t\t\t\t\t\t\t\t\tAND SFPV0.IBLOCK_ELEMENT_ID = BE.ID\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = 'trackers' AND " . $userId . " IN (\n\t\t\t\t\t\t\t\t\tSELECT SFPV0.VALUE_NUM\n\t\t\t\t\t\t\t\t\tFROM b_iblock_element_property SFPV0\n\t\t\t\t\t\t\t\t\t\tINNER JOIN b_iblock_property SFP0 ON (SFPV0.IBLOCK_PROPERTY_ID = SFP0.ID)\n\t\t\t\t\t\t\t\t\tWHERE " . CIBlock::_Upper("SFP0.CODE") . "='TASKTRACKERS'\n\t\t\t\t\t\t\t\t\t\tAND SFP0.IBLOCK_ID = BE.IBLOCK_ID\n\t\t\t\t\t\t\t\t\t\tAND SFPV0.IBLOCK_ELEMENT_ID = BE.ID\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = '" . ("USER_" . $userId) . "')\n\t\t\t\t\t\t\t)\n\t\t\t\t\t)";
                 }
                 break;
             case "CHECK_BP_VIRTUAL_PERMISSIONS":
                 if (IsModuleInstalled('bizproc') && (!is_object($USER) || !$USER->IsAdmin())) {
                     if (!in_array($val, array("read", "create", "admin"))) {
                         $val = "admin";
                     }
                     $userId = is_object($USER) ? intval($USER->GetID()) : 0;
                     if (is_object($USER)) {
                         $arUserGroups = $USER->GetUserGroupArray();
                     }
                     if (!is_array($arUserGroups) || count($arUserGroups) <= 0) {
                         $arUserGroups = array(2);
                     }
                     $arSqlSearch[] = "EXISTS (\n\t\t\t\t\t\tSELECT S.DOCUMENT_ID_INT\n\t\t\t\t\t\tFROM b_bp_workflow_state S\n\t\t\t\t\t\t\tINNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID\n\t\t\t\t\t\tWHERE S.DOCUMENT_ID_INT = BE.ID\n\t\t\t\t\t\t\tAND S.MODULE_ID = 'bizproc'\n\t\t\t\t\t\t\tAND S.ENTITY = 'CBPVirtualDocument'\n\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\t(P.PERMISSION = '" . $val . "'\n\t\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t\tP.OBJECT_ID IN ('" . implode("', '", $arUserGroups) . "')\n\t\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = " . $userId . ")\n\t\t\t\t\t\t\t\t\tOR (P.OBJECT_ID = " . $DB->Concat("'USER_'", "'" . $userId . "'") . ")\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t)";
                 }
                 break;
             case "TASKSTATUS":
                 if (IsModuleInstalled('bizproc')) {
                     $arSqlSearch[] = ($cOperationType == "N" ? "NOT " : "") . "EXISTS (\n\t\t\t\t\t\tSELECT S.DOCUMENT_ID_INT\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\tb_bp_workflow_state S\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tS.DOCUMENT_ID_INT = BE.ID\n\t\t\t\t\t\t\tAND S.MODULE_ID = 'intranet'\n\t\t\t\t\t\t\tAND S.ENTITY = 'CIntranetTasksDocument'\n\t\t\t\t\t\t\tAND S.STATE = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t)";
                 }
                 break;
             case "LID":
             case "SITE_ID":
             case "IBLOCK_LID":
             case "IBLOCK_SITE_ID":
                 $flt = CIBlock::FilterCreateEx("SITE_ID", $val, "string_equal", $bFullJoinTmp, $cOperationType);
                 if (strlen($flt)) {
                     $arSqlSearch[] = ($cOperationType == "N" ? "NOT " : "") . "EXISTS (\n\t\t\t\t\t\tSELECT IBLOCK_ID FROM b_iblock_site WHERE IBLOCK_ID = B.ID\n\t\t\t\t\t\tAND " . $flt . "\n\t\t\t\t\t)";
                 }
                 break;
             case "DATE_ACTIVE_FROM":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ACTIVE_FROM", $val, "date", $bFullJoinTmp, $cOperationType);
                 break;
             case "DATE_ACTIVE_TO":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ACTIVE_TO", $val, "date", $bFullJoinTmp, $cOperationType);
                 break;
             case "IBLOCK_ACTIVE":
                 $flt = CIBlock::FilterCreateEx("B.ACTIVE", $val, "string_equal", $bFullJoinTmp, $cOperationType);
                 $arSqlSearch[] = $flt;
                 break;
             case "IBLOCK_CODE":
                 $flt = CIBlock::FilterCreateEx("B.CODE", $val, "string", $bFullJoinTmp, $cOperationType);
                 $arSqlSearch[] = $flt;
                 break;
             case "ID_ABOVE":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ID", $val, "number_above", $bFullJoinTmp, $cOperationType);
                 break;
             case "ID_LESS":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.ID", $val, "number_less", $bFullJoinTmp, $cOperationType);
                 break;
             case "ACTIVE_FROM":
                 if (strlen($val) > 0) {
                     $arSqlSearch[] = "(BE.ACTIVE_FROM " . ($cOperationType == "N" ? "<" : ">=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") . ($cOperationType == "N" ? "" : " OR BE.ACTIVE_FROM IS NULL") . ")";
                 }
                 break;
             case "ACTIVE_TO":
                 if (strlen($val) > 0) {
                     $arSqlSearch[] = "(BE.ACTIVE_TO " . ($cOperationType == "N" ? ">" : "<=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") . ($cOperationType == "N" ? "" : " OR BE.ACTIVE_TO IS NULL") . ")";
                 }
                 break;
             case "ACTIVE_DATE":
                 if (strlen($val) > 0) {
                     $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))";
                 }
                 break;
             case "DATE_MODIFY_FROM":
                 if (strlen($val) > 0) {
                     $arSqlSearch[] = "(BE.TIMESTAMP_X " . ($cOperationType == "N" ? "<" : ">=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") . ($cOperationType == "N" ? "" : " OR BE.TIMESTAMP_X IS NULL") . ")";
                 }
                 break;
             case "DATE_MODIFY_TO":
                 if (strlen($val) > 0) {
                     $arSqlSearch[] = "(BE.TIMESTAMP_X " . ($cOperationType == "N" ? ">" : "<=") . $DB->CharToDateFunction($DB->ForSql($val), "FULL") . ($cOperationType == "N" ? "" : " OR BE.TIMESTAMP_X IS NULL") . ")";
                 }
                 break;
             case "WF_NEW":
                 if ($val == "Y" || $val == "N") {
                     $arSqlSearch[] = CIBlock::FilterCreateEx("BE.WF_NEW", "Y", "string_equal", $bFullJoinTmp, $val == "Y" ? false : true, false);
                 }
                 break;
             case "MODIFIED_USER_ID":
             case "MODIFIED_BY":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.MODIFIED_BY", $val, "number", $bFullJoinTmp, $cOperationType);
                 break;
             case "CREATED_USER_ID":
             case "CREATED_BY":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.CREATED_BY", $val, "number", $bFullJoinTmp, $cOperationType);
                 break;
             case "RATING_USER_ID":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("RVV.USER_ID", $val, "number", $bFullJoinTmp, $cOperationType);
                 $arJoinProps["RVV"] = array("bFullJoin" => $bFullJoinTmp);
                 break;
             case "WF_STATUS":
                 $arSqlSearch[] = CIBlock::FilterCreateEx("BE.WF_STATUS_ID", $val, "number", $bFullJoinTmp, $cOperationType);
                 break;
             case "WF_LOCK_STATUS":
                 if (strlen($val) > 0) {
                     $USER_ID = is_object($USER) ? intval($USER->GetID()) : 0;
                     $arSqlSearch[] = " if(BE.WF_DATE_LOCK is null, 'green', if(DATE_ADD(BE.WF_DATE_LOCK, interval " . COption::GetOptionInt("workflow", "MAX_LOCK_TIME", 60) . " MINUTE)<now(), 'green', if(BE.WF_LOCKED_BY=" . $USER_ID . ", 'yellow', 'red'))) = '" . $DB->ForSql($val) . "'";
                 }
                 break;
             case "WF_LAST_STATUS_ID":
                 $arSqlSearch[] = "exists (\n\t\t\t\t\tselect\n\t\t\t\t\t\thistory.ID\n\t\t\t\t\tfrom\n\t\t\t\t\t\tb_iblock_element history\n\t\t\t\t\twhere\n\t\t\t\t\t\thistory.WF_PARENT_ELEMENT_ID = BE.ID\n\t\t\t\t\t\tand history.WF_STATUS_ID = " . intval($val) . "\n\t\t\t\t\t\tand history.ID = (\n\t\t\t\t\t\t\tselect max(history0.ID) LAST_ID\n\t\t\t\t\t\t\tfrom b_iblock_element history0\n\t\t\t\t\t\t\twhere history0.WF_PARENT_ELEMENT_ID = BE.ID\n\t\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t\t";
                 break;
             case "SECTION_ACTIVE":
                 if ($arFilter["INCLUDE_SUBSECTIONS"] === "Y") {
                     $arSectionFilter["BS"][] = "BSubS.ACTIVE = 'Y'";
                 } else {
                     $arSectionFilter["BS"][] = "BS.ACTIVE = 'Y'";
                 }
                 break;
             case "SECTION_GLOBAL_ACTIVE":
                 if ($arFilter["INCLUDE_SUBSECTIONS"] === "Y") {
                     $arSectionFilter["BS"][] = "BSubS.GLOBAL_ACTIVE = 'Y'";
                 } else {
                     $arSectionFilter["BS"][] = "BS.GLOBAL_ACTIVE = 'Y'";
                 }
                 break;
             case "SUBSECTION":
                 if (!is_array($val)) {
                     $val = array($val);
                 }
                 //Find out margins of sections
                 $arUnknownMargins = array();
                 foreach ($val as $i => $section) {
                     if (!is_array($section)) {
                         $arUnknownMargins[intval($section)] = intval($section);
                     }
                 }
                 if (count($arUnknownMargins) > 0) {
                     $rs = $DB->Query("SELECT ID, LEFT_MARGIN, RIGHT_MARGIN FROM b_iblock_section WHERE ID in (" . implode(", ", $arUnknownMargins) . ")");
                     while ($ar = $rs->Fetch()) {
                         $arUnknownMargins[intval($ar["ID"])] = array(intval($ar["LEFT_MARGIN"]), intval($ar["RIGHT_MARGIN"]));
                     }
                     foreach ($val as $i => $section) {
                         if (!is_array($section)) {
                             $val[$i] = $arUnknownMargins[intval($section)];
                         }
                     }
                 }
                 //Now sort them out
                 $arMargins = array();
                 foreach ($val as $i => $section) {
                     if (is_array($section) && count($section) == 2) {
                         $left = intval($section[0]);
                         $right = intval($section[1]);
                         if ($left > 0 && $right > 0) {
                             $arMargins[$left] = $right;
                         }
                     }
                 }
                 ksort($arMargins);
                 //Remove subsubsections of the sections
                 $prev_right = 0;
                 foreach ($arMargins as $left => $right) {
                     if ($right <= $prev_right) {
                         unset($arMargins[$left]);
                     } else {
                         $prev_right = $right;
                     }
                 }
                 if (isset($arFilter["INCLUDE_SUBSECTIONS"]) && $arFilter["INCLUDE_SUBSECTIONS"] === "Y") {
                     $bsAlias = "BSubS";
                 } else {
                     $bsAlias = "BS";
                 }
                 $res = "";
                 foreach ($arMargins as $left => $right) {
                     if ($res != "") {
                         $res .= $cOperationType == "N" ? " AND " : " OR ";
                     }
                     $res .= ($cOperationType == "N" ? " NOT " : " ") . "({$bsAlias}.LEFT_MARGIN >= " . $left . " AND {$bsAlias}.RIGHT_MARGIN <= " . $right . ")\n";
                 }
                 if ($res != "") {
                     $arSectionFilter["BS"][] = "(" . $res . ")";
                 }
                 break;
             case "SECTION_ID":
                 if (!is_array($val)) {
                     $val = array($val);
                 }
                 $arSections = array();
                 foreach ($val as $section_id) {
                     $section_id = intval($section_id);
                     $arSections[$section_id] = $section_id;
                 }
                 if ($cOperationType == "N") {
                     if (array_key_exists(0, $arSections)) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS<>'N'";
                         $arSectionFilter["LOGIC"] = "AND";
                         unset($arSections[0]);
                         if (count($arSections) > 0) {
                             $arSectionFilter["BS"][] = "BS.ID NOT IN (" . implode(", ", $arSections) . ")";
                         }
                     } elseif (count($arSections) > 0) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
                         $arSectionFilter["LOGIC"] = "OR";
                         $arSectionFilter["BS"][] = "BS.ID NOT IN (" . implode(", ", $arSections) . ")";
                     }
                 } else {
                     if (array_key_exists(0, $arSections)) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
                         $arSectionFilter["LOGIC"] = "OR";
                         unset($arSections[0]);
                     }
                     if (count($arSections) > 0) {
                         $arSectionFilter["BS"][] = "BS.ID IN (" . implode(", ", $arSections) . ")";
                     }
                 }
                 break;
             case "SECTION_CODE":
                 if (!is_array($val)) {
                     $val = array($val);
                 }
                 $arSections = array();
                 foreach ($val as $section_code) {
                     $section_code = $DB->ForSql($section_code);
                     $arSections[$section_code] = $section_code;
                 }
                 if ($cOperationType == "N") {
                     if (array_key_exists("", $arSections)) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS<>'N'";
                         $arSectionFilter["LOGIC"] = "AND";
                         unset($arSections[""]);
                         if (count($arSections) > 0) {
                             $arSectionFilter["BS"][] = "BS.CODE NOT IN ('" . implode("', '", $arSections) . "')";
                         }
                     } elseif (count($arSections) > 0) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
                         $arSectionFilter["LOGIC"] = "OR";
                         $arSectionFilter["BS"][] = "BS.CODE NOT IN ('" . implode("', '", $arSections) . "')";
                     }
                 } else {
                     if (array_key_exists("", $arSections)) {
                         $arSectionFilter["BE"][] = "BE.IN_SECTIONS='N'";
                         $arSectionFilter["LOGIC"] = "OR";
                         unset($arSections[""]);
                     }
                     if (count($arSections) > "") {
                         $arSectionFilter["BS"][] = "BS.CODE IN ('" . implode("', '", $arSections) . "')";
                     }
                 }
                 break;
             case "PROPERTY":
                 foreach ($val as $propID => $propVAL) {
                     $res = CIBlock::MkOperationFilter($propID);
                     $res["LOGIC"] = $Logic;
                     $res["LEFT_JOIN"] = $bPropertyLeftJoin;
                     if (preg_match("/^([^.]+)\\.([^.]+)\$/", $res["FIELD"], $arMatch)) {
                         $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"], $arFilter["~IBLOCK_ID"], $arFilter["~IBLOCK_CODE"]));
                         if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E") {
                             $res["FIELD"] = $arMatch;
                             CIBlockElement::MkPropertyFilter($res, $cOperationType, $propVAL, $db_prop, $arJoinProps, $arSqlSearch);
                         }
                     } else {
                         if ($db_prop = CIBlockProperty::GetPropertyArray($res["FIELD"], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"], $arFilter["~IBLOCK_ID"], $arFilter["~IBLOCK_CODE"]))) {
                             CIBlockElement::MkPropertyFilter($res, $cOperationType, $propVAL, $db_prop, $arJoinProps, $arSqlSearch);
                         }
                     }
                 }
                 break;
             default:
                 if (is_numeric($orig_key)) {
                     //Here is hint for better property resolution:
                     if (!is_array($val) || !array_key_exists("~IBLOCK_ID", $val)) {
                         if (array_key_exists("IBLOCK_ID", $arFilter)) {
                             $val["~IBLOCK_ID"] = $arFilter["IBLOCK_ID"];
                         } elseif (array_key_exists("~IBLOCK_ID", $arFilter)) {
                             $val["~IBLOCK_ID"] = $arFilter["~IBLOCK_ID"];
                         }
                     }
                     if (!is_array($val) || !array_key_exists("~IBLOCK_CODE", $val)) {
                         if (array_key_exists("IBLOCK_CODE", $arFilter)) {
                             $val["~IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"];
                         } elseif (array_key_exists("~IBLOCK_CODE", $arFilter)) {
                             $val["~IBLOCK_CODE"] = $arFilter["~IBLOCK_CODE"];
                         }
                     }
                     //Subfilter process
                     $arSubSqlSearch = CIBlockElement::MkFilter($val, $arJoinProps, $arAddWhereFields, $level + 1, $bPropertyLeftJoin);
                     if (strlen(trim($arSubSqlSearch[0], "\n\t"))) {
                         $arSqlSearch[] = str_replace("\n\t\t\t", "\n\t\t\t\t", $arSubSqlSearch[0]);
                     }
                 } elseif (strtoupper(substr($key, 0, 8)) == "CATALOG_" && CModule::IncludeModule("catalog")) {
                     $res_catalog = CCatalogProduct::GetQueryBuildArrays(array(), array($orig_key => $val), array());
                     if (strlen($res_catalog["WHERE"])) {
                         $arSqlSearch[] = substr($res_catalog["WHERE"], 5);
                         // " AND ".$res
                         $arAddWhereFields[$orig_key] = $val;
                     }
                 }
                 break;
         }
     }
     //SECTION sub filter
     $sWhere = "";
     foreach ($arSectionFilter["BS"] as $strFilter) {
         if (strlen($strFilter)) {
             if (strlen($sWhere)) {
                 $sWhere .= " " . $Logic . " ";
             }
             $sWhere .= "(" . $strFilter . ")";
         }
     }
     $bINCLUDE_SUBSECTIONS = isset($arFilter["INCLUDE_SUBSECTIONS"]) && $arFilter["INCLUDE_SUBSECTIONS"] === "Y";
     if (strlen($sWhere)) {
         $sectionScope = "";
         if (isset($arFilter["SECTION_SCOPE"])) {
             if ($arFilter["SECTION_SCOPE"] == "IBLOCK") {
                 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID IS NULL";
             } elseif ($arFilter["SECTION_SCOPE"] == "PROPERTY") {
                 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID IS NOT NULL";
             } elseif (preg_match("/^PROPERTY_(\\d+)\$/", $arFilter["SECTION_SCOPE"], $match)) {
                 $sectionScope = "AND BSE.ADDITIONAL_PROPERTY_ID = " . $match[1];
             }
         }
         //Try to convert correlated subquery to join subquery
         if ($level == 0 && $Logic == "AND" && !count($arSectionFilter["BE"])) {
             $arJoinProps["BES"] .= " INNER JOIN (\n\t\t\t\t\tSELECT DISTINCT BSE.IBLOCK_ELEMENT_ID\n\t\t\t\t\tFROM b_iblock_section_element BSE\n\t\t\t\t\t" . ($bINCLUDE_SUBSECTIONS ? "\n\t\t\t\t\tINNER JOIN b_iblock_section BSubS ON BSE.IBLOCK_SECTION_ID = BSubS.ID\n\t\t\t\t\tINNER JOIN b_iblock_section BS ON (BSubS.IBLOCK_ID=BS.IBLOCK_ID\n\t\t\t\t\t\tAND BSubS.LEFT_MARGIN>=BS.LEFT_MARGIN\n\t\t\t\t\t\tAND BSubS.RIGHT_MARGIN<=BS.RIGHT_MARGIN)\n\t\t\t\t\t" : "\n\t\t\t\t\tINNER JOIN b_iblock_section BS ON BSE.IBLOCK_SECTION_ID = BS.ID\n\t\t\t\t\t") . "\n\t\t\t\t\tWHERE (" . $sWhere . "){$sectionScope}\n\t\t\t\t\t) BES ON BES.IBLOCK_ELEMENT_ID = BE.ID\n";
         } else {
             $arSqlSearch[] = "(" . (count($arSectionFilter["BE"]) ? implode(" " . $arSectionFilter["LOGIC"] . " ", $arSectionFilter["BE"]) . " " . $arSectionFilter["LOGIC"] : "") . " EXISTS (\n\t\t\t\t\tSELECT BSE.IBLOCK_ELEMENT_ID\n\t\t\t\t\tFROM b_iblock_section_element BSE\n\t\t\t\t\t" . ($bINCLUDE_SUBSECTIONS ? "\n\t\t\t\t\tINNER JOIN b_iblock_section BSubS ON BSE.IBLOCK_SECTION_ID = BSubS.ID\n\t\t\t\t\tINNER JOIN b_iblock_section BS ON (BSubS.IBLOCK_ID=BS.IBLOCK_ID\n\t\t\t\t\t\tAND BSubS.LEFT_MARGIN>=BS.LEFT_MARGIN\n\t\t\t\t\t\tAND BSubS.RIGHT_MARGIN<=BS.RIGHT_MARGIN)\n\t\t\t\t\t" : "\n\t\t\t\t\tINNER JOIN b_iblock_section BS ON BSE.IBLOCK_SECTION_ID = BS.ID\n\t\t\t\t\t") . "\n\t\t\t\t\tWHERE BSE.IBLOCK_ELEMENT_ID = BE.ID\n\t\t\t\t\tAND (" . $sWhere . "){$sectionScope}\n\t\t\t\t\t))";
         }
     } elseif (count($arSectionFilter["BE"])) {
         foreach ($arSectionFilter["BE"] as $strFilter) {
             $arSqlSearch[] = $strFilter;
         }
     }
     $sWhere = "";
     foreach ($arSqlSearch as $strFilter) {
         if (strlen(trim($strFilter, "\n\t"))) {
             if (strlen($sWhere)) {
                 $sWhere .= "\n\t\t\t\t" . $Logic . " ";
             } else {
                 $sWhere .= "\n\t\t\t\t";
             }
             $sWhere .= "(" . $strFilter . ")";
         }
     }
     $arSqlSearch = array("\n\t\t\t" . $sWhere . "\n\t\t\t");
     $SHOW_BP_NEW = "";
     $SHOW_NEW = isset($arFilter["SHOW_NEW"]) && $arFilter["SHOW_NEW"] == "Y" ? "Y" : "N";
     if ($SHOW_NEW == "Y" && isset($arFilter["SHOW_BP_NEW"]) && is_array($arFilter["SHOW_BP_NEW"]) && IsModuleInstalled('bizproc') && (!is_object($USER) || !$USER->IsAdmin())) {
         $MODULE_ID = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["MODULE_ID"]);
         $ENTITY = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["ENTITY"]);
         $PERMISSION = $DB->ForSQL($arFilter["SHOW_BP_NEW"]["PERMISSION"]);
         $arUserGroups = array();
         if (is_array($arFilter["SHOW_BP_NEW"]["GROUPS"])) {
             $USER_ID = intval($arFilter["SHOW_BP_NEW"]["USER_ID"]);
             foreach ($arFilter["SHOW_BP_NEW"]["GROUPS"] as $GROUP_ID) {
                 $GROUP_ID = intval($GROUP_ID);
                 if ($GROUP_ID) {
                     $arUserGroups[$GROUP_ID] = $GROUP_ID;
                 }
             }
         } else {
             $USER_ID = false;
             $arUserGroups = false;
         }
         if ($PERMISSION == "read" || $PERMISSION == "write") {
             if (!is_array($arUserGroups)) {
                 $USER_ID = is_object($USER) ? intval($USER->GetID()) : 0;
                 if (is_object($USER)) {
                     $arUserGroups = $USER->GetUserGroupArray();
                 }
             }
             if (!is_array($arUserGroups) || count($arUserGroups) <= 0) {
                 $arUserGroups = array(2);
             }
             $SHOW_BP_NEW = " AND EXISTS (\n\t\t\t\t\tSELECT S.DOCUMENT_ID_INT\n\t\t\t\t\tFROM\n\t\t\t\t\tb_bp_workflow_state S\n\t\t\t\t\tINNER JOIN b_bp_workflow_permissions P ON S.ID = P.WORKFLOW_ID\n\t\t\t\t\tWHERE\n\t\t\t\t\t\tS.DOCUMENT_ID_INT = BE.ID\n\t\t\t\t\t\tAND S.MODULE_ID = '{$MODULE_ID}'\n\t\t\t\t\t\tAND S.ENTITY = '{$ENTITY}'\n\t\t\t\t\t\tAND P.PERMISSION = '{$PERMISSION}'\n\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\tP.OBJECT_ID IN ('" . implode("', '", $arUserGroups) . "')\n\t\t\t\t\t\t\tOR (P.OBJECT_ID = 'Author' AND BE.CREATED_BY = {$USER_ID})\n\t\t\t\t\t\t\tOR (P.OBJECT_ID = " . $DB->Concat("'USER_'", "'{$USER_ID}'") . ")\n\t\t\t\t\t\t)\n\t\t\t\t)";
         }
     }
     if (!isset($arFilter["SHOW_HISTORY"]) || $arFilter["SHOW_HISTORY"] != "Y") {
         $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 . ")" : "") . ")";
     }
     if ($permSQL) {
         $arSqlSearch[] = $permSQL;
     }
     if (isset($this) && is_object($this) && isset($this->subQueryProp)) {
         //Subquery list value should not be null
         $this->MkPropertyFilter(CIBlock::MkOperationFilter("!" . substr($this->strField, 9)), "NE", false, $this->subQueryProp, $arJoinProps, $arSqlSearch);
     }
     return $arSqlSearch;
 }