3 * Global Search Engine for Moodle
4 * Michael Champanis (mchampan) [cynnical@gmail.com]
5 * review 1.8+ : Valery Fremaux [valery.fremaux@club-internet.fr]
8 * document handling for forum activity module
9 * This file contains the mapping between a forum post and it's indexable counterpart,
11 * Functions for iterating and retrieving the necessary records are now also included
12 * in this file, rather than mod/forum/lib.php
14 /* see wiki_document.php for descriptions */
16 require_once("$CFG->dirroot/search/documents/document.php");
17 require_once("$CFG->dirroot/mod/forum/lib.php");
20 * a class for representing searchable information
23 class ForumSearchDocument
extends SearchDocument
{
29 public function __construct(&$post, $forum_id, $course_id, $itemtype, $context_id) {
30 // generic information
31 $doc->docid
= $post['id'];
32 $doc->documenttype
= SEARCH_TYPE_FORUM
;
33 $doc->itemtype
= $itemtype;
34 $doc->contextid
= $context_id;
36 $doc->title
= $post['subject'];
37 $doc->author
= $post['firstname']." ".$post['lastname'];
38 $doc->contents
= $post['message'];
39 $doc->date
= $post['created'];
40 $doc->url
= forum_make_link($post['discussion'], $post['id']);
42 // module specific information
43 $data->forum
= $forum_id;
44 $data->discussion
= $post['discussion'];
46 parent
::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], PATH_FOR_SEARCH_TYPE_FORUM
);
48 } //ForumSearchDocument
51 * constructs a valid link to a chat content
52 * @param discussion_id the discussion
53 * @param post_id the id of a single post
54 * @return a well formed link to forum message display
56 function forum_make_link($discussion_id, $post_id) {
59 return $CFG->wwwroot
.'/mod/forum/discuss.php?d='.$discussion_id.'#'.$post_id;
66 function forum_iterator() {
67 $forums = get_records('forum');
73 * @param forum a forum instance
74 * @return an array of searchable documents
76 function forum_get_content_for_index(&$forum) {
79 if (!$forum) return $documents;
81 $posts = forum_get_discussions_fast($forum->id
);
82 if (!$posts) return $documents;
84 $coursemodule = get_field('modules', 'id', 'name', 'forum');
85 $cm = get_record('course_modules', 'course', $forum->course
, 'module', $coursemodule, 'instance', $forum->id
);
86 $context = get_context_instance(CONTEXT_MODULE
, $cm->id
);
88 foreach($posts as $aPost) {
89 $aPost->itemtype
= 'head';
91 if (strlen($aPost->message
) > 0) {
92 $documents[] = new ForumSearchDocument(get_object_vars($aPost), $forum->id
, $forum->course
, 'head', $context->id
);
94 if ($children = forum_get_child_posts_fast($aPost->id
, $forum->id
)) {
95 foreach($children as $aChild) {
96 $aChild->itemtype
= 'post';
97 if (strlen($aChild->message
) > 0) {
98 $documents[] = new ForumSearchDocument(get_object_vars($child), $forum->id
, $forum->course
, 'post', $context->id
);
105 } //forum_get_content_for_index
108 * returns a single forum search document based on a forum entry id
109 * @param id an id for a single information stub
110 * @param itemtype the type of information
112 function forum_single_document($id, $itemtype) {
114 // both known item types are posts so get them the same way
115 $post = get_record('forum_posts', 'id', $id);
116 $discussion = get_record('forum_discussions', 'id', $post->discussion
);
117 $coursemodule = get_field('modules', 'id', 'name', 'forum');
118 $cm = get_record('course_modules', 'course', $discussion->course
, 'module', $coursemodule, 'instance', $discussion->forum
);
119 $context = get_context_instance(CONTEXT_MODULE
, $cm->id
);
120 return new ForumSearchDocument(get_object_vars($post), $discussion->forum
, $discussion->course
, $itemtype, $context->id
);
121 } //forum_single_document
124 * dummy delete function that aggregates id with itemtype.
125 * this was here for a reason, but I can't remember it at the moment.
128 function forum_delete($info, $itemtype) {
130 $object->itemtype
= $itemtype;
135 * returns the var names needed to build a sql query for addition/deletions
138 function forum_db_names() {
139 //[primary id], [table name], [time created field name], [time modified field name]
141 array('id', 'forum_posts', 'created', 'modified', 'head', 'parent = 0'),
142 array('id', 'forum_posts', 'created', 'modified', 'post', 'parent != 0')
147 * reworked faster version from /mod/forum/lib.php
148 * @param forum_id a forum identifier
149 * @return an array of posts
151 function forum_get_discussions_fast($forum_id) {
155 if (!empty($CFG->forum_enabletimedposts
)) {
156 if (!((isadmin() and !empty($CFG->admineditalways
)) ||
isteacher(get_field('forum', 'course', 'id', $forum_id)))) {
158 $timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')";
159 if (!empty($USER->id
)) {
160 $timelimit .= " OR d.userid = '$USER->id'";
178 {$CFG->prefix}forum_discussions d
180 {$CFG->prefix}forum_posts p
188 d.forum = '{$forum_id}' AND
194 return get_records_sql($query);
195 } //forum_get_discussions_fast
198 * reworked faster version from /mod/forum/lib.php
199 * @param parent the id of the first post within the discussion
200 * @param forum_id the forum identifier
201 * @return an array of posts
203 function forum_get_child_posts_fast($parent, $forum_id) {
213 {$forum_id} AS forum,
218 {$CFG->prefix}forum_posts p
224 p.parent = '{$parent}'
228 return get_records_sql($query);
229 } //forum_get_child_posts_fast
232 * this function handles the access policy to contents indexed as searchable documents. If this
233 * function does not exist, the search engine assumes access is allowed.
234 * When this point is reached, we already know that :
235 * - user is legitimate in the surrounding context
236 * - user may be guest and guest access is allowed to the module
237 * - the function may perform local checks within the module information logic
238 * @param path the access path to the module script code
239 * @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
240 * @param this_id the item id within the information class denoted by itemtype. In forums, this id
241 * points out the individual post.
242 * @param user the user record denoting the user who searches
243 * @param group_id the current group used by the user when searching
244 * @return true if access is allowed, false elsewhere
246 function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id){
249 include_once("{$CFG->dirroot}/{$path}/lib.php");
251 // get the glossary object and all related stuff
252 $post = get_record('forum_posts', 'id', $this_id);
253 $dicussion = get_record('forum_discussion', 'id', $post->discussion
);
254 $course = get_record('course', 'id', $discussion->course
);
255 $context_module = get_record('context', 'id', $context_id);
256 $cm = get_record('course_modules', 'id', $context_module->instanceid
);
257 if (!$cm->visible
and !has_capability('moodle/course:viewhiddenactivities', $context_module)) return false;
259 // approval check : entries should be approved for being viewed, or belongs to the user
260 if (!$post->mailed
&& !has_capability('mod/forum:viewhiddentimeposts')) return false;
262 // group check : entries should be in accessible groups
263 $current_group = get_current_group($course->id
);
264 if ((groupmode($course, $cm) == SEPARATEGROUPS
) && ($group_id != $current_group) && !has_capability('mod/forum:viewdiscussionsfromallgroups')) return false;
267 } //forum_check_text_access