• Модуль: search
  • Путь к файлу: ~/bitrix/modules/search/classes/general/search.php
  • Класс: CAllSearch
  • Вызов: CAllSearch::PrepareSearchResult
function PrepareSearchResult($str)
{
	//$words - contains what we will highlight
	$words = array();
	foreach ($this->Query->m_words as $v)
	{
		$v = ToUpper($v);
		$words[$v] = "KAV";
		if (mb_strpos($v, """) !== false)
			$words[str_replace(""", """, $v)] = "KAV";
	}

	foreach ($this->Query->m_stemmed_words as $v)
		$words[ToUpper($v)] = "STEM";

	//Prepare upper case version of the string
	if ($this->Query->bStemming)
	{
		//And add missing stemming words
		$arStemInfo = stemming_init($this->Query->m_lang);
		$a = stemming($this->Query->m_query, $this->Query->m_lang, true);
		foreach ($a as $stem => $cnt)
		{
			if (!preg_match("/cut[56]/i", $stem))
				$words[$stem] = "STEM";
		}
		$pcreLettersClass = "[".$arStemInfo["pcre_letters"]."]";
		$strUpp = stemming_upper($str, $this->Query->m_lang);
	}
	else
	{
		$strUpp = ToUpper($str);
		$pcreLettersClass = "";
	}

	$wordsCount = count($words);

	//We'll use regexp to find positions of the words in the text
	$pregMask = "";
	foreach ($words as $search => $type)
	{
		if ($type == "STEM")
			$pregMask = "(?Query->m_lang, true);
				foreach ($a as $stem => $cnt)
				{
					if (isset($words[$stem]))
					{
						$search = $stem;
						break;
					}
				}
			}

			if (isset($search))
			{
				$p = $oneCase[0][1];
				if (!isset($arPos[$search]))
					$arPos[$search] = $p;
				//Add to the tail of the running window
				$arPosP[] = $p;
				$arPosW[] = $search;
				$cc = count($arPosW);
				if ($cc >= $wordsCount)
				{
					//This cuts the tail of the running window
					while ($cc > $wordsCount)
					{
						array_shift($arPosW);
						array_shift($arPosP);
						$cc--;
					}
					//Check if all the words present in the current window
					if (count(array_unique($arPosW)) == $wordsCount)
					{
						//And check if positions is the best
						if (
							!$arPosLast
							|| (
								(max($arPosP) - min($arPosP)) < (max($arPosLast) - min($arPosLast))
							)
						)
							$arPosLast = $arPosP;
					}
				}
			}
		}
	}

	if ($arPosLast)
		$arPos = $arPosLast;

	//Nothing found just cut some text
	if (empty($arPos))
	{
		$str_len = mb_strlen($str);
		$pos_end = 500;
		while (($pos_end < $str_len) && (mb_strpos(" ,.nr", mb_substr($str, $pos_end, 1)) === false))
			$pos_end++;
		return mb_substr($str, 0, $pos_end).($pos_end < $str_len? "..." : "");
	}

	sort($arPos);

	$str_len = strlen($str);
	$delta = 250 / count($arPos);
	$arOtr = array();
	//Have to do it two times because Positions eat each other
	for ($i = 0; $i < 2; $i++)
	{
		$arOtr = array();
		$last_pos = -1;
		foreach ($arPos as $pos_mid)
		{
			//Find where sentence begins
			$pos_beg = $pos_mid - $delta;
			if ($pos_beg <= 0)
				$pos_beg = 0;
			while (($pos_beg > 0) && (mb_strpos(" ,.!?nr", substr($str, $pos_beg, 1)) === false))
				$pos_beg--;

			//Find where sentence ends
			$pos_end = $pos_mid + $delta;
			if ($pos_end > $str_len)
				$pos_end = $str_len;
			while (($pos_end < $str_len) && (mb_strpos(" ,.!?nr", substr($str, $pos_end, 1)) === false))
				$pos_end++;

			if ($pos_beg <= $last_pos)
				$arOtr[count($arOtr) - 1][1] = $pos_end;
			else
				$arOtr[] = array($pos_beg, $pos_end);

			$last_pos = $pos_end;
		}
		//Adjust length of the text
		$delta = 250 / count($arOtr);
	}

	$str_result = "";
	foreach ($arOtr as $borders)
	{
		$str_result .= ($borders[0] <= 0? "": " ...")
			.substr($str, $borders[0], $borders[1] - $borders[0] + 1)
			.($borders[1] >= $str_len? "": "... ");
	}

	foreach ($words as $search => $type)
	{
		$str_result = $this->Repl($search, $type, $str_result);
	}

	$str_result = str_replace("%/^%", "", str_replace("%^%", "", $str_result));

	return $str_result;
}