From 3efa38a41d8f17b73ee58b4fe34a9784f42c7c97 Mon Sep 17 00:00:00 2001 From: diml Date: Sat, 31 May 2008 15:17:28 +0000 Subject: [PATCH] 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 --- search/lib.php | 16 ++--- search/query.php | 38 ++++++++--- search/querylib.php | 140 +++++++++++++++++++++++------------------ search/searchtypes.php | 33 ++++++++++ 4 files changed, 148 insertions(+), 79 deletions(-) create mode 100644 search/searchtypes.php diff --git a/search/lib.php b/search/lib.php index 9a5f23ac76..638fea885e 100644 --- a/search/lib.php +++ b/search/lib.php @@ -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 diff --git a/search/query.php b/search/query.php index b9024166e7..e8affc712c 100644 --- a/search/query.php +++ b/search/query.php @@ -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 @@ 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 "
  • url)."'>$listing->title
    \n" - ."".search_shorten_url($listing->url, 70)."
    \n" - ."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3); + echo "
  • url) + ."'>\"\"/ $listing->title (".$courseword.": '".$coursename."')
    \n"; + // print "
  • url)."'>$listing->title
    \n" + // ."".search_shorten_url($listing->url, 70)."
    \n" + // ."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3); if (!empty($listing->author)){ - print ", {$authorstr}: ".$listing->author."\n" + echo ", {$authorstr}: ".$listing->author."\n" ."
  • \n"; } } - print ""; - print $page_links; + echo ""; + echo $page_links; } print_box_end(); ?> diff --git a/search/querylib.php b/search/querylib.php index 3683628f50..7db4eef9ab 100644 --- a/search/querylib.php +++ b/search/querylib.php @@ -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)); + + // 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"; - return true; + 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; } /** diff --git a/search/searchtypes.php b/search/searchtypes.php new file mode 100644 index 0000000000..16f1a5cf8b --- /dev/null +++ b/search/searchtypes.php @@ -0,0 +1,33 @@ + 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'); + +?> \ No newline at end of file -- 2.39.5