<? // 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 = "<ol>"; $matches = array(); $matchingFileIndices = array(); $rankings = array(); $isFirst = true; foreach($keywords as $word) { if (!array_key_exists($word, $wordDictionary)) { return "<strong>Nothing found</strong>"; } $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 "<strong>Nothing found</strong>"; } // 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); if(count($rankings) > 99) break; } // 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 .= "<li><a href=\"$f\" target=\"_blank\">$t</a></li>"; } $sb .= "</ol"; if(count($rankings) < count($matchingFileIndices)) { $c = count(matchingFileIndices) - count(rankings); $sb .= "<p>Omitted $c more results</p>"; } return $sb; } function cmprank($x, $y) { return $y->rank - $x->rank; } function cmprankbytitle($x, $y) { return strcmp($x->pageTitle, $y->pageTitle); } ?>