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