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
/*
// 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) {
/**
* 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){
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;
}
}
$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;
}
}
}
/**
-* 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
*/
foreach($extras as $extra) {
$temp->name = $extra;
$temp->location = 'internal';
- $ret[] = clone($temp);
+ $ret[$temp->name] = clone($temp);
}
return $ret;
} //search_get_additional_modules
$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
$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);
}
<?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();
$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();
?>
$doctype,
$author,
$score,
- $number;
+ $number,
+ $courseid;
}
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:');
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;
}
}
} else {
//no caching :(
- //print "Caching disabled!";
+ // print "Caching disabled!";
$resultdocs = $this->process_results();
}
return $resultdocs;
* @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;
/**
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;
}
/**
--- /dev/null
+<?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');
+
+?>
\ No newline at end of file