rss MDL-23391 rerefactored rss feed generation
[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
4df53223
AD
46 $forumid = $args[3];
47
48 $uservalidated = false;
49
50 $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST);
51 if ($cm) {
52 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
53
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;
57 }
58 }
59
60 if (!$uservalidated) {
fcce139a
AD
61 return null;
62 }
8adcb49f 63
fcce139a
AD
64 $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
65
66 if (!rss_enabled('forum', $forum)) {
67 return null;
8adcb49f 68 }
69
fcce139a
AD
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);
83da3d28 72
fcce139a
AD
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);
76
77 //Is the cache out of date?
78 $cachedfilelastmodified = 0;
79 if (file_exists($cachedfilepath)) {
80 $cachedfilelastmodified = filemtime($cachedfilepath);
81 }
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);
83da3d28 87 }
88 }
89
fcce139a
AD
90 //return the path to the cached version
91 return $cachedfilepath;
92}
83da3d28 93
fcce139a
AD
94/**
95 * Given a forum object, deletes all cached RSS files associated with it.
96 *
97 * @param object $forum
98 * @return void
99 */
100function forum_rss_delete_file($forum) {
101 rss_delete_file('forum', $forum);
102}
103
104///////////////////////////////////////////////////////
105//Utility functions
106
107/**
108 * If there is new stuff in the forum since $time this returns true
109 * Otherwise it returns false.
110 *
111 * @param object $forum the forum object
112 * @param object $cm
113 * @param int $time timestamp
114 * @return bool
115 */
116function forum_rss_newstuff($forum, $cm, $time) {
117 global $DB;
118
119 $sql = forum_rss_get_sql($forum, $cm, $time);
120
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));
123}
124
125function forum_rss_get_sql($forum, $cm, $time=0) {
126 $sql = null;
127
128 if (!empty($forum->rsstype)) {
129 if ($forum->rsstype == 1) { //Discussion RSS
130 $sql = forum_rss_feed_discussions_sql($forum, $cm, $time);
131 } else { //Post RSS
132 $sql = forum_rss_feed_posts_sql($forum, $cm, $time);
6069e206 133 }
6069e206 134 }
135
fcce139a
AD
136 return $sql;
137}
8f0cd6ef 138
fcce139a
AD
139function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) {
140 global $CFG, $DB, $USER;
141
142 $timelimit = '';
143
144 $modcontext = null;
145
146 $now = round(time(), -2);
147 $params = array($cm->instance);
148
149 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
150
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;
156 if (isloggedin()) {
157 $timelimit .= " OR d.userid = :userid";
158 $params['userid'] = $USER->id;
8adcb49f 159 }
fcce139a 160 $timelimit .= ")";
8adcb49f 161 }
8adcb49f 162 }
163
fcce139a
AD
164 //do we only want new posts?
165 if ($newsince) {
166 $newsince = " AND p.modified > '$newsince'";
167 } else {
168 $newsince = '';
169 }
8adcb49f 170
fcce139a
AD
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);
8adcb49f 175
fcce139a
AD
176 if ($groupmode && $currentgroup) {
177 $params['groupid'] = $currentgroup;
178 }
8adcb49f 179
fcce139a
AD
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";
182
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";
191 return $sql;
192}
193
194function forum_rss_feed_posts_sql($forum, $cm, $newsince=0) {
195 $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
196
197 //get group enforcement SQL
198 $groupmode = groups_get_activity_groupmode($cm);
199 $currentgroup = groups_get_activity_group($cm);
200
201 $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
202
203 if ($groupmode && $currentgroup) {
204 $params['groupid'] = $currentgroup;
205 }
6069e206 206
fcce139a
AD
207 //do we only want new posts?
208 if ($newsince) {
209 $newsince = " AND p.modified > '$newsince'";
210 } else {
211 $newsince = '';
212 }
ec41cb3c 213
fcce139a
AD
214 $sql = "SELECT p.id AS postid,
215 d.id AS discussionid,
216 d.name AS discussionname,
217 u.id AS userid,
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,
226 {forum_posts} p,
227 {user} u
228 WHERE d.forum = {$forum->id} AND
229 p.discussion = d.id AND
230 u.id = p.userid $newsince
231 $groupselect
232 ORDER BY p.created desc";
233
234 return $sql;
235}
236
237function forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext=null) {
238 $groupselect = '';
239
240 if ($groupmode) {
241 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $modcontext)) {
242 if ($currentgroup) {
243 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
244 $params['groupid'] = $currentgroup;
245 }
246 } else {
247 //seprate groups without access all
248 if ($currentgroup) {
249 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
250 $params['groupid'] = $currentgroup;
251 } else {
252 $groupselect = "AND d.groupid = -1";
8adcb49f 253 }
254 }
8adcb49f 255 }
8f0cd6ef 256
fcce139a
AD
257 return $groupselect;
258}
8adcb49f 259
8adcb49f 260
fcce139a 261
8adcb49f 262
fcce139a
AD
263/**
264 * This function return the XML rss contents about the forum
265 * It returns false if something is wrong
266 *
267 * @param object $forum
268 * @param bool
269 */
270function forum_rss_feed_contents($forum, $sql) {
271 global $CFG, $DB;
6069e206 272
fcce139a
AD
273 $status = true;
274
275 $params = array();
276 //$params['forumid'] = $forum->id;
277 $recs = $DB->get_recordset_sql($sql, $params, 0, $forum->rssarticles);
278
279 //set a flag. Are we displaying discussions or posts?
280 $isdiscussion = true;
281 if (!empty($forum->rsstype) && $forum->rsstype!=1) {
282 $isdiscussion = false;
283 }
318f2100 284
fcce139a
AD
285 $formatoptions = new object;
286 $items = array();
287 foreach ($recs as $rec) {
288 unset($item);
289 unset($user);
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;
295 if ($isdiscussion) {
296 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid;
297 } else {
8f0cd6ef 298 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid;
fcce139a 299 }
410a24c0 300
fcce139a
AD
301 $formatoptions->trusted = $rec->posttrust;
302 $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course);
410a24c0 303
fcce139a
AD
304 //TODO: implement post attachment handling
305 /*if (!$isdiscussion) {
318f2100 306 $post_file_area_name = str_replace('//', '/', "$forum->course/$CFG->moddata/forum/$forum->id/$rec->postid");
410a24c0 307 $post_files = get_directory_list("$CFG->dataroot/$post_file_area_name");
4e445355 308
309 if (!empty($post_files)) {
410a24c0 310 $item->attachments = array();
410a24c0 311 }
fcce139a
AD
312 }*/
313
314 $items[] = $item;
315 }
316 $recs->close();
410a24c0 317
fcce139a
AD
318
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);
327 }
328 //Now the RSS footer
329 if (!empty($header) && !empty($articles)) {
330 $footer = rss_standard_footer();
8adcb49f 331 }
fcce139a
AD
332 //Now, if everything is ok, concatenate it
333 if (!empty($header) && !empty($articles) && !empty($footer)) {
334 $status = $header.$articles.$footer;
335 } else {
336 $status = false;
337 }
338 } else {
339 $status = false;
340 }
341
342 return $status;
343}