848bb113 |
1 | <?php |
2 | |
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/>. |
1515a89e |
17 | |
848bb113 |
18 | /** |
19 | * Library of functions and constants for module chat |
20 | * |
b2d5a79a |
21 | * @package mod-chat |
848bb113 |
22 | * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
24 | */ |
25 | |
26 | /** Include portfoliolib.php */ |
214b1cf7 |
27 | require_once($CFG->libdir.'/portfoliolib.php'); |
c4d588cc |
28 | |
1515a89e |
29 | // The HTML head for the message window to start with (<!-- nix --> is used to get some browsers starting with output |
17da2e6f |
30 | global $CHAT_HTMLHEAD; |
1f8abb89 |
31 | $CHAT_HTMLHEAD = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head></head>\n<body>\n\n".padding(200); |
1515a89e |
32 | |
33 | // The HTML head for the message window to start with (with js scrolling) |
17da2e6f |
34 | global $CHAT_HTMLHEAD_JS; |
1f8abb89 |
35 | $CHAT_HTMLHEAD_JS = <<<EOD |
36 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
37 | <html><head><script type="text/javascript"> |
38 | //<![CDATA[ |
39 | function move(){ |
40 | if (scroll_active) |
41 | window.scroll(1,400000); |
42 | window.setTimeout("move()",100); |
43 | } |
44 | var scroll_active = true; |
45 | move(); |
46 | //]]> |
47 | </script> |
48 | </head> |
49 | <body onBlur="scroll_active = true" onFocus="scroll_active = false"> |
50 | EOD; |
17da2e6f |
51 | global $CHAT_HTMLHEAD_JS; |
1f8abb89 |
52 | $CHAT_HTMLHEAD_JS .= padding(200); |
1515a89e |
53 | |
54 | // The HTML code for standard empty pages (e.g. if a user was kicked out) |
17da2e6f |
55 | global $CHAT_HTMLHEAD_OUT; |
1f8abb89 |
56 | $CHAT_HTMLHEAD_OUT = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head><title>You are out!</title></head><body></body></html>"; |
1515a89e |
57 | |
58 | // The HTML head for the message input page |
17da2e6f |
59 | global $CHAT_HTMLHEAD_MSGINPUT; |
1f8abb89 |
60 | $CHAT_HTMLHEAD_MSGINPUT = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head><title>Message Input</title></head><body>"; |
1515a89e |
61 | |
62 | // The HTML code for the message input page, with JavaScript |
17da2e6f |
63 | global $CHAT_HTMLHEAD_MSGINPUT_JS; |
1d507186 |
64 | $CHAT_HTMLHEAD_MSGINPUT_JS = <<<EOD |
65 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
66 | <html> |
67 | <head><title>Message Input</title> |
68 | <script type="text/javascript"> |
69 | //<![CDATA[ |
70 | scroll_active = true; |
71 | function empty_field_and_submit(){ |
72 | document.fdummy.arsc_message.value=document.f.arsc_message.value; |
73 | document.fdummy.submit(); |
74 | document.f.arsc_message.focus(); |
75 | document.f.arsc_message.select(); |
76 | return false; |
77 | } |
78 | //]]> |
79 | </script> |
80 | </head><body OnLoad="document.f.arsc_message.focus();document.f.arsc_message.select();">; |
81 | EOD; |
1515a89e |
82 | |
fbabbd23 |
83 | // Dummy data that gets output to the browser as needed, in order to make it show output |
17da2e6f |
84 | global $CHAT_DUMMY_DATA; |
6e5f40ea |
85 | $CHAT_DUMMY_DATA = padding(200); |
5c2f6a7f |
86 | |
848bb113 |
87 | /** |
88 | * @param int $n |
89 | * @return string |
90 | */ |
6e5f40ea |
91 | function padding($n){ |
5c2f6a7f |
92 | $str = ''; |
633c3341 |
93 | for($i=0; $i<$n; $i++){ |
1f8abb89 |
94 | $str.="<!-- nix -->\n"; |
5c2f6a7f |
95 | } |
96 | return $str; |
97 | } |
1515a89e |
98 | |
848bb113 |
99 | /** |
100 | * Given an object containing all the necessary data, |
101 | * (defined by the form in mod_form.php) this function |
102 | * will create a new instance and return the id number |
103 | * of the new instance. |
104 | * |
105 | * @global object |
106 | * @param object $chat |
107 | * @return int |
108 | */ |
1515a89e |
109 | function chat_add_instance($chat) { |
c18269c7 |
110 | global $DB; |
1515a89e |
111 | |
112 | $chat->timemodified = time(); |
113 | |
c18269c7 |
114 | if ($returnid = $DB->insert_record("chat", $chat)) { |
8496c4af |
115 | |
116 | $event = NULL; |
117 | $event->name = $chat->name; |
9b010a10 |
118 | $event->description = format_module_intro('chat', $chat, $chat->coursemodule); |
8496c4af |
119 | $event->courseid = $chat->course; |
120 | $event->groupid = 0; |
121 | $event->userid = 0; |
122 | $event->modulename = 'chat'; |
123 | $event->instance = $returnid; |
124 | $event->eventtype = $chat->schedule; |
125 | $event->timestart = $chat->chattime; |
126 | $event->timeduration = 0; |
127 | |
128 | add_event($event); |
129 | } |
130 | |
131 | return $returnid; |
1515a89e |
132 | } |
133 | |
848bb113 |
134 | /** |
135 | * Given an object containing all the necessary data, |
136 | * (defined by the form in mod_form.php) this function |
137 | * will update an existing instance with new data. |
138 | * |
139 | * @global object |
140 | * @param object $chat |
141 | * @return int |
142 | */ |
1515a89e |
143 | function chat_update_instance($chat) { |
c18269c7 |
144 | global $DB; |
1515a89e |
145 | |
146 | $chat->timemodified = time(); |
147 | $chat->id = $chat->instance; |
148 | |
1515a89e |
149 | |
c18269c7 |
150 | if ($returnid = $DB->update_record("chat", $chat)) { |
8496c4af |
151 | |
264867fd |
152 | $event = new object(); |
8496c4af |
153 | |
c18269c7 |
154 | if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
8496c4af |
155 | |
156 | $event->name = $chat->name; |
9b010a10 |
157 | $event->description = format_module_intro('chat', $chat, $chat->coursemodule); |
8496c4af |
158 | $event->timestart = $chat->chattime; |
159 | |
160 | update_event($event); |
161 | } |
162 | } |
163 | |
164 | return $returnid; |
1515a89e |
165 | } |
166 | |
848bb113 |
167 | /** |
168 | * Given an ID of an instance of this module, |
169 | * this function will permanently delete the instance |
170 | * and any data that depends on it. |
171 | * |
172 | * @global object |
173 | * @param int $id |
174 | * @return bool |
175 | */ |
1515a89e |
176 | function chat_delete_instance($id) { |
c18269c7 |
177 | global $DB; |
848bb113 |
178 | |
1515a89e |
179 | |
c18269c7 |
180 | if (! $chat = $DB->get_record('chat', array('id'=>$id))) { |
1515a89e |
181 | return false; |
182 | } |
183 | |
184 | $result = true; |
185 | |
186 | # Delete any dependent records here # |
187 | |
c18269c7 |
188 | if (! $DB->delete_records('chat', array('id'=>$chat->id))) { |
a71efae3 |
189 | $result = false; |
190 | } |
c18269c7 |
191 | if (! $DB->delete_records('chat_messages', array('chatid'=>$chat->id))) { |
a71efae3 |
192 | $result = false; |
193 | } |
6e5f40ea |
194 | if (! $DB->delete_records('chat_messages_current', array('chatid'=>$chat->id))) { |
195 | $result = false; |
196 | } |
c18269c7 |
197 | if (! $DB->delete_records('chat_users', array('chatid'=>$chat->id))) { |
1515a89e |
198 | $result = false; |
199 | } |
200 | |
c18269c7 |
201 | if (! $DB->delete_records('event', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
36eb856f |
202 | $result = false; |
203 | } |
204 | |
1515a89e |
205 | return $result; |
206 | } |
207 | |
848bb113 |
208 | /** |
209 | * Return a small object with summary information about what a |
210 | * user has done with a given particular instance of this module |
211 | * Used for user activity reports. |
212 | * <code> |
213 | * $return->time = the time they did it |
214 | * $return->info = a short text description |
215 | * </code> |
216 | * |
217 | * @param object $course |
218 | * @param object $user |
219 | * @param object $mod |
220 | * @param object $chat |
221 | * @return void |
222 | */ |
1515a89e |
223 | function chat_user_outline($course, $user, $mod, $chat) { |
d3bf6f92 |
224 | return NULL; |
1515a89e |
225 | } |
226 | |
848bb113 |
227 | /** |
228 | * Print a detailed representation of what a user has done with |
229 | * a given particular instance of this module, for user activity reports. |
230 | * |
231 | * @param object $course |
232 | * @param object $user |
233 | * @param object $mod |
234 | * @param object $chat |
235 | * @return bool |
236 | */ |
1515a89e |
237 | function chat_user_complete($course, $user, $mod, $chat) { |
1515a89e |
238 | return true; |
239 | } |
240 | |
848bb113 |
241 | /** |
242 | * Given a course and a date, prints a summary of all chat rooms past and present |
243 | * This function is called from course/lib.php: print_recent_activity() |
244 | * |
245 | * @global object |
246 | * @global object |
247 | * @global object |
248 | * @param object $course |
249 | * @param array $viewfullnames |
250 | * @param int|string $timestart Timestamp |
251 | * @return bool |
252 | */ |
dd97c328 |
253 | function chat_print_recent_activity($course, $viewfullnames, $timestart) { |
e09fc68b |
254 | global $CFG, $USER, $DB, $OUTPUT; |
dd97c328 |
255 | |
256 | // this is approximate only, but it is really fast ;-) |
257 | $timeout = $CFG->chat_old_ping * 10; |
258 | |
d3bf6f92 |
259 | if (!$mcms = $DB->get_records_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime |
260 | FROM {course_modules} cm |
261 | JOIN {modules} md ON md.id = cm.module |
262 | JOIN {chat} ch ON ch.id = cm.instance |
263 | JOIN {chat_messages} chm ON chm.chatid = ch.id |
264 | WHERE chm.timestamp > ? AND ch.course = ? AND md.name = 'chat' |
265 | GROUP BY cm.id |
266 | ORDER BY lasttime ASC", array($timestart, $course->id))) { |
dd97c328 |
267 | return false; |
268 | } |
269 | |
270 | $past = array(); |
271 | $current = array(); |
272 | $modinfo =& get_fast_modinfo($course); // reference needed because we might load the groups |
273 | |
fd4d41c3 |
274 | foreach ($mcms as $cmid=>$mcm) { |
275 | if (!array_key_exists($cmid, $modinfo->cms)) { |
dd97c328 |
276 | continue; |
277 | } |
fd4d41c3 |
278 | $cm = $modinfo->cms[$cmid]; |
279 | $cm->lasttime = $mcm->lasttime; |
dd97c328 |
280 | if (!$modinfo->cms[$cm->id]->uservisible) { |
281 | continue; |
282 | } |
b7602a11 |
283 | |
dd97c328 |
284 | if (groups_get_activity_groupmode($cm) != SEPARATEGROUPS |
285 | or has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) { |
286 | if ($timeout > time() - $cm->lasttime) { |
287 | $current[] = $cm; |
288 | } else { |
289 | $past[] = $cm; |
290 | } |
291 | |
292 | continue; |
293 | } |
294 | |
295 | if (is_null($modinfo->groups)) { |
296 | $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo |
297 | } |
c5a05b95 |
298 | |
dd97c328 |
299 | // verify groups in separate mode |
300 | if (!$mygroupids = $modinfo->groups[$cm->groupingid]) { |
301 | continue; |
302 | } |
0469cccf |
303 | |
dd97c328 |
304 | // ok, last post was not for my group - we have to query db to get last message from one of my groups |
305 | // only minor problem is that the order will not be correct |
306 | $mygroupids = implode(',', $mygroupids); |
307 | $cm->mygroupids = $mygroupids; |
308 | |
d3bf6f92 |
309 | if (!$mcm = $DB->get_record_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime |
310 | FROM {course_modules} cm |
311 | JOIN {chat} ch ON ch.id = cm.instance |
6e5f40ea |
312 | JOIN {chat_messages_current} chm ON chm.chatid = ch.id |
d3bf6f92 |
313 | WHERE chm.timestamp > ? AND cm.id = ? AND |
314 | (chm.groupid IN ($mygroupids) OR chm.groupid = 0) |
315 | GROUP BY cm.id", array($timestart, $cm->id))) { |
dd97c328 |
316 | continue; |
317 | } |
fd4d41c3 |
318 | |
319 | $cm->lasttime = $mcm->lasttime; |
dd97c328 |
320 | if ($timeout > time() - $cm->lasttime) { |
321 | $current[] = $cm; |
322 | } else { |
323 | $past[] = $cm; |
324 | } |
325 | } |
326 | |
327 | if (!$past and !$current) { |
b7602a11 |
328 | return false; |
329 | } |
1515a89e |
330 | |
dd97c328 |
331 | $strftimerecent = get_string('strftimerecent'); |
332 | |
333 | if ($past) { |
e09fc68b |
334 | echo $OUTPUT->heading(get_string("pastchats", 'chat').':'); |
dd97c328 |
335 | |
336 | foreach ($past as $cm) { |
337 | $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id; |
338 | $date = userdate($cm->lasttime, $strftimerecent); |
339 | echo '<div class="head"><div class="date">'.$date.'</div></div>'; |
340 | echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name,true).'</a></div>'; |
b7602a11 |
341 | } |
8f7dc7f1 |
342 | } |
343 | |
344 | if ($current) { |
e09fc68b |
345 | echo $OUTPUT->heading(get_string("currentchats", 'chat').':'); |
dd97c328 |
346 | |
347 | $oldest = floor((time()-$CFG->chat_old_ping)/10)*10; // better db caching |
348 | |
349 | $timeold = time() - $CFG->chat_old_ping; |
350 | $timeold = floor($timeold/10)*10; // better db caching |
351 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts |
352 | $timeoldext = floor($timeoldext/10)*10; // better db caching |
353 | |
d3bf6f92 |
354 | $params = array('timeold'=>$timeold, 'timeoldext'=>$timeoldext, 'cmid'=>$cm->id); |
355 | |
356 | $timeout = "AND (chu.version<>'basic' AND chu.lastping>:timeold) OR (chu.version='basic' AND chu.lastping>:timeoldext)"; |
dd97c328 |
357 | |
358 | foreach ($current as $cm) { |
359 | //count users first |
360 | if (isset($cm->mygroupids)) { |
361 | $groupselect = "AND (chu.groupid IN ({$cm->mygroupids}) OR chu.groupid = 0)"; |
362 | } else { |
363 | $groupselect = ""; |
364 | } |
fd4d41c3 |
365 | |
d3bf6f92 |
366 | if (!$users = $DB->get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email, u.picture |
367 | FROM {course_modules} cm |
368 | JOIN {chat} ch ON ch.id = cm.instance |
369 | JOIN {chat_users} chu ON chu.chatid = ch.id |
370 | JOIN {user} u ON u.id = chu.userid |
371 | WHERE cm.id = :cmid $timeout $groupselect |
372 | GROUP BY u.id, u.firstname, u.lastname, u.email, u.picture", $params)) { |
dd97c328 |
373 | } |
374 | |
375 | $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id; |
376 | $date = userdate($cm->lasttime, $strftimerecent); |
377 | |
378 | echo '<div class="head"><div class="date">'.$date.'</div></div>'; |
379 | echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name,true).'</a></div>'; |
380 | echo '<div class="userlist">'; |
381 | if ($users) { |
382 | echo '<ul>'; |
383 | foreach ($users as $user) { |
384 | echo '<li>'.fullname($user, $viewfullnames).'</li>'; |
385 | } |
386 | echo '</ul>'; |
387 | } |
388 | echo '</div>'; |
389 | } |
b7602a11 |
390 | } |
391 | |
392 | return true; |
1515a89e |
393 | } |
394 | |
848bb113 |
395 | /** |
396 | * Function to be run periodically according to the moodle cron |
397 | * This function searches for things that need to be done, such |
398 | * as sending out mail, toggling flags etc ... |
399 | * |
400 | * @global object |
401 | * @return bool |
402 | */ |
1515a89e |
403 | function chat_cron () { |
d3bf6f92 |
404 | global $DB; |
1515a89e |
405 | |
fcd3a1ee |
406 | chat_update_chat_times(); |
407 | |
7d792369 |
408 | chat_delete_old_users(); |
409 | |
319038c3 |
410 | /// Delete old messages with a |
411 | /// single SQL query. |
412 | $subselect = "SELECT c.keepdays |
d3bf6f92 |
413 | FROM {chat} c |
414 | WHERE c.id = {chat_messages}.chatid"; |
4388027c |
415 | |
319038c3 |
416 | $sql = "DELETE |
d3bf6f92 |
417 | FROM {chat_messages} |
6e5f40ea |
418 | WHERE ($subselect) > 0 AND timestamp < ( ".time()." -($subselect) * 24 * 3600)"; |
419 | |
420 | $DB->execute($sql); |
421 | |
422 | $sql = "DELETE |
423 | FROM {chat_messages_current} |
424 | WHERE timestamp < ( ".time()." - 8 * 3600)"; |
4388027c |
425 | |
d3bf6f92 |
426 | $DB->execute($sql); |
22a4491a |
427 | |
1515a89e |
428 | return true; |
429 | } |
430 | |
848bb113 |
431 | /** |
432 | * Returns the users with data in one chat |
433 | * (users with records in chat_messages, students) |
434 | * |
435 | * @global object |
436 | * @param int $chatid |
437 | * @param int $groupid |
438 | * @return array |
439 | */ |
84a2fdd7 |
440 | function chat_get_participants($chatid, $groupid=0) { |
d3bf6f92 |
441 | global $DB; |
05855091 |
442 | |
d3bf6f92 |
443 | $params = array('groupid'=>$groupid, 'chatid'=>$chatid); |
05855091 |
444 | |
84a2fdd7 |
445 | if ($groupid) { |
d3bf6f92 |
446 | $groupselect = " AND (c.groupid=:groupid OR c.groupid='0')"; |
84a2fdd7 |
447 | } else { |
448 | $groupselect = ""; |
449 | } |
450 | |
05855091 |
451 | //Get students |
d3bf6f92 |
452 | $students = $DB->get_records_sql("SELECT DISTINCT u.id, u.id |
453 | FROM {user} u, {chat_messages} c |
454 | WHERE c.chatid = :chatid $groupselect |
455 | AND u.id = c.userid", $params); |
1515a89e |
456 | |
05855091 |
457 | //Return students array (it contains an array of unique users) |
458 | return ($students); |
459 | } |
1515a89e |
460 | |
848bb113 |
461 | /** |
462 | * This standard function will check all instances of this module |
463 | * and make sure there are up-to-date events created for each of them. |
464 | * If courseid = 0, then every chat event in the site is checked, else |
465 | * only chat events belonging to the course specified are checked. |
466 | * This function is used, in its new format, by restore_refresh_events() |
467 | * |
468 | * @global object |
469 | * @param int $courseid |
470 | * @return bool |
471 | */ |
8496c4af |
472 | function chat_refresh_events($courseid = 0) { |
d3bf6f92 |
473 | global $DB; |
8496c4af |
474 | |
475 | if ($courseid) { |
d3bf6f92 |
476 | if (! $chats = $DB->get_records("chat", array("course"=>$courseid))) { |
8496c4af |
477 | return true; |
478 | } |
479 | } else { |
d3bf6f92 |
480 | if (! $chats = $DB->get_records("chat")) { |
8496c4af |
481 | return true; |
482 | } |
483 | } |
d3bf6f92 |
484 | $moduleid = $DB->get_field('modules', 'id', array('name'=>'chat')); |
8496c4af |
485 | |
486 | foreach ($chats as $chat) { |
9b010a10 |
487 | $cm = get_coursemodule_from_id('chat', $chat->id); |
488 | $event = new object(); |
d3bf6f92 |
489 | $event->name = $chat->name; |
9b010a10 |
490 | $event->description = format_module_intro('chat', $chat, $cm->id); |
8496c4af |
491 | $event->timestart = $chat->chattime; |
492 | |
d3bf6f92 |
493 | if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
8496c4af |
494 | update_event($event); |
495 | |
496 | } else { |
497 | $event->courseid = $chat->course; |
498 | $event->groupid = 0; |
499 | $event->userid = 0; |
500 | $event->modulename = 'chat'; |
501 | $event->instance = $chat->id; |
502 | $event->eventtype = $chat->schedule; |
503 | $event->timeduration = 0; |
d3bf6f92 |
504 | $event->visible = $DB->get_field('course_modules', 'visible', array('module'=>$moduleid, 'instance'=>$chat->id)); |
b5de723d |
505 | |
8496c4af |
506 | add_event($event); |
507 | } |
508 | } |
509 | return true; |
510 | } |
511 | |
516121bd |
512 | |
1515a89e |
513 | ////////////////////////////////////////////////////////////////////// |
514 | /// Functions that require some SQL |
515 | |
848bb113 |
516 | /** |
517 | * @global object |
518 | * @param int $chatid |
519 | * @param int $groupid |
520 | * @param int $groupingid |
521 | * @return array |
522 | */ |
a12e11c1 |
523 | function chat_get_users($chatid, $groupid=0, $groupingid=0) { |
d3bf6f92 |
524 | global $DB; |
1515a89e |
525 | |
d3bf6f92 |
526 | $params = array('chatid'=>$chatid, 'groupid'=>$groupid, 'groupingid'=>$groupingid); |
84a2fdd7 |
527 | |
528 | if ($groupid) { |
d3bf6f92 |
529 | $groupselect = " AND (c.groupid=:groupid OR c.groupid='0')"; |
84a2fdd7 |
530 | } else { |
531 | $groupselect = ""; |
532 | } |
6e5f40ea |
533 | |
a12e11c1 |
534 | if (!empty($CFG->enablegroupings) && !(empty($groupingid))) { |
d3bf6f92 |
535 | $groupingjoin = "JOIN {groups_members} gm ON u.id = gm.userid |
536 | JOIN {groupings_groups} gg ON gm.groupid = gg.groupid AND gg.groupingid = :groupingid "; |
6e5f40ea |
537 | |
a12e11c1 |
538 | } else { |
539 | $groupingjoin = ''; |
540 | } |
b5de723d |
541 | |
547ac664 |
542 | return $DB->get_records_sql("SELECT |
543 | DISTINCT u.id, u.firstname, u.lastname, u.picture, c.lastmessageping, c.firstping, u.imagealt |
544 | FROM {chat_users} c JOIN {user} u ON u.id = c.userid $groupingjoin |
545 | WHERE c.chatid = :chatid $groupselect |
546 | ORDER BY c.firstping ASC", $params); |
1515a89e |
547 | } |
548 | |
848bb113 |
549 | /** |
550 | * @global object |
551 | * @param int $chatid |
552 | * @param int $groupid |
553 | * @return array |
554 | */ |
84a2fdd7 |
555 | function chat_get_latest_message($chatid, $groupid=0) { |
f33e1ed4 |
556 | global $DB; |
1515a89e |
557 | |
d3bf6f92 |
558 | $params = array('chatid'=>$chatid, 'groupid'=>$groupid); |
1515a89e |
559 | |
84a2fdd7 |
560 | if ($groupid) { |
d3bf6f92 |
561 | $groupselect = "AND (groupid=:groupid OR groupid=0)"; |
84a2fdd7 |
562 | } else { |
563 | $groupselect = ""; |
564 | } |
565 | |
547ac664 |
566 | $sql = "SELECT * |
567 | FROM {chat_messages_current} WHERE chatid = :chatid $groupselect |
568 | ORDER BY timestamp DESC"; |
03cedd62 |
569 | |
547ac664 |
570 | // return the lastest one message |
f33e1ed4 |
571 | return $DB->get_record_sql($sql, $params, true); |
1515a89e |
572 | } |
573 | |
5a8625e4 |
574 | |
1515a89e |
575 | ////////////////////////////////////////////////////////////////////// |
516121bd |
576 | // login if not already logged in |
1515a89e |
577 | |
848bb113 |
578 | /** |
579 | * login if not already logged in |
580 | * |
581 | * @global object |
582 | * @global object |
583 | * @param int $chatid |
584 | * @param string $version |
585 | * @param int $groupid |
586 | * @param object $course |
587 | * @return bool|int Returns the chat users sid or false |
588 | */ |
a32c7772 |
589 | function chat_login_user($chatid, $version, $groupid, $course) { |
d3bf6f92 |
590 | global $USER, $DB; |
591 | |
592 | if (($version != 'sockets') and $chatuser = $DB->get_record('chat_users', array('chatid'=>$chatid, 'userid'=>$USER->id, 'groupid'=>$groupid))) { |
7f0483f6 |
593 | // this will update logged user information |
516121bd |
594 | $chatuser->version = $version; |
d96466d2 |
595 | $chatuser->ip = $USER->lastip; |
516121bd |
596 | $chatuser->lastping = time(); |
597 | $chatuser->lang = current_language(); |
1515a89e |
598 | |
d96466d2 |
599 | // Sometimes $USER->lastip is not setup properly |
d13ef2fb |
600 | // during login. Update with current value if possible |
f83edcb1 |
601 | // or provide a dummy value for the db |
d13ef2fb |
602 | if (empty($chatuser->ip)) { |
603 | $chatuser->ip = getremoteaddr(); |
604 | if (empty($chatuser->ip)) { |
f83edcb1 |
605 | $chatuser->ip = ''; |
d13ef2fb |
606 | } |
607 | } |
608 | |
7f0483f6 |
609 | if (($chatuser->course != $course->id) or ($chatuser->userid != $USER->id)) { |
516121bd |
610 | return false; |
611 | } |
a8c31db2 |
612 | $DB->update_record('chat_users', $chatuser); |
613 | |
516121bd |
614 | } else { |
6ee78cee |
615 | $chatuser = new object(); |
516121bd |
616 | $chatuser->chatid = $chatid; |
617 | $chatuser->userid = $USER->id; |
618 | $chatuser->groupid = $groupid; |
619 | $chatuser->version = $version; |
d96466d2 |
620 | $chatuser->ip = $USER->lastip; |
516121bd |
621 | $chatuser->lastping = $chatuser->firstping = $chatuser->lastmessageping = time(); |
622 | $chatuser->sid = random_string(32); |
3dfd307f |
623 | $chatuser->course = $course->id; //caching - needed for current_language too |
624 | $chatuser->lang = current_language(); //caching - to resource intensive to find out later |
516121bd |
625 | |
d96466d2 |
626 | // Sometimes $USER->lastip is not setup properly |
274f0091 |
627 | // during login. Update with current value if possible |
628 | // or provide a dummy value for the db |
629 | if (empty($chatuser->ip)) { |
630 | $chatuser->ip = getremoteaddr(); |
631 | if (empty($chatuser->ip)) { |
632 | $chatuser->ip = ''; |
633 | } |
634 | } |
635 | |
636 | |
a8c31db2 |
637 | $DB->insert_record('chat_users', $chatuser); |
516121bd |
638 | |
a32c7772 |
639 | if ($version == 'sockets') { |
640 | // do not send 'enter' message, chatd will do it |
641 | } else { |
6ee78cee |
642 | $message = new object(); |
2ac0d13b |
643 | $message->chatid = $chatuser->chatid; |
644 | $message->userid = $chatuser->userid; |
645 | $message->groupid = $groupid; |
646 | $message->message = 'enter'; |
647 | $message->system = 1; |
648 | $message->timestamp = time(); |
649 | |
7826abc7 |
650 | $DB->insert_record('chat_messages', $message); |
651 | $DB->insert_record('chat_messages_current', $message); |
516121bd |
652 | } |
1515a89e |
653 | } |
654 | |
655 | return $chatuser->sid; |
656 | } |
657 | |
848bb113 |
658 | /** |
659 | * Delete the old and in the way |
660 | * |
661 | * @global object |
662 | * @global object |
663 | */ |
7d792369 |
664 | function chat_delete_old_users() { |
665 | // Delete the old and in the way |
d3bf6f92 |
666 | global $CFG, $DB; |
b5012f3e |
667 | |
e7fbd0b3 |
668 | $timeold = time() - $CFG->chat_old_ping; |
953eb6f3 |
669 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts |
a32c7772 |
670 | |
d3bf6f92 |
671 | $query = "(version<>'basic' AND lastping<?) OR (version='basic' AND lastping<?)"; |
672 | $params = array($timeold, $timeoldext); |
7d792369 |
673 | |
d3bf6f92 |
674 | if ($oldusers = $DB->get_records_select('chat_users', $query, $params) ) { |
675 | $DB->delete_records_select('chat_users', $query, $params); |
7d792369 |
676 | foreach ($oldusers as $olduser) { |
6ee78cee |
677 | $message = new object(); |
516121bd |
678 | $message->chatid = $olduser->chatid; |
679 | $message->userid = $olduser->userid; |
680 | $message->groupid = $olduser->groupid; |
681 | $message->message = 'exit'; |
682 | $message->system = 1; |
7d792369 |
683 | $message->timestamp = time(); |
b5de723d |
684 | |
7826abc7 |
685 | $DB->insert_record('chat_messages', $message); |
686 | $DB->insert_record('chat_messages_current', $message); |
7d792369 |
687 | } |
688 | } |
689 | } |
1515a89e |
690 | |
848bb113 |
691 | /** |
692 | * Updates chat records so that the next chat time is correct |
693 | * |
694 | * @global object |
695 | * @param int $chatid |
696 | * @return void |
697 | */ |
fcd3a1ee |
698 | function chat_update_chat_times($chatid=0) { |
699 | /// Updates chat records so that the next chat time is correct |
d3bf6f92 |
700 | global $DB; |
fcd3a1ee |
701 | |
702 | $timenow = time(); |
d3bf6f92 |
703 | |
704 | $params = array('timenow'=>$timenow, 'chatid'=>$chatid); |
705 | |
fcd3a1ee |
706 | if ($chatid) { |
d3bf6f92 |
707 | if (!$chats[] = $DB->get_record_select("chat", "id = :chatid AND chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee |
708 | return; |
709 | } |
710 | } else { |
d3bf6f92 |
711 | if (!$chats = $DB->get_records_select("chat", "chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee |
712 | return; |
713 | } |
714 | } |
715 | |
716 | foreach ($chats as $chat) { |
717 | switch ($chat->schedule) { |
718 | case 1: // Single event - turn off schedule and disable |
719 | $chat->chattime = 0; |
720 | $chat->schedule = 0; |
721 | break; |
722 | case 2: // Repeat daily |
f0d3bb9e |
723 | while ($chat->chattime <= $timenow) { |
724 | $chat->chattime += 24 * 3600; |
725 | } |
fcd3a1ee |
726 | break; |
727 | case 3: // Repeat weekly |
f0d3bb9e |
728 | while ($chat->chattime <= $timenow) { |
729 | $chat->chattime += 7 * 24 * 3600; |
730 | } |
fcd3a1ee |
731 | break; |
732 | } |
d3bf6f92 |
733 | $DB->update_record("chat", $chat); |
734 | |
735 | $event = new object(); // Update calendar too |
8496c4af |
736 | |
d3bf6f92 |
737 | $cond = "modulename='chat' AND instance = :chatid AND timestart <> :chattime"; |
738 | $params = array('chattime'=>$chat->chattime, 'chatid'=>$chatid); |
739 | |
740 | if ($event->id = $DB->get_field_select('event', 'id', $cond, $params)) { |
8496c4af |
741 | $event->timestart = $chat->chattime; |
742 | update_event($event); |
743 | } |
fcd3a1ee |
744 | } |
745 | } |
746 | |
848bb113 |
747 | /** |
748 | * @global object |
749 | * @global object |
750 | * @param object $message |
751 | * @param int $courseid |
752 | * @param object $sender |
753 | * @param object $currentuser |
754 | * @param string $chat_lastrow |
755 | * @return bool|string Returns HTML or false |
756 | */ |
aa5c32fd |
757 | function chat_format_message_manually($message, $courseid, $sender, $currentuser, $chat_lastrow=NULL) { |
83064f9c |
758 | global $CFG, $USER, $OUTPUT, $COURSE; |
1515a89e |
759 | |
83064f9c |
760 | $result = new object(); |
761 | $result->beep = false; // by default |
762 | $result->refreshusers = false; // by default |
7d792369 |
763 | |
72989350 |
764 | // Use get_user_timezone() to find the correct timezone for displaying this message: |
765 | // It's either the current user's timezone or else decided by some Moodle config setting |
970f144e |
766 | // First, "reset" $USER->timezone (which could have been set by a previous call to here) |
767 | // because otherwise the value for the previous $currentuser will take precedence over $CFG->timezone |
768 | $USER->timezone = 99; |
72989350 |
769 | $tz = get_user_timezone($currentuser->timezone); |
b5de723d |
770 | |
72989350 |
771 | // Before formatting the message time string, set $USER->timezone to the above. |
772 | // This will allow dst_offset_on (called by userdate) to work correctly, otherwise the |
773 | // message times appear off because DST is not taken into account when it should be. |
774 | $USER->timezone = $tz; |
b5de723d |
775 | $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz); |
776 | |
af7bad79 |
777 | $message->picture = $OUTPUT->user_picture(moodle_user_picture::make($sender, $courseid)); |
83064f9c |
778 | if (empty($courseid)) { |
779 | $courseid = $COURSE->id; |
582de679 |
780 | } |
83064f9c |
781 | $message->picture = "<a target='_blank' href=\"$CFG->wwwroot/user/view.php?id=$sender->id&course=$courseid\">$message->picture</a>"; |
1515a89e |
782 | |
aa5c32fd |
783 | //Calculate the row class |
784 | if ($chat_lastrow !== NULL) { |
785 | $rowclass = ' class="r'.$chat_lastrow.'" '; |
786 | } else { |
787 | $rowclass = ''; |
788 | } |
789 | |
b5de723d |
790 | // Start processing the message |
b5de723d |
791 | if(!empty($message->system)) { |
792 | // System event |
83064f9c |
793 | $result->text = $message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender)); |
794 | |
795 | $result->html = '<div class="chat-event">'; |
796 | $result->html .= '<span class="time">'.$message->strtime.'</span> '; |
797 | $userlink = "<a target='_blank' href=\"$CFG->wwwroot/user/view.php?id=$sender->id&course=$courseid\">".fullname($sender)."</a>"; |
798 | $result->html .= '<span class="event">'.get_string('message'.$message->message, 'chat', $userlink).'</span> '; |
799 | $result->html .= '</div>'; |
800 | |
801 | $result->basic = '<dl><dt class="event">'.$message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender)).'</dt></dl>'; |
7d792369 |
802 | |
516121bd |
803 | if($message->message == 'exit' or $message->message == 'enter') { |
83064f9c |
804 | $result->refreshusers = true; //force user panel refresh ASAP |
516121bd |
805 | } |
83064f9c |
806 | return $result; |
1515a89e |
807 | } |
808 | |
82a524ef |
809 | // It's not a system event |
b5de723d |
810 | $text = $message->message; |
82a524ef |
811 | |
812 | /// Parse the text to clean and filter it |
6ee78cee |
813 | $options = new object(); |
82a524ef |
814 | $options->para = false; |
815 | $text = format_text($text, FORMAT_MOODLE, $options, $courseid); |
927a7808 |
816 | |
b5de723d |
817 | // And now check for special cases |
927a7808 |
818 | $special = false; |
83064f9c |
819 | $outtime = $message->strtime; |
927a7808 |
820 | |
b5de723d |
821 | if (substr($text, 0, 5) == 'beep ') { |
6e5f40ea |
822 | /// It's a beep! |
927a7808 |
823 | $special = true; |
7d792369 |
824 | $beepwho = trim(substr($text, 5)); |
9f85bed4 |
825 | |
b5de723d |
826 | if ($beepwho == 'all') { // everyone |
83064f9c |
827 | $outmain = get_string('messagebeepseveryone', 'chat', fullname($sender)); |
828 | $result->beep = true; // (eventually this should be set to |
7d792369 |
829 | // to a filename uploaded by the user) |
830 | |
82a524ef |
831 | } else if ($beepwho == $currentuser->id) { // current user |
83064f9c |
832 | $outmain = get_string('messagebeepsyou', 'chat', fullname($sender)); |
833 | $result->beep = true; |
264867fd |
834 | |
0eda0a46 |
835 | } else { //something is not caught? |
7d792369 |
836 | return false; |
837 | } |
b5de723d |
838 | } else if (substr($text, 0, 1) == '/') { /// It's a user command |
1d507186 |
839 | // support some IRC commands |
840 | $pattern = '#(^\/)(\w+).*#'; |
841 | preg_match($pattern, trim($text), $matches); |
842 | $command = $matches[2]; |
843 | switch ($command){ |
844 | case 'me': |
927a7808 |
845 | $special = true; |
1d507186 |
846 | $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>'; |
847 | break; |
1515a89e |
848 | } |
7f0483f6 |
849 | } elseif (substr($text, 0, 2) == 'To') { |
850 | $pattern = '#To[[:space:]](.*):(.*)#'; |
851 | preg_match($pattern, trim($text), $matches); |
852 | $special = true; |
83064f9c |
853 | $outmain = $sender->firstname.' <b>'.get_string('saidto', 'chat').'</b> <i>'.$matches[1].'</i>: '.$matches[2]; |
927a7808 |
854 | } |
9f85bed4 |
855 | |
927a7808 |
856 | if(!$special) { |
7d792369 |
857 | $outmain = $text; |
1515a89e |
858 | } |
264867fd |
859 | |
83064f9c |
860 | $result->text = strip_tags($outtime.': '.$outmain); |
1515a89e |
861 | |
83064f9c |
862 | $result->html = "<table class=\"chat-message\"><tr$rowclass><td class=\"picture\" valign=\"top\">$message->picture</td><td class=\"text\">"; |
7d792369 |
863 | |
83064f9c |
864 | $result->html .= "<span class=\"time\">[{$outtime}]</span> "; |
865 | if(!$special) { |
866 | $result->html .= "<span class=\"user\">{$sender->firstname}</span>"; |
867 | $result->html .= ": $outmain"; |
6ee78cee |
868 | } else { |
83064f9c |
869 | $result->html .= "$outmain"; |
7d792369 |
870 | } |
83064f9c |
871 | $result->html .= "</td></tr></table>"; |
872 | |
873 | $result->basic = '<dl><dt>'; |
874 | $result->basic .= '<span cass="time">['.$outtime.']</span> '; |
875 | $result->basic .= '<span class="user">'.$sender->firstname.'</span>'; |
876 | $result->basic .= ': '; |
877 | $result->basic .= '</dt>'; |
878 | $result->basic .= '<dd class="text">'.$outmain.'</dd>'; |
879 | $result->basic .= '</dl>'; |
880 | |
881 | return $result; |
b5de723d |
882 | } |
883 | |
848bb113 |
884 | /** |
885 | * @global object |
886 | * @param object $message |
887 | * @param int $courseid |
888 | * @param object $currentuser |
889 | * @param string $chat_lastrow |
890 | * @return bool|string Returns HTML or false |
891 | */ |
aa5c32fd |
892 | function chat_format_message($message, $courseid, $currentuser, $chat_lastrow=NULL) { |
b5de723d |
893 | /// Given a message object full of information, this function |
894 | /// formats it appropriately into text and html, then |
895 | /// returns the formatted data. |
d3bf6f92 |
896 | global $DB; |
b5de723d |
897 | |
78c98892 |
898 | static $users; // Cache user lookups |
899 | |
900 | if (isset($users[$message->userid])) { |
901 | $user = $users[$message->userid]; |
d3bf6f92 |
902 | } else if ($user = $DB->get_record('user', array('id'=>$message->userid), 'id,picture,firstname,lastname')) { |
78c98892 |
903 | $users[$message->userid] = $user; |
904 | } else { |
905 | return NULL; |
b5de723d |
906 | } |
aa5c32fd |
907 | return chat_format_message_manually($message, $courseid, $user, $currentuser, $chat_lastrow); |
1515a89e |
908 | } |
909 | |
83064f9c |
910 | /** |
911 | * @global object $DB |
912 | * @global object $CFG |
913 | * @global object $COURSE |
914 | * @global object $OUTPUT |
915 | * @param object $users |
916 | * @param object $course |
917 | * @return array return formatted user list |
918 | */ |
919 | function chat_format_userlist($users, $course) { |
920 | global $CFG, $DB, $COURSE, $OUTPUT; |
921 | $result = array(); |
922 | foreach($users as $user){ |
923 | $item = array(); |
924 | $item['name'] = fullname($user); |
ff0e58c8 |
925 | $item['url'] = $CFG->wwwroot.'/user/view.php?id='.$user->id.'&course='.$course->id; |
83064f9c |
926 | $item['picture'] = $OUTPUT->user_picture(moodle_user_picture::make($user, $COURSE->id)); |
927 | $item['id'] = $user->id; |
928 | $result[] = $item; |
929 | } |
930 | return $result; |
931 | } |
932 | |
933 | /** |
934 | * Print json format error |
935 | * @param string $level |
936 | * @param string $msg |
937 | */ |
938 | function chat_print_error($level, $msg) { |
939 | header('Content-Length: ' . ob_get_length() ); |
940 | $error = new stdclass; |
941 | $error->level = $level; |
942 | $error->msg = $msg; |
943 | $response['error'] = $error; |
944 | echo json_encode($response); |
945 | ob_end_flush(); |
946 | exit; |
947 | } |
948 | |
848bb113 |
949 | /** |
950 | * @return array |
951 | */ |
f3221af9 |
952 | function chat_get_view_actions() { |
953 | return array('view','view all','report'); |
954 | } |
955 | |
848bb113 |
956 | /** |
957 | * @return array |
958 | */ |
f3221af9 |
959 | function chat_get_post_actions() { |
960 | return array('talk'); |
961 | } |
962 | |
848bb113 |
963 | /** |
964 | * @global object |
965 | * @global object |
966 | * @param array $courses |
967 | * @param array $htmlarray Passed by reference |
968 | */ |
9ca0187e |
969 | function chat_print_overview($courses, &$htmlarray) { |
970 | global $USER, $CFG; |
971 | |
972 | if (empty($courses) || !is_array($courses) || count($courses) == 0) { |
973 | return array(); |
974 | } |
975 | |
976 | if (!$chats = get_all_instances_in_courses('chat',$courses)) { |
977 | return; |
978 | } |
979 | |
980 | $strchat = get_string('modulename', 'chat'); |
981 | $strnextsession = get_string('nextsession', 'chat'); |
9ca0187e |
982 | |
983 | foreach ($chats as $chat) { |
9ca0187e |
984 | if ($chat->chattime and $chat->schedule) { // A chat is scheduled |
a2a37336 |
985 | $str = '<div class="chat overview"><div class="name">'. |
986 | $strchat.': <a '.($chat->visible?'':' class="dimmed"'). |
987 | ' href="'.$CFG->wwwroot.'/mod/chat/view.php?id='.$chat->coursemodule.'">'. |
988 | $chat->name.'</a></div>'; |
989 | $str .= '<div class="info">'.$strnextsession.': '.userdate($chat->chattime).'</div></div>'; |
990 | |
991 | if (empty($htmlarray[$chat->course]['chat'])) { |
992 | $htmlarray[$chat->course]['chat'] = $str; |
993 | } else { |
994 | $htmlarray[$chat->course]['chat'] .= $str; |
995 | } |
9ca0187e |
996 | } |
9ca0187e |
997 | } |
998 | } |
999 | |
0b5a80a1 |
1000 | |
1001 | /** |
1002 | * Implementation of the function for printing the form elements that control |
1003 | * whether the course reset functionality affects the chat. |
848bb113 |
1004 | * |
1005 | * @param object $mform form passed by reference |
0b5a80a1 |
1006 | */ |
1007 | function chat_reset_course_form_definition(&$mform) { |
1008 | $mform->addElement('header', 'chatheader', get_string('modulenameplural', 'chat')); |
1009 | $mform->addElement('advcheckbox', 'reset_chat', get_string('removemessages','chat')); |
1010 | } |
1011 | |
1012 | /** |
1013 | * Course reset form defaults. |
848bb113 |
1014 | * |
1015 | * @param object $course |
1016 | * @return array |
0b5a80a1 |
1017 | */ |
1018 | function chat_reset_course_form_defaults($course) { |
1019 | return array('reset_chat'=>1); |
1020 | } |
1021 | |
1022 | /** |
1023 | * Actual implementation of the rest coures functionality, delete all the |
1024 | * chat messages for course $data->courseid. |
848bb113 |
1025 | * |
1026 | * @global object |
1027 | * @global object |
1028 | * @param object $data the data submitted from the reset course. |
0b5a80a1 |
1029 | * @return array status array |
1030 | */ |
1031 | function chat_reset_userdata($data) { |
d3bf6f92 |
1032 | global $CFG, $DB; |
0b5a80a1 |
1033 | |
1034 | $componentstr = get_string('modulenameplural', 'chat'); |
1035 | $status = array(); |
1036 | |
1037 | if (!empty($data->reset_chat)) { |
1038 | $chatessql = "SELECT ch.id |
d3bf6f92 |
1039 | FROM {chat} ch |
1040 | WHERE ch.course=?"; |
1041 | $params = array($data->courseid); |
0b5a80a1 |
1042 | |
d3bf6f92 |
1043 | $DB->delete_records_select('chat_messages', "chatid IN ($chatessql)", $params); |
6e5f40ea |
1044 | $DB->delete_records_select('chat_messages_current', "chatid IN ($chatessql)", $params); |
d3bf6f92 |
1045 | $DB->delete_records_select('chat_users', "chatid IN ($chatessql)", $params); |
0b5a80a1 |
1046 | $status[] = array('component'=>$componentstr, 'item'=>get_string('removemessages', 'chat'), 'error'=>false); |
1047 | } |
1048 | |
1049 | /// updating dates - shift may be negative too |
1050 | if ($data->timeshift) { |
1051 | shift_course_mod_dates('chat', array('chattime'), $data->timeshift, $data->courseid); |
1052 | $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); |
1053 | } |
1054 | |
1055 | return $status; |
1056 | } |
1057 | |
f432bebf |
1058 | /** |
1059 | * Returns all other caps used in module |
848bb113 |
1060 | * |
1061 | * @return array |
f432bebf |
1062 | */ |
1063 | function chat_get_extra_capabilities() { |
1064 | return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames'); |
1065 | } |
1066 | |
848bb113 |
1067 | /** |
b2d5a79a |
1068 | * @package mod-chat |
848bb113 |
1069 | * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} |
1070 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
1071 | */ |
47cfd331 |
1072 | class chat_portfolio_caller extends portfolio_module_caller_base { |
848bb113 |
1073 | /** @var object */ |
47cfd331 |
1074 | private $chat; |
848bb113 |
1075 | /** @var int Timestamp */ |
0d06b6fd |
1076 | protected $start; |
848bb113 |
1077 | /** @var int Timestamp */ |
0d06b6fd |
1078 | protected $end; |
848bb113 |
1079 | /** |
1080 | * @return array |
1081 | */ |
0d06b6fd |
1082 | public static function expected_callbackargs() { |
1083 | return array( |
1084 | 'id' => true, |
1085 | 'start' => false, |
1086 | 'end' => false, |
1087 | ); |
1088 | } |
848bb113 |
1089 | /** |
1090 | * @global object |
1091 | */ |
0d06b6fd |
1092 | public function load_data() { |
1093 | global $DB; |
47cfd331 |
1094 | |
0d06b6fd |
1095 | if (!$this->cm = get_coursemodule_from_id('chat', $this->id)) { |
34035201 |
1096 | throw new portfolio_caller_exception('invalidid', 'chat'); |
47cfd331 |
1097 | } |
1098 | $this->chat = $DB->get_record('chat', array('id' => $this->cm->instance)); |
1099 | $select = 'chatid = ?'; |
1100 | $params = array($this->chat->id); |
0d06b6fd |
1101 | if ($this->start && $this->end) { |
47cfd331 |
1102 | $select .= ' AND timestamp >= ? AND timestamp <= ?'; |
0d06b6fd |
1103 | $params[] = $this->start; |
1104 | $params[] = $this->end; |
47cfd331 |
1105 | } |
1106 | $this->messages = $DB->get_records_select( |
1107 | 'chat_messages', |
1108 | $select, |
1109 | $params, |
1110 | 'timestamp ASC' |
1111 | ); |
1112 | $select .= ' AND userid = ?'; |
0d06b6fd |
1113 | $params[] = $this->user->id; |
47cfd331 |
1114 | $this->participated = $DB->record_exists_select( |
1115 | 'chat_messages', |
1116 | $select, |
1117 | $params |
1118 | ); |
0d06b6fd |
1119 | } |
848bb113 |
1120 | /** |
1121 | * @return array |
1122 | */ |
a7d90683 |
1123 | public static function supported_formats() { |
6be1dcae |
1124 | return array(PORTFOLIO_FORMAT_PLAINHTML); |
47cfd331 |
1125 | } |
848bb113 |
1126 | /** |
1127 | * |
1128 | */ |
47cfd331 |
1129 | public function expected_time() { |
d8606b20 |
1130 | return portfolio_expected_time_db(count($this->messages)); |
47cfd331 |
1131 | } |
848bb113 |
1132 | /** |
1133 | * @return string |
1134 | */ |
47cfd331 |
1135 | public function get_sha1() { |
1136 | $str = ''; |
1137 | ksort($this->messages); |
1138 | foreach ($this->messages as $m) { |
1139 | $str .= implode('', (array)$m); |
1140 | } |
1141 | return sha1($str); |
1142 | } |
1143 | |
848bb113 |
1144 | /** |
1145 | * @return bool |
1146 | */ |
47cfd331 |
1147 | public function check_permissions() { |
1148 | $context = get_context_instance(CONTEXT_MODULE, $this->cm->id); |
1149 | return has_capability('mod/chat:exportsession', $context) |
1150 | || ($this->participated |
1151 | && has_capability('mod/chat:exportparticipatedsession', $context)); |
1152 | } |
848bb113 |
1153 | |
1154 | /** |
1155 | * @todo Document this function |
1156 | */ |
47cfd331 |
1157 | public function prepare_package() { |
1158 | $content = ''; |
5a04379a |
1159 | $lasttime = 0; |
1160 | $sessiongap = 5 * 60; // 5 minutes silence means a new session |
47cfd331 |
1161 | foreach ($this->messages as $message) { // We are walking FORWARDS through messages |
5a04379a |
1162 | $m = clone $message; // grrrrrr - this causes the sha1 to change as chat_format_message changes what it's passed. |
47cfd331 |
1163 | $formatmessage = chat_format_message($m, null, $this->user); |
1164 | if (!isset($formatmessage->html)) { |
1165 | continue; |
1166 | } |
5a04379a |
1167 | if (empty($lasttime) || (($message->timestamp - $lasttime) > $sessiongap)) { |
1168 | $content .= '<hr />'; |
1169 | $content .= userdate($message->timestamp); |
1170 | } |
47cfd331 |
1171 | $content .= $formatmessage->html; |
5a04379a |
1172 | $lasttime = $message->timestamp; |
47cfd331 |
1173 | } |
1174 | $content = preg_replace('/\<img[^>]*\>/', '', $content); |
1175 | |
6be1dcae |
1176 | $this->exporter->write_new_file($content, clean_filename($this->cm->name . '-session.html'), false); |
47cfd331 |
1177 | } |
1178 | |
848bb113 |
1179 | /** |
1180 | * @return string |
1181 | */ |
47cfd331 |
1182 | public static function display_name() { |
1183 | return get_string('modulename', 'chat'); |
1184 | } |
1185 | |
848bb113 |
1186 | /** |
1187 | * @global object |
1188 | * @return string |
1189 | */ |
47cfd331 |
1190 | public function get_return_url() { |
1191 | global $CFG; |
1192 | |
1193 | return $CFG->wwwroot . '/mod/chat/report.php?id=' |
1194 | . $this->cm->id . ((isset($this->start)) |
1195 | ? '&start=' . $this->start . '&end=' . $this->end |
1196 | : ''); |
1197 | } |
1198 | } |
1199 | |
42f103be |
1200 | /** |
1201 | * @param string $feature FEATURE_xx constant for requested feature |
1202 | * @return mixed True if module supports feature, null if doesn't know |
1203 | */ |
1204 | function chat_supports($feature) { |
1205 | switch($feature) { |
1206 | case FEATURE_GROUPS: return true; |
1207 | case FEATURE_GROUPINGS: return true; |
1208 | case FEATURE_GROUPMEMBERSONLY: return true; |
dc5c2bd9 |
1209 | case FEATURE_MOD_INTRO: return true; |
42f103be |
1210 | case FEATURE_COMPLETION_TRACKS_VIEWS: return false; |
1211 | case FEATURE_GRADE_HAS_GRADE: return false; |
1212 | case FEATURE_GRADE_OUTCOMES: return true; |
1213 | |
1214 | default: return null; |
1215 | } |
1216 | } |
b14ae498 |
1217 | |
1218 | function chat_extend_navigation($navigation, $course, $module, $cm) { |
1219 | global $CFG, $USER, $PAGE, $OUTPUT; |
1220 | if (has_capability('mod/chat:chat',$cm->context)) { |
1221 | $strenterchat = get_string('enterchat', 'chat'); |
1222 | $currentgroup = groups_get_activity_group($cm, true); |
1223 | |
1224 | $target = $CFG->wwwroot.'/mod/chat/'; |
1225 | $params = array('id'=>$cm->instance); |
1226 | |
1227 | if ($currentgroup) { |
1228 | $params['groupid'] = $currentgroup; |
1229 | } |
1230 | |
1231 | $links = array(); |
1232 | |
1233 | if (!empty($USER->screenreader)) { |
1234 | $links[] = html_link::make(new moodle_url($target.'gui_basic/index.php', $params), $strenterchat); |
1235 | } else { |
1236 | $links[] = html_link::make(new moodle_url($target.'gui_'.$CFG->chat_method.'/index.php', $params), $strenterchat); |
1237 | } |
1238 | |
1239 | if ($CFG->enableajax) { |
1240 | $links[] = html_link::make(new moodle_url($target.'gui_ajax/index.php', $params), get_string('ajax_gui', 'message')); |
1241 | } |
1242 | |
1243 | if ($CFG->chat_method == 'header_js' && empty($USER->screenreader)) { |
1244 | $links[] = html_link::make(new moodle_url($target.'gui_basic/index.php', $params), get_string('noframesjs', 'message')); |
1245 | } |
1246 | |
1247 | foreach ($links as $link) { |
1248 | $link->add_action(new popup_action('click', $link->url, 'chat'.$course->id.$cm->instance.$currentgroup, array('height' => 500, 'width' => 700))); |
1249 | $link->title = get_string('modulename', 'chat'); |
1250 | $navigation->add($link->title, $link, navigation_node::TYPE_ACTIVITY, null ,null, $OUTPUT->old_icon_url('c/group')); |
1251 | } |
1252 | } |
1253 | |
1254 | $chatusers = chat_get_users($cm->instance, $currentgroup, $cm->groupingid); |
1255 | if (is_array($chatusers) && count($chatusers)>0) { |
1256 | $userskey = $navigation->add(get_string('currentusers', 'chat')); |
1257 | $users = $navigation->get($userskey); |
1258 | foreach ($chatusers as $chatuser) { |
1259 | $userlink = new moodle_url($CFG->wwwroot.'/user/view.php', array('id'=>$chatuser->id,'course'=>$course->id)); |
1260 | $users->add(fullname($chatuser).' '.format_time(time() - $chatuser->lastmessageping), $userlink, navigation_node::TYPE_USER, null, null, $OUTPUT->old_icon_url('c/user')); |
1261 | } |
1262 | } |
1263 | } |
1264 | |
1265 | function chat_extend_settings_navigation($settingsnav, $module) { |
1266 | global $DB, $PAGE, $USER, $CFG; |
1267 | $chat = $DB->get_record("chat", array("id" => $PAGE->cm->instance)); |
1268 | $chatnavkey = $settingsnav->add(get_string('chatadministration', 'chat')); |
1269 | $chatnav = $settingsnav->get($chatnavkey); |
1270 | $chatnav->forceopen = true; |
1271 | if ($chat->chattime && $chat->schedule) { |
1272 | $key = $chatnav->add(get_string('nextsession', 'chat').': '.userdate($chat->chattime).' ('.usertimezone($USER->timezone)); |
1273 | $chatnav->get($key)->add_class('note'); |
1274 | } |
1275 | |
1276 | $currentgroup = groups_get_activity_group($PAGE->cm, true); |
1277 | if ($currentgroup) { |
1278 | $groupselect = " AND groupid = '$currentgroup'"; |
1279 | } else { |
1280 | $groupselect = ''; |
1281 | } |
1282 | |
1283 | if ($chat->studentlogs || has_capability('mod/chat:readlog',$PAGE->cm->context)) { |
1284 | if ($DB->get_records_select('chat_messages', "chatid = ? $groupselect", array($chat->id))) { |
1285 | $chatnav->add(get_string('viewreport', 'chat'), new moodle_url($CFG->wwwroot.'/mod/chat/report.php', array('id'=>$PAGE->cm->id))); |
1286 | } |
1287 | } |
1288 | |
1289 | if (has_capability('moodle/course:manageactivities', $PAGE->cm->context)) { |
1290 | $chatnav->add(get_string('updatethis', '', get_string('modulename', 'chat')), new moodle_url($CFG->wwwroot.'/course/mod.php', array('update' => $PAGE->cm->id, 'return' => true, 'sesskey' => sesskey()))); |
1291 | } |
1292 | } |