From a25a3912f736ceb42a686b401ac70e721ca9ac85 Mon Sep 17 00:00:00 2001 From: mchampan Date: Tue, 11 Jul 2006 17:15:22 +0000 Subject: [PATCH] Search functions moved from mod/name/lib.php to search/documents/mod_document.php. Pagination added to query page. Various small changes and amendments. --- blocks/search/block_search.php | 6 +- mod/wiki/lib.php | 106 ------------------- search/README.txt | 36 ++++++- search/db/mysql.sql | 2 +- search/db/postgres7.sql | 2 +- search/documents/document.php | 16 ++- search/documents/forum_document.php | 155 ++++++++++++++++++++++++++++ search/documents/wiki_document.php | 128 +++++++++++++++++++++-- search/indexer.php | 79 ++++++++------ search/indexersplash.php | 7 +- search/lib.php | 3 +- search/query.php | 104 +++++++++++++++---- search/stats.php | 2 +- search/tests/index.php | 90 ++++++++++++++++ 14 files changed, 555 insertions(+), 181 deletions(-) create mode 100644 search/documents/forum_document.php create mode 100644 search/tests/index.php diff --git a/blocks/search/block_search.php b/blocks/search/block_search.php index 3cafd10da7..c370ca2925 100644 --- a/blocks/search/block_search.php +++ b/blocks/search/block_search.php @@ -6,7 +6,7 @@ this block, the broadest possible selection of documents is searched. Author: Michael Champanis (mchampan) - Date: 2006 06 23 + Date: 2006 06 25 Todo: make strings -> get_string() */ @@ -15,7 +15,7 @@ function init() { $this->title = "Global Search"; //get_string() - $this->version = 20060625; + $this->version = 2006062500; } //init // only one instance of this block is required @@ -46,7 +46,7 @@ //basic search form $this->content->text = - '
' + '' . "" . '' . '' diff --git a/mod/wiki/lib.php b/mod/wiki/lib.php index 6f99d2543e..54fe22d4f7 100644 --- a/mod/wiki/lib.php +++ b/mod/wiki/lib.php @@ -352,112 +352,6 @@ function wiki_get_entries(&$wiki, $byindex=NULL) { } } - -/*==== Global search modifications - * Author: Michael Champanis (mchampan) - * Last date: 2006 06 25 - * These modifications allow wiki documents to be indexed in the new - * search engine module - they are probably not final, and as such - * shouldn't be used by other stuff for the time being - **/ - -//rescued and converted from ewikimoodlelib.php -//retrieves latest version of a page -function wiki_get_latest_page(&$entry, $pagename, $version=0) { - $pagename = "'".addslashes($pagename)."'"; - - if ($version > 0 and is_int($version)) { - $version = "AND (version=$version)"; - } else { - $version = ''; - } //else - - $select = "(pagename=$pagename) AND wiki=".$entry->id." $version "; - $sort = 'version DESC'; - - //change this to recordset_select, as per http://docs.moodle.org/en/Datalib_Notes - if ($result_arr = get_records_select('wiki_pages', $select, $sort, '*', 0, 1)) { - foreach ($result_arr as $obj) { - $result_obj = $obj; - } //foreach - } //if - - if (isset($result_obj)) { - $result_obj->meta = @unserialize($result_obj->meta); - return $result_obj; - } else { - return false; - } //else -} //wiki_get_latest_page - -//fetches all pages, including old versions -function wiki_get_pages(&$entry) { - return get_records('wiki_pages', 'wiki', $entry->id); -} //wiki_get_pages - -//fetches all the latest versions of all the pages -function wiki_get_latest_pages(&$entry) { - //== (My)SQL for this - /* select * from wiki_pages - inner join - (select wiki_pages.pagename, max(wiki_pages.version) as ver - from wiki_pages group by pagename) as a - on ((wiki_pages.version = a.ver) and - (wiki_pages.pagename like a.pagename)) */ - - $pages = array(); - - //http://moodle.org/bugs/bug.php?op=show&bugid=5877&pos=0 - //if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { - if ($rs = get_recordset('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { - $ids = $rs->GetRows(); - //-- - foreach ($ids as $id) { - $pages[] = wiki_get_latest_page($entry, $id[0]); - } //foreach - } else { - return false; - } //else - - return $pages; -} //wiki_get_latest_pages - -function wiki_iterator() { - return get_all_instances_in_courses("wiki", get_courses()); -} //wiki_search_index - -function wiki_get_content_for_index(&$wiki) { - $documents = array(); - - $entries = wiki_get_entries($wiki); - foreach($entries as $entry) { - //all pages - //$pages = wiki_get_pages($entry); - - //latest pages - $pages = wiki_get_latest_pages($entry); - $i = 0; - - if (is_array($pages)) { - foreach($pages as $page) { - if (strlen($page->content) > 0) { - $i++; - $documents[] = new WikiSearchDocument($page, $entry->wikiid, $entry->course, $entry->groupid); - } //if - } //foreach - - //print "$entry->id : $i"; print "
"; - } else { - print $pages; - } //else - } //foreach - - return $documents; -} //wiki_get_content_for_index - -/*==== Global search modifications end */ - - function wiki_get_default_entry(&$wiki, &$course, $userid=0, $groupid=0) { /// Returns the wiki entry according to the wiki type. /// Optionally, will return wiki entry for $userid student wiki, or diff --git a/search/README.txt b/search/README.txt index f473073714..e039bc9447 100644 --- a/search/README.txt +++ b/search/README.txt @@ -1,4 +1,38 @@ -latest +2006/07/11 +---------- +(Warning: It took me 1900 seconds to index the forum, go make coffee +whilst you wait.) + +Forum search functions changed to use 'get_recordset' instead of +'get_records', for speed reasons. This provides a significant improvement, +but indexing is still slow - getting data from the database and Zend's +tokenising _seem_ to be the prime suspects at the moment. + +/search/tests/ added - index.php can be used to see which modules are +ready to be included in the search index, and it informs you of any +errors - should be a prerequisite for indexing. + +Search result pagination added to query.php, will default to 20 until +an admin page for the search module is written. + +2006/07/07 +---------- +Search-enabling functions moved out've the mod's lib.php files and into +/search/documents/mod_document.php - this requires the search module to +operate without requiring modification of lib files. + +SearchDocument base class improved, and the way module documents extend +it. A custom-data field has been added to allow modules to add any custom +data they wish to be stored in the index - this field is serialised into +the index as a binary field. + +Database field 'type' renamed to 'doctype' to match the renaming in the +index, 'type' seems to be a reserved word in Lucene. Several index field +names change to be more descriptive (cid -> course_id). URLs are now +stored in the index, and don't have to be generated on the fly during +display of query results. + +2006/07/05 ------ Started cleaning and standardising things. diff --git a/search/db/mysql.sql b/search/db/mysql.sql index 1efb7e442d..2507a495bb 100644 --- a/search/db/mysql.sql +++ b/search/db/mysql.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS `prefix_search_documents` ( `id` int(11) NOT NULL auto_increment, - `type` varchar(12) NOT NULL default 'none', + `doctype` varchar(12) NOT NULL default 'none', `title` varchar(100) NOT NULL default '', `url` varchar(100) NOT NULL default '', `updated` timestamp NOT NULL default CURRENT_TIMESTAMP, diff --git a/search/db/postgres7.sql b/search/db/postgres7.sql index 52d1be4bf9..3903a65c32 100644 --- a/search/db/postgres7.sql +++ b/search/db/postgres7.sql @@ -1,6 +1,6 @@ CREATE TABLE prefix_search_documents ( id SERIAL8 PRIMARY KEY, - "type" varchar(12) NOT NULL DEFAULT 'none', + doctype varchar(12) NOT NULL DEFAULT 'none', title varchar(100) NOT NULL default '', url varchar(100) NOT NULL default '', updated timestamp NOT NULL DEFAULT NOW(), diff --git a/search/documents/document.php b/search/documents/document.php index c09ec37c90..83762aa2ce 100644 --- a/search/documents/document.php +++ b/search/documents/document.php @@ -4,10 +4,18 @@ * */ class SearchDocument extends Zend_Search_Lucene_Document { - public function __construct($document_type, $cid, $gid) { - $this->addField(Zend_Search_Lucene_Field::Keyword('type', $document_type)); - $this->addField(Zend_Search_Lucene_Field::Keyword('courseid', $cid)); - $this->addField(Zend_Search_Lucene_Field::Keyword('groupid', $gid)); + public function __construct(&$doc, &$data, $document_type, $course_id, $group_id) { + $this->addField(Zend_Search_Lucene_Field::Keyword('id', $doc->id)); + $this->addField(Zend_Search_Lucene_Field::Text('title', $doc->title)); + $this->addField(Zend_Search_Lucene_Field::Text('author', $doc->author)); + $this->addField(Zend_Search_Lucene_Field::UnStored('contents', $doc->contents)); + $this->addField(Zend_Search_Lucene_Field::UnIndexed('url', $doc->url)); + + $this->addField(Zend_Search_Lucene_Field::Binary('data', serialize($data))); + + $this->addField(Zend_Search_Lucene_Field::Keyword('doctype', $document_type)); + $this->addField(Zend_Search_Lucene_Field::Keyword('course_id', $course_id)); + $this->addField(Zend_Search_Lucene_Field::Keyword('group_id', $group_id)); } //constructor } //SearchDocument diff --git a/search/documents/forum_document.php b/search/documents/forum_document.php new file mode 100644 index 0000000000..c1b81d7a4a --- /dev/null +++ b/search/documents/forum_document.php @@ -0,0 +1,155 @@ +dirroot/search/documents/document.php"); + require_once("$CFG->dirroot/mod/forum/lib.php"); + + class ForumSearchDocument extends SearchDocument { + public function __construct(&$post, $forum_id, $course_id, $group_id) { + // generic information + /*$doc->id = $post->id; + $doc->title = $post->subject; + $doc->author = $post->firstname." ".$post->lastname; + $doc->contents = $post->message;*/ + + $doc->id = $post['id']; + $doc->title = $post['subject']; + $doc->author = $post['firstname']." ".$post['lastname']; + $doc->contents = $post['message']; + + $doc->url = forum_make_link($post['discussion'], $post['id']); + + // module specific information + $data->forum = $forum_id; + $data->discussion = $post['discussion']; + + parent::__construct($doc, $data, SEARCH_FORUM_TYPE, $course_id, $group_id); + } //constructor + } //ForumSearchDocument + + function forum_make_link($discussion_id, $post_id) { + global $CFG; + return $CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion_id.'#'.$post_id; + } //forum_make_link + + function forum_iterator() { + //no @ = Undefined index: 82 in /home/michael/public_html/moodle/lib/datalib.php on line 2671 + return @get_all_instances_in_courses("forum", get_courses()); + } //forum_iterator + + function forum_get_content_for_index(&$forum) { + $documents = array(); + if (!$forum) return $documents; + + $posts = forum_get_discussions_fast($forum->id); + if (!$posts) return $documents; + + while (!$posts->EOF) { + $post = $posts->fields; + + if (is_array($post)) { + if (strlen($post['message']) > 0 && ($post['deleted'] != 1)) { + $documents[] = new ForumSearchDocument($post, $forum->id, $forum->course, $post['groupid']); + } //if + + if ($children = forum_get_child_posts_fast($post['id'], $forum->id)) { + while (!$children->EOF) { + $child = $children->fields; + + if (strlen($child['message']) > 0 && ($child['deleted'] != 1)) { + $documents[] = new ForumSearchDocument($child, $forum->id, $forum->course, $post['groupid']); + } //if + + $children->MoveNext(); + } //foreach + } //if + } //if + + $posts->MoveNext(); + } //foreach + + return $documents; + } //forum_get_content_for_index + + //old slower version + function forum_get_content_for_index_old(&$forum) { + $documents = array(); + if (!$forum) return $documents; + + $posts = forum_get_discussions($forum->id); + if (!$posts) return $documents; + + foreach($posts as $post) { + if (is_object($post)) { + if (strlen($post->message) > 0 && ($post->deleted != 1)) { + $documents[] = new ForumSearchDocument($post, $forum->id, $forum->course, $post->groupid); + } //if + + if ($children = forum_get_child_posts($post->id, $forum->id)) { + foreach ($children as $child) { + if (strlen($child->message) > 0 && ($child->deleted != 1)) { + $documents[] = new ForumSearchDocument($child, $forum->id, $forum->course, $post->groupid); + } //if + } //foreach + } //if + } //if + } //foreach + + return $documents; + } //forum_get_content_for_index_old + + //reworked faster version from /mod/forum/lib.php + function forum_get_discussions_fast($forum) { + global $CFG, $USER; + + $timelimit=''; + + if (!empty($CFG->forum_enabletimedposts)) { + if (!((isadmin() and !empty($CFG->admineditalways)) || isteacher(get_field('forum', 'course', 'id', $forum)))) { + $now = time(); + $timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')"; + if (!empty($USER->id)) { + $timelimit .= " OR d.userid = '$USER->id'"; + } + $timelimit .= ')'; + } + } + + if ($CFG->dbtype == 'postgres7') { + return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message, + p.deleted, d.groupid, u.firstname, u.lastname + FROM {$CFG->prefix}forum_discussions d + JOIN {$CFG->prefix}forum_posts p ON p.discussion = d.id + JOIN {$CFG->prefix}user u ON p.userid = u.id + WHERE d.forum = '$forum' + AND p.parent = 0 + $timelimit + ORDER BY d.timemodified DESC"); + } else { + return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message, p.deleted, + d.groupid, u.firstname, u.lastname + FROM ({$CFG->prefix}forum_posts p, + {$CFG->prefix}user u, + {$CFG->prefix}forum_discussions d) + WHERE d.forum = '$forum' + AND p.discussion = d.id + AND p.parent = 0 + AND p.userid = u.id $timelimit + ORDER BY d.timemodified DESC"); + } //else + } //forum_get_discussions_fast + + //reworked faster version from /mod/forum/lib.php + function forum_get_child_posts_fast($parent, $forumid) { + global $CFG; + + return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message, p.deleted, + $forumid AS forum, u.firstname, u.lastname + FROM {$CFG->prefix}forum_posts p + LEFT JOIN {$CFG->prefix}user u ON p.userid = u.id + WHERE p.parent = '$parent' + ORDER BY p.created ASC"); + } //forum_get_child_posts_fast + +?> \ No newline at end of file diff --git a/search/documents/wiki_document.php b/search/documents/wiki_document.php index c70fa5ccb9..24ed20d173 100644 --- a/search/documents/wiki_document.php +++ b/search/documents/wiki_document.php @@ -1,28 +1,134 @@ title = wikipage->pagename + * + * Functions for iterating and retrieving the necessary records are now also included + * in this file, rather than mod/wiki/lib.php + * */ require_once("$CFG->dirroot/search/documents/document.php"); + require_once("$CFG->dirroot/mod/wiki/lib.php"); + /* All the $doc->___ fields are required by the base document class! + * Each and every module that requires search functionality must correctly + * map their internal fields to the five $doc fields (id, title, author, contents + * and url). Any module specific data can be added to the $data object, which is + * serialised into a binary field in the index. + * */ class WikiSearchDocument extends SearchDocument { - public function __construct(&$page, $wiki_id, $cid, $gid) { - $this->addField(Zend_Search_Lucene_Field::Text('title', $page->pagename)); - $this->addField(Zend_Search_Lucene_Field::Text('author', $page->author)); - $this->addField(Zend_Search_Lucene_Field::UnStored('contents', $page->content)); + public function __construct(&$page, $wiki_id, $course_id, $group_id) { + // generic information; required + $doc->id = $page->id; + $doc->title = $page->pagename; + $doc->author = $page->author; + $doc->contents = $page->content; + $doc->url = wiki_make_link($wiki_id, $page->pagename, $page->version); - $this->addField(Zend_Search_Lucene_Field::Keyword('id', $page->id)); - $this->addField(Zend_Search_Lucene_Field::Keyword('version', $page->version)); - $this->addField(Zend_Search_Lucene_Field::Keyword('wiki', $wiki_id)); + // module specific information; optional + $data->version = $page->version; + $data->wiki = $wiki_id; - parent::__construct(SEARCH_WIKI_TYPE, $cid, $gid); + // construct the parent class + parent::__construct($doc, $data, SEARCH_WIKI_TYPE, $course_id, $group_id); } //constructor } //WikiSearchDocument function wiki_name_convert($str) { return str_replace(' ', '+', $str); } //wiki_name_convert - - function wiki_make_link(&$doc) { + + function wiki_make_link($wiki_id, $title, $version) { global $CFG; - return $CFG->wwwroot.'/mod/wiki/view.php?wid='.$doc->wiki.'&page='.wiki_name_convert($doc->title).'&version='.$doc->version; + return $CFG->wwwroot.'/mod/wiki/view.php?wid='.$wiki_id.'&page='.wiki_name_convert($title).'&version='.$version; } //wiki_make_link + //rescued and converted from ewikimoodlelib.php + //retrieves latest version of a page + function wiki_get_latest_page(&$entry, $pagename, $version=0) { + $pagename = "'".addslashes($pagename)."'"; + + if ($version > 0 and is_int($version)) { + $version = "AND (version=$version)"; + } else { + $version = ''; + } //else + + $select = "(pagename=$pagename) AND wiki=".$entry->id." $version "; + $sort = 'version DESC'; + + //change this to recordset_select, as per http://docs.moodle.org/en/Datalib_Notes + if ($result_arr = get_records_select('wiki_pages', $select, $sort, '*', 0, 1)) { + foreach ($result_arr as $obj) { + $result_obj = $obj; + } //foreach + } //if + + if (isset($result_obj)) { + $result_obj->meta = @unserialize($result_obj->meta); + return $result_obj; + } else { + return false; + } //else + } //wiki_get_latest_page + + //fetches all pages, including old versions + function wiki_get_pages(&$entry) { + return get_records('wiki_pages', 'wiki', $entry->id); + } //wiki_get_pages + + //fetches all the latest versions of all the pages + function wiki_get_latest_pages(&$entry) { + //== (My)SQL for this + /* select * from wiki_pages + inner join + (select wiki_pages.pagename, max(wiki_pages.version) as ver + from wiki_pages group by pagename) as a + on ((wiki_pages.version = a.ver) and + (wiki_pages.pagename like a.pagename)) */ + + $pages = array(); + + //http://moodle.org/bugs/bug.php?op=show&bugid=5877&pos=0 + //if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { + if ($rs = get_recordset('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { + $ids = $rs->GetRows(); + //-- + foreach ($ids as $id) { + $pages[] = wiki_get_latest_page($entry, $id[0]); + } //foreach + } else { + return false; + } //else + + return $pages; + } //wiki_get_latest_pages + + function wiki_iterator() { + return get_all_instances_in_courses("wiki", get_courses()); + } //wiki_iterator + + function wiki_get_content_for_index(&$wiki) { + $documents = array(); + + $entries = wiki_get_entries($wiki); + foreach($entries as $entry) { + //all pages + //$pages = wiki_get_pages($entry); + + //latest pages + $pages = wiki_get_latest_pages($entry); + + if (is_array($pages)) { + foreach($pages as $page) { + if (strlen($page->content) > 0) { + $documents[] = new WikiSearchDocument($page, $entry->wikiid, $entry->course, $entry->groupid); + } //if + } //foreach + } //if + } //foreach + + return $documents; + } //wiki_get_content_for_index + ?> \ No newline at end of file diff --git a/search/indexer.php b/search/indexer.php index 5fda789744..a56302e59d 100644 --- a/search/indexer.php +++ b/search/indexer.php @@ -1,12 +1,17 @@ dirroot/search/Zend/Search/Lucene.php"); - //begin timer - search_stopwatch(); + if (get_config("search_indexer_busy") == 1) { + } //if + + //turn on busy flag + set_config("search_indexer_busy", 1); mtrace('
Server Time: '.date('r',time())."\n");
   
   //paths
@@ -63,21 +71,30 @@
   } else {
     mtrace("Using $index_path as data directory.");
   } //else
-
+  
   $index = new Zend_Search_Lucene($index_path, true);
   
   //create the database tables
   $tables = $db->MetaTables();
     
   if (in_array($CFG->prefix.'search_documents', $tables)) {
-    delete_records('search_documents');
+    //delete_records('search_documents');    
+    //temporary measure - db doesn't have update scripts and I realised that cvs 1.1 db
+    //is incompatible with cvs 1.2! Must fix ASAP.    
+    execute_sql('drop table '.$CFG->prefix.'search_documents', false);
+    
+    ob_start(); //turn output buffering on - to hide modify_database() output
+    modify_database($index_db_file, '', false);
+    ob_end_clean(); //chuck the buffer and resume normal operation
   } else {        
     ob_start(); //turn output buffering on - to hide modify_database() output
     modify_database($index_db_file, '', false);
     ob_end_clean(); //chuck the buffer and resume normal operation
   } //else
-    
-  mtrace('Starting activity modules');
+
+  //begin timer
+  search_stopwatch();
+  mtrace("Starting activity modules\n");
   
   //the presence of the required search functions -
   // * mod_iterator
@@ -86,23 +103,18 @@
   
   if ($mods = get_records_select('modules' /*'index this module?' where statement*/)) {
     foreach ($mods as $mod) {
-      $libfile = "$CFG->dirroot/mod/$mod->name/lib.php";
+      $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';              
       
-      if (file_exists($libfile)) {
-        include_once($libfile);
+      if (file_exists($class_file)) {
+        include_once($class_file);
         
         $iter_function = $mod->name.'_iterator';
         $index_function = $mod->name.'_get_content_for_index';
-        
-        //specific module search document class
-        $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-        
+                
         $counter = 0;
         $doc = new stdClass;
                 
-        if (file_exists($class_file) && function_exists($index_function) && function_exists($iter_function)) {
-          include_once($class_file);
-          
+        if (function_exists($index_function) && function_exists($iter_function)) {
           mtrace("Processing module function $index_function ...");
                      
           foreach ($iter_function() as $i) {
@@ -113,30 +125,30 @@
             foreach($documents as $document) {
               $counter++;
                             
-              //data object for db
-              $doc->type = $document->type;
-              $doc->title = search_escape_string($document->title);
-              $doc->update = time();              
-              $doc->url = 'none';
-              $doc->courseid = $document->courseid;              
-              $doc->groupid = $document->groupid;
+              //object to insert into db                            
+              $doc->doctype   = $document->doctype;
+              $doc->title     = search_escape_string($document->title);
+              $doc->url       = search_escape_string($document->url);              
+              $doc->update    = time();                            
+              $doc->courseid  = $document->course_id;              
+              $doc->groupid   = $document->group_id;              
               
               //insert summary into db
               $id = insert_record('search_documents', $doc);
               
               //synchronise db with index
-              $document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $id));
+              $document->addField(Zend_Search_Lucene_Field::Keyword('db_id', $id));
               
               //add document to index
               $index->addDocument($document);                  
                             
               //commit every x new documents, and print a status message                            
-              if (($counter%200) == 0) {
+              if (($counter%2000) == 0) {
                 $index->commit();
-                mtrace(".. $counter");                
+                mtrace(".. $counter");
               } //if
             } //foreach
-            
+
             //end transaction
             
           } //foreach
@@ -145,7 +157,7 @@
           $index->commit();
           
           mtrace("-- $counter documents indexed");
-          mtrace('done.');          
+          mtrace("done.\n");          
         } //if
       } //if
     } //foreach
@@ -160,5 +172,8 @@
   
   mtrace(".
Back to query page."); mtrace('
'); + + //finished, turn busy flag off + set_config("search_indexer_busy", 0); ?> \ No newline at end of file diff --git a/search/indexersplash.php b/search/indexersplash.php index 35e798f097..aa3b91b5a8 100644 --- a/search/indexersplash.php +++ b/search/indexersplash.php @@ -42,7 +42,12 @@ ."started and cancelled an indexing session. Follow the link if you are sure that\n" ."you want to continue indexing - this will replace any existing index data (no\n" ."Moodle data is affected).\n" - ."\n" + ."\n" + ."You are encouraged to use the 'Test indexing' script before continuing onto\n" + ."indexing - this will check if the modules are set up correctly. Please correct\n" + ."any errors before proceeding.\n" + ."\n" + ."Test indexing or " ."Continue indexing or Back to query page." .""); } else { diff --git a/search/lib.php b/search/lib.php index f6c17a8cca..17d16784fd 100644 --- a/search/lib.php +++ b/search/lib.php @@ -6,10 +6,11 @@ //document types that can be searched define('SEARCH_NO_TYPE', 'none'); define('SEARCH_WIKI_TYPE', 'wiki'); + define('SEARCH_FORUM_TYPE', 'forum'); //returns all the document type constants function search_get_document_types() { - $r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE); + $r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE, SEARCH_FORUM_TYPE); return $r; } //search_get_document_types diff --git a/search/query.php b/search/query.php index 5a65273fdb..9590695f9f 100644 --- a/search/query.php +++ b/search/query.php @@ -1,16 +1,44 @@ dirroot/search/lib.php"); //check for php5, but don't die yet (see line 27) if ($check = search_check_php5()) { require_once("$CFG->dirroot/search/Zend/Search/Lucene.php"); - require_once("$CFG->dirroot/search/documents/wiki_document.php"); - $query_string = optional_param('query_string', '', PARAM_CLEAN); + $query_string = optional_param('query_string', '', PARAM_CLEAN); + $page_number = optional_param('page', 1, PARAM_INT); + + if ($page_number < 1) { + $page_number = 1; + } //if + $index_path = "$CFG->dataroot/search"; $no_index = false; //optimism! + $results_per_page = 10; try { $index = new Zend_Search_Lucene($index_path, false); @@ -23,7 +51,7 @@ if (!$site = get_site()) { redirect("index.php"); } //if - + $strsearch = "Search"; //get_string(); $strquery = "Enter your search query"; //get_string(); @@ -45,7 +73,7 @@ ?> - +    Advanced search Statistics
@@ -77,27 +105,65 @@ if ($no_index and isadmin()) { print_simple_box_start('center', '50%', 'white', 10); search_stopwatch(); - $hits = $index->find(strtolower($query_string)); - - if (count($hits) > 0) { - $link_function = $hits[0]->type.'_make_link'; - } //if + $hits = $index->find(strtolower($query_string)); + $hit_count = count($hits); print "
"; - print count($hits)." results returned for '".$query_string."'."; - print "

"; + print $hit_count." results returned for '".stripslashes($query_string)."'."; + print "
"; + + if ($hit_count > 0) { + if ($hit_count < $results_per_page) { + $page_number = 1; + } else if ($page_number > ceil($hit_count/$results_per_page)) { + $page_number = $hit_count/$results_per_page; + } //if - print "
    "; + $start = ($page_number - 1)*$results_per_page; + $end = $start + $results_per_page; + + print "
      "; - foreach ($hits as $listing) { - print "
    1. $listing->title
      \n" - ."".search_shorten_url($link_function($listing), 70)."
      \n" - ."Type: ".$listing->type.", score: ".round($listing->score, 3)."
      \n" - ."
    2. \n"; - } //foreach + for ($i = $start; $i < $end; $i++) { + if ($i >= $hit_count) { + break; + } //if + + $listing = $hits[$i]; + + print "
    3. $listing->title
      \n" + ."".search_shorten_url($listing->url, 70)."
      \n" + ."Type: ".$listing->doctype.", score: ".round($listing->score, 3).", author: ".$listing->author."
      \n" + ."
    4. \n"; + } //for + + print "
    "; + } //if + + print "
    "; + + if ($page_number > 1) { + print "< Back "; + } else { + print "< Back "; + } //else + + for ($i = 1; $i <= ceil($hit_count/$results_per_page); $i++) { + if ($page_number == $i) { + print "[$i] "; + } else { + print "$i "; + } //else + } //for + + if ($page_number < ceil($hit_count/$results_per_page)) { + print "Next > "; + } else { + print "Next > "; + } //else - print "
"; + print ""; print_simple_box_end(); } //if diff --git a/search/stats.php b/search/stats.php index 37ac6f5834..8736bda99d 100644 --- a/search/stats.php +++ b/search/stats.php @@ -27,7 +27,7 @@ $type_counts['Total'] = count_records('search_documents'); foreach($types as $type) { - $c = count_records('search_documents', 'type', $type); + $c = count_records('search_documents', 'doctype', $type); $type_counts[$type] = (int)$c; } //foreach } else { diff --git a/search/tests/index.php b/search/tests/index.php new file mode 100644 index 0000000000..91f72bf601 --- /dev/null +++ b/search/tests/index.php @@ -0,0 +1,90 @@ +dirroot/search/lib.php"); + + require_login(); + + if (!isadmin()) { + error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php"); + } //if + + mtrace('
Server Time: '.date('r',time()));
+  mtrace("Testing global search capabilities:\n");
+  
+  $phpversion = phpversion();
+  
+  if (!search_check_php5()) {    
+    mtrace("ERROR: PHP 5.0.0 or later required (currently using version $phpversion).");
+    exit(0);
+  } else {
+    mtrace("Success: PHP 5.0.0 or later is installed ($phpversion).\n");
+  } //else
+
+  //fix paths for testing
+  set_include_path(get_include_path().":../");
+  require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
+  
+  mtrace("Checking activity modules:\n");
+  
+  //the presence of the required search functions -
+  // * mod_iterator
+  // * mod_get_content_for_index
+  //are the sole basis for including a module in the index at the moment.
+  
+  if ($mods = get_records_select('modules')) {
+    foreach ($mods as $mod) {
+      $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';              
+      
+      if (file_exists($class_file)) {
+        include_once($class_file);
+        
+        if (!defined('SEARCH_'.strtoupper($mod->name).'_TYPE')) {
+          mtrace("ERROR: Constant 'SEARCH_".strtoupper($mod->name)."_TYPE' is not defined in /search/lib.php");
+          continue;
+        } //if
+        
+        $iter_function = $mod->name.'_iterator';
+        $index_function = $mod->name.'_get_content_for_index';
+                                
+        if (function_exists($index_function) && function_exists($iter_function)) {
+          if (is_array($iter_function())) {
+            $documents = $index_function(array_pop($iter_function()));
+            
+            if (is_array($documents)) {
+              mtrace("Success: '$mod->name' module seems to be ready for indexing.");
+            } else {
+              mtrace("ERROR: $index_function() doesn't seem to be returning an array.");
+            } //else
+          } else {
+            mtrace("ERROR: $iter_function() doesn't seem to be returning an object array.");
+          } //else
+        } else {
+          mtrace("ERROR: $iter_function() and/or $index_function() does not exist in $class_file");
+        } //else
+      } else {
+        mtrace("Notice: $class_file does not exist, this module will not be indexed.");
+      } //else
+    } //foreach
+  } //if
+  
+  //finished modules
+  mtrace("\nFinished checking activity modules.");
+  
+  //now blocks...
+  //
+  
+  mtrace("
Back to query page or Start indexing."); + mtrace('
'); + +?> \ No newline at end of file -- 2.39.5