3 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
19 * This file adds support to rss feeds generation
22 * @copyright 2001 Eloy Lafuente (stronk7) http://contiento.com
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 * Returns the path to the cached rss feed contents. Creates/updates the cache if necessary.
30 * @param object $context the context
31 * @param int $forumid the ID of the forum
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.
35 function forum_rss_get_feed($context, $args) {
40 //are RSS feeds enabled?
41 if (empty($CFG->forum_enablerssfeeds)) {
42 debugging('DISABLED (module configuration)');
48 $uservalidated = false;
50 $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST);
52 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
54 //context id from db should match the submitted one
55 if ($context->id==$modcontext->id && has_capability('mod/forum:viewdiscussion', $modcontext)) {
56 $uservalidated = true;
60 if (!$uservalidated) {
64 $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
66 if (!rss_enabled('forum', $forum)) {
70 //the sql that will retreive the data for the feed and be hashed to get the cache filename
71 $sql = forum_rss_get_sql($forum, $cm);
73 //hash the sql to get the cache file name
74 $filename = rss_get_file_name($forum, $sql);
75 $cachedfilepath = rss_get_file_full_name('forum', $filename);
77 //Is the cache out of date?
78 $cachedfilelastmodified = 0;
79 if (file_exists($cachedfilepath)) {
80 $cachedfilelastmodified = filemtime($cachedfilepath);
82 if (forum_rss_newstuff($forum, $cm, $cachedfilelastmodified)) {
83 //need to regenerate the cached version
84 $result = forum_rss_feed_contents($forum, $sql);
85 if (!empty($result)) {
86 $status = rss_save_file('forum',$filename,$result);
90 //return the path to the cached version
91 return $cachedfilepath;
95 * Given a forum object, deletes all cached RSS files associated with it.
97 * @param object $forum
100 function forum_rss_delete_file($forum) {
101 rss_delete_file('forum', $forum);
104 ///////////////////////////////////////////////////////
108 * If there is new stuff in the forum since $time this returns true
109 * Otherwise it returns false.
111 * @param object $forum the forum object
113 * @param int $time timestamp
116 function forum_rss_newstuff($forum, $cm, $time) {
119 $sql = forum_rss_get_sql($forum, $cm, $time);
121 $recs = $DB->get_records_sql($sql, null, 0, 1);//limit of 1. If we get even 1 back we have new stuff
122 return ($recs && !empty($recs));
125 function forum_rss_get_sql($forum, $cm, $time=0) {
128 if (!empty($forum->rsstype)) {
129 if ($forum->rsstype == 1) { //Discussion RSS
130 $sql = forum_rss_feed_discussions_sql($forum, $cm, $time);
132 $sql = forum_rss_feed_posts_sql($forum, $cm, $time);
139 function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) {
140 global $CFG, $DB, $USER;
146 $now = round(time(), -2);
147 $params = array($cm->instance);
149 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
151 if (!empty($CFG->forum_enabletimedposts)) { /// Users must fulfill timed posts
152 if (!has_capability('mod/forum:viewhiddentimedposts', $modcontext)) {
153 $timelimit = " AND ((d.timestart <= :now1 AND (d.timeend = 0 OR d.timeend > :now2))";
154 $params['now1'] = $now;
155 $params['now2'] = $now;
157 $timelimit .= " OR d.userid = :userid";
158 $params['userid'] = $USER->id;
164 //do we only want new posts?
166 $newsince = " AND p.modified > '$newsince'";
171 //get group enforcing SQL
172 $groupmode = groups_get_activity_groupmode($cm);
173 $currentgroup = groups_get_activity_group($cm);
174 $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
176 if ($groupmode && $currentgroup) {
177 $params['groupid'] = $currentgroup;
180 $forumsort = "d.timemodified DESC";
181 $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";
183 $sql = "SELECT $postdata, d.id as discussionid, d.name as discussionname, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend,
184 u.firstname as userfirstname, u.lastname as userlastname, u.email, u.picture, u.imagealt
185 FROM {forum_discussions} d
186 JOIN {forum_posts} p ON p.discussion = d.id
187 JOIN {user} u ON p.userid = u.id
188 WHERE d.forum = {$forum->id} AND p.parent = 0
189 $timelimit $groupselect $newsince
190 ORDER BY $forumsort";
194 function forum_rss_feed_posts_sql($forum, $cm, $newsince=0) {
195 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
197 //get group enforcement SQL
198 $groupmode = groups_get_activity_groupmode($cm);
199 $currentgroup = groups_get_activity_group($cm);
201 $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
203 if ($groupmode && $currentgroup) {
204 $params['groupid'] = $currentgroup;
207 //do we only want new posts?
209 $newsince = " AND p.modified > '$newsince'";
214 $sql = "SELECT p.id AS postid,
215 d.id AS discussionid,
216 d.name AS discussionname,
218 u.firstname AS userfirstname,
219 u.lastname AS userlastname,
220 p.subject AS postsubject,
221 p.message AS postmessage,
222 p.created AS postcreated,
223 p.messageformat AS postformat,
224 p.messagetrust AS posttrust
225 FROM {forum_discussions} d,
228 WHERE d.forum = {$forum->id} AND
229 p.discussion = d.id AND
230 u.id = p.userid $newsince
232 ORDER BY p.created desc";
237 function forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext=null) {
241 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $modcontext)) {
243 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
244 $params['groupid'] = $currentgroup;
247 //seprate groups without access all
249 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
250 $params['groupid'] = $currentgroup;
252 $groupselect = "AND d.groupid = -1";
264 * This function return the XML rss contents about the forum
265 * It returns false if something is wrong
267 * @param object $forum
270 function forum_rss_feed_contents($forum, $sql) {
276 //$params['forumid'] = $forum->id;
277 $recs = $DB->get_recordset_sql($sql, $params, 0, $forum->rssarticles);
279 //set a flag. Are we displaying discussions or posts?
280 $isdiscussion = true;
281 if (!empty($forum->rsstype) && $forum->rsstype!=1) {
282 $isdiscussion = false;
285 $formatoptions = new object;
287 foreach ($recs as $rec) {
290 $item->title = format_string($rec->discussionname);
291 $user->firstname = $rec->userfirstname;
292 $user->lastname = $rec->userlastname;
293 $item->author = fullname($user);
294 $item->pubdate = $rec->postcreated;
296 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid;
298 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid;
301 $formatoptions->trusted = $rec->posttrust;
302 $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course);
304 //TODO: implement post attachment handling
305 /*if (!$isdiscussion) {
306 $post_file_area_name = str_replace('//', '/', "$forum->course/$CFG->moddata/forum/$forum->id/$rec->postid");
307 $post_files = get_directory_list("$CFG->dataroot/$post_file_area_name");
309 if (!empty($post_files)) {
310 $item->attachments = array();
319 if (!empty($items)) {
320 //First the RSS header
321 $header = rss_standard_header(strip_tags(format_string($forum->name,true)),
322 $CFG->wwwroot."/mod/forum/view.php?f=".$forum->id,
323 format_string($forum->intro,true)); // TODO: fix format
324 //Now all the rss items
325 if (!empty($header)) {
326 $articles = rss_add_items($items);
329 if (!empty($header) && !empty($articles)) {
330 $footer = rss_standard_footer();
332 //Now, if everything is ok, concatenate it
333 if (!empty($header) && !empty($articles) && !empty($footer)) {
334 $status = $header.$articles.$footer;