blob: ec21bc55803cdc3ce5e3a9cbf051b938e7231370 [file] [log] [blame]
<?
// Contributed to the Sandcastle Help File Builder project by Thomas Levesque
class Ranking
{
public $filename;
public $pageTitle;
public $rank;
function __construct($file, $title, $rank)
{
$this->filename = $file;
$this->pageTitle = $title;
$this->rank = $rank;
}
}
/// <summary>
/// Split the search text up into keywords
/// </summary>
/// <param name="keywords">The keywords to parse</param>
/// <returns>A list containing the words for which to search</returns>
function ParseKeywords($keywords)
{
$keywordList = array();
$words = preg_split("/[^\w]+/", $keywords);
foreach($words as $word)
{
$checkWord = strtolower($word);
$first = substr($checkWord, 0, 1);
if(strlen($checkWord) > 2 && !ctype_digit($first) && !in_array($checkWord, $keywordList))
{
array_push($keywordList, $checkWord);
}
}
return $keywordList;
}
/// <summary>
/// Search for the specified keywords and return the results as a block of
/// HTML.
/// </summary>
/// <param name="keywords">The keywords for which to search</param>
/// <param name="fileInfo">The file list</param>
/// <param name="wordDictionary">The dictionary used to find the words</param>
/// <param name="sortByTitle">True to sort by title, false to sort by
/// ranking</param>
/// <returns>A block of HTML representing the search results.</returns>
function Search($keywords, $fileInfo, $wordDictionary, $sortByTitle)
{
$sb = "";
$matches = array();
$matchingFileIndices = array();
$rankings = array();
$isFirst = true;
foreach($keywords as $word)
{
if (!array_key_exists($word, $wordDictionary))
{
return "<b class=\"PaddedText\">Nothing found</b>";
}
$occurrences = $wordDictionary[$word];
$matches[$word] = $occurrences;
$occurrenceIndices = array();
// Get a list of the file indices for this match
foreach($occurrences as $entry)
array_push($occurrenceIndices, ($entry >> 16));
if($isFirst)
{
$isFirst = false;
foreach($occurrenceIndices as $i)
{
array_push($matchingFileIndices, $i);
}
}
else
{
// After the first match, remove files that do not appear for
// all found keywords.
for($idx = 0; $idx < count($matchingFileIndices); $idx++)
{
if (!in_array($matchingFileIndices[$idx], $occurrenceIndices))
{
array_splice($matchingFileIndices, $idx, 1);
$idx--;
}
}
}
}
if(count($matchingFileIndices) == 0)
{
return "<b class=\"PaddedText\">Nothing found</b>";
}
// Rank the files based on the number of times the words occurs
foreach($matchingFileIndices as $index)
{
// Split out the title, filename, and word count
$fileIndex = explode("\x00", $fileInfo[$index]);
$title = $fileIndex[0];
$filename = $fileIndex[1];
$wordCount = intval($fileIndex[2]);
$matchCount = 0;
foreach($keywords as $words)
{
$occurrences = $matches[$word];
foreach($occurrences as $entry)
{
if(($entry >> 16) == $index)
$matchCount += $entry & 0xFFFF;
}
}
$r = new Ranking($filename, $title, $matchCount * 1000 / $wordCount);
array_push($rankings, $r);
}
// Sort by rank in descending order or by page title in ascending order
if($sortByTitle)
{
usort($rankings, "cmprankbytitle");
}
else
{
usort($rankings, "cmprank");
}
// Format the file list and return the results
foreach($rankings as $r)
{
$f = $r->filename;
$t = $r->pageTitle;
$sb .= "<div class=\"TreeItem\">\r\n<img src=\"Item.gif\"/>" .
"<a class=\"UnselectedNode\" target=\"TopicContent\" " .
"href=\"$f\" onclick=\"javascript: SelectSearchNode(this);\">" .
"$t</a>\r\n</div>\r\n";
}
// Return the keywords used as well in a hidden span
$k = implode(" ", $keywords);
$sb .= "<span id=\"SearchKeywords\" style=\"display: none\">$k</span>";
return $sb;
}
function cmprank($x, $y)
{
return $y->rank - $x->rank;
}
function cmprankbytitle($x, $y)
{
return strcmp($x->pageTitle, $y->pageTitle);
}
?>