weekly release 2.3dev
[moodle.git] / mod / forum / rsslib.php
CommitLineData
1adbd2c3 1<?php
8adcb49f 2
8f685009
SH
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
fcce139a
AD
19* This file adds support to rss feeds generation
20*
21* @package mod-forum
22* @copyright 2001 Eloy Lafuente (stronk7) http://contiento.com
23* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24*/
25
26/**
27 * Returns the path to the cached rss feed contents. Creates/updates the cache if necessary.
28 * @global object $CFG
29 * @global object $DB
30 * @param object $context the context
31 * @param int $forumid the ID of the forum
fcce139a
AD
32 * @param array $args the arguments received in the url
33 * @return string the full path to the cached RSS feed directory. Null if there is a problem.
8f685009 34 */
274f9840 35function forum_rss_get_feed($context, $args) {
fcce139a 36 global $CFG, $DB;
8f685009 37
fcce139a 38 $status = true;
8adcb49f 39
fcce139a
AD
40 //are RSS feeds enabled?
41 if (empty($CFG->forum_enablerssfeeds)) {
42 debugging('DISABLED (module configuration)');
43 return null;
44 }
8adcb49f 45
e65ce4c1 46 $forumid = clean_param($args[3], PARAM_INT);
4df53223
AD
47 $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST);
48 if ($cm) {
49 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
50
51 //context id from db should match the submitted one
3ad3f248 52 if ($context->id != $modcontext->id || !has_capability('mod/forum:viewdiscussion', $modcontext)) {
53 return null;
4df53223
AD
54 }
55 }
56
fcce139a 57 $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
43b92251 58 if (!rss_enabled_for_mod('forum', $forum)) {
fcce139a 59 return null;
8adcb49f 60 }
61
fcce139a
AD
62 //the sql that will retreive the data for the feed and be hashed to get the cache filename
63 $sql = forum_rss_get_sql($forum, $cm);
83da3d28 64
fcce139a
AD
65 //hash the sql to get the cache file name
66 $filename = rss_get_file_name($forum, $sql);
43b92251 67 $cachedfilepath = rss_get_file_full_name('mod_forum', $filename);
fcce139a
AD
68
69 //Is the cache out of date?
70 $cachedfilelastmodified = 0;
71 if (file_exists($cachedfilepath)) {
72 $cachedfilelastmodified = filemtime($cachedfilepath);
73 }
da8ae44e
AD
74 //if the cache is more than 60 seconds old and there's new stuff
75 $dontrecheckcutoff = time()-60;
76 if ( $dontrecheckcutoff > $cachedfilelastmodified && forum_rss_newstuff($forum, $cm, $cachedfilelastmodified)) {
fcce139a
AD
77 //need to regenerate the cached version
78 $result = forum_rss_feed_contents($forum, $sql);
79 if (!empty($result)) {
43b92251 80 $status = rss_save_file('mod_forum',$filename,$result);
83da3d28 81 }
82 }
83
fcce139a
AD
84 //return the path to the cached version
85 return $cachedfilepath;
86}
83da3d28 87
fcce139a
AD
88/**
89 * Given a forum object, deletes all cached RSS files associated with it.
90 *
91 * @param object $forum
92 * @return void
93 */
94function forum_rss_delete_file($forum) {
43b92251 95 rss_delete_file('mod_forum', $forum);
fcce139a
AD
96}
97
98///////////////////////////////////////////////////////
99//Utility functions
100
101/**
102 * If there is new stuff in the forum since $time this returns true
103 * Otherwise it returns false.
104 *
105 * @param object $forum the forum object
106 * @param object $cm
107 * @param int $time timestamp
108 * @return bool
109 */
110function forum_rss_newstuff($forum, $cm, $time) {
111 global $DB;
112
113 $sql = forum_rss_get_sql($forum, $cm, $time);
114
115 $recs = $DB->get_records_sql($sql, null, 0, 1);//limit of 1. If we get even 1 back we have new stuff
116 return ($recs && !empty($recs));
117}
118
119function forum_rss_get_sql($forum, $cm, $time=0) {
120 $sql = null;
121
122 if (!empty($forum->rsstype)) {
123 if ($forum->rsstype == 1) { //Discussion RSS
124 $sql = forum_rss_feed_discussions_sql($forum, $cm, $time);
125 } else { //Post RSS
126 $sql = forum_rss_feed_posts_sql($forum, $cm, $time);
6069e206 127 }
6069e206 128 }
129
fcce139a
AD
130 return $sql;
131}
8f0cd6ef 132
fcce139a
AD
133function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) {
134 global $CFG, $DB, $USER;
135
136 $timelimit = '';
137
138 $modcontext = null;
139
140 $now = round(time(), -2);
141 $params = array($cm->instance);
142
143 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
144
145 if (!empty($CFG->forum_enabletimedposts)) { /// Users must fulfill timed posts
146 if (!has_capability('mod/forum:viewhiddentimedposts', $modcontext)) {
147 $timelimit = " AND ((d.timestart <= :now1 AND (d.timeend = 0 OR d.timeend > :now2))";
148 $params['now1'] = $now;
149 $params['now2'] = $now;
150 if (isloggedin()) {
151 $timelimit .= " OR d.userid = :userid";
152 $params['userid'] = $USER->id;
8adcb49f 153 }
fcce139a 154 $timelimit .= ")";
8adcb49f 155 }
8adcb49f 156 }
157
fcce139a
AD
158 //do we only want new posts?
159 if ($newsince) {
160 $newsince = " AND p.modified > '$newsince'";
161 } else {
162 $newsince = '';
163 }
8adcb49f 164
fcce139a
AD
165 //get group enforcing SQL
166 $groupmode = groups_get_activity_groupmode($cm);
167 $currentgroup = groups_get_activity_group($cm);
168 $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
8adcb49f 169
fcce139a
AD
170 if ($groupmode && $currentgroup) {
171 $params['groupid'] = $currentgroup;
172 }
8adcb49f 173
fcce139a
AD
174 $forumsort = "d.timemodified DESC";
175 $postdata = "p.id, p.subject, p.created as postcreated, p.modified, p.discussion, p.userid, p.message as postmessage, p.messageformat AS postformat, p.messagetrust AS posttrust";
176
177 $sql = "SELECT $postdata, d.id as discussionid, d.name as discussionname, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend,
178 u.firstname as userfirstname, u.lastname as userlastname, u.email, u.picture, u.imagealt
179 FROM {forum_discussions} d
180 JOIN {forum_posts} p ON p.discussion = d.id
181 JOIN {user} u ON p.userid = u.id
182 WHERE d.forum = {$forum->id} AND p.parent = 0
183 $timelimit $groupselect $newsince
184 ORDER BY $forumsort";
185 return $sql;
186}
187
188function forum_rss_feed_posts_sql($forum, $cm, $newsince=0) {
189 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
46d39cf3 190
fcce139a
AD
191 //get group enforcement SQL
192 $groupmode = groups_get_activity_groupmode($cm);
193 $currentgroup = groups_get_activity_group($cm);
194
195 $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
196
197 if ($groupmode && $currentgroup) {
198 $params['groupid'] = $currentgroup;
199 }
6069e206 200
fcce139a
AD
201 //do we only want new posts?
202 if ($newsince) {
203 $newsince = " AND p.modified > '$newsince'";
204 } else {
205 $newsince = '';
206 }
ec41cb3c 207
fcce139a
AD
208 $sql = "SELECT p.id AS postid,
209 d.id AS discussionid,
210 d.name AS discussionname,
211 u.id AS userid,
212 u.firstname AS userfirstname,
213 u.lastname AS userlastname,
214 p.subject AS postsubject,
215 p.message AS postmessage,
216 p.created AS postcreated,
217 p.messageformat AS postformat,
218 p.messagetrust AS posttrust
219 FROM {forum_discussions} d,
220 {forum_posts} p,
221 {user} u
222 WHERE d.forum = {$forum->id} AND
223 p.discussion = d.id AND
224 u.id = p.userid $newsince
225 $groupselect
226 ORDER BY p.created desc";
227
228 return $sql;
229}
230
231function forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext=null) {
232 $groupselect = '';
233
234 if ($groupmode) {
235 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $modcontext)) {
236 if ($currentgroup) {
237 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
238 $params['groupid'] = $currentgroup;
239 }
240 } else {
241 //seprate groups without access all
242 if ($currentgroup) {
243 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
244 $params['groupid'] = $currentgroup;
245 } else {
246 $groupselect = "AND d.groupid = -1";
8adcb49f 247 }
248 }
8adcb49f 249 }
8f0cd6ef 250
fcce139a
AD
251 return $groupselect;
252}
8adcb49f 253
8adcb49f 254
46d39cf3 255
8adcb49f 256
fcce139a
AD
257/**
258 * This function return the XML rss contents about the forum
259 * It returns false if something is wrong
260 *
261 * @param object $forum
262 * @param bool
263 */
264function forum_rss_feed_contents($forum, $sql) {
265 global $CFG, $DB;
6069e206 266
fcce139a
AD
267 $status = true;
268
269 $params = array();
270 //$params['forumid'] = $forum->id;
271 $recs = $DB->get_recordset_sql($sql, $params, 0, $forum->rssarticles);
272
273 //set a flag. Are we displaying discussions or posts?
274 $isdiscussion = true;
275 if (!empty($forum->rsstype) && $forum->rsstype!=1) {
cc771939 276 $isdiscussion = false;
fcce139a 277 }
318f2100 278
39790bd8 279 $formatoptions = new stdClass();
fcce139a
AD
280 $items = array();
281 foreach ($recs as $rec) {
39790bd8
PS
282 $item = new stdClass();
283 $user = new stdClass();
cc771939
AD
284 if ($isdiscussion && !empty($rec->discussionname)) {
285 $item->title = format_string($rec->discussionname);
286 } else if (!empty($rec->postsubject)) {
7c810d07
AD
287 $item->title = format_string($rec->postsubject);
288 } else {
cc771939 289 //we should have an item title by now but if we dont somehow then substitute something somewhat meaningful
7c810d07
AD
290 $item->title = format_string($forum->name.' '.userdate($rec->postcreated,get_string('strftimedatetimeshort', 'langconfig')));
291 }
fcce139a
AD
292 $user->firstname = $rec->userfirstname;
293 $user->lastname = $rec->userlastname;
294 $item->author = fullname($user);
295 $item->pubdate = $rec->postcreated;
296 if ($isdiscussion) {
297 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid;
298 } else {
8f0cd6ef 299 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid;
fcce139a 300 }
410a24c0 301
fcce139a
AD
302 $formatoptions->trusted = $rec->posttrust;
303 $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course);
410a24c0 304
fcce139a
AD
305 //TODO: implement post attachment handling
306 /*if (!$isdiscussion) {
318f2100 307 $post_file_area_name = str_replace('//', '/', "$forum->course/$CFG->moddata/forum/$forum->id/$rec->postid");
410a24c0 308 $post_files = get_directory_list("$CFG->dataroot/$post_file_area_name");
4e445355 309
310 if (!empty($post_files)) {
410a24c0 311 $item->attachments = array();
410a24c0 312 }
fcce139a 313 }*/
46d39cf3 314
fcce139a
AD
315 $items[] = $item;
316 }
317 $recs->close();
410a24c0 318
fcce139a
AD
319
320 if (!empty($items)) {
321 //First the RSS header
322 $header = rss_standard_header(strip_tags(format_string($forum->name,true)),
323 $CFG->wwwroot."/mod/forum/view.php?f=".$forum->id,
324 format_string($forum->intro,true)); // TODO: fix format
325 //Now all the rss items
326 if (!empty($header)) {
327 $articles = rss_add_items($items);
328 }
329 //Now the RSS footer
330 if (!empty($header) && !empty($articles)) {
331 $footer = rss_standard_footer();
8adcb49f 332 }
fcce139a
AD
333 //Now, if everything is ok, concatenate it
334 if (!empty($header) && !empty($articles) && !empty($footer)) {
335 $status = $header.$articles.$footer;
336 } else {
337 $status = false;
338 }
339 } else {
340 $status = false;
341 }
342
343 return $status;
344}