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]; |
277 | $cm->lasttime = $mcm->lasttime; | |
dd97c328 | 278 | if (!$modinfo->cms[$cm->id]->uservisible) { |
279 | continue; | |
280 | } | |
b7602a11 | 281 | |
dd97c328 | 282 | if (groups_get_activity_groupmode($cm) != SEPARATEGROUPS |
6536217c | 283 | or has_capability('moodle/site:accessallgroups', context_module::instance($cm->id))) { |
dd97c328 | 284 | if ($timeout > time() - $cm->lasttime) { |
285 | $current[] = $cm; | |
286 | } else { | |
287 | $past[] = $cm; | |
288 | } | |
289 | ||
290 | continue; | |
291 | } | |
292 | ||
293 | if (is_null($modinfo->groups)) { | |
294 | $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo | |
295 | } | |
c5a05b95 | 296 | |
dd97c328 | 297 | // verify groups in separate mode |
298 | if (!$mygroupids = $modinfo->groups[$cm->groupingid]) { | |
299 | continue; | |
300 | } | |
0469cccf | 301 | |
dd97c328 | 302 | // ok, last post was not for my group - we have to query db to get last message from one of my groups |
303 | // only minor problem is that the order will not be correct | |
304 | $mygroupids = implode(',', $mygroupids); | |
305 | $cm->mygroupids = $mygroupids; | |
306 | ||
d3bf6f92 | 307 | if (!$mcm = $DB->get_record_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime |
308 | FROM {course_modules} cm | |
309 | JOIN {chat} ch ON ch.id = cm.instance | |
6e5f40ea | 310 | JOIN {chat_messages_current} chm ON chm.chatid = ch.id |
d3bf6f92 | 311 | WHERE chm.timestamp > ? AND cm.id = ? AND |
312 | (chm.groupid IN ($mygroupids) OR chm.groupid = 0) | |
313 | GROUP BY cm.id", array($timestart, $cm->id))) { | |
dd97c328 | 314 | continue; |
315 | } | |
fd4d41c3 | 316 | |
317 | $cm->lasttime = $mcm->lasttime; | |
dd97c328 | 318 | if ($timeout > time() - $cm->lasttime) { |
319 | $current[] = $cm; | |
320 | } else { | |
321 | $past[] = $cm; | |
322 | } | |
323 | } | |
324 | ||
325 | if (!$past and !$current) { | |
b7602a11 | 326 | return false; |
327 | } | |
1515a89e | 328 | |
dd97c328 | 329 | $strftimerecent = get_string('strftimerecent'); |
330 | ||
331 | if ($past) { | |
e09fc68b | 332 | echo $OUTPUT->heading(get_string("pastchats", 'chat').':'); |
dd97c328 | 333 | |
334 | foreach ($past as $cm) { | |
335 | $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id; | |
336 | $date = userdate($cm->lasttime, $strftimerecent); | |
337 | echo '<div class="head"><div class="date">'.$date.'</div></div>'; | |
338 | echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name,true).'</a></div>'; | |
b7602a11 | 339 | } |
8f7dc7f1 | 340 | } |
341 | ||
342 | if ($current) { | |
e09fc68b | 343 | echo $OUTPUT->heading(get_string("currentchats", 'chat').':'); |
dd97c328 | 344 | |
345 | $oldest = floor((time()-$CFG->chat_old_ping)/10)*10; // better db caching | |
346 | ||
347 | $timeold = time() - $CFG->chat_old_ping; | |
348 | $timeold = floor($timeold/10)*10; // better db caching | |
349 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts | |
350 | $timeoldext = floor($timeoldext/10)*10; // better db caching | |
351 | ||
d3bf6f92 | 352 | $params = array('timeold'=>$timeold, 'timeoldext'=>$timeoldext, 'cmid'=>$cm->id); |
353 | ||
354 | $timeout = "AND (chu.version<>'basic' AND chu.lastping>:timeold) OR (chu.version='basic' AND chu.lastping>:timeoldext)"; | |
dd97c328 | 355 | |
356 | foreach ($current as $cm) { | |
357 | //count users first | |
358 | if (isset($cm->mygroupids)) { | |
359 | $groupselect = "AND (chu.groupid IN ({$cm->mygroupids}) OR chu.groupid = 0)"; | |
360 | } else { | |
361 | $groupselect = ""; | |
362 | } | |
fd4d41c3 | 363 | |
d3bf6f92 | 364 | if (!$users = $DB->get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email, u.picture |
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; | |
374 | $date = userdate($cm->lasttime, $strftimerecent); | |
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 { | |
39790bd8 | 605 | $message = new stdClass(); |
2ac0d13b | 606 | $message->chatid = $chatuser->chatid; |
607 | $message->userid = $chatuser->userid; | |
608 | $message->groupid = $groupid; | |
609 | $message->message = 'enter'; | |
610 | $message->system = 1; | |
611 | $message->timestamp = time(); | |
612 | ||
7826abc7 | 613 | $DB->insert_record('chat_messages', $message); |
614 | $DB->insert_record('chat_messages_current', $message); | |
516121bd | 615 | } |
1515a89e | 616 | } |
617 | ||
618 | return $chatuser->sid; | |
619 | } | |
620 | ||
848bb113 | 621 | /** |
622 | * Delete the old and in the way | |
623 | * | |
624 | * @global object | |
625 | * @global object | |
626 | */ | |
7d792369 | 627 | function chat_delete_old_users() { |
628 | // Delete the old and in the way | |
d3bf6f92 | 629 | global $CFG, $DB; |
b5012f3e | 630 | |
e7fbd0b3 | 631 | $timeold = time() - $CFG->chat_old_ping; |
953eb6f3 | 632 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts |
a32c7772 | 633 | |
d3bf6f92 | 634 | $query = "(version<>'basic' AND lastping<?) OR (version='basic' AND lastping<?)"; |
635 | $params = array($timeold, $timeoldext); | |
7d792369 | 636 | |
d3bf6f92 | 637 | if ($oldusers = $DB->get_records_select('chat_users', $query, $params) ) { |
638 | $DB->delete_records_select('chat_users', $query, $params); | |
7d792369 | 639 | foreach ($oldusers as $olduser) { |
39790bd8 | 640 | $message = new stdClass(); |
516121bd | 641 | $message->chatid = $olduser->chatid; |
642 | $message->userid = $olduser->userid; | |
643 | $message->groupid = $olduser->groupid; | |
644 | $message->message = 'exit'; | |
645 | $message->system = 1; | |
7d792369 | 646 | $message->timestamp = time(); |
b5de723d | 647 | |
7826abc7 | 648 | $DB->insert_record('chat_messages', $message); |
649 | $DB->insert_record('chat_messages_current', $message); | |
7d792369 | 650 | } |
651 | } | |
652 | } | |
1515a89e | 653 | |
848bb113 | 654 | /** |
655 | * Updates chat records so that the next chat time is correct | |
656 | * | |
657 | * @global object | |
658 | * @param int $chatid | |
659 | * @return void | |
660 | */ | |
fcd3a1ee | 661 | function chat_update_chat_times($chatid=0) { |
662 | /// Updates chat records so that the next chat time is correct | |
d3bf6f92 | 663 | global $DB; |
fcd3a1ee | 664 | |
665 | $timenow = time(); | |
d3bf6f92 | 666 | |
667 | $params = array('timenow'=>$timenow, 'chatid'=>$chatid); | |
668 | ||
fcd3a1ee | 669 | if ($chatid) { |
d3bf6f92 | 670 | if (!$chats[] = $DB->get_record_select("chat", "id = :chatid AND chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee | 671 | return; |
672 | } | |
673 | } else { | |
d3bf6f92 | 674 | if (!$chats = $DB->get_records_select("chat", "chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee | 675 | return; |
676 | } | |
677 | } | |
678 | ||
679 | foreach ($chats as $chat) { | |
680 | switch ($chat->schedule) { | |
681 | case 1: // Single event - turn off schedule and disable | |
682 | $chat->chattime = 0; | |
683 | $chat->schedule = 0; | |
684 | break; | |
685 | case 2: // Repeat daily | |
f0d3bb9e | 686 | while ($chat->chattime <= $timenow) { |
687 | $chat->chattime += 24 * 3600; | |
688 | } | |
fcd3a1ee | 689 | break; |
690 | case 3: // Repeat weekly | |
f0d3bb9e | 691 | while ($chat->chattime <= $timenow) { |
692 | $chat->chattime += 7 * 24 * 3600; | |
693 | } | |
fcd3a1ee | 694 | break; |
695 | } | |
d3bf6f92 | 696 | $DB->update_record("chat", $chat); |
697 | ||
39790bd8 | 698 | $event = new stdClass(); // Update calendar too |
8496c4af | 699 | |
d3bf6f92 | 700 | $cond = "modulename='chat' AND instance = :chatid AND timestart <> :chattime"; |
701 | $params = array('chattime'=>$chat->chattime, 'chatid'=>$chatid); | |
702 | ||
703 | if ($event->id = $DB->get_field_select('event', 'id', $cond, $params)) { | |
8496c4af | 704 | $event->timestart = $chat->chattime; |
89b8211e | 705 | $calendarevent = calendar_event::load($event->id); |
1d5bd3d2 | 706 | $calendarevent->update($event, false); |
8496c4af | 707 | } |
fcd3a1ee | 708 | } |
709 | } | |
710 | ||
848bb113 | 711 | /** |
712 | * @global object | |
713 | * @global object | |
714 | * @param object $message | |
715 | * @param int $courseid | |
716 | * @param object $sender | |
717 | * @param object $currentuser | |
718 | * @param string $chat_lastrow | |
719 | * @return bool|string Returns HTML or false | |
720 | */ | |
aa5c32fd | 721 | function chat_format_message_manually($message, $courseid, $sender, $currentuser, $chat_lastrow=NULL) { |
d3222955 | 722 | global $CFG, $USER, $OUTPUT; |
1515a89e | 723 | |
39790bd8 | 724 | $output = new stdClass(); |
75d07096 | 725 | $output->beep = false; // by default |
726 | $output->refreshusers = false; // by default | |
7d792369 | 727 | |
72989350 | 728 | // Use get_user_timezone() to find the correct timezone for displaying this message: |
729 | // It's either the current user's timezone or else decided by some Moodle config setting | |
970f144e | 730 | // First, "reset" $USER->timezone (which could have been set by a previous call to here) |
731 | // because otherwise the value for the previous $currentuser will take precedence over $CFG->timezone | |
732 | $USER->timezone = 99; | |
72989350 | 733 | $tz = get_user_timezone($currentuser->timezone); |
b5de723d | 734 | |
72989350 | 735 | // Before formatting the message time string, set $USER->timezone to the above. |
736 | // This will allow dst_offset_on (called by userdate) to work correctly, otherwise the | |
737 | // message times appear off because DST is not taken into account when it should be. | |
738 | $USER->timezone = $tz; | |
b5de723d | 739 | $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz); |
740 | ||
812dbaf7 | 741 | $message->picture = $OUTPUT->user_picture($sender, array('size'=>false, 'courseid'=>$courseid, 'link'=>false)); |
d3222955 | 742 | |
75d07096 | 743 | if ($courseid) { |
744 | $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 | 745 | } |
1515a89e | 746 | |
aa5c32fd | 747 | //Calculate the row class |
748 | if ($chat_lastrow !== NULL) { | |
749 | $rowclass = ' class="r'.$chat_lastrow.'" '; | |
750 | } else { | |
751 | $rowclass = ''; | |
752 | } | |
753 | ||
b5de723d | 754 | // Start processing the message |
75d07096 | 755 | |
b5de723d | 756 | if(!empty($message->system)) { |
757 | // System event | |
75d07096 | 758 | $output->text = $message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender)); |
759 | $output->html = '<table class="chat-event"><tr'.$rowclass.'><td class="picture">'.$message->picture.'</td><td class="text">'; | |
760 | $output->html .= '<span class="event">'.$output->text.'</span></td></tr></table>'; | |
83f47164 JM |
761 | $output->basic = '<tr class="r1"> |
762 | <th scope="row" class="cell c1 title"></th> | |
763 | <td class="cell c2 text">' . get_string('message'.$message->message, 'chat', fullname($sender)) . '</td> | |
764 | <td class="cell c3">' . $message->strtime . '</td> | |
765 | </tr>'; | |
516121bd | 766 | if($message->message == 'exit' or $message->message == 'enter') { |
75d07096 | 767 | $output->refreshusers = true; //force user panel refresh ASAP |
516121bd | 768 | } |
75d07096 | 769 | return $output; |
1515a89e | 770 | } |
771 | ||
82a524ef | 772 | // It's not a system event |
6c6ed54a | 773 | $text = trim($message->message); |
82a524ef | 774 | |
775 | /// Parse the text to clean and filter it | |
39790bd8 | 776 | $options = new stdClass(); |
82a524ef | 777 | $options->para = false; |
778 | $text = format_text($text, FORMAT_MOODLE, $options, $courseid); | |
927a7808 | 779 | |
b5de723d | 780 | // And now check for special cases |
6c6ed54a | 781 | $patternTo = '#^\s*To\s([^:]+):(.*)#'; |
927a7808 | 782 | $special = false; |
783 | ||
b5de723d | 784 | if (substr($text, 0, 5) == 'beep ') { |
6e5f40ea | 785 | /// It's a beep! |
927a7808 | 786 | $special = true; |
7d792369 | 787 | $beepwho = trim(substr($text, 5)); |
9f85bed4 | 788 | |
b5de723d | 789 | if ($beepwho == 'all') { // everyone |
83f47164 JM |
790 | $outinfobasic = get_string('messagebeepseveryone', 'chat', fullname($sender)); |
791 | $outinfo = $message->strtime . ': ' . $outinfobasic; | |
75d07096 | 792 | $outmain = ''; |
83f47164 | 793 | |
75d07096 | 794 | $output->beep = true; // (eventually this should be set to |
7d792369 | 795 | // to a filename uploaded by the user) |
796 | ||
82a524ef | 797 | } else if ($beepwho == $currentuser->id) { // current user |
83f47164 JM |
798 | $outinfobasic = get_string('messagebeepsyou', 'chat', fullname($sender)); |
799 | $outinfo = $message->strtime . ': ' . $outinfobasic; | |
75d07096 | 800 | $outmain = ''; |
801 | $output->beep = true; | |
264867fd | 802 | |
0eda0a46 | 803 | } else { //something is not caught? |
7d792369 | 804 | return false; |
805 | } | |
b5de723d | 806 | } else if (substr($text, 0, 1) == '/') { /// It's a user command |
6c6ed54a | 807 | $special = true; |
1d507186 | 808 | $pattern = '#(^\/)(\w+).*#'; |
6c6ed54a FM |
809 | preg_match($pattern, $text, $matches); |
810 | $command = isset($matches[2]) ? $matches[2] : false; | |
811 | // Support some IRC commands. | |
1d507186 | 812 | switch ($command){ |
6c6ed54a FM |
813 | case 'me': |
814 | $outinfo = $message->strtime; | |
815 | $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>'; | |
816 | break; | |
817 | default: | |
818 | // Error, we set special back to false to use the classic message output. | |
819 | $special = false; | |
820 | break; | |
1515a89e | 821 | } |
6c6ed54a | 822 | } else if (preg_match($patternTo, $text)) { |
7f0483f6 | 823 | $special = true; |
6c6ed54a FM |
824 | $matches = array(); |
825 | preg_match($patternTo, $text, $matches); | |
826 | if (isset($matches[1]) && isset($matches[2])) { | |
827 | $outinfo = $message->strtime; | |
828 | $outmain = $sender->firstname.' '.get_string('saidto', 'chat').' <i>'.$matches[1].'</i>: '.$matches[2]; | |
829 | } else { | |
830 | // Error, we set special back to false to use the classic message output. | |
831 | $special = false; | |
832 | } | |
927a7808 | 833 | } |
9f85bed4 | 834 | |
927a7808 | 835 | if(!$special) { |
75d07096 | 836 | $outinfo = $message->strtime.' '.$sender->firstname; |
7d792369 | 837 | $outmain = $text; |
1515a89e | 838 | } |
264867fd | 839 | |
75d07096 | 840 | /// Format the message as a small table |
1515a89e | 841 | |
75d07096 | 842 | $output->text = strip_tags($outinfo.': '.$outmain); |
7d792369 | 843 | |
75d07096 | 844 | $output->html = "<table class=\"chat-message\"><tr$rowclass><td class=\"picture\" valign=\"top\">$message->picture</td><td class=\"text\">"; |
845 | $output->html .= "<span class=\"title\">$outinfo</span>"; | |
846 | if ($outmain) { | |
847 | $output->html .= ": $outmain"; | |
83f47164 JM |
848 | $output->basic = '<tr class="r0"> |
849 | <th scope="row" class="cell c1 title">' . $sender->firstname . '</th> | |
850 | <td class="cell c2 text">' . $outmain . '</td> | |
851 | <td class="cell c3">' . $message->strtime . '</td> | |
852 | </tr>'; | |
6ee78cee | 853 | } else { |
83f47164 JM |
854 | $output->basic = '<tr class="r1"> |
855 | <th scope="row" class="cell c1 title"></th> | |
856 | <td class="cell c2 text">' . $outinfobasic . '</td> | |
857 | <td class="cell c3">' . $message->strtime . '</td> | |
858 | </tr>'; | |
7d792369 | 859 | } |
75d07096 | 860 | $output->html .= "</td></tr></table>"; |
861 | return $output; | |
b5de723d | 862 | } |
863 | ||
848bb113 | 864 | /** |
865 | * @global object | |
866 | * @param object $message | |
867 | * @param int $courseid | |
868 | * @param object $currentuser | |
869 | * @param string $chat_lastrow | |
870 | * @return bool|string Returns HTML or false | |
871 | */ | |
aa5c32fd | 872 | function chat_format_message($message, $courseid, $currentuser, $chat_lastrow=NULL) { |
b5de723d | 873 | /// Given a message object full of information, this function |
874 | /// formats it appropriately into text and html, then | |
875 | /// returns the formatted data. | |
d3bf6f92 | 876 | global $DB; |
b5de723d | 877 | |
78c98892 | 878 | static $users; // Cache user lookups |
879 | ||
880 | if (isset($users[$message->userid])) { | |
881 | $user = $users[$message->userid]; | |
5605789a | 882 | } else if ($user = $DB->get_record('user', array('id'=>$message->userid), user_picture::fields())) { |
78c98892 | 883 | $users[$message->userid] = $user; |
884 | } else { | |
885 | return NULL; | |
b5de723d | 886 | } |
aa5c32fd | 887 | return chat_format_message_manually($message, $courseid, $user, $currentuser, $chat_lastrow); |
1515a89e | 888 | } |
889 | ||
75d07096 | 890 | /** |
891 | * @global object | |
d0157d82 RT |
892 | * @param object $message message to be displayed. |
893 | * @param mixed $chatuser user chat data | |
894 | * @param object $currentuser current user for whom the message should be displayed. | |
895 | * @param int $groupingid course module grouping id | |
896 | * @param string $theme name of the chat theme. | |
75d07096 | 897 | * @return bool|string Returns HTML or false |
898 | */ | |
d0157d82 | 899 | function chat_format_message_theme ($message, $chatuser, $currentuser, $groupingid, $theme = 'bubble') { |
a2592fec AD |
900 | global $CFG, $USER, $OUTPUT, $COURSE, $DB, $PAGE; |
901 | require_once($CFG->dirroot.'/mod/chat/locallib.php'); | |
75d07096 | 902 | |
903 | static $users; // Cache user lookups | |
904 | ||
39790bd8 | 905 | $result = new stdClass(); |
75d07096 | 906 | |
907 | if (file_exists($CFG->dirroot . '/mod/chat/gui_ajax/theme/'.$theme.'/config.php')) { | |
908 | include($CFG->dirroot . '/mod/chat/gui_ajax/theme/'.$theme.'/config.php'); | |
909 | } | |
910 | ||
911 | if (isset($users[$message->userid])) { | |
912 | $sender = $users[$message->userid]; | |
3a11c09f | 913 | } else if ($sender = $DB->get_record('user', array('id'=>$message->userid), user_picture::fields())) { |
75d07096 | 914 | $users[$message->userid] = $sender; |
915 | } else { | |
916 | return NULL; | |
917 | } | |
918 | ||
919 | $USER->timezone = 99; | |
920 | $tz = get_user_timezone($currentuser->timezone); | |
921 | $USER->timezone = $tz; | |
922 | ||
d0157d82 | 923 | if (empty($chatuser->course)) { |
75d07096 | 924 | $courseid = $COURSE->id; |
d0157d82 RT |
925 | } else { |
926 | $courseid = $chatuser->course; | |
75d07096 | 927 | } |
928 | ||
929 | $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz); | |
812dbaf7 | 930 | $message->picture = $OUTPUT->user_picture($sender, array('courseid'=>$courseid)); |
75d07096 | 931 | |
932 | $message->picture = "<a target='_blank' href=\"$CFG->wwwroot/user/view.php?id=$sender->id&course=$courseid\">$message->picture</a>"; | |
933 | ||
934 | // Start processing the message | |
935 | if(!empty($message->system)) { | |
936 | $result->type = 'system'; | |
937 | ||
a2592fec AD |
938 | $senderprofile = $CFG->wwwroot.'/user/view.php?id='.$sender->id.'&course='.$courseid; |
939 | $event = get_string('message'.$message->message, 'chat', fullname($sender)); | |
940 | $eventmessage = new event_message($senderprofile, fullname($sender), $message->strtime, $event, $theme); | |
941 | ||
942 | $output = $PAGE->get_renderer('mod_chat'); | |
943 | $result->html = $output->render($eventmessage); | |
944 | ||
75d07096 | 945 | return $result; |
946 | } | |
947 | ||
948 | // It's not a system event | |
6c6ed54a | 949 | $text = trim($message->message); |
75d07096 | 950 | |
951 | /// Parse the text to clean and filter it | |
39790bd8 | 952 | $options = new stdClass(); |
75d07096 | 953 | $options->para = false; |
954 | $text = format_text($text, FORMAT_MOODLE, $options, $courseid); | |
955 | ||
956 | // And now check for special cases | |
957 | $special = false; | |
958 | $outtime = $message->strtime; | |
959 | ||
6c6ed54a | 960 | // Initialise variables. |
d0157d82 | 961 | $outmain = ''; |
6c6ed54a | 962 | $patternTo = '#^\s*To\s([^:]+):(.*)#'; |
d0157d82 | 963 | |
75d07096 | 964 | if (substr($text, 0, 5) == 'beep ') { |
965 | $special = true; | |
966 | /// It's a beep! | |
967 | $result->type = 'beep'; | |
968 | $beepwho = trim(substr($text, 5)); | |
969 | ||
970 | if ($beepwho == 'all') { // everyone | |
971 | $outmain = get_string('messagebeepseveryone', 'chat', fullname($sender)); | |
972 | } else if ($beepwho == $currentuser->id) { // current user | |
973 | $outmain = get_string('messagebeepsyou', 'chat', fullname($sender)); | |
974 | } else if ($sender->id == $currentuser->id) { //something is not caught? | |
d0157d82 RT |
975 | //allow beep for a active chat user only, else user can beep anyone and get fullname |
976 | if (!empty($chatuser) && is_numeric($beepwho)) { | |
977 | $chatusers = chat_get_users($chatuser->chatid, $chatuser->groupid, $groupingid); | |
978 | if (array_key_exists($beepwho, $chatusers)) { | |
979 | $outmain = get_string('messageyoubeep', 'chat', fullname($chatusers[$beepwho])); | |
980 | } else { | |
981 | $outmain = get_string('messageyoubeep', 'chat', $beepwho); | |
982 | } | |
983 | } else { | |
984 | $outmain = get_string('messageyoubeep', 'chat', $beepwho); | |
985 | } | |
75d07096 | 986 | } |
987 | } else if (substr($text, 0, 1) == '/') { /// It's a user command | |
988 | $special = true; | |
989 | $result->type = 'command'; | |
75d07096 | 990 | $pattern = '#(^\/)(\w+).*#'; |
6c6ed54a FM |
991 | preg_match($pattern, $text, $matches); |
992 | $command = isset($matches[2]) ? $matches[2] : false; | |
993 | // Support some IRC commands. | |
75d07096 | 994 | switch ($command){ |
6c6ed54a FM |
995 | case 'me': |
996 | $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>'; | |
997 | break; | |
998 | default: | |
999 | // Error, we set special back to false to use the classic message output. | |
1000 | $special = false; | |
1001 | break; | |
75d07096 | 1002 | } |
6c6ed54a | 1003 | } else if (preg_match($patternTo, $text)) { |
75d07096 | 1004 | $special = true; |
1005 | $result->type = 'dialogue'; | |
6c6ed54a FM |
1006 | $matches = array(); |
1007 | preg_match($patternTo, $text, $matches); | |
1008 | if (isset($matches[1]) && isset($matches[2])) { | |
1009 | $outmain = $sender->firstname.' <b>'.get_string('saidto', 'chat').'</b> <i>'.$matches[1].'</i>: '.$matches[2]; | |
1010 | } else { | |
1011 | // Error, we set special back to false to use the classic message output. | |
1012 | $special = false; | |
1013 | } | |
75d07096 | 1014 | } |
1015 | ||
6c6ed54a | 1016 | if (!$special) { |
75d07096 | 1017 | $outmain = $text; |
1018 | } | |
1019 | ||
1020 | $result->text = strip_tags($outtime.': '.$outmain); | |
1021 | ||
a2592fec | 1022 | $mymessageclass = ''; |
75d07096 | 1023 | if ($sender->id == $USER->id) { |
a2592fec | 1024 | $mymessageclass = 'chat-message-mymessage'; |
75d07096 | 1025 | } |
1026 | ||
a2592fec AD |
1027 | $senderprofile = $CFG->wwwroot.'/user/view.php?id='.$sender->id.'&course='.$courseid; |
1028 | $usermessage = new user_message($senderprofile, fullname($sender), $message->picture, $mymessageclass, $outtime, $outmain, $theme); | |
1029 | ||
1030 | $output = $PAGE->get_renderer('mod_chat'); | |
1031 | $result->html = $output->render($usermessage); | |
1032 | ||
d0157d82 RT |
1033 | //When user beeps other user, then don't show any timestamp to other users in chat. |
1034 | if (('' === $outmain) && $special) { | |
1035 | return false; | |
1036 | } else { | |
1037 | return $result; | |
1038 | } | |
75d07096 | 1039 | } |
1040 | ||
83064f9c | 1041 | /** |
1042 | * @global object $DB | |
1043 | * @global object $CFG | |
1044 | * @global object $COURSE | |
1045 | * @global object $OUTPUT | |
1046 | * @param object $users | |
1047 | * @param object $course | |
1048 | * @return array return formatted user list | |
1049 | */ | |
1050 | function chat_format_userlist($users, $course) { | |
1051 | global $CFG, $DB, $COURSE, $OUTPUT; | |
1052 | $result = array(); | |
1053 | foreach($users as $user){ | |
1054 | $item = array(); | |
1055 | $item['name'] = fullname($user); | |
ff0e58c8 | 1056 | $item['url'] = $CFG->wwwroot.'/user/view.php?id='.$user->id.'&course='.$course->id; |
812dbaf7 | 1057 | $item['picture'] = $OUTPUT->user_picture($user); |
83064f9c | 1058 | $item['id'] = $user->id; |
1059 | $result[] = $item; | |
1060 | } | |
1061 | return $result; | |
1062 | } | |
1063 | ||
1064 | /** | |
1065 | * Print json format error | |
1066 | * @param string $level | |
1067 | * @param string $msg | |
1068 | */ | |
1069 | function chat_print_error($level, $msg) { | |
1070 | header('Content-Length: ' . ob_get_length() ); | |
6bdfef5d | 1071 | $error = new stdClass(); |
83064f9c | 1072 | $error->level = $level; |
1073 | $error->msg = $msg; | |
1074 | $response['error'] = $error; | |
1075 | echo json_encode($response); | |
1076 | ob_end_flush(); | |
1077 | exit; | |
1078 | } | |
1079 | ||
848bb113 | 1080 | /** |
1081 | * @return array | |
1082 | */ | |
f3221af9 | 1083 | function chat_get_view_actions() { |
1084 | return array('view','view all','report'); | |
1085 | } | |
1086 | ||
848bb113 | 1087 | /** |
1088 | * @return array | |
1089 | */ | |
f3221af9 | 1090 | function chat_get_post_actions() { |
1091 | return array('talk'); | |
1092 | } | |
1093 | ||
848bb113 | 1094 | /** |
1095 | * @global object | |
1096 | * @global object | |
1097 | * @param array $courses | |
1098 | * @param array $htmlarray Passed by reference | |
1099 | */ | |
9ca0187e | 1100 | function chat_print_overview($courses, &$htmlarray) { |
1101 | global $USER, $CFG; | |
1102 | ||
1103 | if (empty($courses) || !is_array($courses) || count($courses) == 0) { | |
1104 | return array(); | |
1105 | } | |
1106 | ||
1107 | if (!$chats = get_all_instances_in_courses('chat',$courses)) { | |
1108 | return; | |
1109 | } | |
1110 | ||
1111 | $strchat = get_string('modulename', 'chat'); | |
1112 | $strnextsession = get_string('nextsession', 'chat'); | |
9ca0187e | 1113 | |
1114 | foreach ($chats as $chat) { | |
9ca0187e | 1115 | if ($chat->chattime and $chat->schedule) { // A chat is scheduled |
a2a37336 | 1116 | $str = '<div class="chat overview"><div class="name">'. |
1117 | $strchat.': <a '.($chat->visible?'':' class="dimmed"'). | |
1118 | ' href="'.$CFG->wwwroot.'/mod/chat/view.php?id='.$chat->coursemodule.'">'. | |
1119 | $chat->name.'</a></div>'; | |
1120 | $str .= '<div class="info">'.$strnextsession.': '.userdate($chat->chattime).'</div></div>'; | |
1121 | ||
1122 | if (empty($htmlarray[$chat->course]['chat'])) { | |
1123 | $htmlarray[$chat->course]['chat'] = $str; | |
1124 | } else { | |
1125 | $htmlarray[$chat->course]['chat'] .= $str; | |
1126 | } | |
9ca0187e | 1127 | } |
9ca0187e | 1128 | } |
1129 | } | |
1130 | ||
0b5a80a1 | 1131 | |
1132 | /** | |
1133 | * Implementation of the function for printing the form elements that control | |
1134 | * whether the course reset functionality affects the chat. | |
848bb113 | 1135 | * |
1136 | * @param object $mform form passed by reference | |
0b5a80a1 | 1137 | */ |
1138 | function chat_reset_course_form_definition(&$mform) { | |
1139 | $mform->addElement('header', 'chatheader', get_string('modulenameplural', 'chat')); | |
1140 | $mform->addElement('advcheckbox', 'reset_chat', get_string('removemessages','chat')); | |
1141 | } | |
1142 | ||
1143 | /** | |
1144 | * Course reset form defaults. | |
848bb113 | 1145 | * |
1146 | * @param object $course | |
1147 | * @return array | |
0b5a80a1 | 1148 | */ |
1149 | function chat_reset_course_form_defaults($course) { | |
1150 | return array('reset_chat'=>1); | |
1151 | } | |
1152 | ||
1153 | /** | |
72d2982e | 1154 | * Actual implementation of the reset course functionality, delete all the |
0b5a80a1 | 1155 | * chat messages for course $data->courseid. |
848bb113 | 1156 | * |
1157 | * @global object | |
1158 | * @global object | |
1159 | * @param object $data the data submitted from the reset course. | |
0b5a80a1 | 1160 | * @return array status array |
1161 | */ | |
1162 | function chat_reset_userdata($data) { | |
d3bf6f92 | 1163 | global $CFG, $DB; |
0b5a80a1 | 1164 | |
1165 | $componentstr = get_string('modulenameplural', 'chat'); | |
1166 | $status = array(); | |
1167 | ||
1168 | if (!empty($data->reset_chat)) { | |
1169 | $chatessql = "SELECT ch.id | |
d3bf6f92 | 1170 | FROM {chat} ch |
1171 | WHERE ch.course=?"; | |
1172 | $params = array($data->courseid); | |
0b5a80a1 | 1173 | |
d3bf6f92 | 1174 | $DB->delete_records_select('chat_messages', "chatid IN ($chatessql)", $params); |
6e5f40ea | 1175 | $DB->delete_records_select('chat_messages_current', "chatid IN ($chatessql)", $params); |
d3bf6f92 | 1176 | $DB->delete_records_select('chat_users', "chatid IN ($chatessql)", $params); |
0b5a80a1 | 1177 | $status[] = array('component'=>$componentstr, 'item'=>get_string('removemessages', 'chat'), 'error'=>false); |
1178 | } | |
1179 | ||
1180 | /// updating dates - shift may be negative too | |
1181 | if ($data->timeshift) { | |
1182 | shift_course_mod_dates('chat', array('chattime'), $data->timeshift, $data->courseid); | |
1183 | $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); | |
1184 | } | |
1185 | ||
1186 | return $status; | |
1187 | } | |
1188 | ||
f432bebf | 1189 | /** |
1190 | * Returns all other caps used in module | |
848bb113 | 1191 | * |
1192 | * @return array | |
f432bebf | 1193 | */ |
1194 | function chat_get_extra_capabilities() { | |
1195 | return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames'); | |
1196 | } | |
1197 | ||
47cfd331 | 1198 | |
42f103be | 1199 | /** |
1200 | * @param string $feature FEATURE_xx constant for requested feature | |
1201 | * @return mixed True if module supports feature, null if doesn't know | |
1202 | */ | |
1203 | function chat_supports($feature) { | |
1204 | switch($feature) { | |
1205 | case FEATURE_GROUPS: return true; | |
1206 | case FEATURE_GROUPINGS: return true; | |
1207 | case FEATURE_GROUPMEMBERSONLY: return true; | |
dc5c2bd9 | 1208 | case FEATURE_MOD_INTRO: return true; |
79447c50 | 1209 | case FEATURE_BACKUP_MOODLE2: return true; |
3a7507d0 | 1210 | case FEATURE_COMPLETION_TRACKS_VIEWS: return true; |
42f103be | 1211 | case FEATURE_GRADE_HAS_GRADE: return false; |
1212 | case FEATURE_GRADE_OUTCOMES: return true; | |
3e4c2435 | 1213 | case FEATURE_SHOW_DESCRIPTION: return true; |
42f103be | 1214 | |
1215 | default: return null; | |
1216 | } | |
1217 | } | |
b14ae498 | 1218 | |
1219 | function chat_extend_navigation($navigation, $course, $module, $cm) { | |
36ab2fed | 1220 | global $CFG; |
0b29477b SH |
1221 | |
1222 | $currentgroup = groups_get_activity_group($cm, true); | |
4f0c2d00 | 1223 | |
6536217c | 1224 | if (has_capability('mod/chat:chat', context_module::instance($cm->id))) { |
b14ae498 | 1225 | $strenterchat = get_string('enterchat', 'chat'); |
b14ae498 | 1226 | |
1227 | $target = $CFG->wwwroot.'/mod/chat/'; | |
1228 | $params = array('id'=>$cm->instance); | |
1229 | ||
1230 | if ($currentgroup) { | |
1231 | $params['groupid'] = $currentgroup; | |
1232 | } | |
1233 | ||
1234 | $links = array(); | |
e7521559 | 1235 | |
36ab2fed DM |
1236 | $url = new moodle_url($target.'gui_'.$CFG->chat_method.'/index.php', $params); |
1237 | $action = new popup_action('click', $url, 'chat'.$course->id.$cm->instance.$currentgroup, array('height' => 500, 'width' => 700)); | |
1238 | $links[] = new action_link($url, $strenterchat, $action); | |
b14ae498 | 1239 | |
af140288 DC |
1240 | $url = new moodle_url($target.'gui_basic/index.php', $params); |
1241 | $action = new popup_action('click', $url, 'chat'.$course->id.$cm->instance.$currentgroup, array('height' => 500, 'width' => 700)); | |
1242 | $links[] = new action_link($url, get_string('noframesjs', 'message'), $action); | |
b14ae498 | 1243 | |
1244 | foreach ($links as $link) { | |
69bc9216 | 1245 | $navigation->add($link->text, $link, navigation_node::TYPE_SETTING, null ,null, new pix_icon('i/group' , '')); |
b14ae498 | 1246 | } |
1247 | } | |
1248 | ||
1249 | $chatusers = chat_get_users($cm->instance, $currentgroup, $cm->groupingid); | |
1250 | if (is_array($chatusers) && count($chatusers)>0) { | |
3406acde | 1251 | $users = $navigation->add(get_string('currentusers', 'chat')); |
b14ae498 | 1252 | foreach ($chatusers as $chatuser) { |
a6855934 | 1253 | $userlink = new moodle_url('/user/view.php', array('id'=>$chatuser->id,'course'=>$course->id)); |
69bc9216 | 1254 | $users->add(fullname($chatuser).' '.format_time(time() - $chatuser->lastmessageping), $userlink, navigation_node::TYPE_USER, null, null, new pix_icon('i/user', '')); |
b14ae498 | 1255 | } |
1256 | } | |
1257 | } | |
1258 | ||
0b29477b SH |
1259 | /** |
1260 | * Adds module specific settings to the settings block | |
1261 | * | |
1262 | * @param settings_navigation $settings The settings navigation object | |
1263 | * @param navigation_node $chatnode The node to add module settings to | |
1264 | */ | |
1265 | function chat_extend_settings_navigation(settings_navigation $settings, navigation_node $chatnode) { | |
1266 | global $DB, $PAGE, $USER; | |
b14ae498 | 1267 | $chat = $DB->get_record("chat", array("id" => $PAGE->cm->instance)); |
0b29477b | 1268 | |
b14ae498 | 1269 | if ($chat->chattime && $chat->schedule) { |
3406acde SH |
1270 | $nextsessionnode = $chatnode->add(get_string('nextsession', 'chat').': '.userdate($chat->chattime).' ('.usertimezone($USER->timezone)); |
1271 | $nextsessionnode->add_class('note'); | |
b14ae498 | 1272 | } |
1273 | ||
1274 | $currentgroup = groups_get_activity_group($PAGE->cm, true); | |
1275 | if ($currentgroup) { | |
1276 | $groupselect = " AND groupid = '$currentgroup'"; | |
1277 | } else { | |
1278 | $groupselect = ''; | |
1279 | } | |
1280 | ||
1281 | if ($chat->studentlogs || has_capability('mod/chat:readlog',$PAGE->cm->context)) { | |
1282 | if ($DB->get_records_select('chat_messages', "chatid = ? $groupselect", array($chat->id))) { | |
0b29477b | 1283 | $chatnode->add(get_string('viewreport', 'chat'), new moodle_url('/mod/chat/report.php', array('id'=>$PAGE->cm->id))); |
b14ae498 | 1284 | } |
1285 | } | |
50d76994 | 1286 | } |
a8e3b008 DC |
1287 | |
1288 | /** | |
1289 | * user logout event handler | |
1290 | * | |
1291 | * @param object $user full $USER object | |
1292 | */ | |
1293 | function chat_user_logout($user) { | |
1294 | global $DB; | |
1295 | $DB->delete_records('chat_users', array('userid'=>$user->id)); | |
1296 | } | |
b1627a92 DC |
1297 | |
1298 | /** | |
1299 | * Return a list of page types | |
1300 | * @param string $pagetype current page type | |
1301 | * @param stdClass $parentcontext Block's parent context | |
1302 | * @param stdClass $currentcontext Current context of block | |
1303 | */ | |
b38e2e28 | 1304 | function chat_page_type_list($pagetype, $parentcontext, $currentcontext) { |
b1627a92 DC |
1305 | $module_pagetype = array('mod-chat-*'=>get_string('page-mod-chat-x', 'chat')); |
1306 | return $module_pagetype; | |
1307 | } |