From 2e47bfb16b833d8fe2950419b69ac60001509aae Mon Sep 17 00:00:00 2001 From: diml Date: Mon, 7 Apr 2008 21:24:49 +0000 Subject: [PATCH] global sync to HEAD for passing fixes --- blocks/search/block_search.php | 21 +- blocks/search/config_global.html | 14 + search/LISEZMOI.txt | 2 +- search/add.php | 248 ++++---- search/cron.php | 5 +- search/cron_php5.php | 7 +- search/delete.php | 214 +++---- search/documents/chat_document.php | 61 +- search/documents/data_document.php | 66 ++- search/documents/document.php | 19 +- search/documents/forum_document.php | 49 +- search/documents/glossary_document.php | 57 +- search/documents/lesson_document.php | 42 +- search/documents/physical_doc.php | 24 +- search/documents/physical_htm.php | 38 +- search/documents/physical_html.php | 14 +- search/documents/physical_pdf.php | 20 +- search/documents/physical_ppt.php | 15 +- search/documents/physical_txt.php | 13 +- search/documents/physical_xml.php | 13 +- search/documents/resource_document.php | 49 +- search/documents/techproject_document.php | 20 +- search/documents/wiki_document.php | 71 +-- search/index.php | 13 +- search/indexer.php | 331 ++++++----- search/indexersplash.php | 109 ++-- search/indexlib.php | 75 ++- search/lib.php | 18 +- search/query.php | 678 +++++++++++----------- search/querylib.php | 159 ++--- search/stats.php | 269 +++++---- search/update.php | 248 ++++---- 32 files changed, 1662 insertions(+), 1320 deletions(-) diff --git a/blocks/search/block_search.php b/blocks/search/block_search.php index f75fa1668ef..d8ab6064d03 100644 --- a/blocks/search/block_search.php +++ b/blocks/search/block_search.php @@ -1,14 +1,17 @@ get_string() + * the user will be redirected to the query page where they can enter more + * advanced queries, and view the results of their search. When searching from + * this block, the broadest possible selection of documents is searched. + * + * + * Todo: make strings -> get_string() + * + * @package search + * @subpackage search block + * @author: Michael Champanis (mchampan), reengineered by Valery Fremaux + * @date: 2006 06 25 */ class block_search extends block_base { @@ -16,7 +19,7 @@ function init() { $this->title = get_string('blockname', 'block_search'); $this->cron = 1; - $this->version = 2007081100; + $this->version = 2008031500; } //init // only one instance of this block is required diff --git a/blocks/search/config_global.html b/blocks/search/config_global.html index d60de30daaf..be8041c74c2 100644 --- a/blocks/search/config_global.html +++ b/blocks/search/config_global.html @@ -55,6 +55,20 @@ } ?>"/>

+ + + : + + + block_search_usemoodleroot)) ? 'checked="checked"' : '' ; + $notusemoodleroot = (!isset($CFG->block_search_usemoodleroot)) ? 'checked="checked"' : '' ; + ?> + value="1"/> - + value="0"/> +

+ + : diff --git a/search/LISEZMOI.txt b/search/LISEZMOI.txt index 8780ee3f741..55026e58236 100644 --- a/search/LISEZMOI.txt +++ b/search/LISEZMOI.txt @@ -1,5 +1,5 @@ Cette distribution partielle contient une refonte du moteur de -recherche globalde Moodle. +recherche globale de Moodle. Le moteur de recherche est capable d'indexer et de rechercher des informations dans un grand nombre de contenus stockés diff --git a/search/add.php b/search/add.php index 6d45795507b..1f99bd200b3 100644 --- a/search/add.php +++ b/search/add.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Asynchronous adder for new indexable contents * @@ -11,134 +15,144 @@ * multiple arity to handle multiple document types modules */ +/** +* includes and requires +*/ require_once('../config.php'); require_once("$CFG->dirroot/search/lib.php"); -require_login(); +/// checks global search activation + + require_login(); + + if (empty($CFG->enableglobalsearch)) { + error(get_string('globalsearchdisabled', 'search')); + } + + if (!isadmin()) { + error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); + } + +/// check for php5 (lib.php) -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} + if (!search_check_php5()) { + $phpversion = phpversion(); + mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version ".phpversion().")"); + exit(0); + } + + require_once("$CFG->dirroot/search/indexlib.php"); + + $index = new Zend_Search_Lucene(SEARCH_INDEX_PATH); + $dbcontrol = new IndexDBControl(); + $addition_count = 0; + $startindextime = time(); + + $indexdate = $CFG->search_indexer_run_date; + + mtrace('Starting index update (additions)...'); + mtrace('Index size before: '.$CFG->search_index_size."\n"); + +/// get all modules + if ($mods = get_records_select('modules')) { + +/// append virtual modules onto array -if (!isadmin()) { - error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); -} - -//check for php5 (lib.php) -if (!search_check_php5()) { - $phpversion = phpversion(); - mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version $phpversion)"); - exit(0); -} - -require_once("$CFG->dirroot/search/indexlib.php"); - -$index = new Zend_Search_Lucene(SEARCH_INDEX_PATH); -$dbcontrol = new IndexDBControl(); -$addition_count = 0; -$startindextime = time(); - -$indexdate = $CFG->search_indexer_run_date; - -mtrace('
Starting index update (additions)...');
-mtrace('Index size before: '.$CFG->search_index_size."\n");
-
-//get all modules
-if ($mods = get_records_select('modules')) {
-
-//append virtual modules onto array
-$mods = array_merge($mods, search_get_additional_modules());
-    foreach ($mods as $mod) {
-        //build include file and function names
-        $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-        $db_names_function = $mod->name.'_db_names';
-        $get_document_function = $mod->name.'_single_document';
-        $get_newrecords_function = $mod->name.'_new_records';
-        $additions = array();
-        
-        if (file_exists($class_file)) {
-            require_once($class_file);
+    $mods = array_merge($mods, search_get_additional_modules());
+        foreach ($mods as $mod) {
+            //build include file and function names
+            $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
+            $db_names_function = $mod->name.'_db_names';
+            $get_document_function = $mod->name.'_single_document';
+            $get_newrecords_function = $mod->name.'_new_records';
+            $additions = array();
             
-            //if both required functions exist
-            if (function_exists($db_names_function) and function_exists($get_document_function)) {
-                mtrace("Checking $mod->name module for additions.");
-                $valuesArray = $db_names_function();
-                if ($valuesArray){
-                    foreach($valuesArray as $values){
-                        $where = (isset($values[5])) ? 'AND ('.$values[5].')' : '';
-                        $itemtypes = ($values[4] != '*') ? " AND itemtype = '{$values[4]}' " : '' ;
-                        
-                        //select records in MODULE table, but not in SEARCH_DATABASE_TABLE
-                        $table = SEARCH_DATABASE_TABLE;
-                        $query = "
-                            SELECT 
-                                docid,
-                                itemtype 
-                            FROM 
-                                {$CFG->prefix}{$table}
-                            WHERE 
-                                doctype = '{$mod->name}'
-                                $itemtypes
-                        ";
-                        $docIds = get_records_sql_menu($query);
-                        $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
-                        
-                        $query =  "
-                            SELECT id, 
-                                {$values[0]} as docid 
-                            FROM 
-                                {$CFG->prefix}{$values[1]} 
-                            WHERE 
-                                id NOT IN ('{$docIdList}') and 
-                                {$values[2]} > {$indexdate}
-                                $where
-                        ";
-                        $records = get_records_sql($query);
-                        
-                        // foreach record, build a module specific search document using the get_document function
-                        if (is_array($records)) {
-                            foreach($records as $record) {
-                                $add = $get_document_function($record->docid, $values[4]);
-                                // some documents may not be indexable
-                                if ($add)
-                                    $additions[] = $add;
+            if (file_exists($class_file)) {
+                require_once($class_file);
+                
+                //if both required functions exist
+                if (function_exists($db_names_function) and function_exists($get_document_function)) {
+                    mtrace("Checking $mod->name module for additions.");
+                    $valuesArray = $db_names_function();
+                    if ($valuesArray){
+                        foreach($valuesArray as $values){
+                            $where = (isset($values[5])) ? 'AND ('.$values[5].')' : '';
+                            $itemtypes = ($values[4] != '*' && $values[4] != 'any') ? " AND itemtype = '{$values[4]}' " : '' ;
+                            
+                            //select records in MODULE table, but not in SEARCH_DATABASE_TABLE
+                            $table = SEARCH_DATABASE_TABLE;
+                            $query = "
+                                SELECT 
+                                    docid,
+                                    itemtype 
+                                FROM 
+                                    {$CFG->prefix}{$table}
+                                WHERE 
+                                    doctype = '{$mod->name}'
+                                    $itemtypes
+                            ";
+                            $docIds = get_records_sql_menu($query);
+                            $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
+                            
+                            $query =  "
+                                SELECT id, 
+                                    {$values[0]} as docid 
+                                FROM 
+                                    {$CFG->prefix}{$values[1]} 
+                                WHERE 
+                                    id NOT IN ('{$docIdList}') and 
+                                    {$values[2]} > {$indexdate}
+                                    $where
+                            ";
+                            $records = get_records_sql($query);
+                            
+                            // foreach record, build a module specific search document using the get_document function
+                            if (is_array($records)) {
+                                foreach($records as $record) {
+                                    $add = $get_document_function($record->docid, $values[4]);
+                                    // some documents may not be indexable
+                                    if ($add)
+                                        $additions[] = $add;
+                                } 
                             } 
                         } 
-                    } 
-                    
-                    // foreach document, add it to the index and database table
-                    foreach ($additions as $add) {
-                        ++$addition_count;
                         
-                        // object to insert into db
-                        $dbid = $dbcontrol->addDocument($add);
-                        
-                        // synchronise db with index
-                        $add->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
-                        
-                        mtrace("  Add: $add->title (database id = $add->dbid, moodle instance id = $add->docid)");
-                        
-                        $index->addDocument($add);
-                    } 
-                }
-                else{
-                    mtrace("No types to add.\n");
-                }
-                mtrace("Finished $mod->name.\n");
+                        // foreach document, add it to the index and database table
+                        foreach ($additions as $add) {
+                            ++$addition_count;
+                            
+                            // object to insert into db
+                            $dbid = $dbcontrol->addDocument($add);
+                            
+                            // synchronise db with index
+                            $add->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
+                            
+                            mtrace("  Add: $add->title (database id = $add->dbid, moodle instance id = $add->docid)");
+                            
+                            $index->addDocument($add);
+                        } 
+                    }
+                    else{
+                        mtrace("No types to add.\n");
+                    }
+                    mtrace("Finished $mod->name.\n");
+                } 
             } 
         } 
     } 
-} 
+    
+/// commit changes
 
-// commit changes
-$index->commit();
+    $index->commit();
+    
+/// update index date and size
 
-// update index date and size
-set_config("search_indexer_run_date", $startindextime);
-set_config("search_index_size", (int)$CFG->search_index_size + (int)$addition_count);
+    set_config("search_indexer_run_date", $startindextime);
+    set_config("search_index_size", (int)$CFG->search_index_size + (int)$addition_count);
+    
+/// print some additional info
 
-// print some additional info
-mtrace("Added $addition_count documents.");
-mtrace('Index size after: '.$index->count().'
'); + mtrace("Added $addition_count documents."); + mtrace('Index size after: '.$index->count()); ?> \ No newline at end of file diff --git a/search/cron.php b/search/cron.php index 15cbb1c1b73..017c2fd45ae 100644 --- a/search/cron.php +++ b/search/cron.php @@ -12,7 +12,10 @@ * adds documents created since the last index run */ - require_once('../config.php'); + if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page + } + require_once("$CFG->dirroot/search/lib.php"); if (!search_check_php5()) { diff --git a/search/cron_php5.php b/search/cron_php5.php index 4aa4b4347ad..4a0e9f9f2c9 100644 --- a/search/cron_php5.php +++ b/search/cron_php5.php @@ -4,6 +4,7 @@ * This is a special externalized code for cron handling in PHP5. * Should never be called by a php 4.3.0 implementation. */ + try{ // overrides php limits $maxtimelimit = ini_get('max_execution_time'); @@ -11,15 +12,15 @@ try{ $maxmemoryamount = ini_get('memory_limit'); ini_set('memory_limit', '48M'); - mtrace("
Starting cron...\n");
-    mtrace("--DELETE----");
+    mtrace("\n--DELETE----");
     require_once("$CFG->dirroot/search/delete.php");
     mtrace("--UPDATE----");
     require_once("$CFG->dirroot/search/update.php");
     mtrace("--ADD-------");
     require_once("$CFG->dirroot/search/add.php");
     mtrace("------------");
-    mtrace("cron finished.
"); + //mtrace("cron finished."); + mtrace('done'); // set back normal values for php limits ini_set('max_execution_time', $maxtimelimit); diff --git a/search/delete.php b/search/delete.php index 3183e7ddb2f..21ed6f61efd 100644 --- a/search/delete.php +++ b/search/delete.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Asynchronous index cleaner * @@ -11,122 +15,128 @@ * multiple arity to handle multiple document types modules */ +/** +* includes and requires +*/ require_once('../config.php'); require_once("$CFG->dirroot/search/lib.php"); -require_login(); -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} - -if (!isadmin()) { - error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); -} //if - -//check for php5 (lib.php) -if (!search_check_php5()) { - $phpversion = phpversion(); - mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version $phpversion)"); - exit(0); -} - -require_once("$CFG->dirroot/search/indexlib.php"); - -$index = new Zend_Search_Lucene(SEARCH_INDEX_PATH); -$dbcontrol = new IndexDBControl(); -$deletion_count = 0; -$startcleantime = time(); - -mtrace('
Starting clean-up of removed records...');
-mtrace('Index size before: '.$CFG->search_index_size."\n");
-
-if ($mods = get_records_select('modules')) {
-    $mods = array_merge($mods, search_get_additional_modules());
+    require_login();
     
-    foreach ($mods as $mod) {
-        //build function names
-        $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-        $delete_function = $mod->name.'_delete';
-        $db_names_function = $mod->name.'_db_names';
-        $deletions = array();
+    if (empty($CFG->enableglobalsearch)) {
+        error(get_string('globalsearchdisabled', 'search'));
+    }
+    
+    if (!isadmin()) {
+        error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php");
+    } //if
+    
+    //check for php5 (lib.php)
+    if (!search_check_php5()) {
+        $phpversion = phpversion();
+        mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version ".phpversion().")");
+        exit(0);
+    }
+    
+    require_once("$CFG->dirroot/search/indexlib.php");
+    
+    $index = new Zend_Search_Lucene(SEARCH_INDEX_PATH);
+    $dbcontrol = new IndexDBControl();
+    $deletion_count = 0;
+    $startcleantime = time();
+    
+    mtrace('Starting clean-up of removed records...');
+    mtrace('Index size before: '.$CFG->search_index_size."\n");
+    
+    if ($mods = get_records_select('modules')) {
+        $mods = array_merge($mods, search_get_additional_modules());
         
-        if (file_exists($class_file)) {
-            require_once($class_file);
+        foreach ($mods as $mod) {
+            //build function names
+            $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
+            $delete_function = $mod->name.'_delete';
+            $db_names_function = $mod->name.'_db_names';
+            $deletions = array();
             
-            //if both required functions exist
-            if (function_exists($delete_function) and function_exists($db_names_function)) {
-                mtrace("Checking $mod->name module for deletions.");
-                $valuesArray = $db_names_function();
-                if ($valuesArray){
-                    foreach($valuesArray as $values){
-                       $where = (isset($values[5])) ? 'WHERE '.$values[5] : '';
-                       $itemtypes = ($values[4] != '*') ? " itemtype = '{$values[4]}' AND " : '' ;
-                       $query = "
-                            SELECT 
-                                id,
-                                {$values[0]}
-                            FROM 
-                                {$CFG->prefix}{$values[1]}
-                                $where
-                        ";
-                        $docIds = get_records_sql($query);
-                        $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
+            if (file_exists($class_file)) {
+                require_once($class_file);
+                
+                //if both required functions exist
+                if (function_exists($delete_function) and function_exists($db_names_function)) {
+                    mtrace("Checking $mod->name module for deletions.");
+                    $valuesArray = $db_names_function();
+                    if ($valuesArray){
+                        foreach($valuesArray as $values){
+                           $where = (isset($values[5])) ? 'WHERE '.$values[5] : '';
+                           $itemtypes = ($values[4] != '*' && $values[4] != 'any') ? " itemtype = '{$values[4]}' AND " : '' ;
+                           $query = "
+                                SELECT 
+                                    id,
+                                    {$values[0]}
+                                FROM 
+                                    {$CFG->prefix}{$values[1]}
+                                    $where
+                            ";
+                            $docIds = get_records_sql($query);
+                            $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
+                            
+                            $table = SEARCH_DATABASE_TABLE;
+                            $query = "
+                                SELECT 
+                                    id, 
+                                    docid 
+                                FROM 
+                                    {$CFG->prefix}{$table}
+                                WHERE 
+                                    doctype = '{$mod->name}' AND 
+                                    $itemtypes
+                                    docid not in ('{$docIdList}')
+                            ";
+                            $records = get_records_sql($query);
+                            
+                            // build an array of all the deleted records
+                            if (is_array($records)) {
+                                foreach($records as $record) {
+                                    $deletions[] = $delete_function($record->docid, $values[4]);
+                                }
+                            }
+                        }
                         
-                        $table = SEARCH_DATABASE_TABLE;
-                        $query = "
-                            SELECT 
-                                id, 
-                                docid 
-                            FROM 
-                                {$CFG->prefix}{$table}
-                            WHERE 
-                                doctype = '{$mod->name}' AND 
-                                $itemtypes
-                                docid not in ('{$docIdList}')
-                        ";
-                        $records = get_records_sql($query);
-                        
-                        // build an array of all the deleted records
-                        if (is_array($records)) {
-                            foreach($records as $record) {
-                                $deletions[] = $delete_function($record->docid, $values[4]);
+                        foreach ($deletions as $delete) {
+                            // find the specific document in the index, using it's docid and doctype as keys
+                            $doc = $index->find("+docid:{$delete->id} +doctype:$mod->name +itemtype:{$delete->itemtype}");
+                            
+                            // get the record, should only be one
+                            foreach ($doc as $thisdoc) {
+                                ++$deletion_count;
+                                mtrace("  Delete: $thisdoc->title (database id = $thisdoc->dbid, index id = $thisdoc->id, moodle instance id = $thisdoc->docid)");
+                                
+                                //remove it from index and database table
+                                $dbcontrol->delDocument($thisdoc);
+                                $index->delete($thisdoc->id);
                             }
                         }
                     }
-                    
-                    foreach ($deletions as $delete) {
-                        // find the specific document in the index, using it's docid and doctype as keys
-                        $doc = $index->find("+docid:{$delete->id} +doctype:$mod->name +itemtype:{$delete->itemtype}");
-                        
-                        // get the record, should only be one
-                        foreach ($doc as $thisdoc) {
-                            ++$deletion_count;
-                            mtrace("  Delete: $thisdoc->title (database id = $thisdoc->dbid, index id = $thisdoc->id, moodle instance id = $thisdoc->docid)");
-                            
-                            //remove it from index and database table
-                            $dbcontrol->delDocument($thisdoc);
-                            $index->delete($thisdoc->id);
-                        }
+                    else{
+                        mtrace("No types to delete.\n");
                     }
+                    mtrace("Finished $mod->name.\n");
                 }
-                else{
-                    mtrace("No types to delete.\n");
-                }
-                mtrace("Finished $mod->name.\n");
             }
         }
     }
-}
+    
+/// commit changes
 
-//commit changes
-$index->commit();
+    $index->commit();
+    
+/// update index date and index size
 
-//update index date and index size
-set_config("search_indexer_cleanup_date", $startcleantime);
-set_config("search_index_size", (int)$CFG->search_index_size - (int)$deletion_count);
-
-mtrace("Finished $deletion_count removals.");
-mtrace('Index size after: '.$index->count().'
'); + set_config("search_indexer_cleanup_date", $startcleantime); + set_config("search_index_size", (int)$CFG->search_index_size - (int)$deletion_count); + + mtrace("Finished $deletion_count removals."); + mtrace('Index size after: '.$index->count()); ?> \ No newline at end of file diff --git a/search/documents/chat_document.php b/search/documents/chat_document.php index c4db95cee78..4361d32d73c 100644 --- a/search/documents/chat_document.php +++ b/search/documents/chat_document.php @@ -1,8 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for chat activity module * This file contains the mapping between a chat history and it's indexable counterpart, @@ -10,23 +15,22 @@ * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/chat/lib.php * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/chat/lib.php"); -/* +/** * a class for representing searchable information * -**/ +*/ class ChatTrackSearchDocument extends SearchDocument { /** * constructor - * */ public function __construct(&$chatsession, $chat_module_id, $course_id, $group_id, $context_id) { // generic information; required @@ -50,8 +54,8 @@ class ChatTrackSearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, $group_id, 0, PATH_FOR_SEARCH_TYPE_CHAT); - } //constructor -} //ChatTrackSearchDocument + } +} /** @@ -59,19 +63,23 @@ class ChatTrackSearchDocument extends SearchDocument { * @param cm_id the chat course module * @param start the start time of the session * @param end th end time of the session +* @uses CFG * @return a well formed link to session display */ function chat_make_link($cm_id, $start, $end) { global $CFG; return $CFG->wwwroot.'/mod/chat/report.php?id='.$cm_id.'&start='.$start.'&end='.$end; -} //chat_make_link +} /** * fetches all the records for a given session and assemble them as a unique track * we revamped here the code of report.php for making sessions, but without any output. * note that we should collect sessions "by groups" if groupmode() is SEPARATEGROUPS. -* @param chat_id the database +* @param int $chat_id the database +* @param int $fromtime +* @param int $totime +* @uses CFG * @return an array of objects representing the chat sessions. */ function chat_get_session_tracks($chat_id, $fromtime = 0, $totime = 0) { @@ -94,8 +102,7 @@ function chat_get_session_tracks($chat_id, $fromtime = 0, $totime = 0) { foreach($messages as $aMessage){ $groupedMessages[$aMessage->groupid][] = $aMessage; } - } - else{ + } else { $groupedMessages[-1] = &$messages; } $sessiongap = 5 * 60; // 5 minutes silence means a new session @@ -122,9 +129,8 @@ function chat_get_session_tracks($chat_id, $fromtime = 0, $totime = 0) { $tracks[count($tracks) - 1]->content .= ' '.$message->message; $tracks[count($tracks) - 1]->sessionstart = $message->timestamp; } - } + } else { // we initiate a new session track (backwards) - else { $track = new Object(); $track->sessionend = $message->timestamp; $track->sessionstart = $message->timestamp; @@ -140,7 +146,7 @@ function chat_get_session_tracks($chat_id, $fromtime = 0, $totime = 0) { } } return $tracks; -} //chat_get_session_tracks +} /** * part of search engine API @@ -149,7 +155,7 @@ function chat_get_session_tracks($chat_id, $fromtime = 0, $totime = 0) { function chat_iterator() { $chatrooms = get_records('chat'); return $chatrooms; -} //chat_iterator +} /** * part of search engine API @@ -169,7 +175,7 @@ function chat_get_content_for_index(&$chat) { foreach($sessionTracks as $aTrackId => $aTrack) { foreach($aTrack->sessionusers as $aUserId){ $user = get_record('user', 'id', $aUserId); - $aTrack->authors = ($user) ? $user->firstname.' '.$user->lastname : '' ; + $aTrack->authors = ($user) ? fullname($user) : '' ; $documents[] = new ChatTrackSearchDocument(get_object_vars($aTrack), $cm->id, $chat->course, $aTrack->groupid, $context->id); } } @@ -177,7 +183,7 @@ function chat_get_content_for_index(&$chat) { return $documents; } return array(); -} //chat_get_content_for_index +} /** * returns a single data search document based on a chat_session id @@ -202,11 +208,11 @@ function chat_single_document($id, $itemtype) { if ($tracks){ $aTrack = $tracks[0]; $document = new ChatTrackSearchDocument(get_object_vars($aTrack), $cm->id, $chat->course, $aTrack->groupid, $context->id); + return $document; } - return $document; } return null; -} //chat_single_document +} /** * dummy delete function that packs id with itemtype. @@ -217,7 +223,7 @@ function chat_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //chat_delete +} /** * returns the var names needed to build a sql query for addition/deletions @@ -226,7 +232,7 @@ function chat_delete($info, $itemtype) { function chat_db_names() { //[primary id], [table name], [time created field name], [time modified field name] return null; -} //chat_db_names +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -241,6 +247,7 @@ function chat_db_names() { * points out a session history which is a close sequence of messages. * @param user the user record denoting the user who searches * @param group_id the current group used by the user when searching +* @uses CFG * @return true if access is allowed, false elsewhere */ function chat_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){ @@ -280,7 +287,7 @@ function chat_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c } return true; -} //chat_check_text_access +} /** * this call back is called when displaying the link for some last post processing @@ -290,5 +297,5 @@ function chat_link_post_processing($title){ setLocale(LC_TIME, substr(current_language(), 0, 2)); $title = preg_replace('/TT_(.*)_TT/e', "userdate(\\1)", $title); return $title; -} //chat_link_post_processing +} ?> \ No newline at end of file diff --git a/search/documents/data_document.php b/search/documents/data_document.php index 63f3c23bc91..aaeeea3928c 100644 --- a/search/documents/data_document.php +++ b/search/documents/data_document.php @@ -1,8 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for data activity module * This file contains the mapping between a database object and it's indexable counterpart, @@ -10,23 +15,22 @@ * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/data/lib.php * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/data/lib.php"); -/* +/** * a class for representing searchable information (data records) * -**/ +*/ class DataSearchDocument extends SearchDocument { /** * constructor - * */ public function __construct(&$record, $course_id, $context_id) { // generic information; required @@ -51,18 +55,17 @@ class DataSearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, $record['groupid'], $record['userid'], PATH_FOR_SEARCH_TYPE_DATA); - } //constructor -} //ChatSearchDocument + } +} -/* +/** * a class for representing searchable information (comments on data records) * -**/ +*/ class DataCommentSearchDocument extends SearchDocument { /** * constructor - * */ public function __construct(&$comment, $course_id, $context_id) { // generic information; required @@ -83,25 +86,27 @@ class DataCommentSearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, $comment['groupid'], $comment['userid'], PATH_FOR_SEARCH_TYPE_DATA); - } //constructor -} //ChatCommentSearchDocument + } +} /** * constructs a valid link to a data record content * @param database_id the database reference * @param record_id the record reference +* @uses CFG * @return a valid url top access the information as a string */ function data_make_link($database_id, $record_id) { global $CFG; return $CFG->wwwroot.'/mod/data/view.php?d='.$database_id.'&rid='.$record_id; -} //data_make_link +} /** * fetches all the records for a given database * @param database_id the database * @param typematch a comma separated list of types that should be considered for searching or * +* @uses CFG * @return an array of objects representing the data records. */ function data_get_records($database_id, $typematch = '*') { @@ -127,19 +132,19 @@ function data_get_records($database_id, $typematch = '*') { if($typematch == '*' || preg_match("/\\b{$fieldset[$aDatum->fieldid]->type}\\b/", $typematch)){ if (!isset($records[$aDatum->recordid])){ $records[$aDatum->recordid]['_first'] = $aDatum->content.' '.$aDatum->content1.' '.$aDatum->content2.' '.$aDatum->content3.' '.$aDatum->content4.' '; - } - else{ + } else { $records[$aDatum->recordid][$fieldset[$aDatum->fieldid]->name] = $aDatum->content.' '.$aDatum->content1.' '.$aDatum->content2.' '.$aDatum->content3.' '.$aDatum->content4.' '; } } } } return $records; -} //data_get_records +} /** * fetches all the comments for a given database * @param database_id the database +* @uses CFG * @return an array of objects representing the data record comments. */ function data_get_comments($database_id) { @@ -163,7 +168,7 @@ function data_get_comments($database_id) { "; $comments = get_records_sql($query); return $comments; -} //data_get_comments +} /** @@ -173,7 +178,7 @@ function data_get_comments($database_id) { function data_iterator() { $databases = get_records('data'); return $databases; -} //data_iterator +} /** * part of search engine API @@ -221,7 +226,7 @@ function data_get_content_for_index(&$database) { } } return $documents; -} //data_get_content_for_index +} /** * returns a single data search document based on a data entry id @@ -256,8 +261,7 @@ function data_single_document($id, $itemtype) { $recordMetaData->content = $accumulator; // make document $documents[] = new DataSearchDocument(get_object_vars($recordMetaData), $record_course, $context->id); - } - elseif($itemtype == 'comment'){ + } elseif($itemtype == 'comment') { // get main records $comment = get_record('data_comments', 'id', $id); $record = get_record('data_records', 'id', $comment->recordid); @@ -272,11 +276,10 @@ function data_single_document($id, $itemtype) { $comment->groupid = $record->groupid; // make document $documents[] = new DataCommentSearchDocument(get_object_vars($comment), $record_course, $context->id); - } - else{ + } else { mtrace('Error : bad or missing item type'); } -} //data_single_document +} /** * dummy delete function that packs id with itemtype. @@ -287,7 +290,7 @@ function data_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //data_delete +} /** * returns the var names needed to build a sql query for addition/deletions @@ -299,7 +302,7 @@ function data_db_names() { array('id', 'data_records', 'timecreated', 'timemodified', 'record'), array('id', 'data_comments', 'created', 'modified', 'comment') ); -} //data_db_names +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -314,6 +317,7 @@ function data_db_names() { * points out an indexed data record page. * @param user the user record denoting the user who searches * @param group_id the current group used by the user when searching +* @uses CFG * @return true if access is allowed, false elsewhere */ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){ @@ -394,5 +398,5 @@ function data_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c } return true; -} // data_check_text_access +} ?> \ No newline at end of file diff --git a/search/documents/document.php b/search/documents/document.php index 205a2ac18a2..266dead49a9 100644 --- a/search/documents/document.php +++ b/search/documents/document.php @@ -1,14 +1,21 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Base search document from which other module/block types can * extend. -**/ +*/ +/** +* +*/ abstract class SearchDocument extends Zend_Search_Lucene_Document { public function __construct(&$doc, &$data, $course_id, $group_id, $user_id, $path) { //document identification and indexing @@ -52,7 +59,7 @@ abstract class SearchDocument extends Zend_Search_Lucene_Document { // of multiple capabilities in their code. This possibility should be left open here. $this->addField(Zend_Search_Lucene_Field::UnIndexed('capabilities', $caps)); */ - } //constructor -} //SearchDocument + } +} ?> \ No newline at end of file diff --git a/search/documents/forum_document.php b/search/documents/forum_document.php index b8d7755388f..ae3b3b21906 100644 --- a/search/documents/forum_document.php +++ b/search/documents/forum_document.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for forum activity module * This file contains the mapping between a forum post and it's indexable counterpart, @@ -11,24 +15,22 @@ * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/forum/lib.php * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ -/* see wiki_document.php for descriptions */ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/forum/lib.php"); -/* +/** * a class for representing searchable information * -**/ +*/ class ForumSearchDocument extends SearchDocument { /** * constructor - * */ public function __construct(&$post, $forum_id, $course_id, $itemtype, $context_id) { // generic information @@ -50,8 +52,8 @@ class ForumSearchDocument extends SearchDocument { $data->discussion = $post['discussion']; parent::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], PATH_FOR_SEARCH_TYPE_FORUM); - } //constructor -} //ForumSearchDocument + } +} /** * constructs a valid link to a chat content @@ -63,7 +65,7 @@ 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 +} /** * search standard API @@ -72,7 +74,7 @@ function forum_make_link($discussion_id, $post_id) { function forum_iterator() { $forums = get_records('forum'); return $forums; -} //forum_iterator +} /** * search standard API @@ -108,7 +110,7 @@ function forum_get_content_for_index(&$forum) { } } return $documents; -} //forum_get_content_for_index +} /** * returns a single forum search document based on a forum entry id @@ -128,7 +130,7 @@ function forum_single_document($id, $itemtype) { return new ForumSearchDocument(get_object_vars($post), $discussion->forum, $discussion->course, $itemtype, $context->id); } return null; -} //forum_single_document +} /** * dummy delete function that aggregates id with itemtype. @@ -139,7 +141,7 @@ function forum_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //forum_delete +} /** * returns the var names needed to build a sql query for addition/deletions @@ -151,11 +153,12 @@ function forum_db_names() { array('id', 'forum_posts', 'created', 'modified', 'head', 'parent = 0'), array('id', 'forum_posts', 'created', 'modified', 'post', 'parent != 0') ); -} //forum_db_names +} /** * reworked faster version from /mod/forum/lib.php * @param forum_id a forum identifier +* @uses CFG, USER * @return an array of posts */ function forum_get_discussions_fast($forum_id) { @@ -202,12 +205,13 @@ function forum_get_discussions_fast($forum_id) { d.timemodified DESC "; return get_records_sql($query); -} //forum_get_discussions_fast +} /** * reworked faster version from /mod/forum/lib.php * @param parent the id of the first post within the discussion * @param forum_id the forum identifier +* @uses CFG * @return an array of posts */ function forum_get_child_posts_fast($parent, $forum_id) { @@ -241,7 +245,7 @@ function forum_get_child_posts_fast($parent, $forum_id) { p.created ASC "; return get_records_sql($query); -} //forum_get_child_posts_fast +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -256,6 +260,7 @@ function forum_get_child_posts_fast($parent, $forum_id) { * points out the individual post. * @param user the user record denoting the user who searches * @param group_id the current group used by the user when searching +* @uses CFG, USER * @return true if access is allowed, false elsewhere */ function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){ @@ -290,6 +295,6 @@ function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id, $ } return true; -} //forum_check_text_access +} ?> \ No newline at end of file diff --git a/search/documents/glossary_document.php b/search/documents/glossary_document.php index b275baabd1a..8d48e112b2c 100644 --- a/search/documents/glossary_document.php +++ b/search/documents/glossary_document.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for glossary activity module * This file contains a mapping between a glossary entry and it's indexable counterpart, @@ -11,17 +15,17 @@ * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/glossary/lib.php * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/documents/document.php"); -/* +/** * a class for representing searchable information * -**/ +*/ class GlossarySearchDocument extends SearchDocument { /** @@ -49,18 +53,17 @@ class GlossarySearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, -1, $entry['userid'], PATH_FOR_SEARCH_TYPE_GLOSSARY); - } //constructor -} //GlossarySearchDocument + } +} -/* +/** * a class for representing searchable information * -**/ +*/ class GlossaryCommentSearchDocument extends SearchDocument { /** * document constructor - * */ public function __construct(&$entry, $glossary_id, $course_id, $context_id) { // generic information; required @@ -83,8 +86,8 @@ class GlossaryCommentSearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, -1, $entry['userid'], PATH_FOR_SEARCH_TYPE_GLOSSARY); - } //constructor -} //GlossaryCommentSearchDocument + } +} /** * constructs valid access links to information @@ -102,7 +105,7 @@ function glossary_make_link($entry_id) { // preserve glossary pop-up, be careful where you place your ' and "s //this function is meant to return a url that is placed between href='[url here]' return "$CFG->wwwroot/mod/glossary/showentry.php?eid=$entry_id' onclick='return openpopup(\"/mod/glossary/showentry.php?eid=$entry_id\", \"entry\", DEFAULT_POPUP_SETTINGS, 0);"; -} //glossary_make_link +} /** * part of search engine API @@ -111,7 +114,7 @@ function glossary_make_link($entry_id) { function glossary_iterator() { $glossaries = get_records('glossary'); return $glossaries; -} //glossary_iterator +} /** * part of search engine API @@ -153,7 +156,7 @@ function glossary_get_content_for_index(&$glossary) { } } return $documents; -} //glossary_get_content_for_index +} /** * part of search engine API @@ -179,7 +182,7 @@ function glossary_single_document($id, $itemtype) { elseif ($itemtype == 'comment'){ return new GlossaryCommentSearchDocument(get_object_vars($comment), $entry->glossaryid, $glossary_course, $context->id); } -} //glossary_single_document +} /** * dummy delete function that packs id with itemtype. @@ -190,7 +193,7 @@ function glossary_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //glossary_delete +} /** * returns the var names needed to build a sql query for addition/deletions @@ -202,7 +205,7 @@ function glossary_db_names() { array('id', 'glossary_entries', 'timecreated', 'timemodified', 'standard'), array('id', 'glossary_comments', 'timemodified', 'timemodified', 'comment') ); -} //glossary_db_names +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -241,6 +244,14 @@ function glossary_check_text_access($path, $itemtype, $this_id, $user, $group_id } return true; -} //glossary_check_text_access +} + +/** +* post processes the url for cleaner output. +* @param string $title +*/ +function glossary_link_post_processing($title){ + return mb_convert_encoding($title, 'auto', 'UTF-8'); +} ?> \ No newline at end of file diff --git a/search/documents/lesson_document.php b/search/documents/lesson_document.php index 7f7a42682cd..42615b8927f 100644 --- a/search/documents/lesson_document.php +++ b/search/documents/lesson_document.php @@ -1,29 +1,31 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for lesson activity module * This file contains the mapping between a lesson page and it's indexable counterpart, * * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/lesson/lib.php -* -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ -/* see wiki_document.php for descriptions */ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/lesson/lib.php"); -/* +/** * a class for representing searchable information * -**/ +*/ class LessonPageSearchDocument extends SearchDocument { /** @@ -48,8 +50,8 @@ class LessonPageSearchDocument extends SearchDocument { $data->lesson = $page['lessonid']; parent::__construct($doc, $data, $course_id, 0, 0, PATH_FOR_SEARCH_TYPE_LESSON); - } //constructor -} //LessonPageSearchDocument + } +} /** * constructs a valid link to a chat content @@ -64,7 +66,7 @@ function lesson_make_link($lessonmoduleid, $itemid, $itemtype) { return "{$CFG->wwwroot}/mod/lesson/view.php?id={$lessonmoduleid}&pageid={$itemid}"; } return $CFG->wwwroot.'/mod/lesson/view.php?id='.$lessonmoduleid; -} //lesson_make_link +} /** * search standard API @@ -73,7 +75,7 @@ function lesson_make_link($lessonmoduleid, $itemid, $itemtype) { function lesson_iterator() { $lessons = get_records('lesson'); return $lessons; -} //lesson_iterator +} /** * search standard API @@ -96,7 +98,7 @@ function lesson_get_content_for_index(&$lesson) { } return $documents; -} //lesson_get_content_for_index +} /** * returns a single lesson search document based on a lesson page id @@ -116,7 +118,7 @@ function lesson_single_document($id, $itemtype) { return new LessonPageSearchDocument(get_object_vars($page), $cm->id, $lesson->course, $itemtype, $context->id); } return null; -} //lesson_single_document +} /** * dummy delete function that aggregates id with itemtype. @@ -127,7 +129,7 @@ function lesson_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //lesson_delete +} /** * returns the var names needed to build a sql query for addition/deletions @@ -138,7 +140,7 @@ function lesson_db_names() { return array( array('id', 'lesson_pages', 'timecreated', 'timemodified', 'page') ); -} //lesson_db_names +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -201,5 +203,5 @@ function lesson_check_text_access($path, $itemtype, $this_id, $user, $group_id, } return true; -} //lesson_check_text_access +} ?> \ No newline at end of file diff --git a/search/documents/physical_doc.php b/search/documents/physical_doc.php index b2f6ccfff52..3b5f1c07ec9 100644 --- a/search/documents/physical_doc.php +++ b/search/documents/physical_doc.php @@ -1,40 +1,50 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ -/* +/** * MS Word extractor +* @param object $resource +* @uses CFG, USER */ - function get_text_for_indexing_doc(&$resource){ global $CFG, $USER; // SECURITY : do not allow non admin execute anything on system !! if (!isadmin($USER->id)) return; + $moodleroot = (@$CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ; + // just call pdftotext over stdout and capture the output if (!empty($CFG->block_search_word_to_text_cmd)){ - if (!file_exists("{$CFG->dirroot}/{$CFG->block_search_word_to_text_cmd}")){ + if (!file_exists("{$moodleroot}{$CFG->block_search_word_to_text_cmd}")){ mtrace('Error with MSWord to text converter command : exectuable not found.'); } else{ $file = escapeshellarg($CFG->dataroot.'/'.$resource->course.'/'.$resource->reference); - $text_converter_cmd = "{$CFG->dirroot}/{$CFG->block_search_word_to_text_cmd} $file"; + $command = trim($CFG->block_search_word_to_text_cmd); + $text_converter_cmd = "{$moodleroot}{$command} \"$file\""; if ($CFG->block_search_word_to_text_env){ putenv($CFG->block_search_word_to_text_env); } + mtrace("Executing : $text_converter_cmd"); $result = shell_exec($text_converter_cmd); if ($result){ return mb_convert_encoding($result, 'UTF8', 'auto'); } else{ - mtrace('Error with MSWord to text converter command : execution failed.'); + mtrace('Error with MSWord to text converter command : execution failed. '); return ''; } } diff --git a/search/documents/physical_htm.php b/search/documents/physical_htm.php index 36878ba492f..76d6073dd69 100644 --- a/search/documents/physical_htm.php +++ b/search/documents/physical_htm.php @@ -1,13 +1,22 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ +/** +* @param object $resource +* @uses CFG, USER +*/ function get_text_for_indexing_htm(&$resource){ global $CFG, $USER; @@ -15,21 +24,32 @@ function get_text_for_indexing_htm(&$resource){ if (!isadmin($USER->id)) return; // just get text - $text = implode('', file("{$CFG->dataroot}/{$resource->course}/($resource->reference)")); + $text = implode('', file("{$CFG->dataroot}/{$resource->course}/{$resource->reference}")); // extract keywords and other interesting meta information and put it back as real content for indexing - if (preg_match('/(.*)]*)>(.*)/is',$text, $matches)){ + if (preg_match('/(.*)]*)>(.*)/is', $text, $matches)){ $prefix = $matches[1]; $meta_attributes = $matches[2]; $suffix = $matches[3]; - if (preg_match('/name="(keywords|description)"/i', $attributes)){ - preg_match('/content="[^"]+"/i', $attributes, $matches); + if (preg_match('/name="(keywords|description)"/i', $meta_attributes)){ + preg_match('/content="([^"]+)"/i', $meta_attributes, $matches); $text = $prefix.' '.$matches[1].' '.$suffix; } } - // filter all html tags - // $text = clean_text($text, FORMAT_PLAIN); - // NOTE : this is done in ResourceSearchDocument __constructor + // brutally filters all html tags + $text = preg_replace("/<[^>]*>/", '', $text); + $text = preg_replace("//", '', $text); + $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8'); + $text = mb_convert_encoding($text, 'UTF-8', 'AUTO'); + + /* + * debug code for tracing input + echo "
"; + $FILE = fopen("filetrace.log", 'w'); + fwrite($FILE, $text); + fclose($FILE); + echo "
"; + */ if (!empty($CFG->block_search_limit_index_body)){ $text = shorten($text, $CFG->block_search_limit_index_body); diff --git a/search/documents/physical_html.php b/search/documents/physical_html.php index 8455e709b40..e03d44566f2 100644 --- a/search/documents/physical_html.php +++ b/search/documents/physical_html.php @@ -1,13 +1,21 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License +* +* this is a format handler for getting text out of a standard html format * so it can be indexed by Lucene search engine */ +/** +* @param object $resource +*/ function get_text_for_indexing_html(&$resource){ // wraps to htm handler diff --git a/search/documents/physical_pdf.php b/search/documents/physical_pdf.php index fabea266364..8ea7abfd1a6 100644 --- a/search/documents/physical_pdf.php +++ b/search/documents/physical_pdf.php @@ -1,28 +1,40 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ +/** +* @param object $resource +* @uses CFG, USER +*/ function get_text_for_indexing_pdf(&$resource){ global $CFG, $USER; // SECURITY : do not allow non admin execute anything on system !! if (!isadmin($USER->id)) return; + $moodleroot = (@$CFG->block_search_usemoodleroot) ? "{$CFG->dirroot}/" : '' ; + // just call pdftotext over stdout and capture the output if (!empty($CFG->block_search_pdf_to_text_cmd)){ preg_match("/^\S+/", $CFG->block_search_pdf_to_text_cmd, $matches); - if (!file_exists("{$CFG->dirroot}/{$matches[0]}")){ + if (!file_exists("{$moodleroot}/{$matches[0]}")){ mtrace('Error with pdf to text converter command : exectuable not found.'); } else{ $file = escapeshellarg($CFG->dataroot.'/'.$resource->course.'/'.$resource->reference); - $text_converter_cmd = "{$CFG->dirroot}/{$CFG->block_search_pdf_to_text_cmd} $file -"; + $command = trim($CFG->block_search_pdf_to_text_cmd); + $text_converter_cmd = "{$moodleroot}/{$command} \"$file\" -"; $result = shell_exec($text_converter_cmd); if ($result){ return $result; diff --git a/search/documents/physical_ppt.php b/search/documents/physical_ppt.php index 7d89e74ed71..2de768ffaf8 100644 --- a/search/documents/physical_ppt.php +++ b/search/documents/physical_ppt.php @@ -1,14 +1,19 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ -/** +/* * first implementation is a trivial heuristic based on ppt character stream : * text sequence always starts with a 00 9F 0F 04 sequence followed by a 15 bytes * sequence @@ -22,6 +27,10 @@ * based on these following rules, here is a little empiric texte extractor for PPT */ +/** +* @param object $resource +* @uses CFG, USER +*/ function get_text_for_indexing_ppt(&$resource){ global $CFG, $USER; diff --git a/search/documents/physical_txt.php b/search/documents/physical_txt.php index 1ef3fd8d379..b20be4152f0 100644 --- a/search/documents/physical_txt.php +++ b/search/documents/physical_txt.php @@ -1,13 +1,22 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ +/** +* @param object $resource +* @uses CFG, USER +*/ function get_text_for_indexing_txt(&$resource){ global $CFG, $USER; diff --git a/search/documents/physical_xml.php b/search/documents/physical_xml.php index 64162a252b0..0fde56cb064 100644 --- a/search/documents/physical_xml.php +++ b/search/documents/physical_xml.php @@ -1,13 +1,22 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * this is a format handler for getting text out of a proprietary binary format * so it can be indexed by Lucene search engine */ +/** +* @param object $resource +* @uses CFG, USER +*/ function get_text_for_indexing_xml(&$resource){ global $CFG, $USER; diff --git a/search/documents/resource_document.php b/search/documents/resource_document.php index 95698a08504..0e60706b2bb 100644 --- a/search/documents/resource_document.php +++ b/search/documents/resource_document.php @@ -1,24 +1,31 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for all resources * This file contains the mapping between a resource and it's indexable counterpart, * * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/resource/lib.php -**/ +*/ +/** +* requires and includes +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/resource/lib.php"); -/* +/* * * a class for representing searchable information * -**/ +*/ class ResourceSearchDocument extends SearchDocument { public function __construct(&$resource, $context_id) { // generic information; required @@ -68,6 +75,7 @@ function resource_iterator() { * this function does not need a content iterator, returns all the info * itself; * @param notneeded to comply API, remember to fake the iterator array though +* @uses CFG * @return an array of searchable documents */ function resource_get_content_for_index(&$notneeded) { @@ -155,7 +163,10 @@ function resource_get_physical_file(&$resource, $context_id, $getsingle, &$docum global $CFG; // cannot index empty references - if (empty($resource->reference)) return false; + if (empty($resource->reference)){ + mtrace("Cannot index, empty reference."); + return false; + } // cannot index remote resources if (resource_is_url($resource->reference)){ @@ -166,6 +177,7 @@ function resource_get_physical_file(&$resource, $context_id, $getsingle, &$docum $fileparts = pathinfo($resource->reference); // cannot index unknown or masked types if (empty($fileparts['extension'])) { + mtrace("Cannot index without explicit extension."); return false; } @@ -189,15 +201,15 @@ function resource_get_physical_file(&$resource, $context_id, $getsingle, &$docum $resource->alltext = $function_name($resource); if (!empty($resource->alltext)){ if ($getsingle){ - return new ResourceSearchDocument(get_object_vars($resource), $context_id); - } - else{ + $single = new ResourceSearchDocument(get_object_vars($resource), $context_id); + mtrace("finished file $resource->name as {$resource->reference}"); + return $single; + } else { $documents[] = new ResourceSearchDocument(get_object_vars($resource), $context_id); } mtrace("finished file $resource->name as {$resource->reference}"); } - } - else{ + } else { mtrace("fulltext handler not found for $ext type"); } return false; @@ -250,8 +262,7 @@ function resource_single_document($id, $itemtype) { $document = resource_get_physical_file($resource, true, $context->id); if (!$document) mtrace("Warning : this document {$resource->name} will not be indexed"); return $document; - } - else{ + } else { return new ResourceSearchDocument(get_object_vars($resource), $context->id); } } @@ -305,5 +316,13 @@ function resource_check_text_access($path, $itemtype, $this_id, $user, $group_id } return true; -} //resource_check_text_access +} + +/** +* post processes the url for cleaner output. +* @param string $title +*/ +function resource_link_post_processing($title){ + return mb_convert_encoding($title, 'auto', 'UTF-8'); +} ?> \ No newline at end of file diff --git a/search/documents/techproject_document.php b/search/documents/techproject_document.php index 2eeb30de728..52976d19283 100644 --- a/search/documents/techproject_document.php +++ b/search/documents/techproject_document.php @@ -1,13 +1,20 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for techproject activity module */ -/* see wiki_document.php for descriptions */ +/** +* requires and includes +*/ require_once("$CFG->dirroot/search/documents/document.php"); require_once("$CFG->dirroot/mod/techproject/lib.php"); @@ -84,6 +91,7 @@ function techproject_get_content_for_index(&$techproject) { foreach($entries as $anEntry) { if ($anEntry) { if (strlen($anEntry->description) > 0) { + $anEntry->author = ''; $documents[] = new TechprojectEntrySearchDocument(get_object_vars($anEntry), $techproject->course, $context->id); } } @@ -113,18 +121,22 @@ function techproject_single_document($id, $itemtype) { switch ($itemtype){ case 'requirement':{ $entry = get_record('techproject_requirement', 'id', $id); + $entry->author = ''; break; } case 'specification':{ $entry = get_record('techproject_specification', 'id', $id); + $entry->author = ''; break; } case 'milestone':{ $entry = get_record('techproject_milestone', 'id', $id); + $entry->author = ''; break; } case 'deliverable':{ $entry = get_record('techproject_deliverable', 'id', $id); + $entry->author = ''; break; } case 'task':{ @@ -136,7 +148,7 @@ function techproject_single_document($id, $itemtype) { break; } } - $techprojet_course = get_field('techproject', 'course', 'id', $entry->projectid); + $techproject_course = get_field('techproject', 'course', 'id', $entry->projectid); $coursemodule = get_field('modules', 'id', 'name', 'techproject'); $cm = get_record('course_modules', 'course', $techproject_course, 'module', $coursemodule, 'instance', $entry->projectid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); diff --git a/search/documents/wiki_document.php b/search/documents/wiki_document.php index f198a3fec7c..23ed2f8a366 100644 --- a/search/documents/wiki_document.php +++ b/search/documents/wiki_document.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * document handling for wiki activity module * This file contains the mapping between a wiki page and it's indexable counterpart, @@ -11,22 +15,21 @@ * * Functions for iterating and retrieving the necessary records are now also included * in this file, rather than mod/wiki/lib.php -* -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 -**/ +*/ +/** +* includes and requires +*/ 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, $course_id, $group_id, $user_id, $context_id) { // generic information; required @@ -36,7 +39,7 @@ class WikiSearchDocument extends SearchDocument { $doc->contextid = $context_id; $doc->title = $page['pagename']; - $doc->date = $page['timemodified']; + $doc->date = $page['lastmodified']; //remove '(ip.ip.ip.ip)' from wiki author field $doc->author = preg_replace('/\(.*?\)/', '', $page['author']); $doc->contents = $page['content']; @@ -48,8 +51,8 @@ class WikiSearchDocument extends SearchDocument { // construct the parent class parent::__construct($doc, $data, $course_id, $group_id, $user_id, PATH_FOR_SEARCH_TYPE_WIKI); - } //constructor -} //WikiSearchDocument + } +} /** * converts a page name to cope Wiki constraints. Transforms spaces in plus. @@ -58,13 +61,14 @@ class WikiSearchDocument extends SearchDocument { */ function wiki_name_convert($str) { return str_replace(' ', '+', $str); -} //wiki_name_convert +} /** * constructs a valid link to a wiki content -* @param wikiId -* @param title -* @param version +* @param int $wikiId +* @param string $title +* @param int $version +* @uses CFG */ function wiki_make_link($wikiId, $title, $version) { global $CFG; @@ -75,9 +79,9 @@ function wiki_make_link($wikiId, $title, $version) { /** * rescued and converted from ewikimoodlelib.php * retrieves latest version of a page -* @param entry the wiki object as a reference -* @param pagename the name of the page known by the wiki engine -* @param version +* @param object $entry the wiki object as a reference +* @param string $pagename the name of the page known by the wiki engine +* @param int $version */ function wiki_get_latest_page(&$entry, $pagename, $version = 0) { $pagename = "'".addslashes($pagename)."'"; @@ -104,20 +108,20 @@ function wiki_get_latest_page(&$entry, $pagename, $version = 0) { } else { return false; } -} //wiki_get_latest_page +} /** * fetches all pages, including old versions -* @param entry the wiki object as a reference +* @param object $entry the wiki object as a reference * @return an array of record objects that represents pages of this wiki object */ 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 -* +* @param object $entry */ function wiki_get_latest_pages(&$entry) { //== (My)SQL for this @@ -134,14 +138,14 @@ function wiki_get_latest_pages(&$entry) { if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { if ($pagesets = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) { foreach ($pagesets as $aPageset) { - $pages[] = wiki_get_latest_page($entry, $aPageset->id); + $pages[] = wiki_get_latest_page($entry, $aPageset->pagename); } } else { return false; } } return $pages; -} //wiki_get_latest_pages +} /** * part of search engine API @@ -150,7 +154,7 @@ function wiki_get_latest_pages(&$entry) { function wiki_iterator() { $wikis = get_records('wiki'); return $wikis; -} //wiki_iterator +} /** * part of search engine API @@ -182,13 +186,13 @@ function wiki_get_content_for_index(&$wiki) { } } return $documents; -} //wiki_get_content_for_index +} /** * returns a single wiki search document based on a wiki_entry id * @param id the id of the wiki * @param itemtype the type of information (standard) -* @retuen a searchable document +* @return a searchable document */ function wiki_single_document($id, $itemtype) { $page = get_record('wiki_pages', 'id', $id); @@ -197,7 +201,7 @@ function wiki_single_document($id, $itemtype) { $cm = get_record('course_modules', 'course', $entry->course, 'module', $coursemodule, 'instance', $entry->wikiid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); return new WikiSearchDocument(get_object_vars($page), $entry->wikiid, $entry->course, $entry->groupid, $page->userid, $context->id); -} //wiki_single_document +} /** * dummy delete function that packs id with itemtype. @@ -208,13 +212,13 @@ function wiki_delete($info, $itemtype) { $object->id = $info; $object->itemtype = $itemtype; return $object; -} //wiki_delete +} //returns the var names needed to build a sql query for addition/deletions function wiki_db_names() { //[primary id], [table name], [time created field name], [time modified field name] return array(array('id', 'wiki_pages', 'created', 'lastmodified', 'standard')); -} //wiki_db_names +} /** * this function handles the access policy to contents indexed as searchable documents. If this @@ -229,6 +233,7 @@ function wiki_db_names() { * points out the indexed wiki page. * @param user the user record denoting the user who searches * @param group_id the current group used by the user when searching +* @uses CFG * @return true if access is allowed, false elsewhere */ function wiki_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){ @@ -256,5 +261,5 @@ function wiki_check_text_access($path, $itemtype, $this_id, $user, $group_id, $c } return true; -} //wiki_check_text_access +} ?> \ No newline at end of file diff --git a/search/index.php b/search/index.php index 264892e33df..089688c9659 100644 --- a/search/index.php +++ b/search/index.php @@ -1,9 +1,18 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License +* * Entry page for /search * Redirects to query.php, because that is the most likely place a * user intended to go to when typing moodle.site/search -**/ +*/ header("Location: query.php"); ?> \ No newline at end of file diff --git a/search/indexer.php b/search/indexer.php index 85afd580be2..379af25fdc5 100644 --- a/search/indexer.php +++ b/search/indexer.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * The indexer logic - * @@ -26,178 +30,195 @@ @ob_implicit_flush(true); @ob_end_flush(); +/** +* includes and requires +*/ require_once('../config.php'); require_once("$CFG->dirroot/search/lib.php"); -//only administrators can index the moodle installation, because access to all pages is required -require_login(); +/// only administrators can index the moodle installation, because access to all pages is required -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} + require_login(); + + if (empty($CFG->enableglobalsearch)) { + error(get_string('globalsearchdisabled', 'search')); + } + + if (!isadmin()) { + error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); + } + +/// confirmation flag to prevent accidental reindexing (indexersplash.php is the correct entry point) -if (!isadmin()) { - error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); -} //if + $sure = strtolower(optional_param('areyousure', '', PARAM_ALPHA)); + + if ($sure != 'yes') { + mtrace("
Sorry, you need to confirm indexing via indexersplash.php"
+              .". (Back to query page).
"); + + exit(0); + } + +/// check for php5 (lib.php) -//confirmation flag to prevent accidental reindexing (indexersplash.php is the correct entry point) -$sure = strtolower(optional_param('areyousure', '', PARAM_ALPHA)); + if (!search_check_php5()) { + $phpversion = phpversion(); + mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version ".phpversion().")"); + exit(0); + } + + //php5 found, continue including php5-only files + //require_once("$CFG->dirroot/search/Zend/Search/Lucene.php"); + require_once("$CFG->dirroot/search/indexlib.php"); + + mtrace(''); + mtrace('
Server Time: '.date('r',time())."\n");
+    
+    if (isset($CFG->search_indexer_busy) && $CFG->search_indexer_busy == '1') {
+        //means indexing was not finished previously
+        mtrace("Warning: Indexing was not successfully completed last time, restarting.\n");
+    }
+    
+/// turn on busy flag
 
-if ($sure != 'yes') {
-    mtrace("
Sorry, you need to confirm indexing via indexersplash.php"
-          .". (Back to query page).
"); + set_config('search_indexer_busy', '1'); + + //paths + $index_path = SEARCH_INDEX_PATH; + $index_db_file = "{$CFG->dirroot}/search/db/$CFG->dbtype.sql"; + $dbcontrol = new IndexDBControl(); + +/// setup directory in data root - exit(0); -} //if - -//check for php5 (lib.php) -if (!search_check_php5()) { - $phpversion = phpversion(); - mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version $phpversion)"); - exit(0); -} - -//php5 found, continue including php5-only files -//require_once("$CFG->dirroot/search/Zend/Search/Lucene.php"); -require_once("$CFG->dirroot/search/indexlib.php"); - -mtrace(''); -mtrace('
Server Time: '.date('r',time())."\n");
-
-if ($CFG->search_indexer_busy == '1') {
-    //means indexing was not finished previously
-    mtrace("Warning: Indexing was not successfully completed last time, restarting.\n");
-}
-
-//turn on busy flag
-set_config('search_indexer_busy', '1');
-
-//paths
-$index_path = SEARCH_INDEX_PATH;
-$index_db_file = "{$CFG->dirroot}/search/db/$CFG->dbtype.sql";
-$dbcontrol = new IndexDBControl();
-
-//setup directory in data root
-if (!file_exists($index_path)) {
-    mtrace("Data directory ($index_path) does not exist, attempting to create.");
-    if (!mkdir($index_path)) {
-        search_pexit("Error creating data directory at: $index_path. Please correct.");
+    if (!file_exists($index_path)) {
+        mtrace("Data directory ($index_path) does not exist, attempting to create.");
+        if (!mkdir($index_path)) {
+            search_pexit("Error creating data directory at: $index_path. Please correct.");
+        } 
+        else {
+            mtrace("Directory successfully created.");
+        } 
     } 
     else {
-        mtrace("Directory successfully created.");
+        mtrace("Using $index_path as data directory.");
     } 
-} 
-else {
-    mtrace("Using $index_path as data directory.");
-} 
-
-$index = new Zend_Search_Lucene($index_path, true);
-
-/*
-OBSOLETE REGENERATION - DB installs with search block by now
-if (!$dbcontrol->checkDB()) {
-    search_pexit("Database error. Please check settings/files.");
-}
-*/
-// New regeneration
-mtrace('Deleting old index entries.');
-delete_records(SEARCH_DATABASE_TABLE);
-
-//begin timer
-search_stopwatch();
-mtrace("Starting 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.
-$searchables = array();
-
-// collects modules
-if ($mods = get_records('modules', '', '', '', 'id,name')) {
-    $searchables = array_merge($searchables, $mods);
-}
-mtrace(count($searchables).' modules found.');
-  
-// collects blocks as indexable information may be found in blocks either
-if ($blocks = get_records('block', '', '', '', 'id,name')) {
-    // prepend the "block_" prefix to discriminate document type plugins
-    foreach(array_keys($blocks) as $aBlockId){
-        $blocks[$aBlockId]->name = 'block_'.$blocks[$aBlockId]->name;
+    
+    $index = new Zend_Search_Lucene($index_path, true);
+    
+    /*
+    OBSOLETE REGENERATION - DB installs with search block by now
+    if (!$dbcontrol->checkDB()) {
+        search_pexit("Database error. Please check settings/files.");
     }
-    $searchables = array_merge($searchables, $blocks);
-    mtrace(count($blocks).' blocks found.');
-}
-  
-//add virtual modules onto the back of the array
-$searchables = array_merge($searchables, search_get_additional_modules());
-if ($searchables){
-    foreach ($searchables as $mod) {
-        $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-     
-        if (file_exists($class_file)) {
-            include_once($class_file);
+    */
 
-            //build function names
-            $iter_function = $mod->name.'_iterator';
-            $index_function = $mod->name.'_get_content_for_index';
-            $counter = 0;
-            if (function_exists($index_function) && function_exists($iter_function)) {
-                mtrace("Processing module function $index_function ...");
-                $sources = $iter_function();
-                if ($sources){
-                    foreach ($sources as $i) {
-                        $documents = $index_function($i);
-              
-                        //begin transaction
-                        if ($documents){
-                            foreach($documents as $document) {
-                                $counter++;
-                                
-                                //object to insert into db
-                                $dbid = $dbcontrol->addDocument($document);
-                                
-                                //synchronise db with index
-                                $document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
-                                
-                                //add document to index
-                                $index->addDocument($document);
-                                
-                                //commit every x new documents, and print a status message
-                                if (($counter % 2000) == 0) {
-                                    $index->commit();
-                                    mtrace(".. $counter");
-                                } 
-                            }
-                        }
-                        //end transaction
-                    }
-                }
-        
-                //commit left over documents, and finish up
-                $index->commit();
+/// New regeneration
+
+    mtrace('Deleting old index entries.');
+    delete_records(SEARCH_DATABASE_TABLE);
+    
+/// begin timer
+
+    search_stopwatch();
+    mtrace("Starting 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.
+    $searchables = array();
+    
+/// collects modules
+
+    if ($mods = get_records('modules', '', '', '', 'id,name')) {
+        $searchables = array_merge($searchables, $mods);
+    }
+    mtrace(count($searchables).' modules found.');
       
-                mtrace("-- $counter documents indexed");
-                mtrace("done.\n");
+    // collects blocks as indexable information may be found in blocks either
+    if ($blocks = get_records('block', '', '', '', 'id,name')) {
+        // prepend the "block_" prefix to discriminate document type plugins
+        foreach(array_keys($blocks) as $aBlockId){
+            $blocks[$aBlockId]->name = 'block_'.$blocks[$aBlockId]->name;
+        }
+        $searchables = array_merge($searchables, $blocks);
+        mtrace(count($blocks).' blocks found.');
+    }
+      
+/// add virtual modules onto the back of the array
+
+    $searchables = array_merge($searchables, search_get_additional_modules());
+    if ($searchables){
+        foreach ($searchables as $mod) {
+            $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
+         
+            if (file_exists($class_file)) {
+                include_once($class_file);
+    
+                //build function names
+                $iter_function = $mod->name.'_iterator';
+                $index_function = $mod->name.'_get_content_for_index';
+                $counter = 0;
+                if (function_exists($index_function) && function_exists($iter_function)) {
+                    mtrace("Processing module function $index_function ...");
+                    $sources = $iter_function();
+                    if ($sources){
+                        foreach ($sources as $i) {
+                            $documents = $index_function($i);
+                  
+                            //begin transaction
+                            if ($documents){
+                                foreach($documents as $document) {
+                                    $counter++;
+                                    
+                                    //object to insert into db
+                                    $dbid = $dbcontrol->addDocument($document);
+                                    
+                                    //synchronise db with index
+                                    $document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
+                                    
+                                    //add document to index
+                                    $index->addDocument($document);
+                                    
+                                    //commit every x new documents, and print a status message
+                                    if (($counter % 2000) == 0) {
+                                        $index->commit();
+                                        mtrace(".. $counter");
+                                    } 
+                                }
+                            }
+                            //end transaction
+                        }
+                    }
+            
+                    //commit left over documents, and finish up
+                    $index->commit();
+          
+                    mtrace("-- $counter documents indexed");
+                    mtrace("done.\n");
+                }
             }
         }
     }
-}
-  
-//finished modules
-mtrace('Finished activity modules');
-search_stopwatch();
+      
+/// finished modules
+
+    mtrace('Finished activity modules');
+    search_stopwatch();
+        
+    mtrace(".
Back to query page."); + mtrace('
'); -mtrace(".
Back to query page."); -mtrace('
'); +/// finished, turn busy flag off -//finished, turn busy flag off -set_config('search_indexer_busy', '0'); + set_config('search_indexer_busy', '0'); + +/// mark the time we last updated -//mark the time we last updated -set_config('search_indexer_run_date', time()); + set_config('search_indexer_run_date', time()); + +/// and the index size -//and the index size -set_config('search_index_size', (int)$index->count()); + set_config('search_index_size', (int)$index->count()); ?> \ No newline at end of file diff --git a/search/indexersplash.php b/search/indexersplash.php index 26b7763a34f..a21f56951ab 100644 --- a/search/indexersplash.php +++ b/search/indexersplash.php @@ -1,55 +1,80 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * This file serves as a splash-screen (entry page) to the indexer script - * it is in place to prevent accidental reindexing which can lead to a loss * of time, amongst other things. -**/ +*/ +/** +* includes and requires +*/ require_once('../config.php'); require_once("$CFG->dirroot/search/lib.php"); -require_login(); +/// check global search is enabled -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} + require_login(); + + if (empty($CFG->enableglobalsearch)) { + error(get_string('globalsearchdisabled', 'search')); + } + + if (!isadmin()) { + error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); + } + +/// check for php5 (lib.php) -if (!isadmin()) { - error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); -} - -//check for php5 (lib.php) -if (!search_check_php5()) { - $phpversion = phpversion(); - mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version $phpversion)"); - exit(0); -} - -require_once("$CFG->dirroot/search/indexlib.php"); -$indexinfo = new IndexInfo(); - -if ($indexinfo->valid()) { - mtrace("
The data directory ($indexinfo->path) contains $indexinfo->filecount files, and\n"
-          ."there are ".$indexinfo->dbcount." records in the block_search_documents table.\n"
-          ."\n"
-          ."This indicates that you have already succesfully indexed this site. Follow the link\n"
-          ."if you are sure that you want to continue indexing - this will replace any existing\n"
-          ."index data (no Moodle data is affected).\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 { - header('Location: indexer.php?areyousure=yes'); -} -?> + if (!search_check_php5()) { + $phpversion = phpversion(); + mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version ".phpversion().")"); + exit(0); + } + + require_once("$CFG->dirroot/search/indexlib.php"); + $indexinfo = new IndexInfo(); + + if ($indexinfo->valid()) { + $strsearch = get_string('search', 'search'); + $strquery = get_string('stats'); + + $navlinks[] = array('name' => $strsearch, 'link' => "index.php", 'type' => 'misc'); + $navlinks[] = array('name' => $strquery, 'link' => "stats.php", 'type' => 'misc'); + $navlinks[] = array('name' => get_string('runindexer','search'), 'link' => null, 'type' => 'misc'); + if ($CFG->version <= 2007021541){ // 1.8 branch stable timestamp + $navigation = ''; + } else { + $navigation = build_navigation($navlinks); + } + $site = get_site(); + print_header("$strsearch", "$site->fullname" , $navigation, "", "", true, " ", navmenu($site)); + + mtrace("
The data directory ($indexinfo->path) contains $indexinfo->filecount files, and\n"
+              ."there are ".$indexinfo->dbcount." records in the block_search_documents table.\n"
+              ."\n"
+              ."This indicates that you have already succesfully indexed this site. Follow the link\n"
+              ."if you are sure that you want to continue indexing - this will replace any existing\n"
+              ."index data (no Moodle data is affected).\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."
+              ."
"); + print_footer(); + } + else { + header('Location: indexer.php?areyousure=yes'); + } +?> \ No newline at end of file diff --git a/search/indexlib.php b/search/indexlib.php index 7ed1be77528..be250ca39e5 100644 --- a/search/indexlib.php +++ b/search/indexlib.php @@ -1,20 +1,32 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Index info class * * Used to retrieve information about an index. * Has methods to check for valid database and data directory, * and the index itself. -**/ +*/ +/** +* includes and requires +*/ require_once("$CFG->dirroot/search/lib.php"); require_once("$CFG->dirroot/search/Zend/Search/Lucene.php"); +/** +* main class for searchable information in the Lucene index +*/ class IndexInfo { + private $path, //index data directory $size, //size of directory (i.e. the whole index) $filecount, //number of files @@ -35,7 +47,7 @@ class IndexInfo { $validindex = true; } catch(Exception $e) { $validindex = false; - } //catch + } //retrieve file system info about the index if it is valid if ($validindex) { @@ -73,32 +85,29 @@ class IndexInfo { $c = count_records(SEARCH_DATABASE_TABLE, 'doctype', $type); $this->types[$type] = (int)$c; } - } - else { + } else { $this->dbcount = 0; $this->types = array(); } //check if the busy flag is set - if ($CFG->search_indexer_busy == '1') { + if (isset($CFG->search_indexer_busy) && $CFG->search_indexer_busy == '1') { $this->complete = false; - } - else { + } else { $this->complete = true; } //get the last run date for the indexer if ($this->valid() && $CFG->search_indexer_run_date) { $this->time = $CFG->search_indexer_run_date; - } - else { + } else { $this->time = 0; } - } //__construct + } /** * returns false on error, and the error message via referenced variable $err - * + * @param array $err array of errors */ public function valid(&$err = null) { $err = array(); @@ -120,7 +129,7 @@ class IndexInfo { } return $ret; - } //valid + } /** * is the index dir valid @@ -129,11 +138,10 @@ class IndexInfo { public function is_valid_dir() { if ($this->filecount > 0) { return true; - } - else { + } else { return false; } - } //is_valid_dir + } /** * is the db table valid @@ -142,34 +150,34 @@ class IndexInfo { public function is_valid_db() { if ($this->dbcount > 0) { return true; - } - else { + } else { return false; } - } //is_valid_db + } /** * shorthand get method for the class variables - * + * @param object $var */ public function __get($var) { if (in_array($var, array_keys(get_class_vars(get_class($this))))) { return $this->$var; } - } //__get -} //IndexInfo + } +} -/* +/** * DB Index control class * * Used to control the search index database table -**/ +*/ class IndexDBControl { /** * does the table exist? - * OBSOLETE + * @deprecated + * @uses CFG, db */ public function checkTableExists() { global $CFG, $db; @@ -186,7 +194,8 @@ class IndexDBControl { /** * is our database setup valid? - * OBSOLETE - Database is installed at install and should not be dropped out + * @uses db, CFG + * @deprecated Database is installed at install and should not be dropped out */ public function checkDB() { global $CFG, $db; @@ -209,6 +218,7 @@ class IndexDBControl { /** * add a document record to the table * @param document must be a Lucene SearchDocument instance + * @uses db, CFG */ public function addDocument($document=null) { global $db, $CFG; @@ -223,7 +233,7 @@ class IndexDBControl { $doc->itemtype = $document->itemtype; $doc->title = search_escape_string($document->title); $doc->url = search_escape_string($document->url); - $doc->update = time(); + $doc->updated = time(); $doc->docdate = $document->date; $doc->courseid = $document->course_id; $doc->groupid = $document->group_id; @@ -232,17 +242,18 @@ class IndexDBControl { $id = insert_record(SEARCH_DATABASE_TABLE, $doc); return $id; - } //addDocument + } /** * remove a document record from the index * @param document must be a Lucene document instance, or at least a dbid enveloppe + * @uses db */ public function delDocument($document) { global $db; delete_records(SEARCH_DATABASE_TABLE, 'id', $document->dbid); - } //delDocument -} //IndexControl + } +} ?> \ No newline at end of file diff --git a/search/lib.php b/search/lib.php index 69365d26b95..af40f8f1d9f 100644 --- a/search/lib.php +++ b/search/lib.php @@ -1,14 +1,20 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License +* +* General function library * * This file must not contain any PHP 5, because it is used to test for PHP 5 * itself, and needs to be able to be executed on PHP 4 installations. * -* Reviewed by: Valery Fremaux (2007) -* - adding techproject search capabilities -* - adding full internationalization -**/ +*/ /* // function reference diff --git a/search/query.php b/search/query.php index 97526fd1800..50a222daeee 100644 --- a/search/query.php +++ b/search/query.php @@ -1,337 +1,361 @@ dirroot/search/lib.php"); - -if ($CFG->forcelogin) { - require_login(); -} - -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} - -$adv = new Object(); - -// check for php5, but don't die yet (see line 52) -if ($check = search_check_php5()) { - require_once("{$CFG->dirroot}/search/querylib.php"); - - $page_number = optional_param('page', -1, PARAM_INT); - $pages = ($page_number == -1) ? false : true; - $advanced = (optional_param('a', '0', PARAM_INT) == '1') ? true : false; - $query_string = optional_param('query_string', '', PARAM_CLEAN); - - if ($pages && isset($_SESSION['search_advanced_query'])) { - // if both are set, then we are busy browsing through the result pages of an advanced query - $adv = unserialize($_SESSION['search_advanced_query']); - } - else if ($advanced) { - // otherwise we are dealing with a new advanced query - unset($_SESSION['search_advanced_query']); - session_unregister('search_advanced_query'); - - // chars to strip from strings (whitespace) - $chars = " \t\n\r\0\x0B,-+"; - - // retrieve advanced query variables - $adv->mustappear = trim(optional_param('mustappear', '', PARAM_CLEAN), $chars); - $adv->notappear = trim(optional_param('notappear', '', PARAM_CLEAN), $chars); - $adv->canappear = trim(optional_param('canappear', '', PARAM_CLEAN), $chars); - $adv->module = optional_param('module', '', PARAM_CLEAN); - $adv->title = trim(optional_param('title', '', PARAM_CLEAN), $chars); - $adv->author = trim(optional_param('author', '', PARAM_CLEAN), $chars); - } - - if ($advanced) { - //parse the advanced variables into a query string - //TODO: move out to external query class (QueryParse?) - - $query_string = ''; - - // get all available module types - $module_types = array_merge(array('all'), array_values(search_get_document_types())); - $adv->module = in_array($adv->module, $module_types) ? $adv->module : 'all'; - - // convert '1 2' into '+1 +2' for required words field - if (strlen(trim($adv->mustappear)) > 0) { - $query_string = ' +'.implode(' +', preg_split("/[\s,;]+/", $adv->mustappear)); - } - - // convert '1 2' into '-1 -2' for not wanted words field - if (strlen(trim($adv->notappear)) > 0) { - $query_string .= ' -'.implode(' -', preg_split("/[\s,;]+/", $adv->notappear)); - } - - // this field is left untouched, apart from whitespace being stripped - if (strlen(trim($adv->canappear)) > 0) { - $query_string .= ' '.implode(' ', preg_split("/[\s,;]+/", $adv->canappear)); - } - - // add module restriction - $doctypestr = get_string('doctype', 'search'); - $titlestr = get_string('title', 'search'); - $authorstr = get_string('author', 'search'); - if ($adv->module != 'all') { - $query_string .= " +{$doctypestr}:".$adv->module; - } - - // create title search string - if (strlen(trim($adv->title)) > 0) { - $query_string .= " +{$titlestr}:".implode(" +{$titlestr}:", preg_split("/[\s,;]+/", $adv->title)); - } - - // create author search string - if (strlen(trim($adv->author)) > 0) { - $query_string .= " +{$authorstr}:".implode(" +{$authorstr}:", preg_split("/[\s,;]+/", $adv->author)); - } - - // save our options if the query is valid - if (!empty($query_string)) { - $_SESSION['search_advanced_query'] = serialize($adv); - } - } - - // normalise page number - if ($page_number < 1) { - $page_number = 1; - } - - //run the query against the index - $sq = new SearchQuery($query_string, $page_number, 10, false); -} - -if (!$site = get_site()) { - redirect("index.php"); -} - -$strsearch = get_string('search', 'search'); -$strquery = get_string('enteryoursearchquery', 'search'); - -print_header("$site->shortname: $strsearch: $strquery", "$site->fullname", - "$strsearch -> $strquery"); - -//keep things pretty, even if php5 isn't available -if (!$check) { - print_heading(search_check_php5(true)); - print_footer(); - exit(0); -} - -print_box_start(); -print_heading($strquery); - -print_box_start(); - -$vars = get_object_vars($adv); - -if (isset($vars)) { - foreach ($vars as $key => $value) { - $adv->$key = stripslashes(htmlentities($value)); - } -} -?> - -
- - -     - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
:
:
:
: - -
:
:

- - - - - -
| 
-
- -
-
- -
-is_valid_index()) { - //use cached variable to show up-to-date index size (takes deletions into account) - print $CFG->search_index_size; -} -else { - print "0"; -} - -print ' '; -print_string('documents', 'search'); -print '.'; - -if (!$sq->is_valid_index() and isadmin()) { - print '

' . get_string('noindexmessage', 'search') . '' . get_string('createanindex', 'search')."

\n"; -} - -?> -
-is_valid()) { - print_box_start(); + /** + * 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 + * + * The query page - accepts a user-entered query string and returns results. + * + * Queries are boolean-aware, e.g.: + * + * '+' term required + * '-' term must not be present + * '' (no modifier) term's presence increases rank, but isn't required + * 'field:' search this field + * + * Examples: + * + * 'earthquake +author:michael' + * Searches for documents written by 'michael' that contain 'earthquake' + * + * 'earthquake +doctype:wiki' + * Search all wiki pages for 'earthquake' + * + * '+author:helen +author:foster' + * All articles written by Helen Foster + * + */ - search_stopwatch(); - $hit_count = $sq->count(); + /** + * includes and requires + */ + require_once('../config.php'); + require_once("$CFG->dirroot/search/lib.php"); + + + if ($CFG->forcelogin) { + require_login(); + } - print "
"; + if (empty($CFG->enableglobalsearch)) { + error(get_string('globalsearchdisabled', 'search')); + } - print $hit_count.' '.get_string('resultsreturnedfor', 'search') . " '".stripslashes($query_string)."'."; - print "
"; + $adv = new Object(); + +/// check for php5, but don't die yet (see line 52) + + if ($check = search_check_php5()) { + require_once("{$CFG->dirroot}/search/querylib.php"); + + $page_number = optional_param('page', -1, PARAM_INT); + $pages = ($page_number == -1) ? false : true; + $advanced = (optional_param('a', '0', PARAM_INT) == '1') ? true : false; + $query_string = optional_param('query_string', '', PARAM_CLEAN); + + if ($pages && isset($_SESSION['search_advanced_query'])) { + // if both are set, then we are busy browsing through the result pages of an advanced query + $adv = unserialize($_SESSION['search_advanced_query']); + } + else if ($advanced) { + // otherwise we are dealing with a new advanced query + unset($_SESSION['search_advanced_query']); + session_unregister('search_advanced_query'); + + // chars to strip from strings (whitespace) + $chars = " \t\n\r\0\x0B,-+"; + + // retrieve advanced query variables + $adv->mustappear = trim(optional_param('mustappear', '', PARAM_CLEAN), $chars); + $adv->notappear = trim(optional_param('notappear', '', PARAM_CLEAN), $chars); + $adv->canappear = trim(optional_param('canappear', '', PARAM_CLEAN), $chars); + $adv->module = optional_param('module', '', PARAM_CLEAN); + $adv->title = trim(optional_param('title', '', PARAM_CLEAN), $chars); + $adv->author = trim(optional_param('author', '', PARAM_CLEAN), $chars); + } - if ($hit_count > 0) { - $page_links = $sq->page_numbers(); - $hits = $sq->results(); - if ($advanced) { - // if in advanced mode, search options are saved in the session, so - // we can remove the query string var from the page links, and replace - // it with a=1 (Advanced = on) instead - $page_links = preg_replace("/query_string=[^&]+/", 'a=1', $page_links); + //parse the advanced variables into a query string + //TODO: move out to external query class (QueryParse?) + + $query_string = ''; + + // get all available module types + $module_types = array_merge(array('all'), array_values(search_get_document_types())); + $adv->module = in_array($adv->module, $module_types) ? $adv->module : 'all'; + + // convert '1 2' into '+1 +2' for required words field + if (strlen(trim($adv->mustappear)) > 0) { + $query_string = ' +'.implode(' +', preg_split("/[\s,;]+/", $adv->mustappear)); + } + + // convert '1 2' into '-1 -2' for not wanted words field + if (strlen(trim($adv->notappear)) > 0) { + $query_string .= ' -'.implode(' -', preg_split("/[\s,;]+/", $adv->notappear)); + } + + // this field is left untouched, apart from whitespace being stripped + if (strlen(trim($adv->canappear)) > 0) { + $query_string .= ' '.implode(' ', preg_split("/[\s,;]+/", $adv->canappear)); + } + + // add module restriction + $doctypestr = get_string('doctype', 'search'); + $titlestr = get_string('title', 'search'); + $authorstr = get_string('author', 'search'); + if ($adv->module != 'all') { + $query_string .= " +{$doctypestr}:".$adv->module; + } + + // create title search string + if (strlen(trim($adv->title)) > 0) { + $query_string .= " +{$titlestr}:".implode(" +{$titlestr}:", preg_split("/[\s,;]+/", $adv->title)); + } + + // create author search string + if (strlen(trim($adv->author)) > 0) { + $query_string .= " +{$authorstr}:".implode(" +{$authorstr}:", preg_split("/[\s,;]+/", $adv->author)); + } + + // save our options if the query is valid + if (!empty($query_string)) { + $_SESSION['search_advanced_query'] = serialize($adv); + } } - - print "
    "; - - $typestr = get_string('type', 'search'); - $scorestr = get_string('score', 'search'); - $authorstr = get_string('author', 'search'); - foreach ($hits as $listing) { - 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"; - if (function_exists($title_post_processing_function)) - $listing->title = $title_post_processing_function($listing->title); - print "
  1. url)."'>$listing->title
    \n" - ."".search_shorten_url($listing->url, 70)."
    \n" - ."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3).", {$authorstr}: ".$listing->author."\n" - ."
  2. \n"; - } - - print "
"; - print $page_links; + + // normalise page number + if ($page_number < 1) { + $page_number = 1; + } + + //run the query against the index + $sq = new SearchQuery($query_string, $page_number, 10, false); } - + + if (!$site = get_site()) { + redirect("index.php"); + } + + $strsearch = get_string('search', 'search'); + $strquery = get_string('enteryoursearchquery', 'search'); + + if ($CFG->version < 2007032200){ + print_header("$site->shortname: $strsearch: $strquery", "$site->fullname", + "$strsearch -> $strquery"); + } else { + $navlinks[] = array('name' => $strsearch, 'link' => "index.php", 'type' => 'misc'); + $navlinks[] = array('name' => $strquery, 'link' => null, 'type' => 'misc'); + $navigation = build_navigation($navlinks); + $site = get_site(); + print_header("$strsearch", "$site->fullname" , $navigation, "", "", true, " ", navmenu($site)); + } + + //keep things pretty, even if php5 isn't available + if (!$check) { + print_heading(search_check_php5(true)); + print_footer(); + exit(0); + } + + print_box_start(); + print_heading($strquery); + + print_box_start(); + + $vars = get_object_vars($adv); + + if (isset($vars)) { + foreach ($vars as $key => $value) { + // htmlentities breaks non-ascii chars + $adv->key = stripslashes($value); + //$adv->$key = stripslashes(htmlentities($value)); + } + } + ?> + +
+ + +     + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
:
:
:
: + +
:
:

+ + + + + +
| 
+
+ +
+
+ +
+ is_valid_index()) { + //use cached variable to show up-to-date index size (takes deletions into account) + print $CFG->search_index_size; + } + else { + print "0"; + } + + print ' '; + print_string('documents', 'search'); + print '.'; + + if (!$sq->is_valid_index() and isadmin()) { + print '

' . get_string('noindexmessage', 'search') . '' . get_string('createanindex', 'search')."

\n"; + } + + ?> +
+ -
-. -
- -is_valid()) { + print_box_start(); + + search_stopwatch(); + $hit_count = $sq->count(); + + print "
"; + + print $hit_count.' '.get_string('resultsreturnedfor', 'search') . " '".stripslashes($query_string)."'."; + print "
"; + + if ($hit_count > 0) { + $page_links = $sq->page_numbers(); + $hits = $sq->results(); + + if ($advanced) { + // if in advanced mode, search options are saved in the session, so + // we can remove the query string var from the page links, and replace + // it with a=1 (Advanced = on) instead + $page_links = preg_replace("/query_string=[^&]+/", 'a=1', $page_links); + } + + print "
    "; + + $typestr = get_string('type', 'search'); + $scorestr = get_string('score', 'search'); + $authorstr = get_string('author', 'search'); + foreach ($hits as $listing) { + //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"; + if (function_exists($title_post_processing_function)) { + $listing->title = $title_post_processing_function($listing->title); + } + + print "
  1. 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" + ."
  2. \n"; + } + } + print "
"; + print $page_links; + } + print_box_end(); + ?> +
+ . +
+ + \ No newline at end of file diff --git a/search/querylib.php b/search/querylib.php index 2db68c1fcf3..2c5b49cdf50 100644 --- a/search/querylib.php +++ b/search/querylib.php @@ -1,4 +1,18 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License +*/ + +/** +* includes and requires +*/ require_once("{$CFG->dirroot}/search/Zend/Search/Lucene.php"); define('DEFAULT_POPUP_SETTINGS', "\"menubar=0,location=0,scrollbars,resizable,width=600,height=450\""); @@ -13,10 +27,12 @@ public $url, $author, $score, $number; -} //SearchResult +} -//split this into Cache class and extend to SearchCache? +/** +* split this into Cache class and extend to SearchCache? +*/ class SearchCache { private $mode, $valid; @@ -32,7 +48,7 @@ private $mode, } //else $this->valid = true; - } //constructor + } /** * returns the search cache status @@ -40,7 +56,7 @@ private $mode, */ public function can_cache() { return $this->valid; - } //can_cache + } /** * @@ -53,7 +69,7 @@ private $mode, //if this query is different from the last, clear out the last one if ($id != false and $last_term != $id) { $this->clear($last_term); - } //if + } //store the new query if id and object are passed in if ($object and $id) { @@ -61,11 +77,10 @@ private $mode, $this->store($id, $object); return true; //otherwise return the stored results - } - else if ($id and $this->exists($id)) { + } else if ($id and $this->exists($id)) { return $this->fetch($id); - } //else - } //cache + } + } /** * do key exist in cache ? @@ -76,8 +91,8 @@ private $mode, switch ($this->mode) { case 'session' : return isset($_SESSION[$id]); - } //switch - } //exists + } + } /** * clears a cached object in cache @@ -90,8 +105,8 @@ private $mode, unset($_SESSION[$id]); session_unregister($id); return; - } //switch - } //clear + } + } /** * fetches a cached object @@ -102,8 +117,8 @@ private $mode, switch ($this->mode) { case 'session' : return ($this->exists($id)) ? unserialize($_SESSION[$id]) : false; - } //switch - } //fetch + } + } /** * put an object in cache @@ -116,9 +131,9 @@ private $mode, case 'session' : $_SESSION[$id] = serialize($object); return; - } //switch - } //store -} //SearchCache + } + } +} /** * Represents a single query with results @@ -156,14 +171,14 @@ class SearchQuery { } catch(Exception $e) { $this->validindex = false; return; - } //catch + } if (empty($this->term)) { $this->validquery = false; } else { $this->set_query($this->term); - } //else - } //constructor + } + } /** * determines state of query object depending on query entry and @@ -173,22 +188,20 @@ class SearchQuery { public function set_query($term = '') { if (!empty($term)) { $this->term = $term; - } //if + } if (empty($this->term)) { $this->validquery = false; - } - else { + } else { $this->validquery = true; - } //else + } if ($this->validquery and $this->validindex) { $this->results = $this->get_results(); - } - else { + } else { $this->results = array(); - } //else - } //set_query + } + } /** * accessor to the result table. @@ -196,11 +209,12 @@ class SearchQuery { */ public function results() { return $this->results; - } //results + } /** * do the effective collection of results - * + * @param boolean $all + * @uses USER */ private function process_results($all=false) { global $USER; @@ -224,22 +238,20 @@ class SearchQuery { if (!$all) { if ($hitcount < $this->results_per_page) { $this->pagenumber = 1; - } - else if ($this->pagenumber > $totalpages) { + } else if ($this->pagenumber > $totalpages) { $this->pagenumber = $totalpages; - } //if + } $start = ($this->pagenumber - 1) * $this->results_per_page; $end = $start + $this->results_per_page; if ($end > $hitcount) { $end = $hitcount; - } //if - } - else { + } + } else { $start = 0; $end = $hitcount; - } //else + } $resultdoc = new SearchResult(); $resultdocs = array(); @@ -258,15 +270,14 @@ class SearchQuery { //and store it $resultdocs[] = clone($resultdoc); - } //if - else{ + } else { // lowers total_results one unit $this->total_results--; } - } //foreach + } return $resultdocs; - } //process_results + } /** * get results of a search query using a caching strategy if available @@ -281,20 +292,17 @@ class SearchQuery { //cache the results so we don't have to compute this on every page-load $cache->cache($this->term, $resultdocs); //print "Using new results."; - } - else { + } else { //There was something in the cache, so we're using that to save time //print "Using cached results."; - } //else - } - else { + } + } else { //no caching :( //print "Caching disabled!"; $resultdocs = $this->process_results(); - } //else - + } return $resultdocs; - } //get_results + } /** * constructs the results paging links on results. @@ -314,7 +322,7 @@ class SearchQuery { $ret .= "< {$back} "; } else { $ret .= "< {$back} "; - } //else + } //don't the current page for ($i = 1; $i <= $pages; $i++) { @@ -322,15 +330,15 @@ class SearchQuery { $ret .= "($i) "; } else { $ret .= "{$i} "; - } //else - } //for + } + } //Next disabled if we're on the last page if ($page < $pages) { $ret .= "{$next} > "; } else { $ret .= "{$next} > "; - } //else + } $ret .= ""; @@ -343,10 +351,10 @@ class SearchQuery { $start = $page + 5; $end = $pages - 3; $ret = preg_replace("/$start<\/a>.*?$end<\/a>/", '...', $ret); - } //if + } return $ret; - } //page_numbers + } /** * can the user see this result ? @@ -359,6 +367,7 @@ class SearchQuery { * @param path the path that routes to the local lib.php of the searched * surrounding object fot that document * @param item_type a subclassing information for complex module data models + * @uses CFG * // TODO reorder parameters more consistently */ private function can_display(&$user, $this_id, $doctype, $course_id, $group_id, $path, $item_type, $context_id) { @@ -411,35 +420,55 @@ class SearchQuery { } return true; - } //can_display + } + /** + * + */ public function count() { return $this->total_results; } //count + /** + * + */ public function is_valid() { return ($this->validquery and $this->validindex); - } //is_valid + } + /** + * + */ public function is_valid_query() { return $this->validquery; - } //is_valid_query + } + /** + * + */ public function is_valid_index() { return $this->validindex; - } //is_valid_index + } + /** + * + */ public function total_pages() { return ceil($this->count()/$this->results_per_page); - } //pages + } + /** + * + */ public function get_pagenumber() { return $this->pagenumber; - } //get_pagenumber + } + /** + * + */ public function get_results_per_page() { return $this->results_per_page; - } //get_results_per_page - } //SearchQuery - + } +} ?> \ No newline at end of file diff --git a/search/stats.php b/search/stats.php index 7a41cf9f5c6..9e64c04cb60 100644 --- a/search/stats.php +++ b/search/stats.php @@ -1,152 +1,163 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Prints some basic statistics about the current index. * Does some diagnostics if you are logged in as an administrator. * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package search -* @version 2007110400 */ +/** +* includes and requires +*/ require_once('../config.php'); require_once("{$CFG->dirroot}/search/lib.php"); -if ($CFG->forcelogin) { - require_login(); -} +/// checks global search is enabled -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} - -//check for php5, but don't die yet -if ($check = search_check_php5()) { - require_once("{$CFG->dirroot}/search/indexlib.php"); - - $indexinfo = new IndexInfo(); -} - -if (!$site = get_site()) { - redirect("index.php"); -} - -$strsearch = get_string('search', 'search'); -$strquery = get_string('statistics', 'search'); - -print_header("$site->shortname: $strsearch: $strquery", "$site->fullname", - "$strsearch -> $strquery"); - -//keep things pretty, even if php5 isn't available -if (!$check) { - print_heading(search_check_php5(true)); - print_footer(); - exit(0); -} - -print_box_start(); -print_heading($strquery); - -print_box_start(); - -$databasestr = get_string('database', 'search'); -$documentsinindexstr = get_string('documentsinindex', 'search'); -$deletionsinindexstr = get_string('deletionsinindex', 'search'); -$documentsindatabasestr = get_string('documentsindatabase', 'search'); -$databasestatestr = get_string('databasestate', 'search'); - -//this table is only for admins, shows index directory size and location -if (isadmin()) { - $datadirectorystr = get_string('datadirectory', 'search'); - $inindexdirectorystr = get_string('filesinindexdirectory', 'search'); - $totalsizestr = get_string('totalsize', 'search'); - $errorsstr = get_string('errors', 'search'); - $solutionsstr = get_string('solutions', 'search'); - $checkdirstr = get_string('checkdir', 'search'); - $checkdbstr = get_string('checkdb', 'search'); - $checkdiradvicestr = get_string('checkdiradvice', 'search'); - $checkdbadvicestr = get_string('checkdbadvice', 'search'); - $runindexerteststr = get_string('runindexertest', 'search'); - $runindexerstr = get_string('runindexer', 'search'); - - $admin_table->tablealign = "center"; - $admin_table->align = array ("right", "left"); - $admin_table->wrap = array ("nowrap", "nowrap"); - $admin_table->cellpadding = 5; - $admin_table->cellspacing = 0; - $admin_table->width = '500'; - - $admin_table->data[] = array("{$datadirectorystr}", ''.$indexinfo->path.''); - $admin_table->data[] = array($inindexdirectorystr, $indexinfo->filecount); - $admin_table->data[] = array($totalsizestr, $indexinfo->size); - - if ($indexinfo->time > 0) { - $admin_table->data[] = array(get_string('createdon', 'search'), date('r', $indexinfo->time)); - } - else { - $admin_table->data[] = array(get_string('createdon', 'search'), '-'); - } - - if (!$indexinfo->valid($errors)) { - $admin_table->data[] = array("{$errorsstr}", ' '); - foreach ($errors as $key => $value) { - $admin_table->data[] = array($key.' ... ', $value); - } + if ($CFG->forcelogin) { + require_login(); } - - print_table($admin_table); - print_spacer(20); - print_heading($solutionsstr); - unset($admin_table->data); - if (isset($errors['dir'])) { - $admin_table->data[] = array($checkdirstr, $checkdiradvicestr); - } - if (isset($errors['db'])) { - $admin_table->data[] = array($checkdbstr, $checkdbadvicestr); + if (empty($CFG->enableglobalsearch)) { + error(get_string('globalsearchdisabled', 'search')); + } + +/// check for php5, but don't die yet + + if ($check = search_check_php5()) { + require_once("{$CFG->dirroot}/search/indexlib.php"); + + $indexinfo = new IndexInfo(); } - $admin_table->data[] = array($runindexerteststr, 'tests/index.php'); - $admin_table->data[] = array($runindexerstr, 'indexersplash.php'); + if (!$site = get_site()) { + redirect("index.php"); + } - print_table($admin_table); - print_spacer(20); -} - -//this is the standard summary table for normal users, shows document counts -$table->tablealign = "center"; -$table->align = array ("right", "left"); -$table->wrap = array ("nowrap", "nowrap"); -$table->cellpadding = 5; -$table->cellspacing = 0; -$table->width = '500'; - -$table->data[] = array("{$databasestr}", "{$CFG->prefix}".SEARCH_DATABASE_TABLE.''); - -//add extra fields if we're admin -if (isadmin()) { - //don't want to confuse users if the two totals don't match (hint: they should) - $table->data[] = array($documentsinindexstr, $indexinfo->indexcount); + $strsearch = get_string('search', 'search'); + $strquery = get_string('statistics', 'search'); - //*cough* they should match if deletions were actually removed from the index, - //as it turns out, they're only marked as deleted and not returned in search results - $table->data[] = array($deletionsinindexstr, (int)$indexinfo->indexcount - (int)$indexinfo->dbcount); -} + print_header("$site->shortname: $strsearch: $strquery", "$site->fullname", + "$strsearch -> $strquery"); + +/// keep things pretty, even if php5 isn't available -$table->data[] = array($documentsindatabasestr, $indexinfo->dbcount); + if (!$check) { + print_heading(search_check_php5(true)); + print_footer(); + exit(0); + } + + print_box_start(); + print_heading($strquery); + + print_box_start(); + + $databasestr = get_string('database', 'search'); + $documentsinindexstr = get_string('documentsinindex', 'search'); + $deletionsinindexstr = get_string('deletionsinindex', 'search'); + $documentsindatabasestr = get_string('documentsindatabase', 'search'); + $databasestatestr = get_string('databasestate', 'search'); + +/// this table is only for admins, shows index directory size and location -foreach($indexinfo->types as $key => $value) { - $table->data[] = array(get_string('documentsfor', 'search') . " '".get_string('modulenameplural', $key)."'", $value); -} + if (isadmin()) { + $datadirectorystr = get_string('datadirectory', 'search'); + $inindexdirectorystr = get_string('filesinindexdirectory', 'search'); + $totalsizestr = get_string('totalsize', 'search'); + $errorsstr = get_string('errors', 'search'); + $solutionsstr = get_string('solutions', 'search'); + $checkdirstr = get_string('checkdir', 'search'); + $checkdbstr = get_string('checkdb', 'search'); + $checkdiradvicestr = get_string('checkdiradvice', 'search'); + $checkdbadvicestr = get_string('checkdbadvice', 'search'); + $runindexerteststr = get_string('runindexertest', 'search'); + $runindexerstr = get_string('runindexer', 'search'); + + $admin_table->tablealign = "center"; + $admin_table->align = array ("right", "left"); + $admin_table->wrap = array ("nowrap", "nowrap"); + $admin_table->cellpadding = 5; + $admin_table->cellspacing = 0; + $admin_table->width = '500'; + + $admin_table->data[] = array("{$datadirectorystr}", ''.$indexinfo->path.''); + $admin_table->data[] = array($inindexdirectorystr, $indexinfo->filecount); + $admin_table->data[] = array($totalsizestr, $indexinfo->size); + + if ($indexinfo->time > 0) { + $admin_table->data[] = array(get_string('createdon', 'search'), date('r', $indexinfo->time)); + } + else { + $admin_table->data[] = array(get_string('createdon', 'search'), '-'); + } + + if (!$indexinfo->valid($errors)) { + $admin_table->data[] = array("{$errorsstr}", ' '); + foreach ($errors as $key => $value) { + $admin_table->data[] = array($key.' ... ', $value); + } + } + + print_table($admin_table); + print_spacer(20); + print_heading($solutionsstr); + + unset($admin_table->data); + if (isset($errors['dir'])) { + $admin_table->data[] = array($checkdirstr, $checkdiradvicestr); + } + if (isset($errors['db'])) { + $admin_table->data[] = array($checkdbstr, $checkdbadvicestr); + } + + $admin_table->data[] = array($runindexerteststr, 'tests/index.php'); + $admin_table->data[] = array($runindexerstr, 'indexersplash.php'); + + print_table($admin_table); + print_spacer(20); + } + +/// this is the standard summary table for normal users, shows document counts -print_heading($databasestatestr); -print_table($table); + $table->tablealign = "center"; + $table->align = array ("right", "left"); + $table->wrap = array ("nowrap", "nowrap"); + $table->cellpadding = 5; + $table->cellspacing = 0; + $table->width = '500'; + + $table->data[] = array("{$databasestr}", "{$CFG->prefix}".SEARCH_DATABASE_TABLE.''); + +/// add extra fields if we're admin -print_box_end(); -print_box_end(); -print_footer(); + if (isadmin()) { + //don't want to confuse users if the two totals don't match (hint: they should) + $table->data[] = array($documentsinindexstr, $indexinfo->indexcount); + + //*cough* they should match if deletions were actually removed from the index, + //as it turns out, they're only marked as deleted and not returned in search results + $table->data[] = array($deletionsinindexstr, (int)$indexinfo->indexcount - (int)$indexinfo->dbcount); + } + + $table->data[] = array($documentsindatabasestr, $indexinfo->dbcount); + + foreach($indexinfo->types as $key => $value) { + $table->data[] = array(get_string('documentsfor', 'search') . " '".get_string('modulenameplural', $key)."'", $value); + } + + print_heading($databasestatestr); + print_table($table); + + print_box_end(); + print_box_end(); + print_footer(); ?> \ No newline at end of file diff --git a/search/update.php b/search/update.php index b7ebe4abc5b..610735dcc64 100644 --- a/search/update.php +++ b/search/update.php @@ -1,9 +1,13 @@ 1.8 +* @date 2008/03/31 +* @license http://www.gnu.org/copyleft/gpl.html GNU Public License * * Index asynchronous updator * @@ -11,133 +15,141 @@ * multiple arity to handle multiple document types modules */ +/** +* includes and requires +*/ require_once('../config.php'); require_once("$CFG->dirroot/search/lib.php"); -require_login(); +/// checks global search activation -if (empty($CFG->enableglobalsearch)) { - error(get_string('globalsearchdisabled', 'search')); -} - -if (!isadmin()) { - error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php"); -} - -//check for php5 (lib.php) -if (!search_check_php5()) { - $phpversion = phpversion(); - mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version $phpversion)"); - exit(0); -} - -require_once("$CFG->dirroot/search/indexlib.php"); - -$index = new Zend_Search_Lucene(SEARCH_INDEX_PATH); -$dbcontrol = new IndexDBControl(); -$update_count = 0; -$indexdate = $CFG->search_indexer_update_date; -$startupdatedate = time(); - -mtrace("
Starting index update (updates)...\n");
-
-if ($mods = get_records_select('modules')) {
-    $mods = array_merge($mods, search_get_additional_modules());
+    require_login();
     
-    foreach ($mods as $mod) {
-        $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-        $get_document_function = $mod->name.'_single_document';
-        $delete_function = $mod->name.'_delete';
-        $db_names_function = $mod->name.'_db_names';
-        $updates = array();
-        
-        if (file_exists($class_file)) {
-            require_once($class_file);
-            
-            //if both required functions exist
-            if (function_exists($delete_function) and function_exists($db_names_function) and function_exists($get_document_function)) {
-                mtrace("Checking $mod->name module for updates.");
-                $valuesArray = $db_names_function();
-                if ($valuesArray){
-                    foreach($valuesArray as $values){
-                    
-                        $where = (isset($values[5])) ? 'AND ('.$values[5].')' : '';
-                        $itemtypes = ($values[4] != '*') ? " AND itemtype = '{$values[4]}' " : '' ;
+    if (empty($CFG->enableglobalsearch)) {
+        error(get_string('globalsearchdisabled', 'search'));
+    }
+    
+    if (!isadmin()) {
+        error(get_string('beadmin', 'search'), "$CFG->wwwroot/login/index.php");
+    } 
+    
+/// check for php5 (lib.php)
 
-                        //TODO: check 'in' syntax with other RDBMS' (add and update.php as well)
-                        $table = SEARCH_DATABASE_TABLE;
-                        $query = "
-                            SELECT 
-                                docid,
-                                itemtype
-                            FROM 
-                                {$CFG->prefix}{$table}
-                            WHERE
-                                doctype = '{$mod->name}'
-                                $itemtypes
-                        ";
-                        $docIds = get_records_sql_menu($query);
-                        $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
+    if (!search_check_php5()) {
+        $phpversion = phpversion();
+        mtrace("Sorry, global search requires PHP 5.0.0 or later (currently using version ".phpversion().")");
+        exit(0);
+    } 
+    
+    require_once("$CFG->dirroot/search/indexlib.php");
+    
+    $index = new Zend_Search_Lucene(SEARCH_INDEX_PATH);
+    $dbcontrol = new IndexDBControl();
+    $update_count = 0;
+    $indexdate = $CFG->search_indexer_update_date;
+    $startupdatedate = time();
+
+/// indexing changed resources
+    
+    mtrace("Starting index update (updates)...\n");
+    
+    if ($mods = get_records_select('modules')) {
+        $mods = array_merge($mods, search_get_additional_modules());
+        
+        foreach ($mods as $mod) {
+            $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
+            $get_document_function = $mod->name.'_single_document';
+            $delete_function = $mod->name.'_delete';
+            $db_names_function = $mod->name.'_db_names';
+            $updates = array();
+            
+            if (file_exists($class_file)) {
+                require_once($class_file);
+                
+                //if both required functions exist
+                if (function_exists($delete_function) and function_exists($db_names_function) and function_exists($get_document_function)) {
+                    mtrace("Checking $mod->name module for updates.");
+                    $valuesArray = $db_names_function();
+                    if ($valuesArray){
+                        foreach($valuesArray as $values){
                         
-                        $query = "
-                            SELECT 
-                                id, 
-                                {$values[0]} as docid
-                            FROM 
-                                {$CFG->prefix}{$values[1]} 
-                            WHERE 
-                                {$values[3]} > {$indexdate} AND 
-                                id IN ('{$docIdList}')
-                                $where
-                        ";
-                        $records = get_records_sql($query);
-                        if (is_array($records)) {
-                            foreach($records as $record) {
-                                $updates[] = $delete_function($record->docid, $docIds[$record->docid]);
+                            $where = (isset($values[5])) ? 'AND ('.$values[5].')' : '';
+                            $itemtypes = ($values[4] != '*' && $values[4] != 'any') ? " AND itemtype = '{$values[4]}' " : '' ;
+    
+                            //TODO: check 'in' syntax with other RDBMS' (add and update.php as well)
+                            $table = SEARCH_DATABASE_TABLE;
+                            $query = "
+                                SELECT 
+                                    docid,
+                                    itemtype
+                                FROM 
+                                    {$CFG->prefix}{$table}
+                                WHERE
+                                    doctype = '{$mod->name}'
+                                    $itemtypes
+                            ";
+                            $docIds = get_records_sql_menu($query);
+                            $docIdList = ($docIds) ? implode("','", array_keys($docIds)) : '' ;
+                            
+                            $query = "
+                                SELECT 
+                                    id, 
+                                    {$values[0]} as docid
+                                FROM 
+                                    {$CFG->prefix}{$values[1]} 
+                                WHERE 
+                                    {$values[3]} > {$indexdate} AND 
+                                    id IN ('{$docIdList}')
+                                    $where
+                            ";
+                            $records = get_records_sql($query);
+                            if (is_array($records)) {
+                                foreach($records as $record) {
+                                    $updates[] = $delete_function($record->docid, $docIds[$record->docid]);
+                                } 
                             } 
+                        }
+                        
+                        foreach ($updates as $update) {
+                            ++$update_count;
+                            
+                            //delete old document
+                            $doc = $index->find("+docid:{$update->id} +doctype:{$mod->name} +itemtype:{$update->itemtype}");
+                            
+                            //get the record, should only be one
+                            foreach ($doc as $thisdoc) {
+                                mtrace("  Delete: $thisdoc->title (database id = $thisdoc->dbid, index id = $thisdoc->id, moodle instance id = $thisdoc->docid)");
+                                $dbcontrol->delDocument($thisdoc);
+                                $index->delete($thisdoc->id);
+                            } 
+                            
+                            //add new modified document back into index
+                            $add = $get_document_function($update->id, $update->itemtype);
+                            
+                            //object to insert into db
+                            $dbid = $dbcontrol->addDocument($add);
+                            
+                            //synchronise db with index
+                            $add->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
+                            mtrace("  Add: $add->title (database id = $add->dbid, moodle instance id = $add->docid)");
+                            $index->addDocument($add);
                         } 
                     }
-                    
-                    foreach ($updates as $update) {
-                        ++$update_count;
-                        
-                        //delete old document
-                        $doc = $index->find("+docid:{$update->id} +doctype:{$mod->name} +itemtype:{$update->itemtype}");
-                        
-                        //get the record, should only be one
-                        foreach ($doc as $thisdoc) {
-                            mtrace("  Delete: $thisdoc->title (database id = $thisdoc->dbid, index id = $thisdoc->id, moodle instance id = $thisdoc->docid)");
-                            $dbcontrol->delDocument($thisdoc);
-                            $index->delete($thisdoc->id);
-                        } 
-                        
-                        //add new modified document back into index
-                        $add = $get_document_function($update->id, $update->itemtype);
-                        
-                        //object to insert into db
-                        $dbid = $dbcontrol->addDocument($add);
-                        
-                        //synchronise db with index
-                        $add->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
-                        mtrace("  Add: $add->title (database id = $add->dbid, moodle instance id = $add->docid)");
-                        $index->addDocument($add);
-                    } 
-                }
-                else{
-                    mtrace("No types to update.\n");
-                }
-                mtrace("Finished $mod->name.\n");
+                    else{
+                        mtrace("No types to update.\n");
+                    }
+                    mtrace("Finished $mod->name.\n");
+                } 
             } 
         } 
     } 
-} 
-
-//commit changes
-$index->commit();
-
-//update index date
-set_config("search_indexer_update_date", $startupdatedate);
-
-mtrace("Finished $update_count updates.
"); + + //commit changes + $index->commit(); + + //update index date + set_config("search_indexer_update_date", $startupdatedate); + + mtrace("Finished $update_count updates"); ?> \ No newline at end of file