MDL-23391 rss cache is now inside the dataroot/cache with the others, so it doesn...
[moodle.git] / mod / forum / rsslib.php
1 <?php
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/>.
18 /**
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 */
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
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.
34  */
35 function forum_rss_get_feed($context, $args) {
36     global $CFG, $DB;
38     $status = true;
40     //are RSS feeds enabled?
41     if (empty($CFG->forum_enablerssfeeds)) {
42         debugging('DISABLED (module configuration)');
43         return null;
44     }
46     if (!is_enrolled($context, null, 'mod/forum:viewdiscussion')) {
47         return null;
48     }
50     $forumid = $args[3];
51     $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
53     if (!rss_enabled('forum', $forum)) {
54         return null;
55     }
57     $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST);
59     //the sql that will retreive the data for the feed and be hashed to get the cache filename
60     $sql = forum_rss_get_sql($forum, $cm);
62     //hash the sql to get the cache file name
63     $filename = rss_get_file_name($forum, $sql);
64     $cachedfilepath = rss_get_file_full_name('forum', $filename);
66     //Is the cache out of date?
67     $cachedfilelastmodified = 0;
68     if (file_exists($cachedfilepath)) {
69         $cachedfilelastmodified = filemtime($cachedfilepath);
70     }
71     if (forum_rss_newstuff($forum, $cm, $cachedfilelastmodified)) {
72         //need to regenerate the cached version
73         $result = forum_rss_feed_contents($forum, $sql);
74         if (!empty($result)) {
75             $status = rss_save_file('forum',$filename,$result);
76         }
77     }
79     //return the path to the cached version
80     return $cachedfilepath;
81 }
83 /**
84  * Given a forum object, deletes all cached RSS files associated with it.
85  *
86  * @param object $forum
87  * @return void
88  */
89 function forum_rss_delete_file($forum) {
90     rss_delete_file('forum', $forum);
91 }
93 ///////////////////////////////////////////////////////
94 //Utility functions
96 /**
97  * If there is new stuff in the forum since $time this returns true
98  * Otherwise it returns false.
99  *
100  * @param object $forum the forum object
101  * @param object $cm
102  * @param int $time timestamp
103  * @return bool
104  */
105 function forum_rss_newstuff($forum, $cm, $time) {
106     global $DB;
108     $sql = forum_rss_get_sql($forum, $cm, $time);
110     $recs = $DB->get_records_sql($sql, null, 0, 1);//limit of 1. If we get even 1 back we have new stuff
111     return ($recs && !empty($recs));
114 function forum_rss_get_sql($forum, $cm, $time=0) {
115     $sql = null;
117     if (!empty($forum->rsstype)) {
118         if ($forum->rsstype == 1) {    //Discussion RSS
119             $sql = forum_rss_feed_discussions_sql($forum, $cm, $time);
120         } else {                //Post RSS
121             $sql = forum_rss_feed_posts_sql($forum, $cm, $time);
122         }
123     }
125     return $sql;
128 function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) {
129     global $CFG, $DB, $USER;
131     $timelimit = '';
133     $modcontext = null;
135     $now = round(time(), -2);
136     $params = array($cm->instance);
138     $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
140     if (!empty($CFG->forum_enabletimedposts)) { /// Users must fulfill timed posts
141         if (!has_capability('mod/forum:viewhiddentimedposts', $modcontext)) {
142             $timelimit = " AND ((d.timestart <= :now1 AND (d.timeend = 0 OR d.timeend > :now2))";
143             $params['now1'] = $now;
144             $params['now2'] = $now;
145             if (isloggedin()) {
146                 $timelimit .= " OR d.userid = :userid";
147                 $params['userid'] = $USER->id;
148             }
149             $timelimit .= ")";
150         }
151     }
153     //do we only want new posts?
154     if ($newsince) {
155         $newsince = " AND p.modified > '$newsince'";
156     } else {
157         $newsince = '';
158     }
160     //get group enforcing SQL
161     $groupmode    = groups_get_activity_groupmode($cm);
162     $currentgroup = groups_get_activity_group($cm);
163     $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
165     if ($groupmode && $currentgroup) {
166         $params['groupid'] = $currentgroup;
167     }
169     $forumsort = "d.timemodified DESC";
170     $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";
172     $sql = "SELECT $postdata, d.id as discussionid, d.name as discussionname, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend,
173                    u.firstname as userfirstname, u.lastname as userlastname, u.email, u.picture, u.imagealt
174               FROM {forum_discussions} d
175                    JOIN {forum_posts} p ON p.discussion = d.id
176                    JOIN {user} u ON p.userid = u.id
177              WHERE d.forum = {$forum->id} AND p.parent = 0
178                    $timelimit $groupselect $newsince
179           ORDER BY $forumsort";
180     return $sql;
183 function forum_rss_feed_posts_sql($forum, $cm, $newsince=0) {
184     $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
185     
186     //get group enforcement SQL
187     $groupmode    = groups_get_activity_groupmode($cm);
188     $currentgroup = groups_get_activity_group($cm);
190     $groupselect = forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext);
192     if ($groupmode && $currentgroup) {
193         $params['groupid'] = $currentgroup;
194     }
196     //do we only want new posts?
197     if ($newsince) {
198         $newsince = " AND p.modified > '$newsince'";
199     } else {
200         $newsince = '';
201     }
203     $sql = "SELECT p.id AS postid,
204                  d.id AS discussionid,
205                  d.name AS discussionname,
206                  u.id AS userid,
207                  u.firstname AS userfirstname,
208                  u.lastname AS userlastname,
209                  p.subject AS postsubject,
210                  p.message AS postmessage,
211                  p.created AS postcreated,
212                  p.messageformat AS postformat,
213                  p.messagetrust AS posttrust
214             FROM {forum_discussions} d,
215                {forum_posts} p,
216                {user} u
217             WHERE d.forum = {$forum->id} AND
218                 p.discussion = d.id AND
219                 u.id = p.userid $newsince
220                 $groupselect
221             ORDER BY p.created desc";
223     return $sql;
226 function forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext=null) {
227     $groupselect = '';
229     if ($groupmode) {
230         if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $modcontext)) {
231             if ($currentgroup) {
232                 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
233                 $params['groupid'] = $currentgroup;
234             }
235         } else {
236             //seprate groups without access all
237             if ($currentgroup) {
238                 $groupselect = "AND (d.groupid = :groupid OR d.groupid = -1)";
239                 $params['groupid'] = $currentgroup;
240             } else {
241                 $groupselect = "AND d.groupid = -1";
242             }
243         }
244     }
246     return $groupselect;
250     
252 /**
253  * This function return the XML rss contents about the forum
254  * It returns false if something is wrong
255  *
256  * @param object $forum
257  * @param bool
258  */
259 function forum_rss_feed_contents($forum, $sql) {
260     global $CFG, $DB;
262     $status = true;
264     $params = array();
265     //$params['forumid'] = $forum->id;
266     $recs = $DB->get_recordset_sql($sql, $params, 0, $forum->rssarticles);
268     //set a flag. Are we displaying discussions or posts?
269     $isdiscussion = true;
270     if (!empty($forum->rsstype) && $forum->rsstype!=1) {
271             $isdiscussion = false;
272     }
274     $formatoptions = new object;
275     $items = array();
276     foreach ($recs as $rec) {
277             unset($item);
278             unset($user);
279             $item->title = format_string($rec->discussionname);
280             $user->firstname = $rec->userfirstname;
281             $user->lastname = $rec->userlastname;
282             $item->author = fullname($user);
283             $item->pubdate = $rec->postcreated;
284             if ($isdiscussion) {
285                 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid;
286             } else {
287                 $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid;
288             }
290             $formatoptions->trusted = $rec->posttrust;
291             $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course);
293             //TODO: implement post attachment handling
294             /*if (!$isdiscussion) {
295                 $post_file_area_name = str_replace('//', '/', "$forum->course/$CFG->moddata/forum/$forum->id/$rec->postid");
296                 $post_files = get_directory_list("$CFG->dataroot/$post_file_area_name");
298                 if (!empty($post_files)) {
299                     $item->attachments = array();
300                 }
301             }*/
302             
303             $items[] = $item;
304         }
305     $recs->close();
308     if (!empty($items)) {
309         //First the RSS header
310         $header = rss_standard_header(strip_tags(format_string($forum->name,true)),
311                                       $CFG->wwwroot."/mod/forum/view.php?f=".$forum->id,
312                                       format_string($forum->intro,true)); // TODO: fix format
313         //Now all the rss items
314         if (!empty($header)) {
315             $articles = rss_add_items($items);
316         }
317         //Now the RSS footer
318         if (!empty($header) && !empty($articles)) {
319             $footer = rss_standard_footer();
320         }
321         //Now, if everything is ok, concatenate it
322         if (!empty($header) && !empty($articles) && !empty($footer)) {
323             $status = $header.$articles.$footer;
324         } else {
325             $status = false;
326         }
327     } else {
328         $status = false;
329     }
331     return $status;