v1.0.0 RC 1
This commit is contained in:
254
inc/searchengine.php
Normal file
254
inc/searchengine.php
Normal file
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Search Engine : Search through all types of databap documents
|
||||
*
|
||||
* Procedure to add a new type in the search
|
||||
* - Add type in Databap->getItemTables()
|
||||
* - Add type in the index builder : SearchEngine->buildIndex()
|
||||
* - Add type in item info : SearchEngine->setItemInfo()
|
||||
* - Add type in Databap->getItemList() and create a Databap->get<type>info()
|
||||
* - Add type text in Databap->getProfile()
|
||||
* - Consider the message types : add + edit in Databap->getMessages() and in chat.html
|
||||
*/
|
||||
class SearchEngine extends PhpObject
|
||||
{
|
||||
//Objects
|
||||
private $oMySql;
|
||||
|
||||
//variables
|
||||
private $asWords;
|
||||
private $iLevelMax;
|
||||
private $asItemRanks;
|
||||
private $asItemInfos;
|
||||
private $asUserInfos;
|
||||
|
||||
//Constants
|
||||
const RESULT_A_PAGE = 20;
|
||||
const KEYWORDS_SEPARATOR = ' ';
|
||||
|
||||
function __construct($oMySql)
|
||||
{
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
$this->oMySql = $oMySql;
|
||||
$this->asWords = $this->setWords('');
|
||||
$this->asItemRanks = array();
|
||||
$this->asItemInfos = array();
|
||||
$this->asUserInfos = array();
|
||||
}
|
||||
|
||||
public function buildIndex($iItemId, $sType)
|
||||
{
|
||||
//Build keywords
|
||||
switch($sType)
|
||||
{
|
||||
case Databap::CODE_TYPE:
|
||||
$asItemData = $this->oMySql->selectRow(Databap::CODE_TABLE, $iItemId);
|
||||
$asWords = array($asItemData[MySqlManager::getText(Databap::CODE_TABLE)], $asItemData['description']);
|
||||
break;
|
||||
case Databap::PROC_TYPE:
|
||||
$sItemIdCol = MySqlManager::getId(Databap::PROC_TABLE);
|
||||
$asItemData = $this->oMySql->selectRow(Databap::PROC_TABLE, $iItemId);
|
||||
$asItemStepsData = $this->oMySql->selectRows(array('select'=>'description', 'from'=>Databap::STEP_TABLE, 'constraint'=>array($sItemIdCol=>$iItemId)));
|
||||
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title']) + $asItemStepsData;
|
||||
break;
|
||||
case Databap::ART_TYPE:
|
||||
$asItemData = $this->oMySql->selectRow(Databap::ART_TABLE, $iItemId);
|
||||
$asWords = array($asItemData['first_name'], $asItemData['last_name'], $asItemData['title']);
|
||||
break;
|
||||
case Databap::DOC_TYPE:
|
||||
$sItemIdCol = MySqlManager::getId(Databap::DOC_TABLE);
|
||||
$asItemData = $this->oMySql->selectRow(Databap::DOC_TABLE, $iItemId);
|
||||
$asItemFilesData = $this->oMySql->selectRows(array('select'=>'description', 'from'=>Databap::FILE_TABLE, 'constraint'=>array($sItemIdCol=>$iItemId)));
|
||||
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title']) + $asItemFilesData;
|
||||
break;
|
||||
case Databap::TABLE_TYPE:
|
||||
$asItemData = $this->oMySql->selectRow(Databap::TABL_TABLE, $iItemId);
|
||||
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title'], 'keywords'=>$asItemData['keywords'], 'system'=>$asItemData['system']);
|
||||
break;
|
||||
default:
|
||||
$this->addError('function '.__FUNCTION__.'(): Incorrect type "'.$sType.'"');
|
||||
break;
|
||||
}
|
||||
$sWords = implode(self::KEYWORDS_SEPARATOR, $asWords);
|
||||
$sWords = mb_strtolower(str_replace("\n", self::KEYWORDS_SEPARATOR, $sWords));
|
||||
$sWords = preg_replace('/(\W+)/u', self::KEYWORDS_SEPARATOR, $sWords); //remove all non-word characters
|
||||
|
||||
//Add / Modify search database
|
||||
$asData = array('id_item'=>$iItemId, 'type'=>$sType, 'refer_id'=>(array_key_exists('refer_id', $asItemData)?$asItemData['refer_id']:$iItemId), 'keywords'=>$sWords);
|
||||
$this->oMySql->insertUpdateRow(Databap::SEARCH_TABLE, $asData, array('id_item', 'type'));
|
||||
}
|
||||
|
||||
public function setWords($sSearchWords)
|
||||
{
|
||||
$this->asWords = $this->getParsedWords($sSearchWords);
|
||||
$this->iLevelMax = count($this->asWords);
|
||||
$this->setResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Customized item preview
|
||||
$sCodeLines = implode("\n...\n", $this->getCodeInfo($iItemId, 'code'));
|
||||
$oCode = new Reader($sCodeLines);
|
||||
$sCodeLines = $oCode->getColoredCode();
|
||||
*/
|
||||
private function setItemInfo($iSearchId, $iItemType, $iItemId)
|
||||
{
|
||||
if(!array_key_exists($iSearchId, $this->asItemInfos))
|
||||
{
|
||||
switch($iItemType)
|
||||
{
|
||||
case Databap::CODE_TYPE:
|
||||
$sItemTable = Databap::CODE_TABLE;
|
||||
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'description', 'led');
|
||||
break;
|
||||
case Databap::PROC_TYPE:
|
||||
$sItemTable = Databap::PROC_TABLE;
|
||||
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
|
||||
break;
|
||||
case Databap::ART_TYPE:
|
||||
$sItemTable = Databap::ART_TABLE;
|
||||
$asItemFields = array('first_name', 'last_name', 'title AS description', 'led');
|
||||
break;
|
||||
case Databap::DOC_TYPE:
|
||||
$sItemTable = Databap::DOC_TABLE;
|
||||
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
|
||||
break;
|
||||
case Databap::TABLE_TYPE:
|
||||
$sItemTable = Databap::TABL_TABLE;
|
||||
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
|
||||
break;
|
||||
}
|
||||
$this->asItemInfos[$iSearchId] = $this->oMySql->selectRow($sItemTable, $iItemId, $asItemFields);
|
||||
$this->asItemInfos[$iSearchId]['type'] = $iItemType;
|
||||
$this->asItemInfos[$iSearchId]['id_item'] = $iItemId;
|
||||
}
|
||||
}
|
||||
|
||||
private function getItemInfo($iSearchId, $sInfoName)
|
||||
{
|
||||
if(array_key_exists($iSearchId, $this->asItemInfos) && array_key_exists($sInfoName, $this->asItemInfos[$iSearchId]))
|
||||
return $this->asItemInfos[$iSearchId][$sInfoName];
|
||||
else return false;
|
||||
}
|
||||
|
||||
private function setUserInfo($iUserId)
|
||||
{
|
||||
if($iUserId > 0 && !array_key_exists($iUserId, $this->asUserInfos))
|
||||
{
|
||||
$sCompanyIdCol = MySqlManager::getId(Databap::COMP_TABLE);
|
||||
$this->asUserInfos[$iUserId] = $this->oMySql->selectRow
|
||||
(
|
||||
Databap::USER_TABLE,
|
||||
$iUserId,
|
||||
array('first_name', 'last_name', $sCompanyIdCol)
|
||||
);
|
||||
|
||||
$this->asUserInfos[$iUserId]['company'] = $this->oMySql->selectValue(Databap::COMP_TABLE, MySqlManager::getText(Databap::COMP_TABLE), $this->asUserInfos[$iUserId][$sCompanyIdCol]);
|
||||
unset($this->asUserInfos[$iUserId][$sCompanyIdCol]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getUserInfo($iUserId, $sInfoName)
|
||||
{
|
||||
if(array_key_exists($iUserId, $this->asUserInfos) && array_key_exists($sInfoName, $this->asUserInfos[$iUserId]))
|
||||
return $this->asUserInfos[$iUserId][$sInfoName];
|
||||
else return false;
|
||||
}
|
||||
|
||||
private function setResults()
|
||||
{
|
||||
if($this->iLevelMax > 0)
|
||||
{
|
||||
//set Results and Ranking
|
||||
$aiLevels = range(1, $this->iLevelMax);
|
||||
arsort($aiLevels);
|
||||
foreach($aiLevels as $iLevel)
|
||||
{
|
||||
//all possibilies at level $iLevel
|
||||
$iIndex = 0;
|
||||
while(($iIndex + $iLevel) <= $this->iLevelMax)
|
||||
{
|
||||
//building query
|
||||
$asSequence = array_slice($this->asWords, $iIndex, $iLevel);
|
||||
$this->oMySql->cleanSql($asSequence);
|
||||
|
||||
//$sRegExp = implode('(.{0,2})', $asSequence);
|
||||
$sRegExp = implode(self::KEYWORDS_SEPARATOR.'?', $asSequence);
|
||||
$sSequence = implode(self::KEYWORDS_SEPARATOR, $asSequence);
|
||||
|
||||
//TODO replace with selectRow()
|
||||
$sQuery = "SELECT id_search, MAX(id_item) AS id_item, type, keywords FROM searchs WHERE keywords REGEXP '{$sRegExp}' GROUP BY type, refer_id";
|
||||
|
||||
//search sequence
|
||||
$asItems = $this->oMySql->getArrayQuery($sQuery, true);
|
||||
foreach($asItems as $asItem)
|
||||
{
|
||||
$iSearchId = $asItem['id_search'];
|
||||
$iItemId = $asItem['id_item'];;
|
||||
$iItemType = $asItem['type'];
|
||||
$sWords = $asItem['keywords'];
|
||||
|
||||
//Calculate bonus points
|
||||
$sWords = str_replace(self::KEYWORDS_SEPARATOR.$sSequence.self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iSeqCount);
|
||||
$sWords = str_replace(self::KEYWORDS_SEPARATOR.$sSequence, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iStaCount);
|
||||
$sWords = str_replace($sSequence.self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iEndCount);
|
||||
$iBonus = $iSeqCount*5 + $iStaCount*2 + $iEndCount;
|
||||
|
||||
$this->incItemRank($iSearchId, $iLevel*10+$iBonus);
|
||||
$this->setItemInfo($iSearchId, $iItemType, $iItemId);
|
||||
$this->setUserInfo($this->getItemInfo($iSearchId, MySqlManager::getId(Databap::USER_TABLE)));
|
||||
}
|
||||
$iIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getResults()
|
||||
{
|
||||
$asResult = array();
|
||||
|
||||
//Mixing info
|
||||
arsort($this->asItemRanks);
|
||||
foreach($this->asItemRanks as $iSearchId=>$iRank)
|
||||
{
|
||||
$iUserId = $this->getItemInfo($iSearchId, MySqlManager::getId(Databap::USER_TABLE));
|
||||
$sFirstName = $this->getUserInfo($iUserId, 'first_name')?$this->getUserInfo($iUserId, 'first_name'):$this->getItemInfo($iSearchId, 'first_name');
|
||||
$sLastName = $this->getUserInfo($iUserId, 'last_name')?$this->getUserInfo($iUserId, 'last_name'):$this->getItemInfo($iSearchId, 'last_name');
|
||||
$sCompany = $this->getUserInfo($iUserId, 'company')?$this->getUserInfo($iUserId, 'company'):'SAP';
|
||||
$asResult[] = array('id_item'=>$this->getItemInfo($iSearchId, 'id_item'),
|
||||
'type'=>$this->getItemInfo($iSearchId, 'type'),
|
||||
'description'=>$this->getItemInfo($iSearchId, 'description'),
|
||||
'rank'=>$iRank,
|
||||
'name'=>Databap::getNameFormat($sFirstName, $sLastName),
|
||||
'company'=>Databap::getCompanyFormat($sCompany),
|
||||
'led'=>Databap::getDateFormat($this->getItemInfo($iSearchId, 'led')));
|
||||
}
|
||||
return $asResult;
|
||||
}
|
||||
|
||||
private function incItemRank($iSearchId, $iRank)
|
||||
{
|
||||
if(array_key_exists($iSearchId, $this->asItemRanks))
|
||||
{
|
||||
$this->asItemRanks[$iSearchId] += $iRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->asItemRanks[$iSearchId] = $iRank;
|
||||
}
|
||||
}
|
||||
|
||||
private function getParsedWords($sSearchWords)
|
||||
{
|
||||
return array_unique(array_filter(explode(' ', $sSearchWords), array($this, 'checkSearchedWords')));
|
||||
}
|
||||
|
||||
private function checkSearchedWords($sWord)
|
||||
{
|
||||
return (mb_strlen($sWord) >= 2);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user