• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/lib/propertyindex/querybuilder.php
  • Класс: BitrixIblockPropertyIndexQueryBuilder
  • Вызов: QueryBuilder::getFilterSql
public function getFilterSql(&$filter, &$sqlSearch)
{
	if (array_key_exists("FACET_OPTIONS", $filter))
	{
		if (is_array($filter["FACET_OPTIONS"]))
		{
			$this->options = $filter["FACET_OPTIONS"];
		}
		unset($filter["FACET_OPTIONS"]);
	}

	$this->distinct = false;
	$fcJoin = "";
	$toUnset = array();
	if (
		isset($filter["IBLOCK_ID"]) && !is_array($filter["IBLOCK_ID"]) && $filter["IBLOCK_ID"] > 0
		&& (
			(isset($filter["SECTION_ID"]) && !is_array($filter["SECTION_ID"]) && $filter["SECTION_ID"] > 0)
			|| ($this->options && !isset($filter["SECTION_ID"]))
		)
		&& isset($filter["ACTIVE"]) && $filter["ACTIVE"] === "Y"
	)
	{
		$where = array();
		$toUnset[] = array(&$filter, "SECTION_ID");

		if (isset($filter["INCLUDE_SUBSECTIONS"]) && $filter["INCLUDE_SUBSECTIONS"] === "Y")
		{
			$subsectionsCondition = "";
			$toUnset[] = array(&$filter, "INCLUDE_SUBSECTIONS");
		}
		else
		{
			$subsectionsCondition = "INCLUDE_SUBSECTIONS=1";
			if (array_key_exists("INCLUDE_SUBSECTIONS", $filter))
				$toUnset[] = array(&$filter, "INCLUDE_SUBSECTIONS");
		}

		$hasAdditionalFilters = false;
		$this->fillWhere($where, $hasAdditionalFilters, $toUnset, $filter);

		if (!$where)
		{
			$where[] = array(
				"TYPE" => Storage::DICTIONARY,
				"OP" => "=",
				"FACET_ID" => 1,
				"VALUES" => array(0),
			);
		}

		if (
			isset($filter["=ID"]) && is_object($filter["=ID"])
			&& $filter["=ID"]->arFilter["IBLOCK_ID"] == $this->facet->getSkuIblockId()
			&& $filter["=ID"]->strField === "PROPERTY_".$this->facet->getSkuPropertyId()
		)
		{
			$hasAdditionalFilters = false;
			$this->fillWhere($where, $hasAdditionalFilters, $toUnset, $filter["=ID"]->arFilter);
			if (!$hasAdditionalFilters)
			{
				$toUnset[] = array(&$filter, "=ID");
			}
		}

		if ($where)
		{
			$filter["SECTION_ID"] = (isset($filter["SECTION_ID"]) ? (int)$filter["SECTION_ID"] : 0);
			$this->facet->setSectionId($filter["SECTION_ID"]);
			if ($this->options)
			{
				if (isset($this->options["CURRENCY_CONVERSION"]) && $this->options["CURRENCY_CONVERSION"])
				{
					$this->facet->enableCurrencyConversion(
						$this->options["CURRENCY_CONVERSION"]["TO"] ?? '',
						$this->options["CURRENCY_CONVERSION"]["FROM"] ?? ''
					);
				}
			}
			$distinctSelectCapable = (BitrixMainApplication::getConnection()->getType() == "mysql");
			if (count($where) == 1 && $distinctSelectCapable)
			{
				$this->distinct = true;
				$fcJoin = "INNER JOIN ".$this->storage->getTableName()." FC on FC.ELEMENT_ID = BE.ID";
				foreach ($where as $facetFilter)
				{
					$sqlWhere = $this->facet->whereToSql($facetFilter, "FC", $subsectionsCondition);
					if ($sqlWhere)
						$sqlSearch[] = $sqlWhere;
				}
			}
			elseif (count($where) <= 5)
			{
				$subJoin = "";
				$subWhere = "";
				$i = 0;
				foreach ($where as $facetFilter)
				{
					if ($i == 0)
						$subJoin .= "FROM ".$this->storage->getTableName()." FC$in";
					else
						$subJoin .= "INNER JOIN ".$this->storage->getTableName()." FC$i ON FC$i.ELEMENT_ID = FC0.ELEMENT_IDn";

					$sqlWhere = $this->facet->whereToSql($facetFilter, "FC$i", $subsectionsCondition);
					if ($sqlWhere)
					{
						if ($subWhere)
							$subWhere .= "nAND ".$sqlWhere;
						else
							$subWhere .= $sqlWhere;
					}

					$i++;
				}

				$fcJoin = "
					INNER JOIN (
						SELECT ".($distinctSelectCapable? "DISTINCT": "")." FC0.ELEMENT_ID
						$subJoin
						WHERE
						$subWhere
					) FC on FC.ELEMENT_ID = BE.ID
				";
			}
			else
			{
				$condition = array();
				foreach ($where as $facetFilter)
				{
					$sqlWhere = $this->facet->whereToSql($facetFilter, "FC0", $subsectionsCondition);
					if ($sqlWhere)
						$condition[] = $sqlWhere;
				}
				$fcJoin = "
					INNER JOIN (
						SELECT FC0.ELEMENT_ID
						FROM ".$this->storage->getTableName()." FC0
						WHERE FC0.SECTION_ID = ".$filter["SECTION_ID"]."
						AND (
						(".implode(")OR(", $condition).")
						)
					GROUP BY FC0.ELEMENT_ID
					HAVING count(DISTINCT FC0.FACET_ID) = ".count($condition)."
					) FC on FC.ELEMENT_ID = BE.ID
				";
			}

			foreach ($toUnset as $command)
			{
				unset($command[0][$command[1]]);
			}
		}
		else
		{
			$fcJoin = "";
		}
	}
	return $fcJoin;
}