| Current Path : /var/www/element/data/www/greenpr.ru/bitrix3/modules/search/classes/mysql/ |
| Current File : /var/www/element/data/www/greenpr.ru/bitrix3/modules/search/classes/mysql/search.php |
<?
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/search/classes/general/search.php");
class CSearch extends CAllSearch
{
function MakeSQL($query, $strSqlWhere, $strSort, $bIncSites, $bStem)
{
global $DB, $USER;
if(strpos($strSort, "TITLE_RANK") !== false)
{
if($bStem)
{
$strSelect = "";
foreach($this->Query->m_stemmed_words as $stem)
{
if(strlen($strSelect) > 0)
$strSelect .= " + ";
$strSelect .= "if(locate('".$stem."', upper(sc.TITLE)) > 0, 1, 0)";
}
$strSelect = ",".$strSelect." TITLE_RANK\n";
}
else
{
$strSelect = "";
foreach($this->Query->m_words as $word)
{
if(strlen($strSelect) > 0)
$strSelect .= " + ";
$strSelect .= "if(locate('".$DB->ForSql(ToUpper($word))."', upper(sc.TITLE)) > 0, 1, 0)";
}
$strSelect = ",".$strSelect." TITLE_RANK\n";
}
}
else
{
$strSelect = "";
}
if($bIncSites && $bStem)
{
if(strpos($query, "sc.")===false)
{
$strSqlWhere = preg_replace('# AND st.TF >= [0-9\.,]+#i', "", $strSqlWhere);
$strSql = "
SELECT
sc.ID
,sc.MODULE_ID
,sc.ITEM_ID
,sc.LID
,sc.TITLE
,sc.TAGS
,sc.BODY
,sc.SEARCHABLE_CONTENT
,sc.PARAM1
,sc.PARAM2
,sc.UPD
,sc.DATE_FROM
,sc.DATE_TO
,L.DIR
,L.SERVER_NAME
,sc.URL as URL
,stt.TF as RANK
,scsite.URL as SITE_URL
,scsite.SITE_ID
,".$DB->DateToCharFunction("sc.DATE_CHANGE")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("sc.DATE_CHANGE", "SHORT")." as DATE_CHANGE
".$strSelect."
FROM b_search_content sc
INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
INNER JOIN b_lang L ON scsite.SITE_ID=L.LID
INNER JOIN ".(count($this->Query->m_stemmed_words) > 1?
"(
select search_content_id, max(st.TF) TF, sum(st.TF/sf.FREQ) as RANK
from b_search_content_stem st, b_search_content_freq sf
where st.language_id = '".$this->Query->m_lang."'
and st.stem = sf.stem
and sf.language_id = st.language_id
and st.stem in ('".implode("' ,'", $this->Query->m_stemmed_words)."')
".($this->tf_hwm > 0? "and st.TF >= ".number_format($this->tf_hwm, 2, ".", ""): "")."
".(strlen($this->tf_hwm_site_id) > 0? "and sf.SITE_ID = '".$DB->ForSQL($this->tf_hwm_site_id, 2)."'": "and sf.SITE_ID IS NULL")."
group by st.search_content_id
having (".$query.")
)"
:
"(
select st0.search_content_id, st0.TF, st0.TF RANK
from b_search_content_stem st0
where st0.language_id = '".$this->Query->m_lang."'
and st0.stem in ('".implode("' ,'", $this->Query->m_stemmed_words)."')
".($this->tf_hwm > 0? "and st0.TF >= ".number_format($this->tf_hwm, 2, ".", ""): "")."
)"
)." stt ON sc.id = stt.search_content_id
WHERE
".CSearch::CheckPermissions("sc.ID")."
".$strSqlWhere."
".$strSort."
";
}
else
{
$strSql = "
SELECT
sc.ID
,sc.MODULE_ID
,sc.ITEM_ID
,sc.LID
,sc.TITLE
,sc.TAGS
,sc.BODY
,sc.SEARCHABLE_CONTENT
,sc.PARAM1
,sc.PARAM2
,sc.UPD
,sc.DATE_FROM
,sc.DATE_TO
,L.DIR
,L.SERVER_NAME
,sc.URL as URL
,".(count($this->Query->m_stemmed_words)>1?"sum(st.TF/sf.FREQ)":"st.TF")." as RANK
,scsite.URL as SITE_URL
,scsite.SITE_ID
,".$DB->DateToCharFunction("sc.DATE_CHANGE")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("sc.DATE_CHANGE", "SHORT")." as DATE_CHANGE
".$strSelect."
FROM b_search_content sc
INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
INNER JOIN b_lang L ON scsite.SITE_ID=L.LID
INNER JOIN b_search_content_stem st ON sc.id = st.search_content_id+0
".(count($this->Query->m_stemmed_words)>1?
"INNER JOIN b_search_content_freq sf ON
st.language_id = sf.language_id
and st.stem=sf.stem
".(strlen($this->tf_hwm_site_id) > 0?
"and sf.SITE_ID = '".$DB->ForSQL($this->tf_hwm_site_id, 2)."'":
"and sf.SITE_ID IS NULL"
):
""
)."
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND st.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')
".(count($this->Query->m_stemmed_words)>1? "AND sf.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')": "")."
AND st.language_id='".$this->Query->m_lang."'
".$strSqlWhere."
".(count($this->Query->m_stemmed_words)>1?"
GROUP BY
sc.ID
,L.DIR
,L.SERVER_NAME
,scsite.URL
,scsite.SITE_ID
HAVING
(".$query.") ": "")."
".$strSort."
";
}
}
elseif($bIncSites && !$bStem)
$strSql = "
SELECT DISTINCT
sc.ID
,sc.MODULE_ID
,sc.ITEM_ID
,sc.LID
,sc.TITLE
,sc.TAGS
,sc.BODY
,sc.SEARCHABLE_CONTENT
,sc.PARAM1
,sc.PARAM2
,sc.UPD
,sc.DATE_FROM
,sc.DATE_TO
,L.DIR
,L.SERVER_NAME
,sc.URL as URL
,1 as RANK
,scsite.URL as SITE_URL
,scsite.SITE_ID
,".$DB->DateToCharFunction("sc.DATE_CHANGE")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("sc.DATE_CHANGE", "SHORT")." as DATE_CHANGE
".$strSelect."
FROM b_search_content sc
INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
INNER JOIN b_lang L ON scsite.SITE_ID=L.LID
".($this->Query->bTagsSearch? "
INNER JOIN b_search_tags stags ON (sc.ID = stags.SEARCH_CONTENT_ID)
WHERE
".CSearch::CheckPermissions("sc.ID")."
".$strSqlWhere."
".(is_array($this->Query->m_tags_words) && count($this->Query->m_tags_words)>0? "AND stags.NAME in ('".implode("','", $this->Query->m_tags_words)."')": "")."
GROUP BY
sc.ID
,L.DIR
,L.SERVER_NAME
,scsite.URL
,scsite.SITE_ID
HAVING
(".$query.")": "
WHERE
".CSearch::CheckPermissions("sc.ID")." AND (".$query.") ".$strSqlWhere."")."
".$strSort."
";
elseif(!$bIncSites && $bStem)
$strSql = "
SELECT
sc.ID
,sc.MODULE_ID
,sc.ITEM_ID
,sc.LID
,sc.TITLE
,sc.TAGS
,sc.BODY
,sc.SEARCHABLE_CONTENT
,sc.PARAM1
,sc.PARAM2
,sc.UPD
,sc.DATE_FROM
,sc.DATE_TO
,L.DIR
,L.SERVER_NAME
,sc.URL as URL
".(count($this->Query->m_stemmed_words)>1?",sum(st.TF/sf.FREQ)":",st.TF")." as RANK
,".$DB->DateToCharFunction("sc.DATE_CHANGE")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("sc.DATE_CHANGE", "SHORT")." as DATE_CHANGE
".$strSelect."
FROM b_search_content sc
INNER JOIN b_lang L ON sc.LID=L.LID
INNER JOIN b_search_content_stem st ON sc.id = st.search_content_id
".(count($this->Query->m_stemmed_words)>1?
"INNER JOIN b_search_content_freq sf ON
st.language_id = sf.language_id
and st.stem=sf.stem
".(strlen($this->tf_hwm_site_id) > 0?
"and sf.SITE_ID = '".$DB->ForSQL($this->tf_hwm_site_id, 2)."'":
"and sf.SITE_ID IS NULL"
):
""
)."
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND st.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')
".(count($this->Query->m_stemmed_words)>1? "AND sf.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')": "")."
AND st.language_id='".$this->Query->m_lang."'
".$strSqlWhere."
".(count($this->Query->m_stemmed_words)>1?"
GROUP BY
sc.ID
,L.DIR
,L.SERVER_NAME
HAVING
(".$query.") ": "")."
".$strSort."
";
else //if(!$bIncSites && !$bStem)
$strSql = "
SELECT DISTINCT
sc.ID
,sc.MODULE_ID
,sc.ITEM_ID
,sc.LID
,sc.TITLE
,sc.TAGS
,sc.BODY
,sc.SEARCHABLE_CONTENT
,sc.PARAM1
,sc.PARAM2
,sc.UPD
,sc.DATE_FROM
,sc.DATE_TO
,L.DIR
,L.SERVER_NAME
,sc.URL as URL
,1 as RANK
,".$DB->DateToCharFunction("sc.DATE_CHANGE")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("sc.DATE_CHANGE", "SHORT")." as DATE_CHANGE
".$strSelect."
FROM b_search_content sc
INNER JOIN b_lang L ON sc.LID=L.LID
".($this->Query->bTagsSearch? "INNER JOIN b_search_tags stags ON (sc.ID = stags.SEARCH_CONTENT_ID)
WHERE
".CSearch::CheckPermissions("sc.ID")."
".$strSqlWhere."
".(is_array($this->Query->m_tags_words) && count($this->Query->m_tags_words)>0? "AND stags.NAME in ('".implode("','", $this->Query->m_tags_words)."')": "")."
GROUP BY
sc.ID
,L.DIR
,L.SERVER_NAME
HAVING
(".$query.")" :
" WHERE
(".$query.")
".$strSqlWhere."
")."
".$strSort."
";
$limit = COption::GetOptionInt("search", "max_result_size");
if($limit<1)
$limit=500;
return $strSql."LIMIT ".$limit;
}
function CheckPermissions($FIELD = "sc.ID")
{
global $USER;
$arResult = array();
if($USER->IsAdmin())
{
$arResult[] = "1=1";
}
else
{
$arResult[] = "
EXISTS (
SELECT 1
FROM b_search_content_group scg
WHERE ".$FIELD." = scg.SEARCH_CONTENT_ID
AND scg.GROUP_ID IN (".implode(",", $USER->GetUserGroupArray()).")
)";
$events = GetModuleEvents("search", "OnSearchCheckPermissions");
while($arEvent = $events->Fetch())
{
$strCheck = ExecuteModuleEvent($arEvent, $FIELD);
if(strlen($strCheck))
$arResult[] = $strCheck;
}
}
return "((".implode(") OR (", $arResult)."))";
}
function tagsMakeSQL($query, $strSqlWhere, $strSort, $bIncSites, $bStem, $limit = 100)
{
global $DB, $USER;
$limit = intVal($limit);
if($bStem && count($this->Query->m_stemmed_words)>1)
{//We have to make some magic in case quotes was used in query
//We have to move (sc.searchable_content LIKE '%".ToUpper($word)."%') from $query to $strSqlWhere
while(preg_match("/(AND\s+\(sc.searchable_content LIKE \'\%.+?\%\'\))/", $query, $arMatches))
{
$strSqlWhere .= $arMatches[0];
$query = str_replace($arMatches[0], "", $query);
}
}
if($bIncSites && $bStem)
$strSql = "
SELECT
stags.NAME
,COUNT(DISTINCT stags.SEARCH_CONTENT_ID) as CNT
,MAX(sc.DATE_CHANGE) DC_TMP
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)", "SHORT")." as DATE_CHANGE
".(count($this->Query->m_stemmed_words)>1 && strpos($query, "searchable_content")!==false?"
,sc.SEARCHABLE_CONTENT
": "")."
FROM b_search_tags stags
INNER JOIN b_search_content sc ON (stags.SEARCH_CONTENT_ID=sc.ID)
INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID
INNER JOIN b_search_content_stem st ON sc.id = st.search_content_id
".(count($this->Query->m_stemmed_words)>1?
"INNER JOIN b_search_content_freq sf ON
st.language_id = sf.language_id
and st.stem=sf.stem
".(strlen($this->tf_hwm_site_id) > 0?
"and sf.SITE_ID = '".$DB->ForSQL($this->tf_hwm_site_id, 2)."'":
"and sf.SITE_ID IS NULL"
):
""
)."
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND st.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')
".(count($this->Query->m_stemmed_words)>1? "AND sf.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')": "")."
AND st.language_id='".$this->Query->m_lang."'
AND stags.SITE_ID = scsite.SITE_ID
".$strSqlWhere."
GROUP BY
stags.NAME
".((count($this->Query->m_stemmed_words)>1)?"
HAVING
(".$query.") ": "")."
".$strSort."
";
elseif($bIncSites && !$bStem)
{
if($query == "1=1")
{
$strSql = "
SELECT
stags2.NAME
,COUNT(DISTINCT stags2.SEARCH_CONTENT_ID) as CNT
,MAX(sc.DATE_CHANGE) DC_TMP
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)", "SHORT")." as DATE_CHANGE
FROM b_search_tags stags2
INNER JOIN b_search_content sc ON (stags2.SEARCH_CONTENT_ID=sc.ID)
INNER JOIN b_search_content_site scsite ON (sc.ID=scsite.SEARCH_CONTENT_ID AND stags2.SITE_ID=scsite.SITE_ID)
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND ".($this->Query->bTagsSearch? (
//Index range scan optimization (make it for other queries ???)
is_array($this->Query->m_tags_words) && count($this->Query->m_tags_words)?
"stags.name in ('".implode("', '", $this->Query->m_tags_words)."')":
"(1=1)"
) : "(".$query.")")." ".$strSqlWhere."
GROUP BY
stags2.NAME
".$strSort."
";
}
else
{
$strSql = "
SELECT
stags2.NAME
,COUNT(DISTINCT stags.SEARCH_CONTENT_ID) as CNT
,MAX(sc.DATE_CHANGE) DC_TMP
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)", "SHORT")." as DATE_CHANGE
FROM b_search_tags stags2
INNER JOIN b_search_tags stags ON (stags.SEARCH_CONTENT_ID=stags2.SEARCH_CONTENT_ID and stags.SITE_ID=stags2.SITE_ID)
INNER JOIN b_search_content sc ON (stags.SEARCH_CONTENT_ID=sc.ID)
INNER JOIN b_search_content_site scsite ON (sc.ID=scsite.SEARCH_CONTENT_ID AND stags.SITE_ID=scsite.SITE_ID)
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND ".($this->Query->bTagsSearch? (
//Index range scan optimization (make it for other queries ???)
is_array($this->Query->m_tags_words) && count($this->Query->m_tags_words)?
"stags.name in ('".implode("', '", $this->Query->m_tags_words)."')":
"(1=1)"
) : "(".$query.")")." ".$strSqlWhere."
GROUP BY
stags2.NAME
".($this->Query->bTagsSearch? "
HAVING
(".$query.")": "")."
".$strSort."
";
}
}
elseif(!$bIncSites && $bStem)
$strSql = "
SELECT
stags.NAME
,COUNT(DISTINCT stags.SEARCH_CONTENT_ID) as CNT
,MAX(sc.DATE_CHANGE) DC_TMP
, ".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)")." as FULL_DATE_CHANGE
, ".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)", "SHORT")." as DATE_CHANGE
".(count($this->Query->m_stemmed_words)>1 && strpos($query, "searchable_content")!==false?"
,sc.SEARCHABLE_CONTENT
": "")."
FROM b_search_tags stags
INNER JOIN b_search_content sc ON (stags.SEARCH_CONTENT_ID=sc.ID)
INNER JOIN b_search_content_stem st ON sc.id = st.search_content_id
".(count($this->Query->m_stemmed_words)>1?
"INNER JOIN b_search_content_freq sf ON
st.language_id = sf.language_id
and st.stem=sf.stem
".(strlen($this->tf_hwm_site_id) > 0?
"and sf.SITE_ID = '".$DB->ForSQL($this->tf_hwm_site_id, 2)."'":
"and sf.SITE_ID IS NULL"
):
""
)."
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND st.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')
".(count($this->Query->m_stemmed_words)>1? "AND sf.STEM in ('".implode("','", $this->Query->m_stemmed_words)."')": "")."
AND st.language_id='".$this->Query->m_lang."'
".$strSqlWhere."
GROUP BY
stags.NAME
".(count($this->Query->m_stemmed_words)>1?"
,sc.ID
,sc.SEARCHABLE_CONTENT
HAVING
(".$query.") ": "")."
".$strSort."
";
else //if(!$bIncSites && !$bStem)
$strSql = "
SELECT
stags2.NAME
,COUNT(DISTINCT stags.SEARCH_CONTENT_ID) as CNT
,MAX(sc.DATE_CHANGE) DC_TMP
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)")." as FULL_DATE_CHANGE
,".$DB->DateToCharFunction("MAX(sc.DATE_CHANGE)", "SHORT")." as DATE_CHANGE
FROM b_search_tags stags2
INNER JOIN b_search_tags stags ON (stags.SEARCH_CONTENT_ID=stags2.SEARCH_CONTENT_ID and stags.SITE_ID=stags2.SITE_ID)
INNER JOIN b_search_content sc ON (stags.SEARCH_CONTENT_ID=sc.ID)
WHERE
".CSearch::CheckPermissions("sc.ID")."
AND ".($this->Query->bTagsSearch? (
//Index range scan optimization (make it for other queries ???)
is_array($this->Query->m_tags_words) && count($this->Query->m_tags_words)?
"stags.name in ('".implode("', '", $this->Query->m_tags_words)."')":
"(1=1)"
) : "(".$query.")")." ".$strSqlWhere."
GROUP BY
stags2.NAME
".($this->Query->bTagsSearch? "
HAVING
(".$query.")": "")."
".$strSort."
";
if($limit < 1)
$limit = 150;
return $strSql."LIMIT ".$limit;
}
function ReindexLock()
{
//do not lock for mysql database
}
function DeleteOld($SESS_ID, $MODULE_ID="", $SITE_ID="")
{
global $DB;
$strFilter = "";
if($MODULE_ID!="")
$strFilter.=" AND MODULE_ID = '".$DB->ForSql($MODULE_ID)."' ";
$strJoin = "";
if($SITE_ID!="")
{
$strFilter.=" AND scsite.SITE_ID = '".$DB->ForSql($SITE_ID)."' ";
$strJoin.=" INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID ";
}
if(!is_array($SESS_ID))
$SESS_ID = array($SESS_ID);
$strSql = "
SELECT ID
FROM b_search_content sc
".$strJoin."
WHERE (UPD not in ('".implode("', '", $SESS_ID)."') OR UPD IS NULL)
".$strFilter."
";
$arEvents = array();
$db_events = GetModuleEvents("search", "OnBeforeIndexDelete");
while($arEvent = $db_events->Fetch())
$arEvents[] = $arEvent;
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
foreach($arEvents as $arEvent)
ExecuteModuleEvent($arEvent, "SEARCH_CONTENT_ID = ".$ar["ID"]);
$DB->Query("DELETE FROM b_search_content_group WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_stem WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_tags WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_site WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content WHERE ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
CSearchTags::CleanCache();
}
function DeleteForReindex($MODULE_ID)
{
global $DB;
$MODULE_ID = $DB->ForSql($MODULE_ID);
$strSql = "SELECT ID FROM b_search_content WHERE MODULE_ID = '".$MODULE_ID."'";
$arEvents = array();
$db_events = GetModuleEvents("search", "OnBeforeIndexDelete");
while($arEvent = $db_events->Fetch())
$arEvents[] = $arEvent;
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
foreach($arEvents as $arEvent)
ExecuteModuleEvent($arEvent, "SEARCH_CONTENT_ID = ".$ar["ID"]);
$DB->Query("DELETE FROM b_search_content_group WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_stem WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_tags WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_site WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content WHERE ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
CSearchTags::CleanCache();
}
function OnLangDelete($lang)
{
global $DB;
$lang = $DB->ForSql($lang);
$strSql = "
SELECT SEARCH_CONTENT_ID ID
FROM b_search_content_site
WHERE SITE_ID='".$lang."'
GROUP BY SEARCH_CONTENT_ID
HAVING COUNT(*)=1
";
$arEvents = array();
$db_events = GetModuleEvents("search", "OnBeforeIndexDelete");
while($arEvent = $db_events->Fetch())
$arEvents[] = $arEvent;
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
foreach($arEvents as $arEvent)
ExecuteModuleEvent($arEvent, "SEARCH_CONTENT_ID = ".$ar["ID"]);
$DB->Query("DELETE FROM b_search_content_group WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_stem WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_tags WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_site WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content WHERE ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
$DB->Query("DELETE FROM b_search_content_site WHERE SITE_ID='".$lang."'", false, "File: ".__FILE__."<br>Line: ".__LINE__);
$r = $DB->Query("
SELECT sc.ID, MIN(scsite.SITE_ID) as SITE_ID
FROM b_search_content sc, b_search_content_site scsite
WHERE sc.LID = '".$lang."'
AND sc.ID = scsite.SEARCH_CONTENT_ID
AND scsite.SITE_ID <> '".$lang."'
GROUP BY sc.ID
", false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($arR = $r->Fetch())
$DB->Query("UPDATE b_search_content SET LID = '".$arR["SITE_ID"]."' WHERE ID=".$arR["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content WHERE LID='".$lang."'", false, "File: ".__FILE__."<br>Line: ".__LINE__);
CSearchTags::CleanCache();
}
function ChangePermission($MODULE_ID, $arGroups, $ITEM_ID=false, $PARAM1=false, $PARAM2=false, $SITE_ID=false)
{
global $DB;
$strSqlWhere = CSearch::__PrepareFilter(Array("MODULE_ID"=>$MODULE_ID, "ITEM_ID"=>$ITEM_ID, "PARAM1"=>$PARAM1, "PARAM2"=>$PARAM2, "SITE_ID"=>$SITE_ID), $bIncSites);
$strSql = "
SELECT sc.ID
FROM b_search_content sc
".($bIncSites? "INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID": "")."
WHERE
".$strSqlWhere."
";
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
$DB->Query("DELETE FROM b_search_content_group WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$arNewGroups = array();
foreach($arGroups as $group)
{
$group = intval($group);
if($group > 0)
$arNewGroups[$group] = $group;
}
if(count($arNewGroups))
{
if(strlen($strSqlWhere)>0)
$strSqlWhere = "AND ".$strSqlWhere;
$strSql = "
INSERT INTO b_search_content_group(SEARCH_CONTENT_ID, GROUP_ID)
SELECT DISTINCT sc.ID, g.ID
FROM b_group g, b_search_content sc
".($bIncSites?" INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID ":"")."
WHERE g.ID IN (".implode(",", $arNewGroups).")
".$strSqlWhere."
";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
function ChangeSite($MODULE_ID, $arSite, $ITEM_ID=false, $PARAM1=false, $PARAM2=false, $SITE_ID=false)
{
global $DB;
$strSqlWhere = CSearch::__PrepareFilter(Array("MODULE_ID"=>$MODULE_ID, "ITEM_ID"=>$ITEM_ID, "PARAM1"=>$PARAM1, "PARAM2"=>$PARAM2, "SITE_ID"=>$SITE_ID), $bIncSites);
$strSql = "
SELECT sc.ID
FROM b_search_content sc
".($bIncSites? "INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID": "")."
WHERE
".$strSqlWhere."
";
$r = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($arR = $r->Fetch())
{
$DB->Query("DELETE FROM b_search_content_site WHERE SEARCH_CONTENT_ID = ".$arR["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$bFirst = true;
foreach($arSite as $site => $url)
{
if($bFirst)
{
$strSql = "
UPDATE b_search_content
SET LID = '".$DB->ForSql($site, 2)."',
URL = '".$DB->ForSql($url, 2000)."'
WHERE ID = ".$arR["ID"]."
";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
$bFirst = false;
}
$strSql = "
INSERT INTO b_search_content_site(SEARCH_CONTENT_ID, SITE_ID, URL)
VALUES(".$arR["ID"].", '".$DB->ForSql($site, 2)."', '".$DB->ForSql($url, 2000)."')";
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
}
function DeleteIndex($MODULE_ID, $ITEM_ID=false, $PARAM1=false, $PARAM2=false, $SITE_ID=false)
{
global $DB;
if($PARAM1 !== false && $PARAM2 !== false)
$strSqlWhere = CSearch::__PrepareFilter(Array("MODULE_ID"=>$MODULE_ID, "ITEM_ID"=>$ITEM_ID, array("=PARAM1"=>$PARAM1, "PARAM2"=>$PARAM2), "SITE_ID"=>$SITE_ID), $bIncSites);
else
$strSqlWhere = CSearch::__PrepareFilter(Array("MODULE_ID"=>$MODULE_ID, "ITEM_ID"=>$ITEM_ID, "PARAM1"=>$PARAM1, "PARAM2"=>$PARAM2, "SITE_ID"=>$SITE_ID), $bIncSites);
$strSql = "
SELECT sc.ID
FROM b_search_content sc
".($bIncSites? "INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID" :"")."
WHERE
".$strSqlWhere."
";
$arEvents = array();
$db_events = GetModuleEvents("search", "OnBeforeIndexDelete");
while($arEvent = $db_events->Fetch())
$arEvents[] = $arEvent;
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
foreach($arEvents as $arEvent)
ExecuteModuleEvent($arEvent, "SEARCH_CONTENT_ID = ".$ar["ID"]);
$DB->Query("DELETE FROM b_search_content_group WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_stem WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_tags WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content_site WHERE SEARCH_CONTENT_ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
$DB->Query("DELETE FROM b_search_content WHERE ID = ".$ar["ID"], false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
CSearchTags::CleanCache();
}
function FormatDateString($strField)
{
return "DATE_FORMAT(".$strField.", '%d.%m.%Y %H:%i:%s')";
}
function FormatLimit($strSql, $limit)
{
return str_replace("/*TOP*/", "", $strSql)."LIMIT ".intval($limit);
}
function Update($ID, $arFields)
{
global $DB;
if(is_set($arFields, "LAST_MODIFIED"))
$arFields["DATE_CHANGE"] = $arFields["LAST_MODIFIED"];
elseif(is_set($arFields, "DATE_CHANGE"))
$arFields["DATE_CHANGE"] = $DB->FormatDate($arFields["DATE_CHANGE"], "DD.MM.YYYY HH.MI.SS", CLang::GetDateFormat());
$strUpdate = $DB->PrepareUpdate("b_search_content", $arFields);
if(strlen($strUpdate) > 0)
{
$DB->Query("UPDATE b_search_content SET ".$strUpdate." WHERE ID=".intval($ID), false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
function CleanFreqCache($ID)
{
global $DB;
$rs = $DB->Query("SELECT LANGUAGE_ID,STEM FROM b_search_content_stem WHERE SEARCH_CONTENT_ID = ".intval($ID), false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
$DB->Query("
UPDATE b_search_content_freq SET TF = null
WHERE TF is not null
AND LANGUAGE_ID = '".$DB->ForSQL($ar["LANGUAGE_ID"])."'
AND STEM = '".$DB->ForSQL($ar["STEM"])."'
", false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
function StemIndex($arLID, $ID, $sContent)
{
global $DB;
static $CACHE_SITE_LANGS = array();
$arLang=array();
if(!is_array($arLID))
$arLID = Array();
foreach($arLID as $site=>$url)
{
if(!array_key_exists($site, $CACHE_SITE_LANGS))
{
$db_site_tmp = CSite::GetByID($site);
if ($ar_site_tmp = $db_site_tmp->Fetch())
$CACHE_SITE_LANGS[$site] = array(
"LANGUAGE_ID" => $ar_site_tmp["LANGUAGE_ID"],
"CHARSET" => $ar_site_tmp["CHARSET"],
"SERVER_NAME" => $ar_site_tmp["SERVER_NAME"]
);
else
$CACHE_SITE_LANGS[$site] = false;
}
if(is_array($CACHE_SITE_LANGS[$site]))
$arLang[$CACHE_SITE_LANGS[$site]["LANGUAGE_ID"]]++;
}
foreach($arLang as $lang=>$value)
{
$arDoc = stemming($sContent, $lang);
$docLength = array_sum($arDoc);
if($docLength > 0)
{
$doc = "";
$logDocLength = log($docLength<20?20:$docLength);
$strSqlPrefix = "
insert into b_search_content_stem
(SEARCH_CONTENT_ID, LANGUAGE_ID, STEM, TF)
values
";
$maxValuesLen = 2048;
$strSqlValues = "";
foreach($arDoc as $word => $count)
{
$strSqlValues .= ",\n(".$ID.", '".$lang."', '".$DB->ForSql($word)."', ".
number_format(log($count+1)/$logDocLength, 4, ".", "").")";
if(strlen($strSqlValues) > $maxValuesLen)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 2), false, "File: ".__FILE__."<br>Line: ".__LINE__);
$strSqlValues = "";
}
}
if(strlen($strSqlValues) > 0)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 2), false, "File: ".__FILE__."<br>Line: ".__LINE__);
$strSqlValues = "";
}
}
}
}
function TagsIndex($arLID, $ID, $sContent)
{
global $DB;
if(!is_array($arLID))
$arLID = Array();
$sContent = str_replace("\x00", "", $sContent);
foreach($arLID as $site_id => $url)
{
$arTags = tags_prepare($sContent, $site_id);
if(!empty($arTags))
{
$strSqlPrefix = "
insert into b_search_tags
(SEARCH_CONTENT_ID, SITE_ID, NAME)
values
";
$maxValuesLen = 2048;
$strSqlValues = "";
CSearchTags::CleanCache($arTags);
foreach($arTags as $tag)
{
$strSqlValues .= ",\n(".$ID.", '".$site_id."', '".$DB->ForSql($tag, 255)."')";
if(strlen($strSqlValues) > $maxValuesLen)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 2), false, "File: ".__FILE__."<br>Line: ".__LINE__);
$strSqlValues = "";
}
}
if(strlen($strSqlValues) > 0)
{
$DB->Query($strSqlPrefix.substr($strSqlValues, 2), false, "File: ".__FILE__."<br>Line: ".__LINE__);
$strSqlValues = "";
}
}
}
}
function ChangeIndex($MODULE_ID, $arFields, $ITEM_ID=false, $PARAM1=false, $PARAM2=false, $SITE_ID=false)
{
global $DB;
if(array_key_exists("TITLE", $arFields))
$arFields["TITLE"] = Trim($arFields["TITLE"]);
if(array_key_exists("BODY", $arFields))
$arFields["BODY"] = Trim($arFields["BODY"]);
if(array_key_exists("PERMISSIONS", $arFields) && is_array($arFields["PERMISSIONS"]))
CSearch::ChangePermission($MODULE_ID, $arFields["PERMISSIONS"], $ITEM_ID, $PARAM1, $PARAM2, $SITE_ID);
if(array_key_exists("SITE_ID", $arFields) && is_array($arFields["SITE_ID"]))
CSearch::ChangeSite($MODULE_ID, $arFields["SITE_ID"], $ITEM_ID, $PARAM1, $PARAM2, $SITE_ID);
$strUpdate = $DB->PrepareUpdate("b_search_content", $arFields);
if(strlen($strUpdate) > 0)
{
$strSqlWhere = CSearch::__PrepareFilter(Array("MODULE_ID"=>$MODULE_ID, "ITEM_ID"=>$ITEM_ID, "PARAM1"=>$PARAM1, "PARAM2"=>$PARAM2, "SITE_ID"=>$SITE_ID), $bIncSites);
$strSql = "
SELECT sc.ID
FROM b_search_content sc
".($bIncSites? "INNER JOIN b_search_content_site scsite ON sc.ID=scsite.SEARCH_CONTENT_ID": "")."
".(strlen($strSqlWhere)>0? "WHERE ".$strSqlWhere: "")."
";
$rs = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
while($ar = $rs->Fetch())
{
$strSql = "UPDATE b_search_content SET ".$strUpdate." WHERE ID=".$ar["ID"];
$DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__);
}
}
}
}
class CSearchQuery extends CAllSearchQuery
{
var $cnt = 0;
function BuildWhereClause($word)
{
global $DB;
$this->cnt++;
if($this->cnt>10)
return "1=1";
if(isset($this->m_kav[$word]))
{
$word = $this->m_kav[$word];
$bInQuotes = true;
}
else
{
$bInQuotes = false;
}
$this->m_words[] = $word;
$word = $DB->ForSql($word, 100);
if($this->bTagsSearch)
{
if(strpos($word, "%")===false)
{
//We can optimize query by doing range scan
if(is_array($this->m_tags_words))
$this->m_tags_words[] = $word;
$op = "=";
}
else
{
//Optimization is not possible
$this->m_tags_words = false;
$op = "like";
}
return "(sum(stags.name ".$op." '".$word."')>0)";
}
elseif($this->bStemming && !$bInQuotes)
{
$word = ToUpper($word);
$this->m_stemmed_words[] = $word;
return "(sum(st.stem = '".$word."')>0)";
}
else
{
return "(sc.searchable_content LIKE '%".str_replace(array("%", "_"), array("\\%", "\\_") ,ToUpper($word))."%')";
}
}
}
?>