* */ /** * Модуль поиска * * @package modules.search * @since 2.0 */ class ModuleSearch extends Module { protected $oMapper; /** * Инициализация модуля */ public function Init() { $this->oMapper=Engine::GetMapper(__CLASS__); } /** * Выполняет поиск топиков по регулярному выражению * * @param $sRegexp * @param $iCurrPage * @param $iPerPage * * @return array */ public function SearchTopics($sRegexp,$iCurrPage,$iPerPage) { $sCacheKey="search_topics_{$sRegexp}_{$iCurrPage}_{$iPerPage}"; if (false===($data=$this->Cache_Get($sCacheKey))) { $data=array( 'collection'=> $this->oMapper->SearchTopics($sRegexp,$iCount,$iCurrPage,$iPerPage), 'count'=> $iCount ); $this->Cache_Set($data,$sCacheKey,array('topic_update','topic_new'),60*60*24*1); } if ($data['collection']) { $data['collection']=$this->Topic_GetTopicsAdditionalData($data['collection']); } return $data; } /** * Выполняет поиск комментариев по регулярному выражению * * @param $sRegexp * @param $iCurrPage * @param $iPerPage * @param $sTargetType * * @return array */ public function SearchComments($sRegexp,$iCurrPage,$iPerPage,$sTargetType) { $sCacheKey="search_comments_{$sRegexp}_{$iCurrPage}_{$iPerPage}_".serialize($sTargetType); if (false===($data=$this->Cache_Get($sCacheKey))) { $data=array( 'collection'=> $this->oMapper->SearchComments($sRegexp,$iCount,$iCurrPage,$iPerPage,$sTargetType), 'count'=> $iCount ); $this->Cache_Set($data,$sCacheKey,array('comment_new'),60*60*24*1); } if ($data['collection']) { $data['collection']=$this->Comment_GetCommentsAdditionalData($data['collection']); } return $data; } /** * Выделяет отрывки из текста с необходимыми словами (делает сниппеты) * * @param string $sText Исходный текст * @param array|string $aWords Список слов * @param array $aParams Список параметром * * @return string */ public function BuildExcerpts($sText,$aWords,$aParams=array()) { $iMaxLengthBetweenWords=isset($aParams['iMaxLengthBetweenWords']) ? $aParams['iMaxLengthBetweenWords'] : 200; $iLengthIndentSection=isset($aParams['iLengthIndentSection']) ? $aParams['iLengthIndentSection'] : 100; $iMaxCountSections=isset($aParams['iMaxCountSections']) ? $aParams['iMaxCountSections'] : 3; $sWordWrapBegin=isset($aParams['sWordWrapBegin']) ? $aParams['sWordWrapBegin'] : ''; $sWordWrapEnd=isset($aParams['sWordWrapEnd']) ? $aParams['sWordWrapEnd'] : ''; $sGlueSections=isset($aParams['sGlueSections']) ? $aParams['sGlueSections'] : "\r\n"; $sText=strip_tags($sText); $sText=trim($sText); if (is_string($aWords)) { $aWords=preg_split('#[\W]+#u',$aWords); } $sPregWords=join('|',array_filter($aWords,'preg_quote')); $aSections=array(); if (preg_match_all("#{$sPregWords}#i",$sText,$aMatchAll,PREG_OFFSET_CAPTURE)) { $aSectionItems=array(); $iCountDiff=-1; foreach($aMatchAll[0] as $aMatch) { if ($iCountDiff==-1 or $aMatch[1]-$iCountDiff<=$iMaxLengthBetweenWords) { $aSectionItems[]=$aMatch; $iCountDiff=$aMatch[1]; } else { $aSections[]=array('items'=>$aSectionItems); $aSectionItems=array(); $aSectionItems[]=$aMatch; $iCountDiff=$aMatch[1]; } } if (count($aSectionItems)) { $aSections[]=array('items'=>$aSectionItems); } } $aSections=array_slice($aSections,0,$iMaxCountSections); $sTextResult=''; if ($aSections) { foreach($aSections as $aSection) { /** * Расчитываем дополнительные данные: начало и конец фрагмента, уникальный список слов */ $aItem=reset($aSection['items']); $aSection['begin']=$aItem[1]; $aItem=end($aSection['items']); $aSection['end']=$aItem[1]+mb_strlen($aItem[0],'utf-8'); $aSection['words']=array(); foreach($aSection['items'] as $aItem) { $sKey=mb_strtolower($aItem[0],'utf-8'); $aSection['words'][$sKey]=$aItem[0]; } /** * Формируем фрагменты текста */ /** * Определям правую границу текста по слову */ $iEnd=$aSection['end']; for($i=$iEnd;($i<=$aSection['end']+$iLengthIndentSection) and $i=$aSection['begin']-$iLengthIndentSection) and $i>=0;$i--) { if (preg_match('#^\s$#',mb_substr($sText,$i,1,'utf-8'))) { $iBegin=$i; } } /** * Вырезаем фрагмент текста */ $sTextSection=trim(mb_substr($sText,$iBegin,$iEnd-$iBegin,'utf-8')); if ($iBegin>0) { $sTextSection='...'.$sTextSection; } if ($iEndmb_strlen($sText,'utf-8')) { $iLength=mb_strlen($sText,'utf-8'); } $sTextResult=trim(mb_substr($sText,0,$iLength-1,'utf-8')); } return $sTextResult; } /** * Возвращает массив слов из поискового запроса * * @param $sQuery * * @return array */ public function GetWordsForSearch($sQuery) { /** * Удаляем запрещенные символы */ $sQuery=preg_replace('#[^\w\sа-я\-]+#iu',' ',$sQuery); /** * Разбиваем фразу на слова */ $aWords=preg_split('#[\s]+#u',$sQuery); foreach($aWords as $k=>$sWord) { /** * Короткие слова удаляем */ if (mb_strlen($sWord,'utf-8')<3) { unset($aWords[$k]); } } return $aWords; } /** * Возвращает регулярное выражение для поиска в БД по словам * * @param $aWords * * @return string */ public function GetRegexpForWords($aWords) { return join('|',$aWords); } }