Pagination added to query page. Various small changes and amendments.
this block, the broadest possible selection of documents is searched.
Author: Michael Champanis (mchampan)
- Date: 2006 06 23
+ Date: 2006 06 25
Todo: make strings -> get_string()
*/
function init() {
$this->title = "Global Search"; //get_string()
- $this->version = 20060625;
+ $this->version = 2006062500;
} //init
// only one instance of this block is required
//basic search form
$this->content->text =
- '<form name="query" method="post" action="search/query.php">'
+ '<form name="query" method="get" action="search/query.php">'
. "<label for=''>$label</label>"
. '<input type="text" name="query_string" length="50" value=""/>'
. '<input type="submit" value="'.$button.'"/>'
}
}
-
-/*==== Global search modifications
- * Author: Michael Champanis (mchampan)
- * Last date: 2006 06 25
- * These modifications allow wiki documents to be indexed in the new
- * search engine module - they are probably not final, and as such
- * shouldn't be used by other stuff for the time being
- **/
-
-//rescued and converted from ewikimoodlelib.php
-//retrieves latest version of a page
-function wiki_get_latest_page(&$entry, $pagename, $version=0) {
- $pagename = "'".addslashes($pagename)."'";
-
- if ($version > 0 and is_int($version)) {
- $version = "AND (version=$version)";
- } else {
- $version = '';
- } //else
-
- $select = "(pagename=$pagename) AND wiki=".$entry->id." $version ";
- $sort = 'version DESC';
-
- //change this to recordset_select, as per http://docs.moodle.org/en/Datalib_Notes
- if ($result_arr = get_records_select('wiki_pages', $select, $sort, '*', 0, 1)) {
- foreach ($result_arr as $obj) {
- $result_obj = $obj;
- } //foreach
- } //if
-
- if (isset($result_obj)) {
- $result_obj->meta = @unserialize($result_obj->meta);
- return $result_obj;
- } else {
- return false;
- } //else
-} //wiki_get_latest_page
-
-//fetches all pages, including old versions
-function wiki_get_pages(&$entry) {
- return get_records('wiki_pages', 'wiki', $entry->id);
-} //wiki_get_pages
-
-//fetches all the latest versions of all the pages
-function wiki_get_latest_pages(&$entry) {
- //== (My)SQL for this
- /* select * from wiki_pages
- inner join
- (select wiki_pages.pagename, max(wiki_pages.version) as ver
- from wiki_pages group by pagename) as a
- on ((wiki_pages.version = a.ver) and
- (wiki_pages.pagename like a.pagename)) */
-
- $pages = array();
-
- //http://moodle.org/bugs/bug.php?op=show&bugid=5877&pos=0
- //if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
- if ($rs = get_recordset('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
- $ids = $rs->GetRows();
- //--
- foreach ($ids as $id) {
- $pages[] = wiki_get_latest_page($entry, $id[0]);
- } //foreach
- } else {
- return false;
- } //else
-
- return $pages;
-} //wiki_get_latest_pages
-
-function wiki_iterator() {
- return get_all_instances_in_courses("wiki", get_courses());
-} //wiki_search_index
-
-function wiki_get_content_for_index(&$wiki) {
- $documents = array();
-
- $entries = wiki_get_entries($wiki);
- foreach($entries as $entry) {
- //all pages
- //$pages = wiki_get_pages($entry);
-
- //latest pages
- $pages = wiki_get_latest_pages($entry);
- $i = 0;
-
- if (is_array($pages)) {
- foreach($pages as $page) {
- if (strlen($page->content) > 0) {
- $i++;
- $documents[] = new WikiSearchDocument($page, $entry->wikiid, $entry->course, $entry->groupid);
- } //if
- } //foreach
-
- //print "$entry->id : $i"; print "<br>";
- } else {
- print $pages;
- } //else
- } //foreach
-
- return $documents;
-} //wiki_get_content_for_index
-
-/*==== Global search modifications end */
-
-
function wiki_get_default_entry(&$wiki, &$course, $userid=0, $groupid=0) {
/// Returns the wiki entry according to the wiki type.
/// Optionally, will return wiki entry for $userid student wiki, or
-latest
+2006/07/11
+----------
+(Warning: It took me 1900 seconds to index the forum, go make coffee
+whilst you wait.)
+
+Forum search functions changed to use 'get_recordset' instead of
+'get_records', for speed reasons. This provides a significant improvement,
+but indexing is still slow - getting data from the database and Zend's
+tokenising _seem_ to be the prime suspects at the moment.
+
+/search/tests/ added - index.php can be used to see which modules are
+ready to be included in the search index, and it informs you of any
+errors - should be a prerequisite for indexing.
+
+Search result pagination added to query.php, will default to 20 until
+an admin page for the search module is written.
+
+2006/07/07
+----------
+Search-enabling functions moved out've the mod's lib.php files and into
+/search/documents/mod_document.php - this requires the search module to
+operate without requiring modification of lib files.
+
+SearchDocument base class improved, and the way module documents extend
+it. A custom-data field has been added to allow modules to add any custom
+data they wish to be stored in the index - this field is serialised into
+the index as a binary field.
+
+Database field 'type' renamed to 'doctype' to match the renaming in the
+index, 'type' seems to be a reserved word in Lucene. Several index field
+names change to be more descriptive (cid -> course_id). URLs are now
+stored in the index, and don't have to be generated on the fly during
+display of query results.
+
+2006/07/05
------
Started cleaning and standardising things.
CREATE TABLE IF NOT EXISTS `prefix_search_documents` (
`id` int(11) NOT NULL auto_increment,
- `type` varchar(12) NOT NULL default 'none',
+ `doctype` varchar(12) NOT NULL default 'none',
`title` varchar(100) NOT NULL default '',
`url` varchar(100) NOT NULL default '',
`updated` timestamp NOT NULL default CURRENT_TIMESTAMP,
CREATE TABLE prefix_search_documents (
id SERIAL8 PRIMARY KEY,
- "type" varchar(12) NOT NULL DEFAULT 'none',
+ doctype varchar(12) NOT NULL DEFAULT 'none',
title varchar(100) NOT NULL default '',
url varchar(100) NOT NULL default '',
updated timestamp NOT NULL DEFAULT NOW(),
* */
class SearchDocument extends Zend_Search_Lucene_Document {
- public function __construct($document_type, $cid, $gid) {
- $this->addField(Zend_Search_Lucene_Field::Keyword('type', $document_type));
- $this->addField(Zend_Search_Lucene_Field::Keyword('courseid', $cid));
- $this->addField(Zend_Search_Lucene_Field::Keyword('groupid', $gid));
+ public function __construct(&$doc, &$data, $document_type, $course_id, $group_id) {
+ $this->addField(Zend_Search_Lucene_Field::Keyword('id', $doc->id));
+ $this->addField(Zend_Search_Lucene_Field::Text('title', $doc->title));
+ $this->addField(Zend_Search_Lucene_Field::Text('author', $doc->author));
+ $this->addField(Zend_Search_Lucene_Field::UnStored('contents', $doc->contents));
+ $this->addField(Zend_Search_Lucene_Field::UnIndexed('url', $doc->url));
+
+ $this->addField(Zend_Search_Lucene_Field::Binary('data', serialize($data)));
+
+ $this->addField(Zend_Search_Lucene_Field::Keyword('doctype', $document_type));
+ $this->addField(Zend_Search_Lucene_Field::Keyword('course_id', $course_id));
+ $this->addField(Zend_Search_Lucene_Field::Keyword('group_id', $group_id));
} //constructor
} //SearchDocument
--- /dev/null
+<?php
+
+ /* see wiki_document.php for descriptions */
+
+ require_once("$CFG->dirroot/search/documents/document.php");
+ require_once("$CFG->dirroot/mod/forum/lib.php");
+
+ class ForumSearchDocument extends SearchDocument {
+ public function __construct(&$post, $forum_id, $course_id, $group_id) {
+ // generic information
+ /*$doc->id = $post->id;
+ $doc->title = $post->subject;
+ $doc->author = $post->firstname." ".$post->lastname;
+ $doc->contents = $post->message;*/
+
+ $doc->id = $post['id'];
+ $doc->title = $post['subject'];
+ $doc->author = $post['firstname']." ".$post['lastname'];
+ $doc->contents = $post['message'];
+
+ $doc->url = forum_make_link($post['discussion'], $post['id']);
+
+ // module specific information
+ $data->forum = $forum_id;
+ $data->discussion = $post['discussion'];
+
+ parent::__construct($doc, $data, SEARCH_FORUM_TYPE, $course_id, $group_id);
+ } //constructor
+ } //ForumSearchDocument
+
+ function forum_make_link($discussion_id, $post_id) {
+ global $CFG;
+ return $CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion_id.'#'.$post_id;
+ } //forum_make_link
+
+ function forum_iterator() {
+ //no @ = Undefined index: 82 in /home/michael/public_html/moodle/lib/datalib.php on line 2671
+ return @get_all_instances_in_courses("forum", get_courses());
+ } //forum_iterator
+
+ function forum_get_content_for_index(&$forum) {
+ $documents = array();
+ if (!$forum) return $documents;
+
+ $posts = forum_get_discussions_fast($forum->id);
+ if (!$posts) return $documents;
+
+ while (!$posts->EOF) {
+ $post = $posts->fields;
+
+ if (is_array($post)) {
+ if (strlen($post['message']) > 0 && ($post['deleted'] != 1)) {
+ $documents[] = new ForumSearchDocument($post, $forum->id, $forum->course, $post['groupid']);
+ } //if
+
+ if ($children = forum_get_child_posts_fast($post['id'], $forum->id)) {
+ while (!$children->EOF) {
+ $child = $children->fields;
+
+ if (strlen($child['message']) > 0 && ($child['deleted'] != 1)) {
+ $documents[] = new ForumSearchDocument($child, $forum->id, $forum->course, $post['groupid']);
+ } //if
+
+ $children->MoveNext();
+ } //foreach
+ } //if
+ } //if
+
+ $posts->MoveNext();
+ } //foreach
+
+ return $documents;
+ } //forum_get_content_for_index
+
+ //old slower version
+ function forum_get_content_for_index_old(&$forum) {
+ $documents = array();
+ if (!$forum) return $documents;
+
+ $posts = forum_get_discussions($forum->id);
+ if (!$posts) return $documents;
+
+ foreach($posts as $post) {
+ if (is_object($post)) {
+ if (strlen($post->message) > 0 && ($post->deleted != 1)) {
+ $documents[] = new ForumSearchDocument($post, $forum->id, $forum->course, $post->groupid);
+ } //if
+
+ if ($children = forum_get_child_posts($post->id, $forum->id)) {
+ foreach ($children as $child) {
+ if (strlen($child->message) > 0 && ($child->deleted != 1)) {
+ $documents[] = new ForumSearchDocument($child, $forum->id, $forum->course, $post->groupid);
+ } //if
+ } //foreach
+ } //if
+ } //if
+ } //foreach
+
+ return $documents;
+ } //forum_get_content_for_index_old
+
+ //reworked faster version from /mod/forum/lib.php
+ function forum_get_discussions_fast($forum) {
+ global $CFG, $USER;
+
+ $timelimit='';
+
+ if (!empty($CFG->forum_enabletimedposts)) {
+ if (!((isadmin() and !empty($CFG->admineditalways)) || isteacher(get_field('forum', 'course', 'id', $forum)))) {
+ $now = time();
+ $timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')";
+ if (!empty($USER->id)) {
+ $timelimit .= " OR d.userid = '$USER->id'";
+ }
+ $timelimit .= ')';
+ }
+ }
+
+ if ($CFG->dbtype == 'postgres7') {
+ return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message,
+ p.deleted, d.groupid, u.firstname, u.lastname
+ FROM {$CFG->prefix}forum_discussions d
+ JOIN {$CFG->prefix}forum_posts p ON p.discussion = d.id
+ JOIN {$CFG->prefix}user u ON p.userid = u.id
+ WHERE d.forum = '$forum'
+ AND p.parent = 0
+ $timelimit
+ ORDER BY d.timemodified DESC");
+ } else {
+ return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message, p.deleted,
+ d.groupid, u.firstname, u.lastname
+ FROM ({$CFG->prefix}forum_posts p,
+ {$CFG->prefix}user u,
+ {$CFG->prefix}forum_discussions d)
+ WHERE d.forum = '$forum'
+ AND p.discussion = d.id
+ AND p.parent = 0
+ AND p.userid = u.id $timelimit
+ ORDER BY d.timemodified DESC");
+ } //else
+ } //forum_get_discussions_fast
+
+ //reworked faster version from /mod/forum/lib.php
+ function forum_get_child_posts_fast($parent, $forumid) {
+ global $CFG;
+
+ return get_recordset_sql("SELECT p.id, p.subject, p.discussion, p.message, p.deleted,
+ $forumid AS forum, u.firstname, u.lastname
+ FROM {$CFG->prefix}forum_posts p
+ LEFT JOIN {$CFG->prefix}user u ON p.userid = u.id
+ WHERE p.parent = '$parent'
+ ORDER BY p.created ASC");
+ } //forum_get_child_posts_fast
+
+?>
\ No newline at end of file
<?php
+ /* Wiki Search Document class and functions
+ * This file contains the mapping between a wiki page and it's indexable counterpart,
+ * e.g. searchdocument->title = wikipage->pagename
+ *
+ * Functions for iterating and retrieving the necessary records are now also included
+ * in this file, rather than mod/wiki/lib.php
+ * */
require_once("$CFG->dirroot/search/documents/document.php");
+ require_once("$CFG->dirroot/mod/wiki/lib.php");
+ /* All the $doc->___ fields are required by the base document class!
+ * Each and every module that requires search functionality must correctly
+ * map their internal fields to the five $doc fields (id, title, author, contents
+ * and url). Any module specific data can be added to the $data object, which is
+ * serialised into a binary field in the index.
+ * */
class WikiSearchDocument extends SearchDocument {
- public function __construct(&$page, $wiki_id, $cid, $gid) {
- $this->addField(Zend_Search_Lucene_Field::Text('title', $page->pagename));
- $this->addField(Zend_Search_Lucene_Field::Text('author', $page->author));
- $this->addField(Zend_Search_Lucene_Field::UnStored('contents', $page->content));
+ public function __construct(&$page, $wiki_id, $course_id, $group_id) {
+ // generic information; required
+ $doc->id = $page->id;
+ $doc->title = $page->pagename;
+ $doc->author = $page->author;
+ $doc->contents = $page->content;
+ $doc->url = wiki_make_link($wiki_id, $page->pagename, $page->version);
- $this->addField(Zend_Search_Lucene_Field::Keyword('id', $page->id));
- $this->addField(Zend_Search_Lucene_Field::Keyword('version', $page->version));
- $this->addField(Zend_Search_Lucene_Field::Keyword('wiki', $wiki_id));
+ // module specific information; optional
+ $data->version = $page->version;
+ $data->wiki = $wiki_id;
- parent::__construct(SEARCH_WIKI_TYPE, $cid, $gid);
+ // construct the parent class
+ parent::__construct($doc, $data, SEARCH_WIKI_TYPE, $course_id, $group_id);
} //constructor
} //WikiSearchDocument
function wiki_name_convert($str) {
return str_replace(' ', '+', $str);
} //wiki_name_convert
-
- function wiki_make_link(&$doc) {
+
+ function wiki_make_link($wiki_id, $title, $version) {
global $CFG;
- return $CFG->wwwroot.'/mod/wiki/view.php?wid='.$doc->wiki.'&page='.wiki_name_convert($doc->title).'&version='.$doc->version;
+ return $CFG->wwwroot.'/mod/wiki/view.php?wid='.$wiki_id.'&page='.wiki_name_convert($title).'&version='.$version;
} //wiki_make_link
+ //rescued and converted from ewikimoodlelib.php
+ //retrieves latest version of a page
+ function wiki_get_latest_page(&$entry, $pagename, $version=0) {
+ $pagename = "'".addslashes($pagename)."'";
+
+ if ($version > 0 and is_int($version)) {
+ $version = "AND (version=$version)";
+ } else {
+ $version = '';
+ } //else
+
+ $select = "(pagename=$pagename) AND wiki=".$entry->id." $version ";
+ $sort = 'version DESC';
+
+ //change this to recordset_select, as per http://docs.moodle.org/en/Datalib_Notes
+ if ($result_arr = get_records_select('wiki_pages', $select, $sort, '*', 0, 1)) {
+ foreach ($result_arr as $obj) {
+ $result_obj = $obj;
+ } //foreach
+ } //if
+
+ if (isset($result_obj)) {
+ $result_obj->meta = @unserialize($result_obj->meta);
+ return $result_obj;
+ } else {
+ return false;
+ } //else
+ } //wiki_get_latest_page
+
+ //fetches all pages, including old versions
+ function wiki_get_pages(&$entry) {
+ return get_records('wiki_pages', 'wiki', $entry->id);
+ } //wiki_get_pages
+
+ //fetches all the latest versions of all the pages
+ function wiki_get_latest_pages(&$entry) {
+ //== (My)SQL for this
+ /* select * from wiki_pages
+ inner join
+ (select wiki_pages.pagename, max(wiki_pages.version) as ver
+ from wiki_pages group by pagename) as a
+ on ((wiki_pages.version = a.ver) and
+ (wiki_pages.pagename like a.pagename)) */
+
+ $pages = array();
+
+ //http://moodle.org/bugs/bug.php?op=show&bugid=5877&pos=0
+ //if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
+ if ($rs = get_recordset('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
+ $ids = $rs->GetRows();
+ //--
+ foreach ($ids as $id) {
+ $pages[] = wiki_get_latest_page($entry, $id[0]);
+ } //foreach
+ } else {
+ return false;
+ } //else
+
+ return $pages;
+ } //wiki_get_latest_pages
+
+ function wiki_iterator() {
+ return get_all_instances_in_courses("wiki", get_courses());
+ } //wiki_iterator
+
+ function wiki_get_content_for_index(&$wiki) {
+ $documents = array();
+
+ $entries = wiki_get_entries($wiki);
+ foreach($entries as $entry) {
+ //all pages
+ //$pages = wiki_get_pages($entry);
+
+ //latest pages
+ $pages = wiki_get_latest_pages($entry);
+
+ if (is_array($pages)) {
+ foreach($pages as $page) {
+ if (strlen($page->content) > 0) {
+ $documents[] = new WikiSearchDocument($page, $entry->wikiid, $entry->course, $entry->groupid);
+ } //if
+ } //foreach
+ } //if
+ } //foreach
+
+ return $documents;
+ } //wiki_get_content_for_index
+
?>
\ No newline at end of file
<?php
/* The indexer logic -
- * Look through each installed module's lib file for necessary search functions,
- * and if they're present (and the module search document class file), add the
- * content to the index. Repeat this for blocks.
+ * Look through each installed module's search document class file (/search/documents)
+ * for necessary search functions, and if they're present add the content to the index.
+ * Repeat this for blocks.
+ *
+ * Because the iterator/retrieval functions are now stored in /search/documents/mod_document.php,
+ * /mod/mod/lib.php doesn't have to be modified - and thus the search module becomes quite
+ * self-sufficient. URL's are now stored in the index, stopping us from needing to require
+ * the class files to generate a results page.
*
* Along with the index data, each document's summary gets stored in the database
* and synchronised to the index (flat file) via the primary key ('id') which is mapped
- * to the 'dbid' field in the index
+ * to the 'db_id' field in the index
* */
//this'll take some time, set up the environment
//php5 found, continue including php5-only files
require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
- //begin timer
- search_stopwatch();
+ if (get_config("search_indexer_busy") == 1) {
+ } //if
+
+ //turn on busy flag
+ set_config("search_indexer_busy", 1);
mtrace('<pre>Server Time: '.date('r',time())."\n");
//paths
} else {
mtrace("Using $index_path as data directory.");
} //else
-
+
$index = new Zend_Search_Lucene($index_path, true);
//create the database tables
$tables = $db->MetaTables();
if (in_array($CFG->prefix.'search_documents', $tables)) {
- delete_records('search_documents');
+ //delete_records('search_documents');
+ //temporary measure - db doesn't have update scripts and I realised that cvs 1.1 db
+ //is incompatible with cvs 1.2! Must fix ASAP.
+ execute_sql('drop table '.$CFG->prefix.'search_documents', false);
+
+ ob_start(); //turn output buffering on - to hide modify_database() output
+ modify_database($index_db_file, '', false);
+ ob_end_clean(); //chuck the buffer and resume normal operation
} else {
ob_start(); //turn output buffering on - to hide modify_database() output
modify_database($index_db_file, '', false);
ob_end_clean(); //chuck the buffer and resume normal operation
} //else
-
- mtrace('Starting activity modules');
+
+ //begin timer
+ search_stopwatch();
+ mtrace("Starting activity modules\n");
//the presence of the required search functions -
// * mod_iterator
if ($mods = get_records_select('modules' /*'index this module?' where statement*/)) {
foreach ($mods as $mod) {
- $libfile = "$CFG->dirroot/mod/$mod->name/lib.php";
+ $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
- if (file_exists($libfile)) {
- include_once($libfile);
+ if (file_exists($class_file)) {
+ include_once($class_file);
$iter_function = $mod->name.'_iterator';
$index_function = $mod->name.'_get_content_for_index';
-
- //specific module search document class
- $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
-
+
$counter = 0;
$doc = new stdClass;
- if (file_exists($class_file) && function_exists($index_function) && function_exists($iter_function)) {
- include_once($class_file);
-
+ if (function_exists($index_function) && function_exists($iter_function)) {
mtrace("Processing module function $index_function ...");
foreach ($iter_function() as $i) {
foreach($documents as $document) {
$counter++;
- //data object for db
- $doc->type = $document->type;
- $doc->title = search_escape_string($document->title);
- $doc->update = time();
- $doc->url = 'none';
- $doc->courseid = $document->courseid;
- $doc->groupid = $document->groupid;
+ //object to insert into db
+ $doc->doctype = $document->doctype;
+ $doc->title = search_escape_string($document->title);
+ $doc->url = search_escape_string($document->url);
+ $doc->update = time();
+ $doc->courseid = $document->course_id;
+ $doc->groupid = $document->group_id;
//insert summary into db
$id = insert_record('search_documents', $doc);
//synchronise db with index
- $document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $id));
+ $document->addField(Zend_Search_Lucene_Field::Keyword('db_id', $id));
//add document to index
$index->addDocument($document);
//commit every x new documents, and print a status message
- if (($counter%200) == 0) {
+ if (($counter%2000) == 0) {
$index->commit();
- mtrace(".. $counter");
+ mtrace(".. $counter");
} //if
} //foreach
-
+
//end transaction
} //foreach
$index->commit();
mtrace("-- $counter documents indexed");
- mtrace('done.');
+ mtrace("done.\n");
} //if
} //if
} //foreach
mtrace(".<br><a href='index.php'>Back to query page</a>.");
mtrace('</pre>');
+
+ //finished, turn busy flag off
+ set_config("search_indexer_busy", 0);
?>
\ No newline at end of file
."started and cancelled an indexing session. Follow the link if you are sure that\n"
."you want to continue indexing - this will replace any existing index data (no\n"
."Moodle data is affected).\n"
- ."\n"
+ ."\n"
+ ."You are encouraged to use the 'Test indexing' script before continuing onto\n"
+ ."indexing - this will check if the modules are set up correctly. Please correct\n"
+ ."any errors before proceeding.\n"
+ ."\n"
+ ."<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>");
} else {
//document types that can be searched
define('SEARCH_NO_TYPE', 'none');
define('SEARCH_WIKI_TYPE', 'wiki');
+ define('SEARCH_FORUM_TYPE', 'forum');
//returns all the document type constants
function search_get_document_types() {
- $r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE);
+ $r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE, SEARCH_FORUM_TYPE);
return $r;
} //search_get_document_types
<?php
+ /* 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");
//check for php5, but don't die yet (see line 27)
if ($check = search_check_php5()) {
require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
- require_once("$CFG->dirroot/search/documents/wiki_document.php");
- $query_string = optional_param('query_string', '', PARAM_CLEAN);
+ $query_string = optional_param('query_string', '', PARAM_CLEAN);
+ $page_number = optional_param('page', 1, PARAM_INT);
+
+ if ($page_number < 1) {
+ $page_number = 1;
+ } //if
+
$index_path = "$CFG->dataroot/search";
$no_index = false; //optimism!
+ $results_per_page = 10;
try {
$index = new Zend_Search_Lucene($index_path, false);
if (!$site = get_site()) {
redirect("index.php");
} //if
-
+
$strsearch = "Search"; //get_string();
$strquery = "Enter your search query"; //get_string();
?>
<form name="query" method="get" action="query.php">
- <input type="text" name="query_string" length="50" value="<?php print $query_string ?>"/>
+ <input type="text" name="query_string" length="50" value="<?php print stripslashes(htmlentities($query_string)) ?>"/>
<input type="submit" value="Search"/> <a href="query.php?advanced=yes">Advanced search</a>
<a href="stats.php">Statistics</a>
</form>
print_simple_box_start('center', '50%', 'white', 10);
search_stopwatch();
- $hits = $index->find(strtolower($query_string));
-
- if (count($hits) > 0) {
- $link_function = $hits[0]->type.'_make_link';
- } //if
+ $hits = $index->find(strtolower($query_string));
+ $hit_count = count($hits);
print "<br>";
- print count($hits)." results returned for '".$query_string."'.";
- print "<br><br>";
+ print $hit_count." results returned for '".stripslashes($query_string)."'.";
+ print "<br>";
+
+ if ($hit_count > 0) {
+ if ($hit_count < $results_per_page) {
+ $page_number = 1;
+ } else if ($page_number > ceil($hit_count/$results_per_page)) {
+ $page_number = $hit_count/$results_per_page;
+ } //if
- print "<ol>";
+ $start = ($page_number - 1)*$results_per_page;
+ $end = $start + $results_per_page;
+
+ print "<ol>";
- foreach ($hits as $listing) {
- print "<li><a href='".$link_function($listing)."'>$listing->title</a><br>\n"
- ."<em>".search_shorten_url($link_function($listing), 70)."</em><br>\n"
- ."Type: ".$listing->type.", score: ".round($listing->score, 3)."<br>\n"
- ."<br></li>\n";
- } //foreach
+ for ($i = $start; $i < $end; $i++) {
+ if ($i >= $hit_count) {
+ break;
+ } //if
+
+ $listing = $hits[$i];
+
+ print "<li value='".($i+1)."'><a href='".$listing->url."'>$listing->title</a><br>\n"
+ ."<em>".search_shorten_url($listing->url, 70)."</em><br>\n"
+ ."Type: ".$listing->doctype.", score: ".round($listing->score, 3).", author: ".$listing->author."<br>\n"
+ ."<br></li>\n";
+ } //for
+
+ print "</ol>";
+ } //if
+
+ print "<div align='center'>";
+
+ if ($page_number > 1) {
+ print "<a href='query.php?query_string=$query_string&page=".($page_number-1)."'>< Back</a> ";
+ } else {
+ print "< Back ";
+ } //else
+
+ for ($i = 1; $i <= ceil($hit_count/$results_per_page); $i++) {
+ if ($page_number == $i) {
+ print "[$i] ";
+ } else {
+ print "<a href='query.php?query_string=$query_string&page=$i'>$i</a> ";
+ } //else
+ } //for
+
+ if ($page_number < ceil($hit_count/$results_per_page)) {
+ print "<a href='query.php?query_string=$query_string&page=".($page_number+1)."'>Next ></a> ";
+ } else {
+ print "Next > ";
+ } //else
- print "</ol>";
+ print "</div>";
print_simple_box_end();
} //if
$type_counts['Total'] = count_records('search_documents');
foreach($types as $type) {
- $c = count_records('search_documents', 'type', $type);
+ $c = count_records('search_documents', 'doctype', $type);
$type_counts[$type] = (int)$c;
} //foreach
} else {
--- /dev/null
+<?php
+
+ /* Used to test if modules/blocks are ready to included in the search index.
+ * Carries out some basic function/file existence tests - the search module
+ * is expected to exist, along with the db schema files and the search data
+ * directory.
+ * */
+
+ @set_time_limit(0);
+ @ob_implicit_flush(true);
+ @ob_end_flush();
+
+ require_once('../../config.php');
+ require_once("$CFG->dirroot/search/lib.php");
+
+ require_login();
+
+ if (!isadmin()) {
+ error("You need to be an admin user to use this page.", "$CFG->wwwroot/login/index.php");
+ } //if
+
+ mtrace('<pre>Server Time: '.date('r',time()));
+ mtrace("Testing global search capabilities:\n");
+
+ $phpversion = phpversion();
+
+ if (!search_check_php5()) {
+ mtrace("ERROR: PHP 5.0.0 or later required (currently using version $phpversion).");
+ exit(0);
+ } else {
+ mtrace("Success: PHP 5.0.0 or later is installed ($phpversion).\n");
+ } //else
+
+ //fix paths for testing
+ set_include_path(get_include_path().":../");
+ require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
+
+ mtrace("Checking activity modules:\n");
+
+ //the presence of the required search functions -
+ // * mod_iterator
+ // * mod_get_content_for_index
+ //are the sole basis for including a module in the index at the moment.
+
+ if ($mods = get_records_select('modules')) {
+ foreach ($mods as $mod) {
+ $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
+
+ if (file_exists($class_file)) {
+ include_once($class_file);
+
+ if (!defined('SEARCH_'.strtoupper($mod->name).'_TYPE')) {
+ mtrace("ERROR: Constant 'SEARCH_".strtoupper($mod->name)."_TYPE' is not defined in /search/lib.php");
+ continue;
+ } //if
+
+ $iter_function = $mod->name.'_iterator';
+ $index_function = $mod->name.'_get_content_for_index';
+
+ if (function_exists($index_function) && function_exists($iter_function)) {
+ if (is_array($iter_function())) {
+ $documents = $index_function(array_pop($iter_function()));
+
+ if (is_array($documents)) {
+ mtrace("Success: '$mod->name' module seems to be ready for indexing.");
+ } else {
+ mtrace("ERROR: $index_function() doesn't seem to be returning an array.");
+ } //else
+ } else {
+ mtrace("ERROR: $iter_function() doesn't seem to be returning an object array.");
+ } //else
+ } else {
+ mtrace("ERROR: $iter_function() and/or $index_function() does not exist in $class_file");
+ } //else
+ } else {
+ mtrace("Notice: $class_file does not exist, this module will not be indexed.");
+ } //else
+ } //foreach
+ } //if
+
+ //finished modules
+ mtrace("\nFinished checking activity modules.");
+
+ //now blocks...
+ //
+
+ mtrace("<br><a href='../index.php'>Back to query page</a> or <a href='../indexersplash.php'>Start indexing</a>.");
+ mtrace('</pre>');
+
+?>
\ No newline at end of file