• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/classes/general/iblockelement.php
  • Класс: CAllIBlockElement
  • Вызов: CAllIBlockElement::PrepareGetList
public function PrepareGetList(
	&$arIblockElementFields,
	&$arJoinProps,

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

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

	&$arGroupBy,
	&$sGroupBy,

	&$arOrder,
	&$arSqlOrder,
	&$arAddOrderByFields
)
{
	if(
		is_array($arSelectFields)
		&& (in_array("DETAIL_PAGE_URL", $arSelectFields) || in_array("CANONICAL_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)
		$this->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" => "",
		"RV" => false,
		"RVU" => false,
		"RVV" => false,
		"FC" => "",
	);

	$this->arIBlockMultProps = Array();
	$this->arIBlockAllProps = Array();
	$this->arIBlockNumProps = Array();
	$bWasGroup = false;

	//********************************ORDER BY PART***********************************************

	$iblockIds = CIBlock::_MergeIBArrays(
		$arFilter["IBLOCK_ID"] ?? false,
		$arFilter["IBLOCK_CODE"] ?? false,
	);
	$orderAlias = array(
		'EXTERNAL_ID' => 'XML_ID',
		'DATE_ACTIVE_FROM' => 'ACTIVE_FROM',
		'DATE_ACTIVE_TO' => 'ACTIVE_TO'
	);
	$arSqlOrder = Array();
	$arAddOrderByFields = Array();
	$iOrdNum = -1;
	if(!is_array($arOrder))
		$arOrder = Array();
	foreach($arOrder as $by=>$order)
	{
		$by_orig = $by;
		$by = mb_strtoupper($by);
		//Remove aliases
		if (isset($orderAlias[$by]))
			$by = $orderAlias[$by];

		if (isset($arSqlOrder[$by]))
			continue;

		if ($this->catalogIncluded && CProductQueryBuilder::isValidField($by))
		{
			$iOrdNum++;
			$arAddOrderByFields[$iOrdNum] = Array($by=>$order);
			//Reserve for future fill
			$arSqlOrder[$iOrdNum] = false;
		}
		else
		{
			if($by == "ID") $arSqlOrder[$by] = $this->getIdOrder($order);
			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 == "CREATED_BY") $arSqlOrder[$by] = CIBlock::_Order("BE.CREATED_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 == "IBLOCK_SECTION_ID") $arSqlOrder[$by] = CIBlock::_Order("BE.IBLOCK_SECTION_ID", $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();
			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 == "RATING_TOTAL_VALUE")
			{
				$arSqlOrder[$by] = CIBlock::_Order("RV.TOTAL_VALUE", $order, "desc");
				$arJoinProps["RV"] = true;
			}
			elseif($by == "CNT")
			{
				if (!empty($arGroupBy) && is_array($arGroupBy))
				{
					$arSqlOrder[$by] = ' '.CIBlock::_Order('CNT', $order, 'desc', false).' ';
				}
			}
			elseif(mb_substr($by, 0, 9) == "PROPERTY_")
			{
				$propID = mb_strtoupper(mb_substr($by_orig, 9));
				if(preg_match("/^([^.]+)\.([^.]+)$/", $propID, $arMatch))
				{
					$db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
					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, $iblockIds))
						CIBlockElement::MkPropertyOrder($by, $order, false, $db_prop, $arJoinProps, $arSqlOrder);
				}
			}
			elseif(mb_substr($by, 0, 13) == "PROPERTYSORT_")
			{
				$propID = mb_strtoupper(mb_substr($by_orig, 13));
				if(preg_match("/^([^.]+)\.([^.]+)$/", $propID, $arMatch))
				{
					$db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
					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, $iblockIds))
						CIBlockElement::MkPropertyOrder($by, $order, true, $db_prop, $arJoinProps, $arSqlOrder);
				}
			}
			else
			{
				$by = "ID";
				if(!isset($arSqlOrder[$by]))
					$arSqlOrder[$by] = CIBlock::_Order("BE.ID", $order, "desc");
			}

			//Check if have to add select field in order to correctly sort
			if (isset($arSqlOrder[$by]) && is_array($arSqlOrder[$by]))
			{
				if (!empty($arGroupBy) && is_array($arGroupBy))
					$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 (!empty($arGroupBy) && is_array($arGroupBy))
		{
			if ($by == "STATUS")
			{
				$arGroupBy[] = "WF_STATUS_ID";
			}
			elseif ($by == "CREATED")
			{
				$arGroupBy[] = "DATE_CREATE";
			}
			elseif ($by == "SHOWS")
			{
				$arGroupBy[] = "SHOW_COUNTER";
				$arGroupBy[] = "SHOW_COUNTER_START_X";
			}
			else
			{
				$arGroupBy[] = $by;
			}
		}
		else
		{
			if ($by == "STATUS")
			{
				$arSelectFields[] = "WF_STATUS_ID";
			}
			elseif ($by == "CREATED")
			{
				$arSelectFields[] = "DATE_CREATE";
			}
			elseif ($by == "SHOWS")
			{
				$arSelectFields[] = "SHOW_COUNTER";
				$arSelectFields[] = "SHOW_COUNTER_START_X";
			}
			else
			{
				$arSelectFields[] = $by;
			}
		}
	}

	//*************************GROUP BY PART****************************
	$sGroupBy = "";
	if(!empty($arGroupBy) && is_array($arGroupBy))
	{
		$arSelectFields = $arGroupBy;
		$bWasGroup = true;
		foreach($arSelectFields as $key=>$val)
		{
			$val = mb_strtoupper($val);
			if(array_key_exists($val, $arIblockElementFields))
			{
				$sGroupBy.=",".preg_replace("/(s+ASs+[A-Z_]+)/i", "", $arIblockElementFields[$val]);
			}
			elseif(mb_substr($val, 0, 9) == "PROPERTY_")
			{
				$PR_ID = mb_strtoupper(mb_substr($val, 9));
				if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
					$sGroupBy .= CIBlockElement::MkPropertyGroup($db_prop, $arJoinProps);
			}
			elseif(mb_substr($val, 0, 13) == "PROPERTYSORT_")
			{
				$PR_ID = mb_strtoupper(mb_substr($val, 13));
				if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
					$sGroupBy .= CIBlockElement::MkPropertyGroup($db_prop, $arJoinProps, true);
			}
		}
		if($sGroupBy!="")
			$sGroupBy = " GROUP BY ".mb_substr($sGroupBy, 1)." ";
	}

	//*************************SELECT PART****************************
	$arAddSelectFields = Array();
	if($this->bOnlyCount)
	{
		$sSelect = "COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
	}
	else
	{
		$sSelect = "";
		$arDisplayedColumns = array();
		$bStar = false;
		foreach($arSelectFields as $key=>$val)
		{
			$val = mb_strtoupper($val);
			if(array_key_exists($val, $arIblockElementFields))
			{
				if(isset($arDisplayedColumns[$val]))
					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"]) && $arFilter["IBLOCK_CODE"] <> '')
							$arPropertyFilter["IBLOCK_CODE"] = $arFilter["IBLOCK_CODE"];
						else
							continue;
					}
					else
						continue;
				}

				$rs_prop = CIBlockProperty::GetList(array("sort"=>"asc"), $arPropertyFilter);
				while($db_prop = $rs_prop->Fetch())
					$this->arIBlockAllProps[]=$db_prop;
				$iblock_id = false;
				foreach($this->arIBlockAllProps as $db_prop)
				{
					if($db_prop["USER_TYPE"]!="")
					{
						$arUserType = CIBlockProperty::GetUserType($db_prop["USER_TYPE"]);
						if(array_key_exists("ConvertFromDB", $arUserType))
							$this->arIBlockConvProps["PROPERTY_".$db_prop["ID"]] = array(
								"ConvertFromDB"=>$arUserType["ConvertFromDB"],
								"PROPERTY"=>$db_prop,
							);
					}
					$db_prop["ORIG_ID"] = $db_prop["ID"];
					if($db_prop["MULTIPLE"]=="Y")
						$this->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(mb_substr($val, 0, 9) == "PROPERTY_")
			{
				$PR_ID = mb_strtoupper($val);
				if(isset($arDisplayedColumns[$PR_ID]))
					continue;
				$arDisplayedColumns[$PR_ID] = true;
				$PR_ID = mb_substr($PR_ID, 9);

				$iblockIds = CIBlock::_MergeIBArrays(
					$arFilter["IBLOCK_ID"] ?? false,
					$arFilter["IBLOCK_CODE"] ?? false
				);

				if(preg_match("/^([^.]+)\.([^.]+)$/", $PR_ID, $arMatch))
				{
					$db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
					if (is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
					{
						$this->MkPropertySelect($arMatch, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect);
					}
				}
				else
				{
					$db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds);
					if ($db_prop)
					{
						$this->MkPropertySelect($PR_ID, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect);
					}
				}
			}
			elseif(mb_substr($val, 0, 13) == "PROPERTYSORT_")
			{
				$PR_ID = mb_strtoupper($val);
				if(isset($arDisplayedColumns[$PR_ID]))
					continue;
				$arDisplayedColumns[$PR_ID] = true;
				$PR_ID = mb_substr($PR_ID, 13);

				if(preg_match("/^([^.]+)\.([^.]+)$/", $PR_ID, $arMatch))
				{
					$db_prop = CIBlockProperty::GetPropertyArray($arMatch[1], $iblockIds);
					if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] == "E")
						$this->MkPropertySelect($arMatch, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect, true);
				}
				else
				{
					if($db_prop = CIBlockProperty::GetPropertyArray($PR_ID, $iblockIds))
						$this->MkPropertySelect($PR_ID, $db_prop, $arJoinProps, $bWasGroup, $sGroupBy, $sSelect, true);
				}
			}
			elseif($val == "*")
			{
				$bStar = true;
			}
			elseif ($this->catalogIncluded && CProductQueryBuilder::isValidField($val))
			{
				$arAddSelectFields[] = $val;
			}
			elseif(
				$val == "RATING_TOTAL_VALUE"
				|| $val == "RATING_TOTAL_VOTES"
				|| $val == "RATING_TOTAL_POSITIVE_VOTES"
				|| $val == "RATING_TOTAL_NEGATIVE_VOTES"
			)
			{
				if(isset($arDisplayedColumns[$val]))
					continue;
				$arDisplayedColumns[$val] = true;
				$arSelectFields[$key] = $val;
				$sSelect.=",".preg_replace("/^RATING_/", "RV.", $val)." as ".$val;
				$arJoinProps["RV"] = true;
			}
			elseif($val == "RATING_USER_VOTE_VALUE")
			{
				if(isset($arDisplayedColumns[$val]))
					continue;
				$arDisplayedColumns[$val] = true;
				$arSelectFields[$key] = $val;

				//if(isset($USER) && is_object($USER))
				if ($this->userExists)
				{
					$sSelect.=",".$DB->IsNull('RVU.VALUE', '0')." as ".$val;
					$arJoinProps["RVU"] = true;
				}
				else
				{
					$sSelect.=",0 as ".$val;
				}
			}
		}

		if($bStar)
		{
			foreach($arIblockElementFields as $key=>$val)
			{
				if(isset($arDisplayedColumns[$key]))
					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(isset($arDisplayedColumns["DETAIL_PAGE_URL"]))
				$arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
			elseif(isset($arDisplayedColumns["CANONICAL_PAGE_URL"]))
				$arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
			elseif(isset($arDisplayedColumns["SECTION_PAGE_URL"]))
				$arAddFields = array("LANG_DIR", "ID", "CODE", "EXTERNAL_ID", "IBLOCK_SECTION_ID", "IBLOCK_TYPE_ID", "IBLOCK_ID", "IBLOCK_CODE", "IBLOCK_EXTERNAL_ID", "LID");
			elseif(isset($arDisplayedColumns["LIST_PAGE_URL"]))
				$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(isset($arDisplayedColumns["DETAIL_TEXT"]))
				$arAddFields[] = "DETAIL_TEXT_TYPE";
			if(isset($arDisplayedColumns["PREVIEW_TEXT"]))
				$arAddFields[] = "PREVIEW_TEXT_TYPE";

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

		if($sGroupBy!="")
			$sSelect = mb_substr($sSelect, 1).", COUNT(%%_DISTINCT_%% BE.ID) as CNT ";
		elseif($sSelect !== '')
			$sSelect = "%%_DISTINCT_%% ".mb_substr($sSelect, 1)." ";
	}

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

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

	$sWhere = "";
	foreach ($arSqlSearch as $condition)
		if (trim($condition, "nt") !== '')
			$sWhere .= "ntttAND (".$condition.")";
}