Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / search / documents / forum_document.php
blob3cbe2e108a3476dc4375fd6864ee9dac7041a416
1 <?php
2 /**
3 * Global Search Engine for Moodle
5 * @package search
6 * @category core
7 * @subpackage document_wrappers
8 * @author Michael Campanis (mchampan) [cynnical@gmail.com], Valery Fremaux [valery.fremaux@club-internet.fr] > 1.8
9 * @date 2008/03/31
10 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
12 * document handling for forum activity module
13 * This file contains the mapping between a forum post and it's indexable counterpart,
15 * Functions for iterating and retrieving the necessary records are now also included
16 * in this file, rather than mod/forum/lib.php
20 /**
21 * includes and requires
23 require_once("$CFG->dirroot/search/documents/document.php");
24 require_once("$CFG->dirroot/mod/forum/lib.php");
26 /**
27 * a class for representing searchable information
30 class ForumSearchDocument extends SearchDocument {
32 /**
33 * constructor
35 public function __construct(&$post, $forum_id, $course_id, $itemtype, $context_id) {
36 // generic information
37 $doc->docid = $post['id'];
38 $doc->documenttype = SEARCH_TYPE_FORUM;
39 $doc->itemtype = $itemtype;
40 $doc->contextid = $context_id;
42 $doc->title = $post['subject'];
44 $user = get_record('user', 'id', $post['userid']);
45 $doc->author = fullname($user);
46 $doc->contents = $post['message'];
47 $doc->date = $post['created'];
48 $doc->url = forum_make_link($post['discussion'], $post['id']);
50 // module specific information
51 $data->forum = $forum_id;
52 $data->discussion = $post['discussion'];
54 parent::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], PATH_FOR_SEARCH_TYPE_FORUM);
58 /**
59 * constructs a valid link to a chat content
60 * @param discussion_id the discussion
61 * @param post_id the id of a single post
62 * @return a well formed link to forum message display
64 function forum_make_link($discussion_id, $post_id) {
65 global $CFG;
67 return $CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion_id.'#'.$post_id;
70 /**
71 * search standard API
74 function forum_iterator() {
75 $forums = get_records('forum');
76 return $forums;
79 /**
80 * search standard API
81 * @param forum a forum instance
82 * @return an array of searchable documents
84 function forum_get_content_for_index(&$forum) {
86 $documents = array();
87 if (!$forum) return $documents;
89 $posts = forum_get_discussions_fast($forum->id);
90 if (!$posts) return $documents;
92 $coursemodule = get_field('modules', 'id', 'name', 'forum');
93 $cm = get_record('course_modules', 'course', $forum->course, 'module', $coursemodule, 'instance', $forum->id);
94 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
96 foreach($posts as $aPost) {
97 $aPost->itemtype = 'head';
98 if ($aPost) {
99 if (strlen($aPost->message) > 0) {
100 $documents[] = new ForumSearchDocument(get_object_vars($aPost), $forum->id, $forum->course, 'head', $context->id);
102 if ($children = forum_get_child_posts_fast($aPost->id, $forum->id)) {
103 foreach($children as $aChild) {
104 $aChild->itemtype = 'post';
105 if (strlen($aChild->message) > 0) {
106 $documents[] = new ForumSearchDocument(get_object_vars($aChild), $forum->id, $forum->course, 'post', $context->id);
112 return $documents;
116 * returns a single forum search document based on a forum entry id
117 * @param id an id for a single information stub
118 * @param itemtype the type of information
120 function forum_single_document($id, $itemtype) {
122 // both known item types are posts so get them the same way
123 $post = get_record('forum_posts', 'id', $id);
124 $discussion = get_record('forum_discussions', 'id', $post->discussion);
125 $coursemodule = get_field('modules', 'id', 'name', 'forum');
126 $cm = get_record('course_modules', 'course', $discussion->course, 'module', $coursemodule, 'instance', $discussion->forum);
127 if ($cm){
128 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
129 $post->groupid = $discussion->groupid;
130 return new ForumSearchDocument(get_object_vars($post), $discussion->forum, $discussion->course, $itemtype, $context->id);
132 return null;
136 * dummy delete function that aggregates id with itemtype.
137 * this was here for a reason, but I can't remember it at the moment.
140 function forum_delete($info, $itemtype) {
141 $object->id = $info;
142 $object->itemtype = $itemtype;
143 return $object;
147 * returns the var names needed to build a sql query for addition/deletions
150 function forum_db_names() {
151 //[primary id], [table name], [time created field name], [time modified field name]
152 return array(
153 array('id', 'forum_posts', 'created', 'modified', 'head', 'parent = 0'),
154 array('id', 'forum_posts', 'created', 'modified', 'post', 'parent != 0')
159 * reworked faster version from /mod/forum/lib.php
160 * @param forum_id a forum identifier
161 * @uses CFG, USER
162 * @return an array of posts
164 function forum_get_discussions_fast($forum_id) {
165 global $CFG, $USER;
167 $timelimit='';
168 if (!empty($CFG->forum_enabletimedposts)) {
169 if (!((isadmin() and !empty($CFG->admineditalways)) || isteacher(get_field('forum', 'course', 'id', $forum_id)))) {
170 $now = time();
171 $timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')";
172 if (!empty($USER->id)) {
173 $timelimit .= " OR d.userid = '$USER->id'";
175 $timelimit .= ')';
179 $query = "
180 SELECT
181 p.id,
182 p.subject,
183 p.discussion,
184 p.message,
185 p.created,
186 d.groupid,
187 p.userid,
188 u.firstname,
189 u.lastname
190 FROM
191 {$CFG->prefix}forum_discussions d
192 JOIN
193 {$CFG->prefix}forum_posts p
195 p.discussion = d.id
196 JOIN
197 {$CFG->prefix}user u
199 p.userid = u.id
200 WHERE
201 d.forum = '{$forum_id}' AND
202 p.parent = 0
203 $timelimit
204 ORDER BY
205 d.timemodified DESC
207 return get_records_sql($query);
211 * reworked faster version from /mod/forum/lib.php
212 * @param parent the id of the first post within the discussion
213 * @param forum_id the forum identifier
214 * @uses CFG
215 * @return an array of posts
217 function forum_get_child_posts_fast($parent, $forum_id) {
218 global $CFG;
220 $query = "
221 SELECT
222 p.id,
223 p.subject,
224 p.discussion,
225 p.message,
226 p.created,
227 {$forum_id} AS forum,
228 p.userid,
229 d.groupid,
230 u.firstname,
231 u.lastname
232 FROM
233 {$CFG->prefix}forum_discussions d
234 JOIN
235 {$CFG->prefix}forum_posts p
237 p.discussion = d.id
238 JOIN
239 {$CFG->prefix}user u
241 p.userid = u.id
242 WHERE
243 p.parent = '{$parent}'
244 ORDER BY
245 p.created ASC
247 return get_records_sql($query);
251 * this function handles the access policy to contents indexed as searchable documents. If this
252 * function does not exist, the search engine assumes access is allowed.
253 * When this point is reached, we already know that :
254 * - user is legitimate in the surrounding context
255 * - user may be guest and guest access is allowed to the module
256 * - the function may perform local checks within the module information logic
257 * @param path the access path to the module script code
258 * @param itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
259 * @param this_id the item id within the information class denoted by itemtype. In forums, this id
260 * points out the individual post.
261 * @param user the user record denoting the user who searches
262 * @param group_id the current group used by the user when searching
263 * @uses CFG, USER
264 * @return true if access is allowed, false elsewhere
266 function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
267 global $CFG, $USER;
269 include_once("{$CFG->dirroot}/{$path}/lib.php");
271 // get the forum post and all related stuff
272 $post = get_record('forum_posts', 'id', $this_id);
273 $discussion = get_record('forum_discussions', 'id', $post->discussion);
274 $context = get_record('context', 'id', $context_id);
275 $cm = get_record('course_modules', 'id', $context->instanceid);
276 // $cm = get_coursemodule_from_instance('forum', $discussion->forum, $discussion->course);
277 // $context = get_context_instance(CONTEXT_MODULE, $cm->id);
278 if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $context)){
279 if (!empty($CFG->search_access_debug)) echo "search reject : hidden forum resource ";
280 return false;
283 // approval check : entries should be approved for being viewed, or belongs to the user
284 if (($post->userid != $USER->id) && !$post->mailed && !has_capability('mod/forum:viewhiddentimeposts', $context)){
285 if (!empty($CFG->search_access_debug)) echo "search reject : time hidden forum item";
286 return false;
289 // group check : entries should be in accessible groups
290 $current_group = get_current_group($discussion->course);
291 $course = get_record('course', 'id', $discussion->course);
292 if ($group_id >= 0 && (groupmode($course, $cm) == SEPARATEGROUPS) && ($group_id != $current_group) && !has_capability('mod/forum:viewdiscussionsfromallgroups', $context)){
293 if (!empty($CFG->search_access_debug)) echo "search reject : separated grouped forum item";
294 return false;
297 return true;
301 * post processes the url for cleaner output.
302 * @param string $title
304 function forum_link_post_processing($title){
305 return mb_convert_encoding($title, 'UTF-8', 'auto');