Search functions moved from mod/name/lib.php to search/documents/mod_document.php.
Pagination added to query page. Various small changes and amendments.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
this block, the broadest possible selection of documents is searched.
|
||||
|
||||
Author: Michael Champanis (mchampan)
|
||||
Date: 2006 06 23
|
||||
Date: 2006 06 25
|
||||
|
||||
Todo: make strings -> get_string()
|
||||
*/
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
function init() {
|
||||
$this->title = "Global Search"; //get_string()
|
||||
$this->version = 20060625;
|
||||
$this->version = 2006062500;
|
||||
} //init
|
||||
|
||||
// only one instance of this block is required
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
//basic search form
|
||||
$this->content->text =
|
||||
'<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.'"/>'
|
||||
|
||||
@@ -352,112 +352,6 @@ function wiki_get_entries(&$wiki, $byindex=NULL) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*==== Global search modifications
|
||||
* Author: Michael Champanis (mchampan)
|
||||
* Last date: 2006 06 25
|
||||
* These modifications allow wiki documents to be indexed in the new
|
||||
* search engine module - they are probably not final, and as such
|
||||
* shouldn't be used by other stuff for the time being
|
||||
**/
|
||||
|
||||
//rescued and converted from ewikimoodlelib.php
|
||||
//retrieves latest version of a page
|
||||
function wiki_get_latest_page(&$entry, $pagename, $version=0) {
|
||||
$pagename = "'".addslashes($pagename)."'";
|
||||
|
||||
if ($version > 0 and is_int($version)) {
|
||||
$version = "AND (version=$version)";
|
||||
} else {
|
||||
$version = '';
|
||||
} //else
|
||||
|
||||
$select = "(pagename=$pagename) AND wiki=".$entry->id." $version ";
|
||||
$sort = 'version DESC';
|
||||
|
||||
//change this to recordset_select, as per http://docs.moodle.org/en/Datalib_Notes
|
||||
if ($result_arr = get_records_select('wiki_pages', $select, $sort, '*', 0, 1)) {
|
||||
foreach ($result_arr as $obj) {
|
||||
$result_obj = $obj;
|
||||
} //foreach
|
||||
} //if
|
||||
|
||||
if (isset($result_obj)) {
|
||||
$result_obj->meta = @unserialize($result_obj->meta);
|
||||
return $result_obj;
|
||||
} else {
|
||||
return false;
|
||||
} //else
|
||||
} //wiki_get_latest_page
|
||||
|
||||
//fetches all pages, including old versions
|
||||
function wiki_get_pages(&$entry) {
|
||||
return get_records('wiki_pages', 'wiki', $entry->id);
|
||||
} //wiki_get_pages
|
||||
|
||||
//fetches all the latest versions of all the pages
|
||||
function wiki_get_latest_pages(&$entry) {
|
||||
//== (My)SQL for this
|
||||
/* select * from wiki_pages
|
||||
inner join
|
||||
(select wiki_pages.pagename, max(wiki_pages.version) as ver
|
||||
from wiki_pages group by pagename) as a
|
||||
on ((wiki_pages.version = a.ver) and
|
||||
(wiki_pages.pagename like a.pagename)) */
|
||||
|
||||
$pages = array();
|
||||
|
||||
//http://moodle.org/bugs/bug.php?op=show&bugid=5877&pos=0
|
||||
//if ($ids = get_records('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
|
||||
if ($rs = get_recordset('wiki_pages', 'wiki', $entry->id, '', 'distinct pagename')) {
|
||||
$ids = $rs->GetRows();
|
||||
//--
|
||||
foreach ($ids as $id) {
|
||||
$pages[] = wiki_get_latest_page($entry, $id[0]);
|
||||
} //foreach
|
||||
} else {
|
||||
return false;
|
||||
} //else
|
||||
|
||||
return $pages;
|
||||
} //wiki_get_latest_pages
|
||||
|
||||
function wiki_iterator() {
|
||||
return get_all_instances_in_courses("wiki", get_courses());
|
||||
} //wiki_search_index
|
||||
|
||||
function wiki_get_content_for_index(&$wiki) {
|
||||
$documents = array();
|
||||
|
||||
$entries = wiki_get_entries($wiki);
|
||||
foreach($entries as $entry) {
|
||||
//all pages
|
||||
//$pages = wiki_get_pages($entry);
|
||||
|
||||
//latest pages
|
||||
$pages = wiki_get_latest_pages($entry);
|
||||
$i = 0;
|
||||
|
||||
if (is_array($pages)) {
|
||||
foreach($pages as $page) {
|
||||
if (strlen($page->content) > 0) {
|
||||
$i++;
|
||||
$documents[] = new WikiSearchDocument($page, $entry->wikiid, $entry->course, $entry->groupid);
|
||||
} //if
|
||||
} //foreach
|
||||
|
||||
//print "$entry->id : $i"; print "<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
|
||||
|
||||
+35
-1
@@ -1,4 +1,38 @@
|
||||
latest
|
||||
2006/07/11
|
||||
----------
|
||||
(Warning: It took me 1900 seconds to index the forum, go make coffee
|
||||
whilst you wait.)
|
||||
|
||||
Forum search functions changed to use 'get_recordset' instead of
|
||||
'get_records', for speed reasons. This provides a significant improvement,
|
||||
but indexing is still slow - getting data from the database and Zend's
|
||||
tokenising _seem_ to be the prime suspects at the moment.
|
||||
|
||||
/search/tests/ added - index.php can be used to see which modules are
|
||||
ready to be included in the search index, and it informs you of any
|
||||
errors - should be a prerequisite for indexing.
|
||||
|
||||
Search result pagination added to query.php, will default to 20 until
|
||||
an admin page for the search module is written.
|
||||
|
||||
2006/07/07
|
||||
----------
|
||||
Search-enabling functions moved out've the mod's lib.php files and into
|
||||
/search/documents/mod_document.php - this requires the search module to
|
||||
operate without requiring modification of lib files.
|
||||
|
||||
SearchDocument base class improved, and the way module documents extend
|
||||
it. A custom-data field has been added to allow modules to add any custom
|
||||
data they wish to be stored in the index - this field is serialised into
|
||||
the index as a binary field.
|
||||
|
||||
Database field 'type' renamed to 'doctype' to match the renaming in the
|
||||
index, 'type' seems to be a reserved word in Lucene. Several index field
|
||||
names change to be more descriptive (cid -> course_id). URLs are now
|
||||
stored in the index, and don't have to be generated on the fly during
|
||||
display of query results.
|
||||
|
||||
2006/07/05
|
||||
------
|
||||
Started cleaning and standardising things.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS `prefix_search_documents` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`type` varchar(12) NOT NULL default 'none',
|
||||
`doctype` varchar(12) NOT NULL default 'none',
|
||||
`title` varchar(100) NOT NULL default '',
|
||||
`url` varchar(100) NOT NULL default '',
|
||||
`updated` timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CREATE TABLE prefix_search_documents (
|
||||
id SERIAL8 PRIMARY KEY,
|
||||
"type" varchar(12) NOT NULL DEFAULT 'none',
|
||||
doctype varchar(12) NOT NULL DEFAULT 'none',
|
||||
title varchar(100) NOT NULL default '',
|
||||
url varchar(100) NOT NULL default '',
|
||||
updated timestamp NOT NULL DEFAULT NOW(),
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
* */
|
||||
|
||||
class SearchDocument extends Zend_Search_Lucene_Document {
|
||||
public function __construct($document_type, $cid, $gid) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('type', $document_type));
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('courseid', $cid));
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('groupid', $gid));
|
||||
public function __construct(&$doc, &$data, $document_type, $course_id, $group_id) {
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('id', $doc->id));
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('title', $doc->title));
|
||||
$this->addField(Zend_Search_Lucene_Field::Text('author', $doc->author));
|
||||
$this->addField(Zend_Search_Lucene_Field::UnStored('contents', $doc->contents));
|
||||
$this->addField(Zend_Search_Lucene_Field::UnIndexed('url', $doc->url));
|
||||
|
||||
$this->addField(Zend_Search_Lucene_Field::Binary('data', serialize($data)));
|
||||
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('doctype', $document_type));
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('course_id', $course_id));
|
||||
$this->addField(Zend_Search_Lucene_Field::Keyword('group_id', $group_id));
|
||||
} //constructor
|
||||
} //SearchDocument
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
<?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
|
||||
|
||||
?>
|
||||
@@ -1,28 +1,134 @@
|
||||
<?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
|
||||
|
||||
?>
|
||||
+47
-32
@@ -1,12 +1,17 @@
|
||||
<?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
|
||||
@@ -44,8 +49,11 @@
|
||||
//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
|
||||
@@ -63,21 +71,30 @@
|
||||
} else {
|
||||
mtrace("Using $index_path as data directory.");
|
||||
} //else
|
||||
|
||||
|
||||
$index = new Zend_Search_Lucene($index_path, true);
|
||||
|
||||
//create the database tables
|
||||
$tables = $db->MetaTables();
|
||||
|
||||
if (in_array($CFG->prefix.'search_documents', $tables)) {
|
||||
delete_records('search_documents');
|
||||
//delete_records('search_documents');
|
||||
//temporary measure - db doesn't have update scripts and I realised that cvs 1.1 db
|
||||
//is incompatible with cvs 1.2! Must fix ASAP.
|
||||
execute_sql('drop table '.$CFG->prefix.'search_documents', false);
|
||||
|
||||
ob_start(); //turn output buffering on - to hide modify_database() output
|
||||
modify_database($index_db_file, '', false);
|
||||
ob_end_clean(); //chuck the buffer and resume normal operation
|
||||
} else {
|
||||
ob_start(); //turn output buffering on - to hide modify_database() output
|
||||
modify_database($index_db_file, '', false);
|
||||
ob_end_clean(); //chuck the buffer and resume normal operation
|
||||
} //else
|
||||
|
||||
mtrace('Starting activity modules');
|
||||
|
||||
//begin timer
|
||||
search_stopwatch();
|
||||
mtrace("Starting activity modules\n");
|
||||
|
||||
//the presence of the required search functions -
|
||||
// * mod_iterator
|
||||
@@ -86,23 +103,18 @@
|
||||
|
||||
if ($mods = get_records_select('modules' /*'index this module?' where statement*/)) {
|
||||
foreach ($mods as $mod) {
|
||||
$libfile = "$CFG->dirroot/mod/$mod->name/lib.php";
|
||||
$class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
|
||||
|
||||
if (file_exists($libfile)) {
|
||||
include_once($libfile);
|
||||
if (file_exists($class_file)) {
|
||||
include_once($class_file);
|
||||
|
||||
$iter_function = $mod->name.'_iterator';
|
||||
$index_function = $mod->name.'_get_content_for_index';
|
||||
|
||||
//specific module search document class
|
||||
$class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
|
||||
|
||||
|
||||
$counter = 0;
|
||||
$doc = new stdClass;
|
||||
|
||||
if (file_exists($class_file) && function_exists($index_function) && function_exists($iter_function)) {
|
||||
include_once($class_file);
|
||||
|
||||
if (function_exists($index_function) && function_exists($iter_function)) {
|
||||
mtrace("Processing module function $index_function ...");
|
||||
|
||||
foreach ($iter_function() as $i) {
|
||||
@@ -113,30 +125,30 @@
|
||||
foreach($documents as $document) {
|
||||
$counter++;
|
||||
|
||||
//data object for db
|
||||
$doc->type = $document->type;
|
||||
$doc->title = search_escape_string($document->title);
|
||||
$doc->update = time();
|
||||
$doc->url = 'none';
|
||||
$doc->courseid = $document->courseid;
|
||||
$doc->groupid = $document->groupid;
|
||||
//object to insert into db
|
||||
$doc->doctype = $document->doctype;
|
||||
$doc->title = search_escape_string($document->title);
|
||||
$doc->url = search_escape_string($document->url);
|
||||
$doc->update = time();
|
||||
$doc->courseid = $document->course_id;
|
||||
$doc->groupid = $document->group_id;
|
||||
|
||||
//insert summary into db
|
||||
$id = insert_record('search_documents', $doc);
|
||||
|
||||
//synchronise db with index
|
||||
$document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $id));
|
||||
$document->addField(Zend_Search_Lucene_Field::Keyword('db_id', $id));
|
||||
|
||||
//add document to index
|
||||
$index->addDocument($document);
|
||||
|
||||
//commit every x new documents, and print a status message
|
||||
if (($counter%200) == 0) {
|
||||
if (($counter%2000) == 0) {
|
||||
$index->commit();
|
||||
mtrace(".. $counter");
|
||||
mtrace(".. $counter");
|
||||
} //if
|
||||
} //foreach
|
||||
|
||||
|
||||
//end transaction
|
||||
|
||||
} //foreach
|
||||
@@ -145,7 +157,7 @@
|
||||
$index->commit();
|
||||
|
||||
mtrace("-- $counter documents indexed");
|
||||
mtrace('done.');
|
||||
mtrace("done.\n");
|
||||
} //if
|
||||
} //if
|
||||
} //foreach
|
||||
@@ -160,5 +172,8 @@
|
||||
|
||||
mtrace(".<br><a href='index.php'>Back to query page</a>.");
|
||||
mtrace('</pre>');
|
||||
|
||||
//finished, turn busy flag off
|
||||
set_config("search_indexer_busy", 0);
|
||||
|
||||
?>
|
||||
@@ -42,7 +42,12 @@
|
||||
."started and cancelled an indexing session. Follow the link if you are sure that\n"
|
||||
."you want to continue indexing - this will replace any existing index data (no\n"
|
||||
."Moodle data is affected).\n"
|
||||
."\n"
|
||||
."\n"
|
||||
."You are encouraged to use the 'Test indexing' script before continuing onto\n"
|
||||
."indexing - this will check if the modules are set up correctly. Please correct\n"
|
||||
."any errors before proceeding.\n"
|
||||
."\n"
|
||||
."<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 {
|
||||
|
||||
+2
-1
@@ -6,10 +6,11 @@
|
||||
//document types that can be searched
|
||||
define('SEARCH_NO_TYPE', 'none');
|
||||
define('SEARCH_WIKI_TYPE', 'wiki');
|
||||
define('SEARCH_FORUM_TYPE', 'forum');
|
||||
|
||||
//returns all the document type constants
|
||||
function search_get_document_types() {
|
||||
$r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE);
|
||||
$r = Array(SEARCH_WIKI_TYPE, SEARCH_NO_TYPE, SEARCH_FORUM_TYPE);
|
||||
return $r;
|
||||
} //search_get_document_types
|
||||
|
||||
|
||||
+85
-19
@@ -1,16 +1,44 @@
|
||||
<?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);
|
||||
@@ -23,7 +51,7 @@
|
||||
if (!$site = get_site()) {
|
||||
redirect("index.php");
|
||||
} //if
|
||||
|
||||
|
||||
$strsearch = "Search"; //get_string();
|
||||
$strquery = "Enter your search query"; //get_string();
|
||||
|
||||
@@ -45,7 +73,7 @@
|
||||
?>
|
||||
|
||||
<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>
|
||||
@@ -77,27 +105,65 @@ if ($no_index and isadmin()) {
|
||||
print_simple_box_start('center', '50%', 'white', 10);
|
||||
|
||||
search_stopwatch();
|
||||
$hits = $index->find(strtolower($query_string));
|
||||
|
||||
if (count($hits) > 0) {
|
||||
$link_function = $hits[0]->type.'_make_link';
|
||||
} //if
|
||||
$hits = $index->find(strtolower($query_string));
|
||||
$hit_count = count($hits);
|
||||
|
||||
print "<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;
|
||||
|
||||
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
|
||||
print "<ol>";
|
||||
|
||||
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 "</ol>";
|
||||
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 "</div>";
|
||||
|
||||
print_simple_box_end();
|
||||
} //if
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
$type_counts['Total'] = count_records('search_documents');
|
||||
|
||||
foreach($types as $type) {
|
||||
$c = count_records('search_documents', 'type', $type);
|
||||
$c = count_records('search_documents', 'doctype', $type);
|
||||
$type_counts[$type] = (int)$c;
|
||||
} //foreach
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?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>');
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user