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