sync with HEAD/1.8 compatible

This commit is contained in:
diml
2008-04-07 21:45:07 +00:00
parent ee95c70444
commit d3d9d95f42
14 changed files with 1291 additions and 1139 deletions
+1 -1
View File
@@ -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
+1
View File
@@ -67,6 +67,7 @@ In the actual state, the engine indexes the following information:
- wiki pages
- techproject descriptions
- char sessions
- lesson pages
Extensions
##########
+131 -117
View File
@@ -1,9 +1,13 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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)) {
print_error('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()) {
print_error('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());
?>
+1
View File
@@ -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');
+112 -102
View File
@@ -1,9 +1,13 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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)) {
print_error('globalsearchdisabled', 'search');
}
if (!isadmin()) {
print_error('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());
?>
+11 -2
View File
@@ -1,9 +1,18 @@
<?php
/*
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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");
?>
+182 -163
View File
@@ -1,9 +1,13 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 1.8
* @date 2008/03/31
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*
* The indexer logic -
*
@@ -26,178 +30,193 @@
@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)) {
print_error('globalsearchdisabled', 'search');
}
if (!isadmin()) {
print_error('beadmin', 'search', "$CFG->wwwroot/login/index.php");
} //if
//confirmation flag to prevent accidental reindexing (indexersplash.php is the correct entry point)
$sure = strtolower(optional_param('areyousure', '', PARAM_ALPHA));
if ($sure != 'yes') {
mtrace("<pre>Sorry, you need to confirm indexing via <a href='indexersplash.php'>indexersplash.php</a>"
.". (<a href='index.php'>Back to query page</a>).</pre>");
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('<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head><body>');
mtrace('<pre>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
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.");
}
else {
mtrace("Directory successfully created.");
}
}
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;
require_login();
if (empty($CFG->enableglobalsearch)) {
error(get_string('globalsearchdisabled', 'search'));
}
$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);
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)
//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();
$sure = strtolower(optional_param('areyousure', '', PARAM_ALPHA));
if ($sure != 'yes') {
mtrace("<pre>Sorry, you need to confirm indexing via <a href='indexersplash.php'>indexersplash.php</a>"
.". (<a href='index.php'>Back to query page</a>).</pre>");
exit(0);
}
/// 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('<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head><body>');
mtrace('<pre>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
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.");
} else {
mtrace("Directory successfully created.");
}
} 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.');
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(".<br/><a href='index.php'>Back to query page</a>.");
mtrace('</pre>');
mtrace(".<br/><a href='index.php'>Back to query page</a>.");
mtrace('</pre>');
/// 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());
?>
?>
+67 -53
View File
@@ -1,66 +1,80 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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)) {
print_error('globalsearchdisabled', 'search');
}
if (!isadmin()) {
print_error('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()) {
$strsearch = get_string('search', 'search');
$strquery = get_string('stats');
require_login();
$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');
$navigation = build_navigation($navlinks);
$site = get_site();
print_header("$strsearch", "$site->fullname" , $navigation, "", "", true, "&nbsp;", navmenu($site));
mtrace("<pre>The data directory ($indexinfo->path) contains $indexinfo->filecount files, and\n"
."there are ".$indexinfo->dbcount." records in the <em>block_search_documents</em> 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"
."<a href='tests/index.php'>Test indexing</a> or "
."<a href='indexer.php?areyousure=yes'>Continue indexing</a> or <a href='index.php'>Back to query page</a>."
."</pre>");
print_footer();
}
else {
header('Location: indexer.php?areyousure=yes');
}
?>
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");
$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, "&nbsp;", navmenu($site));
mtrace("<pre>The data directory ($indexinfo->path) contains $indexinfo->filecount files, and\n"
."there are ".$indexinfo->dbcount." records in the <em>block_search_documents</em> 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"
."<a href='tests/index.php'>Test indexing</a> or "
."<a href='indexer.php?areyousure=yes'>Continue indexing</a> or <a href='index.php'>Back to query page</a>."
."</pre>");
print_footer();
}
else {
header('Location: indexer.php?areyousure=yes');
}
?>
+41 -30
View File
@@ -1,20 +1,32 @@
<?php
/*
* Author: Michael Champanis
/**
* Global Search Engine for Moodle
*
* Reviewed by: Valery Fremaux (2007)
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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,8 +85,7 @@ class IndexInfo {
$c = count_records(SEARCH_DATABASE_TABLE, 'doctype', $type);
$this->types[$type] = (int)$c;
}
}
else {
} else {
$this->dbcount = 0;
$this->types = array();
}
@@ -82,23 +93,21 @@ class IndexInfo {
//check if the busy flag is set
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;
@@ -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
}
}
?>
+12 -6
View File
@@ -1,14 +1,20 @@
<?php
/*
* Author: Michael Champanis
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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
+352 -337
View File
@@ -1,346 +1,361 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* 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
*
*/
require_once('../config.php');
require_once("$CFG->dirroot/search/lib.php");
if ($CFG->forcelogin) {
require_login();
}
if (empty($CFG->enableglobalsearch)) {
print_error('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');
$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, "&nbsp;", 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));
}
}
?>
<form id="query" method="get" action="query.php">
<?php
if (!$advanced) {
?>
<input type="text" name="query_string" length="50" value="<?php print stripslashes($query_string) ?>" />
&nbsp;<input type="submit" value="<?php print_string('search', 'search') ?>" /> &nbsp;
<a href="query.php?a=1"><?php print_string('advancedsearch', 'search') ?></a> |
<a href="stats.php"><?php print_string('statistics', 'search') ?></a>
<?php
}
else {
print_box_start();
?>
<input type="hidden" name="a" value="<?php print $advanced; ?>"/>
<table border="0" cellpadding="3" cellspacing="3">
<tr>
<td width="240"><?php print_string('thesewordsmustappear', 'search') ?>:</td>
<td><input type="text" name="mustappear" length="50" value="<?php print $adv->mustappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('thesewordsmustnotappear', 'search') ?>:</td>
<td><input type="text" name="notappear" length="50" value="<?php print $adv->notappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('thesewordshelpimproverank', 'search') ?>:</td>
<td><input type="text" name="canappear" length="50" value="<?php print $adv->canappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('whichmodulestosearch?', 'search') ?>:</td>
<td>
<select name="module">
<?php
foreach($module_types as $mod) {
if ($mod == $adv->module) {
if ($mod != 'all'){
print "<option value='$mod' selected=\"selected\">".get_string('modulenameplural', $mod)."</option>\n";
}
else{
print "<option value='$mod' selected=\"selected\">".get_string('all', 'search')."</option>\n";
}
}
else {
if ($mod != 'all'){
print "<option value='$mod'>".get_string('modulenameplural', $mod)."</option>\n";
}
else{
print "<option value='$mod'>".get_string('all', 'search')."</option>\n";
}
}
}
?>
</select>
</td>
</tr>
<tr>
<td><?php print_string('wordsintitle', 'search') ?>:</td>
<td><input type="text" name="title" length="50" value="<?php print $adv->title; ?>" /></td>
</tr>
<tr>
<td><?php print_string('authorname', 'search') ?>:</td>
<td><input type="text" name="author" length="50" value="<?php print $adv->author; ?>" /></td>
</tr>
<tr>
<td colspan="3" align="center"><br /><input type="submit" value="<?php print_string('search', 'search') ?>" /></td>
</tr>
<tr>
<td colspan="3" align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td><a href="query.php"><?php print_string('normalsearch', 'search') ?></a> |</td>
<td>&nbsp;<a href="stats.php"><?php print_string('statistics', 'search') ?></a></td>
</tr>
</table>
</td>
</tr>
</table>
<?php
print_box_end();
}
?>
</form>
<br/>
<div align="center">
<?php
print_string('searching', 'search') . ': ';
if ($sq->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 '<p>' . get_string('noindexmessage', 'search') . '<a href="indexersplash.php">' . get_string('createanindex', 'search')."</a></p>\n";
}
?>
</div>
<?php
print_box_end();
// prints all the results in a box
if ($sq->is_valid()) {
print_box_start();
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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 "<br />";
if (empty($CFG->enableglobalsearch)) {
error(get_string('globalsearchdisabled', 'search'));
}
print $hit_count.' '.get_string('resultsreturnedfor', 'search') . " '".stripslashes($query_string)."'.";
print "<br />";
$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 "<ol>";
$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 "<li value='".($listing->number+1)."'><a href='".str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)."'>$listing->title</a><br />\n"
."<em>".search_shorten_url($listing->url, 70)."</em><br />\n"
."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3).", {$authorstr}: ".$listing->author."\n"
."</li>\n";
}
print "</ol>";
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",
"<a href=\"index.php\">$strsearch</a> -> $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, "&nbsp;", 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));
}
}
?>
<form id="query" method="get" action="query.php">
<?php
if (!$advanced) {
?>
<input type="text" name="query_string" length="50" value="<?php print stripslashes($query_string) ?>" />
&nbsp;<input type="submit" value="<?php print_string('search', 'search') ?>" /> &nbsp;
<a href="query.php?a=1"><?php print_string('advancedsearch', 'search') ?></a> |
<a href="stats.php"><?php print_string('statistics', 'search') ?></a>
<?php
}
else {
print_box_start();
?>
<input type="hidden" name="a" value="<?php print $advanced; ?>"/>
<table border="0" cellpadding="3" cellspacing="3">
<tr>
<td width="240"><?php print_string('thesewordsmustappear', 'search') ?>:</td>
<td><input type="text" name="mustappear" length="50" value="<?php print $adv->mustappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('thesewordsmustnotappear', 'search') ?>:</td>
<td><input type="text" name="notappear" length="50" value="<?php print $adv->notappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('thesewordshelpimproverank', 'search') ?>:</td>
<td><input type="text" name="canappear" length="50" value="<?php print $adv->canappear; ?>" /></td>
</tr>
<tr>
<td><?php print_string('whichmodulestosearch?', 'search') ?>:</td>
<td>
<select name="module">
<?php
foreach($module_types as $mod) {
if ($mod == $adv->module) {
if ($mod != 'all'){
print "<option value='$mod' selected=\"selected\">".get_string('modulenameplural', $mod)."</option>\n";
}
else{
print "<option value='$mod' selected=\"selected\">".get_string('all', 'search')."</option>\n";
}
}
else {
if ($mod != 'all'){
print "<option value='$mod'>".get_string('modulenameplural', $mod)."</option>\n";
}
else{
print "<option value='$mod'>".get_string('all', 'search')."</option>\n";
}
}
}
?>
</select>
</td>
</tr>
<tr>
<td><?php print_string('wordsintitle', 'search') ?>:</td>
<td><input type="text" name="title" length="50" value="<?php print $adv->title; ?>" /></td>
</tr>
<tr>
<td><?php print_string('authorname', 'search') ?>:</td>
<td><input type="text" name="author" length="50" value="<?php print $adv->author; ?>" /></td>
</tr>
<tr>
<td colspan="3" align="center"><br /><input type="submit" value="<?php print_string('search', 'search') ?>" /></td>
</tr>
<tr>
<td colspan="3" align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td><a href="query.php"><?php print_string('normalsearch', 'search') ?></a> |</td>
<td>&nbsp;<a href="stats.php"><?php print_string('statistics', 'search') ?></a></td>
</tr>
</table>
</td>
</tr>
</table>
<?php
print_box_end();
}
?>
</form>
<br/>
<div align="center">
<?php
print_string('searching', 'search') . ': ';
if ($sq->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 '<p>' . get_string('noindexmessage', 'search') . '<a href="indexersplash.php">' . get_string('createanindex', 'search')."</a></p>\n";
}
?>
</div>
<?php
print_box_end();
?>
<div align="center">
<?php
print_string('ittook', 'search');
search_stopwatch();
print_string('tofetchtheseresults', 'search');
?>.
</div>
<?php
}
print_box_end();
print_footer();
?>
// prints all the results in a box
if ($sq->is_valid()) {
print_box_start();
search_stopwatch();
$hit_count = $sq->count();
print "<br />";
print $hit_count.' '.get_string('resultsreturnedfor', 'search') . " '".stripslashes($query_string)."'.";
print "<br />";
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 "<ol>";
$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 "<li value='".($listing->number+1)."'><a href='".str_replace('DEFAULT_POPUP_SETTINGS', DEFAULT_POPUP_SETTINGS ,$listing->url)."'>$listing->title</a><br />\n"
."<em>".search_shorten_url($listing->url, 70)."</em><br />\n"
."{$typestr}: ".$listing->doctype.", {$scorestr}: ".round($listing->score, 3);
if (!empty($listing->author)){
print ", {$authorstr}: ".$listing->author."\n"
."</li>\n";
}
}
print "</ol>";
print $page_links;
}
print_box_end();
?>
<div align="center">
<?php
print_string('ittook', 'search');
search_stopwatch();
print_string('tofetchtheseresults', 'search');
?>.
</div>
<?php
}
print_box_end();
print_footer();
?>
+94 -65
View File
@@ -1,4 +1,18 @@
<?php
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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 .= "<a href='query.php?query_string={$query}&page=".($page-1)."'>&lt; {$back}</a>&nbsp;";
} else {
$ret .= "&lt; {$back}&nbsp;";
} //else
}
//don't <a href> the current page
for ($i = 1; $i <= $pages; $i++) {
@@ -322,15 +330,15 @@ class SearchQuery {
$ret .= "($i)&nbsp;";
} else {
$ret .= "<a href='query.php?query_string={$query}&page={$i}'>{$i}</a>&nbsp;";
} //else
} //for
}
}
//Next disabled if we're on the last page
if ($page < $pages) {
$ret .= "<a href='query.php?query_string={$query}&page=".($page+1)."'>{$next} &gt;</a>&nbsp;";
} else {
$ret .= "{$next} &gt;&nbsp;";
} //else
}
$ret .= "</div>";
@@ -343,10 +351,10 @@ class SearchQuery {
$start = $page + 5;
$end = $pages - 3;
$ret = preg_replace("/<a\D+\d+\D+>$start<\/a>.*?<a\D+\d+\D+>$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
}
}
?>
+155 -144
View File
@@ -1,152 +1,163 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* Prints some basic statistics about the current index.
* Does some diagnostics if you are logged in as an administrator.
*
*/
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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.
*
*/
/**
* includes and requires
*/
require_once('../config.php');
require_once("{$CFG->dirroot}/search/lib.php");
/// checks global search is enabled
require_once('../config.php');
require_once("{$CFG->dirroot}/search/lib.php");
if ($CFG->forcelogin) {
require_login();
}
if (empty($CFG->enableglobalsearch)) {
print_error('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');
$navlinks = array();
$navlinks[] = array('name' => $strsearch, 'link' => "index.php", 'type' => 'misc');
$navlinks[] = array('name' => $strquery, 'link' => null, 'type' => 'misc');
$navigation = build_navigation($navlinks);
print_header("$site->shortname: $strsearch: $strquery", "$site->fullname", $navigation);
//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("<strong>{$datadirectorystr}</strong>", '<em><strong>'.$indexinfo->path.'</strong></em>');
$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));
if ($CFG->forcelogin) {
require_login();
}
else {
$admin_table->data[] = array(get_string('createdon', 'search'), '-');
if (empty($CFG->enableglobalsearch)) {
error(get_string('globalsearchdisabled', 'search'));
}
/// check for php5, but don't die yet
if (!$indexinfo->valid($errors)) {
$admin_table->data[] = array("<strong>{$errorsstr}</strong>", '&nbsp;');
foreach ($errors as $key => $value) {
$admin_table->data[] = array($key.' ... ', $value);
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",
"<a href=\"index.php\">$strsearch</a> -> $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("<strong>{$datadirectorystr}</strong>", '<em><strong>'.$indexinfo->path.'</strong></em>');
$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("<strong>{$errorsstr}</strong>", '&nbsp;');
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, '<a href="tests/index.php" target="_blank">tests/index.php</a>');
$admin_table->data[] = array($runindexerstr, '<a href="indexersplash.php" target="_blank">indexersplash.php</a>');
print_table($admin_table);
print_spacer(20);
}
/// this is the standard summary table for normal users, shows document counts
print_table($admin_table);
print_spacer(20);
print_heading($solutionsstr);
$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("<strong>{$databasestr}</strong>", "<em><strong>{$CFG->prefix}".SEARCH_DATABASE_TABLE.'</strong></em>');
/// add extra fields if we're admin
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, '<a href="tests/index.php" target="_blank">tests/index.php</a>');
$admin_table->data[] = array($runindexerstr, '<a href="indexersplash.php" target="_blank">indexersplash.php</a>');
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("<strong>{$databasestr}</strong>", "<em><strong>{$CFG->prefix}block_search_documents</strong></em>");
//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);
//*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();
?>
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();
?>
+131 -119
View File
@@ -1,9 +1,13 @@
<?php
/**
* Global Search Engine for Moodle
* Michael Champanis (mchampan) [[email protected]]
* review 1.8+ : Valery Fremaux [[email protected]]
* 2007/08/02
*
* @package search
* @category core
* @subpackage search_engine
* @author Michael Champanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 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)) {
print_error('globalsearchdisabled', 'search');
}
if (!isadmin()) {
print_error('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");
?>
?>