function MkPropertyFilter($res, $cOperationType, $propVAL, $db_prop, &$arJoinProps, &$arSqlSearch)
      {
            global $DB;

            if($res["OPERATION"]!="E")
                  $cOperationType = $res["OPERATION"];

            //Tables counters
            if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
            {
                  if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
                        $iPropCnt = count($arJoinProps["FPS"]);
                  else
                        $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
            }
            else
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
                        $iPropCnt = count($arJoinProps["FPV"]);
                  else
                        $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
            }

            if(!is_array($res["FIELD"]) && (substr(strtoupper($res["FIELD"]), -6) == '_VALUE'))
                  $bValueEnum = true;
            else
                  $bValueEnum = false;

            if($db_prop["PROPERTY_TYPE"] == "L" && $bValueEnum)
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
                        $iFpenCnt = count($arJoinProps["FPEN"]);
                  else
                        $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
            }
            else
            {
                  $iFpenCnt = false;
            }

            if(is_array($res["FIELD"]))
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                        $iElCnt = count($arJoinProps["BE"]);
                  else
                        $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];
            }
            else
            {
                  $iElCnt = false;
            }


            $r = "";

            if(is_array($res["FIELD"]))
            {
                  switch($res["FIELD"][2]."")
                  {
                  case "ACTIVE":
                  case "DETAIL_TEXT_TYPE":
                  case "PREVIEW_TEXT_TYPE":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "string_equal", $bFullJoinTmp, $cOperationType);
                        break;
                  case "EXTERNAL_ID":
                        $res["FIELD"][2] = "XML_ID";
                  case "NAME":
                  case "XML_ID":
                  case "TMP_ID":
                  case "DETAIL_TEXT":
                  case "SEARCHABLE_CONTENT":
                  case "PREVIEW_TEXT":
                  case "CODE":
                  case "TAGS":
                  case "WF_COMMENTS":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "string", $bFullJoinTmp, $cOperationType);
                        break;
                  case "ID":
                  case "SHOW_COUNTER":
                  case "WF_PARENT_ELEMENT_ID":
                  case "WF_STATUS_ID":
                  case "SORT":
                  case "CREATED_BY":
                  case "PREVIEW_PICTURE":
                  case "DETAIL_PICTURE":
                  case "IBLOCK_ID":
                  case "IBLOCK_SECTION_ID":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "number", $bFullJoinTmp, $cOperationType);
                        break;
                  case "TIMESTAMP_X":
                  case "DATE_CREATE":
                  case "SHOW_COUNTER_START":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".".$res["FIELD"][2], $propVAL, "date", $bFullJoinTmp, $cOperationType);
                        break;
                  case "DATE_ACTIVE_FROM":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".ACTIVE_FROM", $propVAL, "date", $bFullJoinTmp, $cOperationType);
                        break;
                  case "DATE_ACTIVE_TO":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".ACTIVE_TO", $propVAL, "date", $bFullJoinTmp, $cOperationType);
                        break;
                  case "ACTIVE_FROM":
                        if(strlen($propVAL)>0)
                              $r = "(BE".$iElCnt.".ACTIVE_FROM ".($cOperationType=="N"?"<":">=").$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").($cOperationType=="N"?"":" OR BE".$iElCnt.".ACTIVE_FROM IS NULL").")";
                        break;
                  case "ACTIVE_TO":
                        if(strlen($propVAL)>0)
                              $r = "(BE".$iElCnt.".ACTIVE_TO ".($cOperationType=="N"?">":"<=").$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").($cOperationType=="N"?"":" OR BE".$iElCnt.".ACTIVE_TO IS NULL").")";
                        break;
                  case "ACTIVE_DATE":
                        if(strlen($propVAL)>0)
                              $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))";
                        break;
                  case "DATE_MODIFY_FROM":
                        if(strlen($propVAL)>0)
                              $r = "(BE".$iElCnt.".TIMESTAMP_X ".
                                    ( $cOperationType=="N" ? "<" : ">=" ).$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").
                                    ( $cOperationType=="N" ? "" : " OR BE".$iElCnt.".TIMESTAMP_X IS NULL").")";
                        break;
                  case "DATE_MODIFY_TO":
                        if(strlen($propVAL)>0)
                              $r = "(BE".$iElCnt.".TIMESTAMP_X ".
                                    ( $cOperationType=="N" ? ">" : "<=" ).$DB->CharToDateFunction($DB->ForSql($propVAL), "FULL").
                                    ( $cOperationType=="N" ? "" : " OR BE".$iElCnt.".TIMESTAMP_X IS NULL").")";
                        break;
                  case "MODIFIED_USER_ID":
                  case "MODIFIED_BY":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".MODIFIED_BY", $propVAL, "number", $bFullJoinTmp, $cOperationType);
                        break;
                  case "CREATED_USER_ID":
                  case "CREATED_BY":
                        $r = CIBlock::FilterCreateEx("BE".$iElCnt.".CREATED_BY", $propVAL, "number", $bFullJoinTmp, $cOperationType);
                        break;
                  default :
                        if(strpos($res["FIELD"][2], "PROPERTY_")===0){
                              $jProp_ID = substr($res["FIELD"][2], 9);
                              $db_jprop = CIBlockProperty::GetPropertyArray($jProp_ID, CIBlock::_MergeIBArrays($db_prop["LINK_IBLOCK_ID"]));
                              if(is_array($db_jprop))
                              {
                                    //join elements
                                    if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                                          $ijElCnt = count($arJoinProps["BE"]);
                                    else
                                          $ijElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];

                                    if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
                                    {
                                          if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
                                                $ijPropCnt = count($arJoinProps["BE_FPS"]);
                                          else
                                                $ijPropCnt = $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]]["CNT"];
                                    }
                                    else
                                    {
                                          if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
                                                $ijPropCnt = count($arJoinProps["BE_FPV"]);
                                          else
                                                $ijPropCnt = $arJoinProps["BE_FPV"][$db_jprop["ID"]]["CNT"];
                                    }

                                    if($db_jprop["PROPERTY_TYPE"] == "L")
                                    {
                                          if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
                                                $ijFpenCnt = count($arJoinProps["BE_FPEN"]);
                                          else
                                                $ijFpenCnt = $arJoinProps["BE_FPEN"][$db_jprop["ID"]]["CNT"];
                                    }


                                    if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
                                    {
                                          if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
                                                $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]] = array(
                                                      "CNT" => $ijPropCnt,
                                                      "JOIN" => $ijElCnt,
                                                );
                                    }
                                    else
                                    {
                                          if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FP"]))
                                                $arJoinProps["BE_FP"][$db_jprop["ID"]] = array(
                                                      "CNT" => count($arJoinProps["BE_FP"]),
                                                      "JOIN" => $ijElCnt,
                                                      "bFullJoin" => false,
                                                );
                                          if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
                                                $arJoinProps["BE_FPV"][$db_jprop["ID"]] = array(
                                                      "CNT" => $ijPropCnt,
                                                      "IBLOCK_ID" => $db_jprop["IBLOCK_ID"],
                                                      "MULTIPLE" => $db_jprop["MULTIPLE"],
                                                      "VERSION" => $db_jprop["VERSION"],
                                                      "JOIN" => $arJoinProps["BE_FP"][$db_jprop["ID"]]["CNT"],
                                                      "BE_JOIN" => $ijElCnt,
                                                      "bFullJoin" => false,
                                                );
                                    }

                                    if($ijFpenCnt >= 0 && !array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
                                          $arJoinProps["BE_FPEN"][$db_jprop["ID"]] = array(
                                                "CNT" => $ijFpenCnt,
                                                "MULTIPLE" => $db_jprop["MULTIPLE"],
                                                "VERSION" => $db_jprop["VERSION"],
                                                "ORIG_ID" => $db_jprop["ORIG_ID"],
                                                "JOIN" => $ijPropCnt,
                                                "bFullJoin" => false,
                                          );

                                    if(!is_array($propVAL))
                                          $propVAL = array($propVAL);

                                    if($db_jprop["PROPERTY_TYPE"]=="L")
                                    {
                                          if($bValueEnum)
                                                $r = CIBlock::FilterCreateEx("JFPEN".$ijFpenCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
                                          elseif($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
                                                $r = CIBlock::FilterCreateEx("JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
                                          else
                                                $r = CIBlock::FilterCreateEx("JFPV".$ijPropCnt.".VALUE_ENUM", $propVAL, "number", $bFullJoin, $cOperationType);
                                    }
                                    elseif($db_jprop["PROPERTY_TYPE"]=="N" || $db_jprop["PROPERTY_TYPE"]=="G" || $db_jprop["PROPERTY_TYPE"]=="E")
                                    {
                                          if($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
                                                $r = CIBlock::FilterCreateEx("JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
                                          else
                                                $r = CIBlock::FilterCreateEx("JFPV".$ijPropCnt.".VALUE_NUM", $propVAL, "number", $bFullJoin, $cOperationType);
                                    }
                                    else
                                    {
                                          if($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
                                                $r = CIBlock::FilterCreateEx("JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"], $propVAL, "string", $bFullJoin, $cOperationType);
                                          else
                                                $r = CIBlock::FilterCreateEx("JFPV".$ijPropCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
                                    }
                                    $r;
                              }
                        }
                        break;
                  }
            }
            else
            {
                  if(!is_array($propVAL))
                        $propVAL = array($propVAL);

                  if($db_prop["PROPERTY_TYPE"]=="L")
                  {
                        if($bValueEnum)
                              $r = CIBlock::FilterCreateEx("FPEN".$iFpenCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
                        elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
                              $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
                        else
                              $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE_ENUM", $propVAL, "number", $bFullJoin, $cOperationType);
                  }
                  elseif($db_prop["PROPERTY_TYPE"]=="N" || $db_prop["PROPERTY_TYPE"]=="G" || $db_prop["PROPERTY_TYPE"]=="E")
                  {
                        if($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
                              $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "number", $bFullJoin, $cOperationType);
                        else
                              $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE_NUM", $propVAL, "number", $bFullJoin, $cOperationType);
                  }
                  else
                  {
                        if($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
                              $r = CIBlock::FilterCreateEx("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $propVAL, "string", $bFullJoin, $cOperationType);
                        else
                              $r = CIBlock::FilterCreateEx("FPV".$iPropCnt.".VALUE", $propVAL, "string", $bFullJoin, $cOperationType);
                  }
            }

            if(strlen($r) > 0)
            {
                  if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
                  {
                        if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
                              $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = $iPropCnt;
                  }
                  else
                  {
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FP"]))
                              $arJoinProps["FP"][$db_prop["ID"]] = array(
                                    "CNT" => count($arJoinProps["FP"]),
                                    "bFullJoin" => false,
                              );

                        if($res["LEFT_JOIN"])
                              $arJoinProps["FP"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
                        else
                              $arJoinProps["FP"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;

                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
                              $arJoinProps["FPV"][$db_prop["ID"]] = array(
                                    "CNT" => $iPropCnt,
                                    "IBLOCK_ID" => $db_prop["IBLOCK_ID"],
                                    "MULTIPLE" => $db_prop["MULTIPLE"],
                                    "VERSION" => $db_prop["VERSION"],
                                    "JOIN" => $arJoinProps["FP"][$db_prop["ID"]]["CNT"],
                                    "bFullJoin" => false,
                              );

                        if($res["LEFT_JOIN"])
                              $arJoinProps["FPV"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
                        else
                              $arJoinProps["FPV"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;
                  }

                  if($db_prop["PROPERTY_TYPE"]=="L" && $bValueEnum)
                  {
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
                              $arJoinProps["FPEN"][$db_prop["ID"]] = array(
                                    "CNT" => $iFpenCnt,
                                    "MULTIPLE" => $db_prop["MULTIPLE"],
                                    "VERSION" => $db_prop["VERSION"],
                                    "ORIG_ID" => $db_prop["ORIG_ID"],
                                    "JOIN" => $iPropCnt,
                                    "bFullJoin" => false,
                              );

                        if($res["LEFT_JOIN"])
                              $arJoinProps["FPEN"][$db_prop["ID"]]["bFullJoin"] &= $bFullJoin;
                        else
                              $arJoinProps["FPEN"][$db_prop["ID"]]["bFullJoin"] |= $bFullJoin;
                  }

                  if(is_array($res["FIELD"]))
                  {
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                              $arJoinProps["BE"][$db_prop["ID"]] = array(
                                    "CNT" => $iElCnt,
                                    "MULTIPLE" => $db_prop["MULTIPLE"],
                                    "VERSION" => $db_prop["VERSION"],
                                    "ORIG_ID" => $db_prop["ORIG_ID"],
                                    "JOIN" => $iPropCnt,
                                    "bJoinIBlock" => false,
                                    "bJoinSection" => false,
                              );
                  }

                  $arSqlSearch[] = $r;
            }
      }



function MkPropertyOrder($by, $order, $bSort, $db_prop, &$arJoinProps, &$arSqlOrder)
      {
            if($bSort && $db_prop["PROPERTY_TYPE"] != "L")
                  return;

            global $DB;
            static $arJoinEFields = false;

            //Tables counters
            if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
            {
                  if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
                        $iPropCnt = count($arJoinProps["FPS"]);
                  else
                        $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
            }
            else
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
                        $iPropCnt = count($arJoinProps["FPV"]);
                  else
                        $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
            }

            if($db_prop["PROPERTY_TYPE"] == "L")
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
                        $iFpenCnt = count($arJoinProps["FPEN"]);
                  else
                        $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];
            }
            else
            {
                  $iFpenCnt = -1;
            }

            $iElCnt = -1;
            $db_jprop = false;
            $ijPropCnt = -1;
            $ijFpenCnt = -1;

            if(is_array($by))
            {
                  if(!$arJoinEFields) $arJoinEFields = array(
                        "ID" => "BE#i#.ID",
                        "TIMESTAMP_X" => "BE#i#.TIMESTAMP_X",
                        "MODIFIED_BY" => "BE#i#.MODIFIED_BY",
                        "CREATED" => "BE#i#.DATE_CREATE",
                        "CREATED_DATE" => $DB->DateFormatToDB("YYYY.MM.DD", "BE#i#.DATE_CREATE"),
                        "CREATED_BY" => "BE#i#.CREATED_BY",
                        "IBLOCK_ID" => "BE#i#.IBLOCK_ID",
                        "IBLOCK_SECTION_ID" => "BE#i#.IBLOCK_SECTION_ID",
                        "ACTIVE" => "BE#i#.ACTIVE",
                        "ACTIVE_FROM" => "BE#i#.ACTIVE_FROM",
                        "ACTIVE_TO" => "BE#i#.ACTIVE_TO",
                        "SORT" => "BE#i#.SORT",
                        "NAME" => "BE#i#.NAME",
                        "SHOW_COUNTER" => "BE#i#.SHOW_COUNTER",
                        "SHOW_COUNTER_START" => "BE#i#.SHOW_COUNTER_START",
                        "CODE" => "BE#i#.CODE",
                        "TAGS" => "BE#i#.TAGS",
                        "XML_ID" => "BE#i#.XML_ID",
                        "STATUS" => "BE#i#.WF_STATUS_ID",
                  );
                  //Joined Elements Field
                  if(array_key_exists($by[2], $arJoinEFields))
                  {
                        //Then join elements
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                              $iElCnt = count($arJoinProps["BE"]);
                        else
                              $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];

                        $arSqlOrder[$by[0]] = CIBLock::_Order(str_replace("#i#", $iElCnt, $arJoinEFields[$by[2]]), $order, "desc");
                  }
                  elseif(substr($by[2], 0, 9) == "PROPERTY_")
                  {
                        $jProp_ID = substr($by[2], 9);
                        $db_jprop = CIBlockProperty::GetPropertyArray($jProp_ID, CIBlock::_MergeIBArrays($db_prop["LINK_IBLOCK_ID"]));
                        if(is_array($db_jprop))
                        {
                              //join elements
                              if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                                    $iElCnt = count($arJoinProps["BE"]);
                              else
                                    $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];

                              if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
                              {
                                    if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
                                          $ijPropCnt = count($arJoinProps["BE_FPS"]);
                                    else
                                          $ijPropCnt = $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]]["CNT"];
                              }
                              else
                              {
                                    if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
                                          $ijPropCnt = count($arJoinProps["BE_FPV"]);
                                    else
                                          $ijPropCnt = $arJoinProps["BE_FPV"][$db_jprop["ID"]]["CNT"];
                              }

                              if($db_jprop["PROPERTY_TYPE"] == "L")
                              {
                                    if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
                                          $ijFpenCnt = count($arJoinProps["BE_FPEN"]);
                                    else
                                          $ijFpenCnt = $arJoinProps["BE_FPEN"][$db_jprop["ID"]]["CNT"];
                              }

                              if($db_jprop["PROPERTY_TYPE"]=="L" && $bSort)
                                    $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBLock::_Order("JFPEN".$ijFpenCnt.".SORT", $order, "desc");
                              elseif($db_jprop["PROPERTY_TYPE"]=="L")
                                    $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBLock::_Order("JFPEN".$ijFpenCnt.".VALUE", $order, "desc");
                              elseif($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
                                    $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBLock::_Order("JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"], $order, "desc");
                              elseif($db_jprop["PROPERTY_TYPE"]=="N")
                                    $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBLock::_Order("JFPV".$ijPropCnt.".VALUE_NUM", $order, "desc");
                              else
                                    $arSqlOrder["PROPERTY_".$by[1]."_".$by[2]] = CIBLock::_Order("JFPV".$ijPropCnt.".VALUE", $order, "desc");

                        }
                  }
            }
            else
            {
                  if($db_prop["PROPERTY_TYPE"]=="L" && $bSort)
                        $arSqlOrder[$by] = CIBLock::_Order("FPEN".$iFpenCnt.".SORT", $order, "desc");
                  elseif($db_prop["PROPERTY_TYPE"]=="L")
                        $arSqlOrder[$by] = CIBLock::_Order("FPEN".$iFpenCnt.".VALUE", $order, "desc");
                  elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
                        $arSqlOrder[$by] = CIBLock::_Order("FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"], $order, "desc");
                  elseif($db_prop["PROPERTY_TYPE"]=="N")
                        $arSqlOrder[$by] = CIBLock::_Order("FPV".$iPropCnt.".VALUE_NUM", $order, "desc");
                  else
                        $arSqlOrder[$by] = CIBLock::_Order("FPV".$iPropCnt.".VALUE", $order, "desc");
            }

            //Pass join "commands" up there
            if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
            {
                  if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
                        $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = $iPropCnt;
            }
            else
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FP"]))
                        $arJoinProps["FP"][$db_prop["ID"]] = array(
                              "CNT" => count($arJoinProps["FP"]),
                              "bFullJoin" => false,
                        );
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
                        $arJoinProps["FPV"][$db_prop["ID"]] = array(
                              "CNT" => $iPropCnt,
                              "IBLOCK_ID" => $db_prop["IBLOCK_ID"],
                              "MULTIPLE" => $db_prop["MULTIPLE"],
                              "VERSION" => $db_prop["VERSION"],
                              "JOIN" => $arJoinProps["FP"][$db_prop["ID"]]["CNT"],
                              "bFullJoin" => false,
                        );
            }

            if($iFpenCnt >= 0 && !array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
                  $arJoinProps["FPEN"][$db_prop["ID"]] = array(
                        "CNT" => $iFpenCnt,
                        "MULTIPLE" => $db_prop["MULTIPLE"],
                        "VERSION" => $db_prop["VERSION"],
                        "ORIG_ID" => $db_prop["ORIG_ID"],
                        "JOIN" => $iPropCnt,
                        "bFullJoin" => false,
                  );

            if($iElCnt >= 0)
            {
                  if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                        $arJoinProps["BE"][$db_prop["ID"]] = array(
                              "CNT" => $iElCnt,
                              "MULTIPLE" => $db_prop["MULTIPLE"],
                              "VERSION" => $db_prop["VERSION"],
                              "ORIG_ID" => $db_prop["ORIG_ID"],
                              "JOIN" => $iPropCnt,
                              "bJoinIBlock" => false,
                              "bJoinSection" => false,
                        );
                  $arJoinProps["BE"][$db_prop["ID"]]["bJoinIBlock"] |= $bJoinIBlock;
                  $arJoinProps["BE"][$db_prop["ID"]]["bJoinSection"] |= $bJoinSection;

                  if(is_array($db_jprop))
                  {
                        if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
                        {
                              if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
                                    $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]] = array(
                                          "CNT" => $ijPropCnt,
                                          "JOIN" => $iElCnt,
                                    );
                        }
                        else
                        {
                              if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FP"]))
                                    $arJoinProps["BE_FP"][$db_jprop["ID"]] = array(
                                          "CNT" => count($arJoinProps["BE_FP"]),
                                          "JOIN" => $iElCnt,
                                          "bFullJoin" => false,
                                    );
                              if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
                                    $arJoinProps["BE_FPV"][$db_jprop["ID"]] = array(
                                          "CNT" => $ijPropCnt,
                                          "IBLOCK_ID" => $db_jprop["IBLOCK_ID"],
                                          "MULTIPLE" => $db_jprop["MULTIPLE"],
                                          "VERSION" => $db_jprop["VERSION"],
                                          "JOIN" => $arJoinProps["BE_FP"][$db_jprop["ID"]]["CNT"],
                                          "BE_JOIN" => $iElCnt,
                                          "bFullJoin" => false,
                                    );
                        }

                        if($ijFpenCnt >= 0 && !array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
                              $arJoinProps["BE_FPEN"][$db_jprop["ID"]] = array(
                                    "CNT" => $ijFpenCnt,
                                    "MULTIPLE" => $db_jprop["MULTIPLE"],
                                    "VERSION" => $db_jprop["VERSION"],
                                    "ORIG_ID" => $db_jprop["ORIG_ID"],
                                    "JOIN" => $ijPropCnt,
                                    "bFullJoin" => false,
                              );
                  }
            }

      }


function MkPropertyGroup($group, $db_prop, &$arJoinProps)
      {
            global $DB;
            static $arJoinEFields = false;

            if(is_array($group))
            {
                  if(!$arJoinEFields) $arJoinEFields = array(
                        "ID" => "BE#i#.ID",
                        "TIMESTAMP_X" => "BE#i#.TIMESTAMP_X",
                        "MODIFIED_BY" => "BE#i#.MODIFIED_BY",
                        "CREATED" => "BE#i#.DATE_CREATE",
                        "CREATED_DATE" => $DB->DateFormatToDB("YYYY.MM.DD", "BE#i#.DATE_CREATE"),
                        "CREATED_BY" => "BE#i#.CREATED_BY",
                        "IBLOCK_ID" => "BE#i#.IBLOCK_ID",
                        "IBLOCK_SECTION_ID" => "BE#i#.IBLOCK_SECTION_ID", 
                        "ACTIVE" => "BE#i#.ACTIVE",
                        "ACTIVE_FROM" => "BE#i#.ACTIVE_FROM",
                        "ACTIVE_TO" => "BE#i#.ACTIVE_TO",
                        "SORT" => "BE#i#.SORT",
                        "NAME" => "BE#i#.NAME",
                        "SHOW_COUNTER" => "BE#i#.SHOW_COUNTER",
                        "SHOW_COUNTER_START" => "BE#i#.SHOW_COUNTER_START",
                        "CODE" => "BE#i#.CODE",
                        "TAGS" => "BE#i#.TAGS",
                        "XML_ID" => "BE#i#.XML_ID",
                        "STATUS" => "BE#i#.WF_STATUS_ID",
                  );
                  //Joined Elements Field
                  if(array_key_exists($group[2], $arJoinEFields))
                  {
                        //Then join elements
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                              $iElCnt = count($arJoinProps["BE"]);
                        else
                              $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];

                        return ", ".str_replace("#i#", $iElCnt, $arJoinEFields[$group[2]]);
                  }
                  elseif(substr($group[2], 0, 9) == "PROPERTY_")
                  {
                        $jProp_ID = substr($group[2], 9);
                        $db_jprop = CIBlockProperty::GetPropertyArray($jProp_ID, CIBlock::_MergeIBArrays($db_prop["LINK_IBLOCK_ID"]));
                        if(is_array($db_jprop))
                        {
                              //join elements
                              if(!array_key_exists($db_prop["ID"], $arJoinProps["BE"]))
                                    $iElCnt = count($arJoinProps["BE"]);
                              else
                                    $iElCnt = $arJoinProps["BE"][$db_prop["ID"]]["CNT"];

                              if($db_jprop["VERSION"] == 2 && $db_jprop["MULTIPLE"]=="N")
                              {
                                    if(!array_key_exists($db_jprop["IBLOCK_ID"], $arJoinProps["BE_FPS"]))
                                          $ijPropCnt = count($arJoinProps["BE_FPS"]);
                                    else
                                          $ijPropCnt = $arJoinProps["BE_FPS"][$db_jprop["IBLOCK_ID"]]["CNT"];
                              }
                              else
                              {
                                    if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPV"]))
                                          $ijPropCnt = count($arJoinProps["BE_FPV"]);
                                    else
                                          $ijPropCnt = $arJoinProps["BE_FPV"][$db_jprop["ID"]]["CNT"];
                              }

                              if($db_jprop["PROPERTY_TYPE"] == "L")
                              {
                                    if(!array_key_exists($db_jprop["ID"], $arJoinProps["BE_FPEN"]))
                                          $ijFpenCnt = count($arJoinProps["BE_FPEN"]);
                                    else
                                          $ijFpenCnt = $arJoinProps["BE_FPEN"][$db_jprop["ID"]]["CNT"];
                              }

                              if($db_jprop["PROPERTY_TYPE"]=="L")
                                    return ", JFPEN".$ijFpenCnt.".VALUE, JFPEN".$ijFpenCnt.".ID";
                              elseif($db_jprop["VERSION"]==2 && $db_jprop["MULTIPLE"]=="N")
                                    return ", JFPS".$ijPropCnt.".PROPERTY_".$db_jprop["ORIG_ID"];
                              elseif($db_jprop["PROPERTY_TYPE"]=="N")
                                    return ", JFPV".$ijPropCnt.".VALUE, FPV".$ijPropCnt.".VALUE_NUM";
                              else
                                    return ", JFPV".$ijPropCnt.".VALUE";                        

                        }
                  }
            }
            else
            {
                  if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"]=="N")
                  {
                        if(!array_key_exists($db_prop["IBLOCK_ID"], $arJoinProps["FPS"]))
                              $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]] = count($arJoinProps["FPS"]);
                        $iPropCnt = $arJoinProps["FPS"][$db_prop["IBLOCK_ID"]];
                  }
                  else
                  {
                        //Join property metadata table
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FP"]))
                              $arJoinProps["FP"][$db_prop["ID"]] = array(
                                    "CNT" => count($arJoinProps["FP"]),
                                    "bFullJoin" => false,
                              );

                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FPV"]))
                              $arJoinProps["FPV"][$db_prop["ID"]] = array(
                                    "CNT" => count($arJoinProps["FPV"]),
                                    "IBLOCK_ID" => $db_prop["IBLOCK_ID"],
                                    "MULTIPLE" => $db_prop["MULTIPLE"],
                                    "VERSION" => $db_prop["VERSION"],
                                    "ORIG_ID" => $db_prop["ORIG_ID"],
                                    "JOIN" => $arJoinProps["FP"][$db_prop["ID"]]["CNT"],
                                    "bFullJoin" => false,
                              );
                        $iPropCnt = $arJoinProps["FPV"][$db_prop["ID"]]["CNT"];
                  }

                  if($db_prop["PROPERTY_TYPE"]=="L")
                  {
                        if(!array_key_exists($db_prop["ID"], $arJoinProps["FPEN"]))
                              $arJoinProps["FPEN"][$db_prop["ID"]] = array(
                                    "CNT" => count($arJoinProps["FPEN"]),
                                    "MULTIPLE" => $db_prop["MULTIPLE"],
                                    "VERSION" => $db_prop["VERSION"],
                                    "ORIG_ID" => $db_prop["ORIG_ID"],
                                    "JOIN" => $iPropCnt,
                                    "bFullJoin" => false,
                              );
                        $iFpenCnt = $arJoinProps["FPEN"][$db_prop["ID"]]["CNT"];

                        return ", FPEN".$iFpenCnt.".VALUE, FPEN".$iFpenCnt.".ID";
                  }
                  elseif($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N")
                  {
                        return ", FPS".$iPropCnt.".PROPERTY_".$db_prop["ORIG_ID"];
                  }
                  elseif($db_prop["PROPERTY_TYPE"]=="N")
                  {
                        return ", FPV".$iPropCnt.".VALUE, FPV".$iPropCnt.".VALUE_NUM";
                  }
                  else
                  {
                        return ", FPV".$iPropCnt.".VALUE";
                  }
            }
      }


function PrepareGetList(
            &$arIblockElementFields,
            &$arJoinProps,
            &$bOnlyCount,
            &$bDistinct,

            &$arSelectFields,
            &$sSelect,
            &$arAddSelectFields,

            &$arFilter,
            &$sWhere,
            &$sSectionWhere,
            &$arAddWhereFields,

            &$arGroupBy,
            &$sGroupBy,

            &$arOrder,
            &$arSqlOrder,
            &$arAddOrderByFields,

            &$arIBlockFilter,
            &$arIBlockMultProps,
            &$arIBlockConvProps,
            &$arIBlockAllProps,
            &$arIBlockNumProps,
            &$arIBlockLongProps
            )
      {
            if(is_array($arSelectFields) && in_array("DETAIL_PAGE_URL", $arSelectFields) && !in_array("LANG_DIR", $arSelectFields))
                  $arSelectFields[] = "LANG_DIR";

            global $DB;

            if((!is_array($arSelectFields) && $arSelectFields=="") || count($arSelectFields)<=0 || $arSelectFields===false)
                  $arSelectFields = Array("*");

            if(is_bool($arGroupBy) && $arGroupBy!==false)
                  $arGroupBy = Array();

            if(is_array($arGroupBy) && count($arGroupBy)==0)
                  $bOnlyCount = true;

            $iPropCnt = 0;
            $arJoinProps = Array(
                  "FP" => array(
                        //CNT
                        //bFullJoin
                  ),
                  "FPV" => array(
                        //CNT
                        //IBLOCK_ID
                        //MULTIPLE
                        //VERSION
                        //JOIN
                        //bFullJoin
                  ),
                  "FPS" => array(
                        //
                  ),
                  "FPEN" => array(
                        //CNT
                        //MULTIPLE
                        //VERSION
                        //ORIG_ID
                        //JOIN
                        //bFullJoin
                  ),
                  "BE" => array(
                        //CNT
                        //MULTIPLE
                        //VERSION
                        //ORIG_ID
                        //JOIN
                        //bJoinIBlock
                        //bJoinSection
                  ),
                  "BE_FP" => array(
                        //CNT
                        //JOIN
                        //bFullJoin
                  ),
                  "BE_FPV" => array(
                        //CNT
                        //IBLOCK_ID
                        //MULTIPLE
                        //VERSION
                        //JOIN
                        //BE_JOIN
                        //bFullJoin
                  ),
                  "BE_FPS" => array(
                        //CNT
                        //JOIN
                  ),
                  "BE_FPEN" => array(
                        //CNT
                        //MULTIPLE
                        //VERSION
                        //ORIG_ID
                        //JOIN
                        //bFullJoin
                  ),
                  "BES" => "",
            );
            $arIBlockMultProps = Array();
            $arIBlockAllProps = Array();
            $arIBlockNumProps = Array();
            $bWasGroup = false;

            //********************************ORDER BY PART***********************************************
            $arSqlOrder = Array();
            $arAddOrderByFields = Array();
            $iOrdNum = -1;
            if(!is_array($arOrder))
                  $arOrder = Array();
            foreach($arOrder as $by=>$order)
            {
                  $by_orig = $by;
                  $by = strtoupper($by);
                  //Remove aliases
                  if($by == "EXTERNAL_ID") $by = "XML_ID";
                  elseif($by == "DATE_ACTIVE_FROM") $by = "ACTIVE_FROM";
                  elseif($by == "DATE_ACTIVE_TO") $by = "ACTIVE_TO";

                  if(array_key_exists($by, $arSqlOrder))
                        continue;

                  if(substr($by, 0, 8) == "CATALOG_")
                  {
                        $iOrdNum++;
                        $arAddOrderByFields[$iOrdNum] = Array($by=>$order);
                        //Reserve for future fill
                        $arSqlOrder[$iOrdNum] = false;
                  }
                  else
                  {
                        if($by == "ID") $arSqlOrder[$by] = CIBlock::_Order("BE.ID", $order, "desc", false);
                        elseif($by == "NAME") $arSqlOrder[$by] = CIBlock::_Order("BE.NAME", $order, "desc", false);
                        elseif($by == "STATUS") $arSqlOrder[$by] = CIBlock::_Order("BE.WF_STATUS_ID", $order, "desc");
                        elseif($by == "XML_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.XML_ID", $order, "desc");
                        elseif($by == "CODE") $arSqlOrder[$by] = CIBlock::_Order("BE.CODE", $order, "desc");
                        elseif($by == "TAGS") $arSqlOrder[$by] = CIBlock::_Order("BE.TAGS", $order, "desc");
                        elseif($by == "TIMESTAMP_X") $arSqlOrder[$by] = CIBlock::_Order("BE.TIMESTAMP_X", $order, "desc");
                        elseif($by == "CREATED") $arSqlOrder[$by] = CIBlock::_Order("BE.DATE_CREATE", $order, "desc");
                        elseif($by == "CREATED_DATE") $arSqlOrder[$by] = CIBlock::_Order($DB->DateFormatToDB("YYYY.MM.DD", "BE.DATE_CREATE"), $order, "desc");
                        elseif($by == "IBLOCK_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_ID", $order, "desc");
                        elseif($by == "MODIFIED_BY") $arSqlOrder[$by] = CIBlock::_Order("BE.MODIFIED_BY", $order, "desc");
                        elseif($by == "ACTIVE") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE", $order, "desc");
                        elseif($by == "ACTIVE_FROM") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_FROM", $order, "desc");
                        elseif($by == "ACTIVE_TO") $arSqlOrder[$by] = CIBlock::_Order("BE.ACTIVE_TO", $order, "desc");
                        elseif($by == "SORT") $arSqlOrder[$by] = CIBlock::_Order("BE.SORT", $order, "desc");
                        elseif($by == "SHOW_COUNTER") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER", $order, "desc");
                        elseif($by == "SHOW_COUNTER_START") $arSqlOrder[$by] = CIBlock::_Order("BE.SHOW_COUNTER_START", $order, "desc");
                        elseif($by == "RAND") $arSqlOrder[$by] = CIBlockElement::GetRandFunction(true);
                        elseif($by == "SHOWS") $arSqlOrder[$by] = CIBlock::_Order(CIBlockElement::GetShowedFunction(), $order, "desc", false);
                        elseif($by == "HAS_PREVIEW_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.PREVIEW_PICTURE"), $order, "desc", false);
                        elseif($by == "HAS_DETAIL_PICTURE") $arSqlOrder[$by] = CIBlock::_Order(CIBlock::_NotEmpty("BE.DETAIL_PICTURE"), $order, "desc", false);
                        elseif($by == "CNT")
                        {
                              if(is_array($arGroupBy) && count($arGroupBy) > 0)
                                    $arSqlOrder[$by] = " CNT ".$order." ";
                        }
                        elseif(substr($by, 0, 9) == "PROPERTY_")
                        {
                              $propID = strtoupper(substr($by_orig, 9));
                              if(preg_match("/^([^.]+)\\.([^.]+)$/", $propID, $arMatch))
                              {
                                    $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"]));
                                    if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
                                          CIBlockElement::MkPropertyOrder($arMatch, $order, false, $db_prop, $arJoinProps, $arSqlOrder);
                              }
                              else
                              {
                                    if($db_prop = CIBlockProperty::GetPropertyArray($propID, CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"])))
                                          CIBlockElement::MkPropertyOrder($by, $order, false, $db_prop, $arJoinProps, $arSqlOrder);
                              }
                        }
                        elseif(substr($by, 0, 13) == "PROPERTYSORT_")
                        {
                              $propID = strtoupper(substr($by_orig, 13));
                              if(preg_match("/^([^.]+)\\.([^.]+)$/", $propID, $arMatch))
                              {
                                    $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"]));
                                    if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
                                          CIBlockElement::MkPropertyOrder($arMatch, $order, true, $db_prop, $arJoinProps, $arSqlOrder);
                              }
                              else
                              {
                                    if($db_prop = CIBlockProperty::GetPropertyArray($propID, CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"])))
                                          CIBlockElement::MkPropertyOrder($by, $order, true, $db_prop, $arJoinProps, $arSqlOrder);
                              }
                        }
                        else
                        {
                              $by = "ID";
                              if(!array_key_exists($by, $arSqlOrder))
                                    $arSqlOrder[$by] = CIBLock::_Order("BE.ID", $order, "desc");
                        }

                        //Check if have to add select field in order to correctly sort
                        if(is_array($arSqlOrder[$by]))
                        {
                              if(is_array($arGroupBy) && count($arGroupBy)>0)
                                    $arGroupBy[] = $arSqlOrder[$by][1];
                              else
                                    $arSelectFields[] = $arSqlOrder[$by][1];
                              // COLUMN ALIAS COLUMN EXPRESSION
                              $arIblockElementFields[$arSqlOrder[$by][1]] = $arSqlOrder[$by][0];
                              // ORDER EXPRESSION
                              $arSqlOrder[$by] = $arSqlOrder[$by][2];
                        }
                  }

                  //Add order by fields to the select list
                  //in order to avoid sql errors
                  if(is_array($arGroupBy) && count($arGroupBy)>0)
                  {
                        if($by == "STATUS") $arGroupBy[] = "WF_STATUS_ID";
                        elseif($by == "CREATED") $arGroupBy[] = "DATE_CREATE";
                        else $arGroupBy[] = $by;
                  }
                  else
                  {
                        if($by == "STATUS") $arSelectFields[] = "WF_STATUS_ID";
                        elseif($by == "CREATED") $arSelectFields[] = "DATE_CREATE";
                        else $arSelectFields[] = $by;
                  }
            }

            //*************************GROUP BY PART****************************
            $sGroupBy = "";
            if(is_array($arGroupBy) && count($arGroupBy)>0)
            {
                  $arSelectFields = array_unique($arGroupBy);      
                  $bWasGroup = true;
                  foreach($arSelectFields as $key=>$val)
                  {
                        $val = strtoupper($val);
                        if(array_key_exists($val, $arIblockElementFields))
                        {
                              $sGroupBy.=",".preg_replace("/(\s+AS\s+[A-Z_]+)/i", "", $arIblockElementFields[$val]);
                        }
                        elseif(substr($val, 0, 9) == "PROPERTY_")
                        {
                              $PR_ID = strtoupper(substr($val, 9));
                              if(preg_match("/^([^.]+)\\.([^.]+)$/", $PR_ID, $arMatch))
                              {
                                    $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"]));
                                    if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
                                          $sGroupBy .= CIBlockElement::MkPropertyGroup($arMatch, $db_prop, $arJoinProps);
                              }
                              else
                              {
                               if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"])))
                                          $sGroupBy .= CIBlockElement::MkPropertyGroup($PR_ID, $db_prop, $arJoinProps);
                              }
                        }
                  }
                  if($sGroupBy!="")
                        $sGroupBy = " GROUP BY ".substr($sGroupBy, 1)." ";
            }

            //*************************SELECT PART****************************
            $arAddSelectFields = Array();
            if($bOnlyCount)
            {
                  $sSelect = "COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
            }
            else
            {
                  $sSelect = "";
                  $arDisplayedColumns = Array();
                  $bStar = false;
                  foreach($arSelectFields as $key=>$val)
                  {
                        $val = strtoupper($val);
                        if(array_key_exists($val, $arIblockElementFields))
                        {
                              if(array_key_exists($val, $arDisplayedColumns))
                                    continue;
                              $arDisplayedColumns[$val] = true;
                              $arSelectFields[$key] = $val;
                              $sSelect.=",".$arIblockElementFields[$val]." as ".$val;
                        }
                        elseif($val == "PROPERTY_*" && !$bWasGroup)
                        {
                              //We have to analyze arFilter IBLOCK_ID and IBLOCK_CODE
                              //in a way to be shure we will get properties of the ONE IBLOCK ONLY!
                              $arPropertyFilter = array(
                                    "ACTIVE"=>"Y",
                                    "VERSION"=>2,
                              );
                              if(array_key_exists("IBLOCK_ID", $arFilter))
                              {
                                    if(is_array($arFilter["IBLOCK_ID"]) && count($arFilter["IBLOCK_ID"])==1)
                                          $arPropertyFilter["IBLOCK_ID"] = $arFilter["IBLOCK_ID"][0];
                                    elseif(!is_array($arFilter["IBLOCK_ID"]) && intval($arFilter["IBLOCK_ID"])>0)
                                          $arPropertyFilter["IBLOCK_ID"] = $arFilter["IBLOCK_ID"];
                              }
                              if(!array_key_exists("IBLOCK_ID", $arPropertyFilter))
                              {
                                    if(array_key_exists("IBLOCK_CODE", $arFilter))
                                    {
                                          if(is_array($arFilter["IBLOCK_CODE"]) && count($arFilter["IBLOCK_CODE"])==1)
                                                $arPropertyFilter["IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"][0];
                                          elseif(!is_array($arFilter["IBLOCK_CODE"]) && strlen($arFilter["IBLOCK_CODE"])>0)
                                                $arPropertyFilter["IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"];
                                          else
                                                continue;
                                    }
                                    else
                                          continue;
                              }

                              $rs_prop = CIBlockProperty::GetList(array("sort"=>"asc"), $arPropertyFilter);
                              while($db_prop = $rs_prop->Fetch())
                                    $arIBlockAllProps[]=$db_prop;
                              $iblock_id = false;
                              foreach($arIBlockAllProps as $db_prop)
                              {
                                    if($db_prop["USER_TYPE"]!="")
                                    {
                                          $arUserType = CIBlockProperty::GetUserType($db_prop["USER_TYPE"]);
                                          if(array_key_exists("ConvertFromDB", $arUserType))
                                                $arIBlockConvProps["PROPERTY_".$db_prop["ID"]] = array(
                                                      "ConvertFromDB"=>$arUserType["ConvertFromDB"],
                                                      "PROPERTY"=>$db_prop,
                                                );
                                    }
                                    $db_prop["ORIG_ID"] = $db_prop["ID"];
                                    if($db_prop["MULTIPLE"]=="Y")
                                          $arIBlockMultProps["PROPERTY_".$db_prop["ID"]] = $db_prop;
                                    $iblock_id = $db_prop["IBLOCK_ID"];
                              }
                              if($iblock_id!==false)
                              {
                                    if(!array_key_exists($iblock_id, $arJoinProps["FPS"]))
                                          $arJoinProps["FPS"][$iblock_id] = count($arJoinProps["FPS"]);
                                    $iPropCnt = $arJoinProps["FPS"][$iblock_id];

                                    $sSelect .= ", FPS".$iPropCnt.".*";
                              }
                        }
                        elseif(substr($val, 0, 9) == "PROPERTY_")
                        {
                              $PR_ID = strtoupper($val);
                              if(array_key_exists($PR_ID, $arDisplayedColumns))
                                    continue;
                              $arDisplayedColumns[$PR_ID] = true;
                              $PR_ID = substr($PR_ID, 9);

                              if(preg_match("/^([^.]+)\\.([^.]+)$/", $PR_ID, $arMatch))
                              {
                                    $db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"]));
                                    if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
                                          CIBlockElement::MkPropertySelect($arMatch, $db_prop, $arIBlockLongProps, $arIBlockConvProps, $arJoinProps, $arIBlockMultProps, $arIBlockNumProps, $bWasGroup, $sGroupBy, $sSelect);
                              }
                              else
                              {
                                    if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, CIBlock::_MergeIBArrays($arFilter["IBLOCK_ID"], $arFilter["IBLOCK_CODE"])))
                                          CIBlockElement::MkPropertySelect($PR_ID, $db_prop, $arIBlockLongProps, $arIBlockConvProps, $arJoinProps, $arIBlockMultProps, $arIBlockNumProps, $bWasGroup, $sGroupBy, $sSelect);
                              }
                        }
                        elseif($val == "*")
                        {
                              $bStar = true;
                        }
                        elseif(substr($val, 0, 14) == "CATALOG_GROUP_")
                        {
                              $arAddSelectFields[] = $val;
                        }
                        elseif(substr($val, 0, 16) == "CATALOG_QUANTITY")
                        {
                              $arAddSelectFields[] = $val;
                        }
                  }

                  if($bStar)
                  {
                        foreach($arIblockElementFields as $key=>$val)
                        {
                              if(array_key_exists($key, $arDisplayedColumns))
                                    continue;
                              $arDisplayedColumns[$key] = true;
                              $arSelectFields[]=$key;
                              $sSelect.=",".$val." as ".$key;
                        }
                  }
                  elseif($sGroupBy=="")
                  {
                         //Try to add missing fields for correct URL translation (only then no grouping)
                        if(array_key_exists("DETAIL_PAGE_URL", $arDisplayedColumns))
                              $arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
                        elseif(array_key_exists("SECTION_PAGE_URL", $arDisplayedColumns))
                              $arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
                        elseif(array_key_exists("LIST_PAGE_URL", $arDisplayedColumns))
                              $arAddFields = array("LANG_DIR", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
                        else
                              $arAddFields = array();

                         //Try to add missing fields for correct PREVIEW and DETAIL text formatting
                        if(array_key_exists("DETAIL_TEXT", $arDisplayedColumns))
                              $arAddFields[] = "DETAIL_TEXT_TYPE";
                        if(array_key_exists("PREVIEW_TEXT", $arDisplayedColumns))
                              $arAddFields[] = "PREVIEW_TEXT_TYPE";

                        foreach($arAddFields as $key)
                        {
                              if(array_key_exists($key, $arDisplayedColumns))
                                    continue;
                              $arDisplayedColumns[$key] = true;
                              $arSelectFields[]=$key;
                              $sSelect.=",".$arIblockElementFields[$key]." as ".$key;
                        }
                  }

                  if($sGroupBy!="")
                        $sSelect = substr($sSelect, 1).", COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
                  elseif(strlen($sSelect) > 0)
                        $sSelect = "%%_DISTINCT_%% ".substr($sSelect, 1)." ";
            }

            //*********************WHERE PART*********************
            $arAddWhereFields = Array();
            if(array_key_exists("CATALOG", $arFilter))
            {
                  $arAddWhereFields = $arFilter["CATALOG"];
                  unset($arFilter["CATALOG"]);
            }

            $arSqlSearch = CIBlockElement::MkFilter($arFilter, $arJoinProps, $arAddWhereFields);
            $bDistinct = false;
            $sSectionWhere = "";

            $sWhere = "";
            for($i=0; $i<count($arSqlSearch); $i++)
                  if(strlen(trim($arSqlSearch[$i], "\n\t")))
                        $sWhere .= "\n\t\t\tAND (".$arSqlSearch[$i].")";
      }