- Модуль: 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;
}