forked from moodle/moodle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathforum_document.php
360 lines (319 loc) · 11.6 KB
/
forum_document.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<?php
/**
* Global Search Engine for Moodle
*
* @package search
* @category core
* @subpackage document_wrappers
* @author Michael Campanis (mchampan) [[email protected]], Valery Fremaux [[email protected]] > 1.8
* @contributor Tatsuva Shirai 20090530
* @date 2008/03/31
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @version Moodle 2.0
*
* document handling for forum activity module
* This file contains the mapping between a forum post and it's indexable counterpart,
*
* Functions for iterating and retrieving the necessary records are now also included
* in this file, rather than mod/forum/lib.php
*
*/
/**
* includes and requires
*/
require_once($CFG->dirroot.'/search/documents/document.php');
require_once($CFG->dirroot.'/mod/forum/lib.php');
/**
* a class for representing searchable information
*
*/
class ForumSearchDocument extends SearchDocument {
/**
* constructor
* @uses $DB;
*/
public function __construct(&$post, $forum_id, $course_id, $itemtype, $context_id) {
global $DB;
// generic information
$doc->docid = $post['id'];
$doc->documenttype = SEARCH_TYPE_FORUM;
$doc->itemtype = $itemtype;
$doc->contextid = $context_id;
$doc->title = $post['subject'];
$user = $DB->get_record('user', array('id' => $post['userid']));
$doc->author = fullname($user);
$doc->contents = $post['message'];
$doc->date = $post['created'];
$doc->url = forum_make_link($post['discussion'], $post['id']);
// module specific information
$data->forum = $forum_id;
$data->discussion = $post['discussion'];
parent::__construct($doc, $data, $course_id, $post['groupid'], $post['userid'], 'mod/'.SEARCH_TYPE_FORUM);
}
}
/**
* constructs a valid link to a chat content
* @uses $CFG
* @param int $discussion_id the discussion
* @param int $post_id the id of a single post
* @return a well formed link to forum message display
*/
function forum_make_link($discussion_id, $post_id) {
global $CFG;
return $CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion_id.'#'.$post_id;
}
/**
* search standard API
* @uses $DB;
*
*/
function forum_iterator() {
global $DB;
$forums = $DB->get_records('forum');
return $forums;
}
/**
* search standard API
* @uses $DB
* @param reference $forum a forum instance
* @return an array of searchable documents
*/
function forum_get_content_for_index(&$forum) {
global $DB;
$documents = array();
if (!$forum) return $documents;
$posts = forum_get_discussions_fast($forum->id);
mtrace("Found ".count($posts)." discussions to analyse in forum ".$forum->name);
if (!$posts) return $documents;
$coursemodule = $DB->get_field('modules', 'id', array('name' => 'forum'));
$cm = $DB->get_record('course_modules', array('course' => $forum->course, 'module' => $coursemodule, 'instance' => $forum->id));
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
foreach($posts as $aPost) {
$aPost->itemtype = 'head';
if ($aPost) {
if (!empty($aPost->message)) {
echo "*";
$documents[] = new ForumSearchDocument(get_object_vars($aPost), $forum->id, $forum->course, 'head', $context->id);
}
if ($children = forum_get_child_posts_fast($aPost->id, $forum->id)) {
foreach($children as $aChild) {
echo ".";
$aChild->itemtype = 'post';
if (strlen($aChild->message) > 0) {
$documents[] = new ForumSearchDocument(get_object_vars($aChild), $forum->id, $forum->course, 'post', $context->id);
}
}
}
}
}
mtrace("Finished discussion");
return $documents;
}
/**
* returns a single forum search document based on a forum entry id
* @uses $DB
* @param int $id an id for a single information stub
* @param string $itemtype the type of information
*/
function forum_single_document($id, $itemtype) {
global $DB;
// both known item types are posts so get them the same way
$post = $DB->get_record('forum_posts', array('id' => $id));
$discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion));
$coursemodule = $DB->get_field('modules', 'id', array('name' => 'forum'));
$cm = $DB->get_record('course_modules', array('course' => $discussion->course, 'module' => $coursemodule, 'instance' => $discussion->forum));
if ($cm){
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
$post->groupid = $discussion->groupid;
return new ForumSearchDocument(get_object_vars($post), $discussion->forum, $discussion->course, $itemtype, $context->id);
}
return null;
}
/**
* dummy delete function that aggregates id with itemtype.
* this was here for a reason, but I can't remember it at the moment.
*
*/
function forum_delete($info, $itemtype) {
$object->id = $info;
$object->itemtype = $itemtype;
return $object;
}
/**
* returns the var names needed to build a sql query for addition/deletions
*
*/
function forum_db_names() {
//[primary id], [table name], [time created field name], [time modified field name]
return array(
array('id', 'forum_posts', 'created', 'modified', 'head', 'parent = 0'),
array('id', 'forum_posts', 'created', 'modified', 'post', 'parent != 0')
);
}
/**
* reworked faster version from /mod/forum/lib.php
* @param int $forum_id a forum identifier
* @uses $CFG, $USER, $DB
* @return an array of posts
*/
function forum_get_discussions_fast($forum_id) {
global $CFG, $USER, $DB;
$timelimit='';
if (!empty($CFG->forum_enabletimedposts)) {
$courseid = $DB->get_field('forum', 'course', array('id'=>$forum_id));
if ($courseid) {
$coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
$systemcontext = get_context_instance(CONTEXT_SYSTEM);
} else {
$coursecontext = get_context_instance(CONTEXT_SYSTEM);
$systemcontext = $coursecontext;
}
if (true) {
// TODO: can not test teachers and admins here, use proper capability and enrolment test
$now = time();
$timelimit = " AND ((d.timestart = 0 OR d.timestart <= '$now') AND (d.timeend = 0 OR d.timeend > '$now')";
if (isloggedin()) {
$timelimit .= " OR d.userid = '$USER->id'";
}
$timelimit .= ')';
}
}
$query = "
SELECT
p.id,
p.subject,
p.discussion,
p.message,
p.created,
d.groupid,
p.userid,
u.firstname,
u.lastname
FROM
{forum_discussions} d
JOIN
{forum_posts} p
ON
p.discussion = d.id
JOIN
{user} u
ON
p.userid = u.id
WHERE
d.forum = ? AND
p.parent = 0
$timelimit
ORDER BY
d.timemodified DESC
";
return $DB->get_records_sql($query, array($forum_id));
}
/**
* reworked faster version from /mod/forum/lib.php
* @param int $parent the id of the first post within the discussion
* @param int $forum_id the forum identifier
* @uses $CFG, $DB
* @return an array of posts
*/
function forum_get_child_posts_fast($parent, $forum_id) {
global $CFG, $DB;
$query = "
SELECT
p.id,
p.subject,
p.discussion,
p.message,
p.created,
? AS forum,
p.userid,
d.groupid,
u.firstname,
u.lastname
FROM
{forum_discussions} d
JOIN
{forum_posts} p
ON
p.discussion = d.id
JOIN
{user} u
ON
p.userid = u.id
WHERE
p.parent = ?
ORDER BY
p.created ASC
";
return $DB->get_records_sql($query, array($forum_id, $parent));
}
/**
* this function handles the access policy to contents indexed as searchable documents. If this
* function does not exist, the search engine assumes access is allowed.
* When this point is reached, we already know that :
* - user is legitimate in the surrounding context
* - user may be guest and guest access is allowed to the module
* - the function may perform local checks within the module information logic
* @param string $path the access path to the module script code
* @param string $itemtype the information subclassing (usefull for complex modules, defaults to 'standard')
* @param int $this_id the item id within the information class denoted by itemtype. In forums, this id
* points out the individual post.
* @param object $user the user record denoting the user who searches
* @param int $group_id the current group used by the user when searching
* @uses $CFG, $USER, $DB
* @return true if access is allowed, false elsewhere
*/
function forum_check_text_access($path, $itemtype, $this_id, $user, $group_id, $context_id){
global $CFG, $USER, $DB, $SESSION;
include_once("{$CFG->dirroot}/{$path}/lib.php");
// get the forum post and all related stuff
$post = $DB->get_record('forum_posts', array('id' => $this_id));
$discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion));
$context = $DB->get_record('context', array('id' => $context_id));
$cm = $DB->get_record('course_modules', array('id' => $context->instanceid));
if (empty($cm)) return false; // Shirai 20090530 - MDL19342 - course module might have been delete
if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $context)){
if (!empty($CFG->search_access_debug)) echo "search reject : hidden forum resource ";
return false;
}
// approval check : entries should be approved for being viewed, or belongs to the user
if (($post->userid != $USER->id) && !$post->mailed && !has_capability('mod/forum:viewhiddentimeposts', $context)){
if (!empty($CFG->search_access_debug)) echo "search reject : time hidden forum item";
return false;
}
// group check : entries should be in accessible groups
if (isset($SESSION->currentgroup[$discussion->course])) {
$current_group = $SESSION->currentgroup[$discussion->course];
} else {
$current_group = groups_get_all_groups($discussion->course, $USER->id);
if (is_array($current_group)) {
$current_group = array_shift(array_keys($current_group));
$SESSION->currentgroup[$discussion->course] = $current_group;
} else {
$current_group = 0;
}
}
$course = $DB->get_record('course', array('id' => $discussion->course));
if (isset($cm->groupmode) && empty($course->groupmodeforce)) {
$groupmode = $cm->groupmode;
} else {
$groupmode = $course->groupmode;
}
if ($group_id >= 0 && ($groupmode == SEPARATEGROUPS) && ($group_id != $current_group) && !has_capability('mod/forum:viewdiscussionsfromallgroups', $context)){
if (!empty($CFG->search_access_debug)) echo "search reject : separated grouped forum item";
return false;
}
return true;
}
/**
* post processes the url for cleaner output.
* @uses $CFG
* @param string $title
*/
function forum_link_post_processing($title){
global $CFG;
if ($CFG->block_search_utf8dir){
return mb_convert_encoding($title, 'UTF-8', 'auto');
}
return mb_convert_encoding($title, 'auto', 'UTF-8');
}
?>