PageRenderTime 30ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/forum/rsslib.php

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