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