fixes result list ordering issue

engine give nicer results with adequate pagination.
Adding icon and reference to course origine.

should contribute to close many global search related issues from

http://tracker.moodle.org/browse/MDL-14646

startpoint
This commit is contained in:
diml 2008-05-31 15:17:28 +00:00
parent f7ed268752
commit 3efa38a41d
4 changed files with 148 additions and 79 deletions

View File

@ -18,7 +18,9 @@
/*
// function reference
function search_collect_searchables($namelist=false, $verbose=true){
function search_get_document_types($prefix = 'SEARCH_TYPE_') {
function search_get_document_types($prefix = 'X_SEARCH_TYPE_') {
function search_get_additional_modules() {
function search_shorten_url($url, $length=30) {
function search_escape_string($str) {
@ -35,8 +37,8 @@ include "{$CFG->dirroot}/search/searchtypes.php";
/**
* collects all searchable items identities
* @param boolean $namelist
* @param boolean $verbose
* @param boolean $namelist if true, only returns list of names of searchable items
* @param boolean $verbose if true, prints a discovering status
* @return an array of names or an array of type descriptors
*/
function search_collect_searchables($namelist=false, $verbose=true){
@ -53,13 +55,13 @@ function search_collect_searchables($namelist=false, $verbose=true){
foreach($mods as $mod){
if (in_array($mod->name, $searchabletypes)){
$mod->location = 'internal';
$searchables[] = $mod;
$searchables[$mod->name] = $mod;
$searchables_names[] = $mod->name;
} else {
$documentfile = $CFG->dirroot."/mod/{$mod->name}/search_document.php";
$mod->location = 'mod';
if (file_exists($documentfile)){
$searchables[] = $mod;
$searchables[$mod->name] = $mod;
$searchables_names[] = $mod->name;
}
}
@ -82,7 +84,7 @@ function search_collect_searchables($namelist=false, $verbose=true){
$documentfile = $CFG->dirroot."/blocks/{$block->dirname}/search_document.php";
if (file_exists($documentfile)){
$mod->location = 'blocks';
$blocks_searchables[] = $block;
$blocks_searchables[$block->name] = $block;
$searchables_names[] = $block->name;
}
}
@ -105,7 +107,7 @@ function search_collect_searchables($namelist=false, $verbose=true){
}
/**
* returns all the document type constants
* returns all the document type constants that are known in core implementation
* @param prefix a pattern for recognizing constants
* @return an array of type labels
*/
@ -138,7 +140,7 @@ function search_get_additional_modules() {
foreach($extras as $extra) {
$temp->name = $extra;
$temp->location = 'internal';
$ret[] = clone($temp);
$ret[$temp->name] = clone($temp);
}
return $ret;
} //search_get_additional_modules

View File

@ -93,8 +93,9 @@
$query_string = '';
// get all available module types
// get all available module types adding third party modules
$module_types = array_merge(array('all'), array_values(search_get_document_types()));
$module_types = array_merge($module_types, array_values(search_get_document_types('X_SEARCH_TYPE')));
$adv->module = in_array($adv->module, $module_types) ? $adv->module : 'all';
// convert '1 2' into '+1 +2' for required words field
@ -141,7 +142,7 @@
$page_number = 1;
}
//run the query against the index
//run the query against the index ensuring internal coding works in UTF-8
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8());
$sq = new SearchQuery($query_string, $page_number, 10, false);
}
@ -308,7 +309,8 @@
<?php
print_box_end();
// prints all the results in a box
/// prints all the results in a box
if ($sq->is_valid()) {
print_box_start();
@ -336,26 +338,42 @@
$typestr = get_string('type', 'search');
$scorestr = get_string('score', 'search');
$authorstr = get_string('author', 'search');
$searchables = search_collect_searchables(false, false);
foreach ($hits as $listing) {
$iconpath = $CFG->modpixpath.'/'.$listing->doctype.'/icon.gif';
$coursename = get_field('course', 'fullname', 'id', $listing->courseid);
$courseword = mb_convert_case(get_string('course', 'moodle'), MB_CASE_LOWER, 'UTF-8');
//if ($CFG->unicodedb) {
//$listing->title = mb_convert_encoding($listing->title, 'auto', 'UTF8');
//}
$title_post_processing_function = $listing->doctype.'_link_post_processing';
require_once "{$CFG->dirroot}/search/documents/{$listing->doctype}_document.php";
$searchable_instance = $searchables[$listing->doctype];
if ($searchable_instance->location == 'internal'){
require_once "{$CFG->dirroot}/search/documents/{$listing->doctype}_document.php";
} else {
require_once "{$CFG->dirroot}/{$searchable_instance->location}/{$listing->doctype}/search_document.php";
}
if (function_exists($title_post_processing_function)) {
$listing->title = $title_post_processing_function($listing->title);
}
print "<li value='".($listing->number+1)."'><a href='".str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)."'>$listing->title</a><br />\n"
."<em>".search_shorten_url($listing->url, 70)."</em><br />\n"
."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3);
echo "<li value='".($listing->number+1)."'><a href='"
.str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)
."'><img align=\"top\" src=\"".$iconpath
."\" class=\"activityicon\" alt=\"\"/> $listing->title</a><strong> (".$courseword.": '".$coursename."')</strong><br />\n";
// print "<li value='".($listing->number+1)."'><a href='".str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)."'>$listing->title</a><br />\n"
// ."<em>".search_shorten_url($listing->url, 70)."</em><br />\n"
// ."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3);
if (!empty($listing->author)){
print ", {$authorstr}: ".$listing->author."\n"
echo ", {$authorstr}: ".$listing->author."\n"
."</li>\n";
}
}
print "</ol>";
print $page_links;
echo "</ol>";
echo $page_links;
}
print_box_end();
?>

View File

@ -26,7 +26,8 @@ public $url,
$doctype,
$author,
$score,
$number;
$number,
$courseid;
}
@ -220,6 +221,7 @@ class SearchQuery {
global $USER;
$term = mb_convert_case($this->term, MB_CASE_LOWER, 'UTF-8');
$page = optional_param('page', 1, PARAM_INT);
//experimental - return more results
$strip_arr = array('author:', 'title:', '+', '-', 'doctype:');
@ -233,49 +235,58 @@ class SearchQuery {
if ($hitcount == 0) return array();
$totalpages = ceil($hitcount/$this->results_per_page);
$resultdoc = new SearchResult();
$resultdocs = array();
$searchables = search_collect_searchables(false, false);
$realindex = 0;
/**
if (!$all) {
if ($hitcount < $this->results_per_page) {
if ($finalresults < $this->results_per_page) {
$this->pagenumber = 1;
} else if ($this->pagenumber > $totalpages) {
} elseif ($this->pagenumber > $totalpages) {
$this->pagenumber = $totalpages;
}
$start = ($this->pagenumber - 1) * $this->results_per_page;
$end = $start + $this->results_per_page;
if ($end > $hitcount) {
$end = $hitcount;
if ($end > $finalresults) {
$end = $finalresults;
}
} else {
$start = 0;
$end = $hitcount;
}
$end = $finalresults;
} */
$resultdoc = new SearchResult();
$resultdocs = array();
for ($i = $start; $i < $end; $i++) {
for ($i = 0; $i < min($hitcount, ($page) * $this->results_per_page); $i++) {
$hit = $hits[$i];
//check permissions on each result
if ($this->can_display($USER, $hit->docid, $hit->doctype, $hit->course_id, $hit->group_id, $hit->path, $hit->itemtype, $hit->context_id )) {
$resultdoc->number = $i;
$resultdoc->url = $hit->url;
$resultdoc->title = $hit->title;
$resultdoc->score = $hit->score;
$resultdoc->doctype = $hit->doctype;
$resultdoc->author = $hit->author;
//and store it
$resultdocs[] = clone($resultdoc);
if ($this->can_display($USER, $hit->docid, $hit->doctype, $hit->course_id, $hit->group_id, $hit->path, $hit->itemtype, $hit->context_id, $searchables )) {
if ($i >= ($page - 1) * $this->results_per_page){
$resultdoc->number = $realindex;
$resultdoc->url = $hit->url;
$resultdoc->title = $hit->title;
$resultdoc->score = $hit->score;
$resultdoc->doctype = $hit->doctype;
$resultdoc->author = $hit->author;
$resultdoc->courseid = $hit->course_id;
//and store it
$resultdocs[] = clone($resultdoc);
}
$realindex++;
} else {
// lowers total_results one unit
$this->total_results--;
}
}
$totalpages = ceil($this->total_results/$this->results_per_page);
return $resultdocs;
}
@ -298,7 +309,7 @@ class SearchQuery {
}
} else {
//no caching :(
//print "Caching disabled!";
// print "Caching disabled!";
$resultdocs = $this->process_results();
}
return $resultdocs;
@ -370,7 +381,7 @@ class SearchQuery {
* @uses CFG
* // TODO reorder parameters more consistently
*/
private function can_display(&$user, $this_id, $doctype, $course_id, $group_id, $path, $item_type, $context_id) {
private function can_display(&$user, $this_id, $doctype, $course_id, $group_id, $path, $item_type, $context_id, &$searchables) {
global $CFG;
/**
@ -381,45 +392,50 @@ class SearchQuery {
return true;
}
// first check course compatibility against user : enrolled users to that course can see.
$myCourses = get_my_courses($user->id);
$unenroled = !in_array($course_id, array_keys($myCourses));
// if guests are allowed, logged guest can see
$isallowedguest = (isguest()) ? get_field('course', 'guest', 'id', $course_id) : false ;
if ($unenroled && !$isallowedguest){
return false;
}
// if user is enrolled or is allowed user and course is hidden, can he see it ?
$visibility = get_field('course', 'visible', 'id', $course_id);
if ($visibility <= 0){
if (!has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course_id))){
return false;
}
}
/**
* prerecorded capabilities
*/
// get context caching information and tries to discard unwanted records here
/**
* final checks
*/
// then give back indexing data to the module for local check
include_once "{$CFG->dirroot}/search/documents/{$doctype}_document.php";
$access_check_function = "{$doctype}_check_text_access";
if (function_exists($access_check_function)){
$modulecheck = $access_check_function($path, $item_type, $this_id, $user, $group_id, $context_id);
// echo "module said $modulecheck for item $doctype/$item_type/$this_id";
return($modulecheck);
}
// first check course compatibility against user : enrolled users to that course can see.
$myCourses = get_my_courses($user->id);
$unenroled = !in_array($course_id, array_keys($myCourses));
return true;
// if guests are allowed, logged guest can see
$isallowedguest = (isguest()) ? get_field('course', 'guest', 'id', $course_id) : false ;
if ($unenroled && !$isallowedguest){
return false;
}
// if user is enrolled or is allowed user and course is hidden, can he see it ?
$visibility = get_field('course', 'visible', 'id', $course_id);
if ($visibility <= 0){
if (!has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course_id))){
return false;
}
}
/**
* prerecorded capabilities
*/
// get context caching information and tries to discard unwanted records here
/**
* final checks
*/
// then give back indexing data to the module for local check
$searchable_instance = $searchables[$doctype];
if ($searchable_instance->location == 'internal'){
include_once "{$CFG->dirroot}/search/documents/{$doctype}_document.php";
} else {
include_once "{$CFG->dirroot}/{$searchable_instance->location}/$doctype/search_document.php";
}
$access_check_function = "{$doctype}_check_text_access";
if (function_exists($access_check_function)){
$modulecheck = $access_check_function($path, $item_type, $this_id, $user, $group_id, $context_id);
// echo "module said $modulecheck for item $doctype/$item_type/$this_id";
return($modulecheck);
}
return true;
}
/**

33
search/searchtypes.php Normal file
View File

@ -0,0 +1,33 @@
<?php
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [cynnical@gmail.com], Valery Fremaux [valery.fremaux@club-internet.fr] > 1.8
* @date 2008/03/31
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*
* Searcheable types
* to disable a type, just comment the two declaration lines for that type
*
*/
//document types that can be searched
//define('SEARCH_TYPE_NONE', 'none');
define('SEARCH_TYPE_WIKI', 'wiki');
define('SEARCH_TYPE_FORUM', 'forum');
define('SEARCH_TYPE_GLOSSARY', 'glossary');
define('SEARCH_TYPE_RESOURCE', 'resource');
define('SEARCH_TYPE_DATA', 'data');
define('SEARCH_TYPE_CHAT', 'chat');
define('SEARCH_TYPE_LESSON', 'lesson');
define('SEARCH_TYPE_ASSIGNMENT', 'assignment');
define('SEARCH_EXTRAS', 'user');
define('SEARCH_TYPE_USER', 'user');
define('PATH_FOR_SEARCH_TYPE_USER', 'user');
?>