My Moodle/Courses: MDL-20472 get_my_courses returns 2 more courses then limit. Repair...
[moodle.git] / mod / chat / lib.php
CommitLineData
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 27require_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 30global $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 34global $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[
39function move(){
40 if (scroll_active)
41 window.scroll(1,400000);
42 window.setTimeout("move()",100);
43}
44var scroll_active = true;
45move();
46//]]>
47</script>
48</head>
49<body onBlur="scroll_active = true" onFocus="scroll_active = false">
50EOD;
17da2e6f 51global $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 55global $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 59global $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 63global $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();">;
81EOD;
1515a89e 82
fbabbd23 83// Dummy data that gets output to the browser as needed, in order to make it show output
17da2e6f 84global $CHAT_DUMMY_DATA;
6e5f40ea 85$CHAT_DUMMY_DATA = padding(200);
5c2f6a7f 86
848bb113 87/**
88 * @param int $n
89 * @return string
90 */
6e5f40ea 91function 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 109function 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 143function 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 176function 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 223function 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 237function 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 253function 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 403function 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 440function 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 472function 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 523function 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 555function 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 589function 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 664function 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 698function 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 757function 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&amp;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&amp;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 892function 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 */
919function 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.'&amp;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 */
938function 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 952function chat_get_view_actions() {
953 return array('view','view all','report');
954}
955
848bb113 956/**
957 * @return array
958 */
f3221af9 959function 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 969function 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 */
1007function 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 */
1018function 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 */
1031function 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 */
1063function 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 1072class 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 */
1204function 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
1218function 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
1265function 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}