1c61c8d6 |
1 | <?php // $Id$ |
1515a89e |
2 | |
3 | /// Library of functions and constants for module chat |
c4d588cc |
4 | require_once($CFG->libdir.'/pagelib.php'); |
214b1cf7 |
5 | require_once($CFG->libdir.'/portfoliolib.php'); |
c4d588cc |
6 | |
1d507186 |
7 | $CFG->chat_ajax_debug = false; |
8 | $CFG->chat_use_cache = false; |
9 | |
1515a89e |
10 | // The HTML head for the message window to start with (<!-- nix --> is used to get some browsers starting with output |
1f8abb89 |
11 | $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 |
12 | |
13 | // The HTML head for the message window to start with (with js scrolling) |
1f8abb89 |
14 | $CHAT_HTMLHEAD_JS = <<<EOD |
15 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
16 | <html><head><script type="text/javascript"> |
17 | //<![CDATA[ |
18 | function move(){ |
19 | if (scroll_active) |
20 | window.scroll(1,400000); |
21 | window.setTimeout("move()",100); |
22 | } |
23 | var scroll_active = true; |
24 | move(); |
25 | //]]> |
26 | </script> |
27 | </head> |
28 | <body onBlur="scroll_active = true" onFocus="scroll_active = false"> |
29 | EOD; |
30 | $CHAT_HTMLHEAD_JS .= padding(200); |
1515a89e |
31 | |
32 | // The HTML code for standard empty pages (e.g. if a user was kicked out) |
1f8abb89 |
33 | $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 |
34 | |
35 | // The HTML head for the message input page |
1f8abb89 |
36 | $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 |
37 | |
38 | // The HTML code for the message input page, with JavaScript |
1d507186 |
39 | $CHAT_HTMLHEAD_MSGINPUT_JS = <<<EOD |
40 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
41 | <html> |
42 | <head><title>Message Input</title> |
43 | <script type="text/javascript"> |
44 | //<![CDATA[ |
45 | scroll_active = true; |
46 | function empty_field_and_submit(){ |
47 | document.fdummy.arsc_message.value=document.f.arsc_message.value; |
48 | document.fdummy.submit(); |
49 | document.f.arsc_message.focus(); |
50 | document.f.arsc_message.select(); |
51 | return false; |
52 | } |
53 | //]]> |
54 | </script> |
55 | </head><body OnLoad="document.f.arsc_message.focus();document.f.arsc_message.select();">; |
56 | EOD; |
1515a89e |
57 | |
fbabbd23 |
58 | // Dummy data that gets output to the browser as needed, in order to make it show output |
6e5f40ea |
59 | $CHAT_DUMMY_DATA = padding(200); |
5c2f6a7f |
60 | |
6e5f40ea |
61 | function padding($n){ |
5c2f6a7f |
62 | $str = ''; |
633c3341 |
63 | for($i=0; $i<$n; $i++){ |
1f8abb89 |
64 | $str.="<!-- nix -->\n"; |
5c2f6a7f |
65 | } |
66 | return $str; |
67 | } |
1515a89e |
68 | |
69 | function chat_add_instance($chat) { |
c18269c7 |
70 | global $DB; |
b5de723d |
71 | /// Given an object containing all the necessary data, |
7cac0c4b |
72 | /// (defined by the form in mod_form.php) this function |
b5de723d |
73 | /// will create a new instance and return the id number |
1515a89e |
74 | /// of the new instance. |
75 | |
76 | $chat->timemodified = time(); |
77 | |
c18269c7 |
78 | if ($returnid = $DB->insert_record("chat", $chat)) { |
8496c4af |
79 | |
80 | $event = NULL; |
81 | $event->name = $chat->name; |
82 | $event->description = $chat->intro; |
83 | $event->courseid = $chat->course; |
84 | $event->groupid = 0; |
85 | $event->userid = 0; |
86 | $event->modulename = 'chat'; |
87 | $event->instance = $returnid; |
88 | $event->eventtype = $chat->schedule; |
89 | $event->timestart = $chat->chattime; |
90 | $event->timeduration = 0; |
91 | |
92 | add_event($event); |
93 | } |
94 | |
95 | return $returnid; |
1515a89e |
96 | } |
97 | |
98 | |
99 | function chat_update_instance($chat) { |
c18269c7 |
100 | global $DB; |
b5de723d |
101 | /// Given an object containing all the necessary data, |
7cac0c4b |
102 | /// (defined by the form in mod_form.php) this function |
1515a89e |
103 | /// will update an existing instance with new data. |
104 | |
105 | $chat->timemodified = time(); |
106 | $chat->id = $chat->instance; |
107 | |
1515a89e |
108 | |
c18269c7 |
109 | if ($returnid = $DB->update_record("chat", $chat)) { |
8496c4af |
110 | |
264867fd |
111 | $event = new object(); |
8496c4af |
112 | |
c18269c7 |
113 | if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
8496c4af |
114 | |
115 | $event->name = $chat->name; |
116 | $event->description = $chat->intro; |
117 | $event->timestart = $chat->chattime; |
118 | |
119 | update_event($event); |
120 | } |
121 | } |
122 | |
123 | return $returnid; |
1515a89e |
124 | } |
125 | |
126 | |
127 | function chat_delete_instance($id) { |
c18269c7 |
128 | global $DB; |
b5de723d |
129 | /// Given an ID of an instance of this module, |
130 | /// this function will permanently delete the instance |
131 | /// and any data that depends on it. |
1515a89e |
132 | |
c18269c7 |
133 | if (! $chat = $DB->get_record('chat', array('id'=>$id))) { |
1515a89e |
134 | return false; |
135 | } |
136 | |
137 | $result = true; |
138 | |
139 | # Delete any dependent records here # |
140 | |
c18269c7 |
141 | if (! $DB->delete_records('chat', array('id'=>$chat->id))) { |
a71efae3 |
142 | $result = false; |
143 | } |
c18269c7 |
144 | if (! $DB->delete_records('chat_messages', array('chatid'=>$chat->id))) { |
a71efae3 |
145 | $result = false; |
146 | } |
6e5f40ea |
147 | if (! $DB->delete_records('chat_messages_current', array('chatid'=>$chat->id))) { |
148 | $result = false; |
149 | } |
c18269c7 |
150 | if (! $DB->delete_records('chat_users', array('chatid'=>$chat->id))) { |
1515a89e |
151 | $result = false; |
152 | } |
153 | |
880d8675 |
154 | $pagetypes = page_import_types('mod/chat/'); |
155 | foreach($pagetypes as $pagetype) { |
19f5b2db |
156 | if(!blocks_delete_all_on_page($pagetype, $chat->id)) { |
880d8675 |
157 | $result = false; |
158 | } |
159 | } |
160 | |
c18269c7 |
161 | if (! $DB->delete_records('event', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
36eb856f |
162 | $result = false; |
163 | } |
164 | |
1515a89e |
165 | return $result; |
166 | } |
167 | |
168 | function chat_user_outline($course, $user, $mod, $chat) { |
b5de723d |
169 | /// Return a small object with summary information about what a |
1515a89e |
170 | /// user has done with a given particular instance of this module |
171 | /// Used for user activity reports. |
172 | /// $return->time = the time they did it |
173 | /// $return->info = a short text description |
d3bf6f92 |
174 | return NULL; |
1515a89e |
175 | } |
176 | |
177 | function chat_user_complete($course, $user, $mod, $chat) { |
b5de723d |
178 | /// Print a detailed representation of what a user has done with |
1515a89e |
179 | /// a given particular instance of this module, for user activity reports. |
1515a89e |
180 | return true; |
181 | } |
182 | |
dd97c328 |
183 | function chat_print_recent_activity($course, $viewfullnames, $timestart) { |
184 | /// Given a course and a date, prints a summary of all chat rooms past and present |
1515a89e |
185 | /// This function is called from course/lib.php: print_recent_activity() |
d3bf6f92 |
186 | global $CFG, $USER, $DB; |
dd97c328 |
187 | |
188 | // this is approximate only, but it is really fast ;-) |
189 | $timeout = $CFG->chat_old_ping * 10; |
190 | |
d3bf6f92 |
191 | if (!$mcms = $DB->get_records_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime |
192 | FROM {course_modules} cm |
193 | JOIN {modules} md ON md.id = cm.module |
194 | JOIN {chat} ch ON ch.id = cm.instance |
195 | JOIN {chat_messages} chm ON chm.chatid = ch.id |
196 | WHERE chm.timestamp > ? AND ch.course = ? AND md.name = 'chat' |
197 | GROUP BY cm.id |
198 | ORDER BY lasttime ASC", array($timestart, $course->id))) { |
dd97c328 |
199 | return false; |
200 | } |
201 | |
202 | $past = array(); |
203 | $current = array(); |
204 | $modinfo =& get_fast_modinfo($course); // reference needed because we might load the groups |
205 | |
fd4d41c3 |
206 | foreach ($mcms as $cmid=>$mcm) { |
207 | if (!array_key_exists($cmid, $modinfo->cms)) { |
dd97c328 |
208 | continue; |
209 | } |
fd4d41c3 |
210 | $cm = $modinfo->cms[$cmid]; |
211 | $cm->lasttime = $mcm->lasttime; |
dd97c328 |
212 | if (!$modinfo->cms[$cm->id]->uservisible) { |
213 | continue; |
214 | } |
b7602a11 |
215 | |
dd97c328 |
216 | if (groups_get_activity_groupmode($cm) != SEPARATEGROUPS |
217 | or has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) { |
218 | if ($timeout > time() - $cm->lasttime) { |
219 | $current[] = $cm; |
220 | } else { |
221 | $past[] = $cm; |
222 | } |
223 | |
224 | continue; |
225 | } |
226 | |
227 | if (is_null($modinfo->groups)) { |
228 | $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo |
229 | } |
c5a05b95 |
230 | |
dd97c328 |
231 | // verify groups in separate mode |
232 | if (!$mygroupids = $modinfo->groups[$cm->groupingid]) { |
233 | continue; |
234 | } |
0469cccf |
235 | |
dd97c328 |
236 | // ok, last post was not for my group - we have to query db to get last message from one of my groups |
237 | // only minor problem is that the order will not be correct |
238 | $mygroupids = implode(',', $mygroupids); |
239 | $cm->mygroupids = $mygroupids; |
240 | |
d3bf6f92 |
241 | if (!$mcm = $DB->get_record_sql("SELECT cm.id, MAX(chm.timestamp) AS lasttime |
242 | FROM {course_modules} cm |
243 | JOIN {chat} ch ON ch.id = cm.instance |
6e5f40ea |
244 | JOIN {chat_messages_current} chm ON chm.chatid = ch.id |
d3bf6f92 |
245 | WHERE chm.timestamp > ? AND cm.id = ? AND |
246 | (chm.groupid IN ($mygroupids) OR chm.groupid = 0) |
247 | GROUP BY cm.id", array($timestart, $cm->id))) { |
dd97c328 |
248 | continue; |
249 | } |
fd4d41c3 |
250 | |
251 | $cm->lasttime = $mcm->lasttime; |
dd97c328 |
252 | if ($timeout > time() - $cm->lasttime) { |
253 | $current[] = $cm; |
254 | } else { |
255 | $past[] = $cm; |
256 | } |
257 | } |
258 | |
259 | if (!$past and !$current) { |
b7602a11 |
260 | return false; |
261 | } |
1515a89e |
262 | |
dd97c328 |
263 | $strftimerecent = get_string('strftimerecent'); |
264 | |
265 | if ($past) { |
266 | print_headline(get_string('pastchats', 'chat').':'); |
267 | |
268 | foreach ($past as $cm) { |
269 | $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id; |
270 | $date = userdate($cm->lasttime, $strftimerecent); |
271 | echo '<div class="head"><div class="date">'.$date.'</div></div>'; |
272 | echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name,true).'</a></div>'; |
b7602a11 |
273 | } |
8f7dc7f1 |
274 | } |
275 | |
276 | if ($current) { |
dd97c328 |
277 | print_headline(get_string('currentchats', 'chat').':'); |
278 | |
279 | $oldest = floor((time()-$CFG->chat_old_ping)/10)*10; // better db caching |
280 | |
281 | $timeold = time() - $CFG->chat_old_ping; |
282 | $timeold = floor($timeold/10)*10; // better db caching |
283 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts |
284 | $timeoldext = floor($timeoldext/10)*10; // better db caching |
285 | |
d3bf6f92 |
286 | $params = array('timeold'=>$timeold, 'timeoldext'=>$timeoldext, 'cmid'=>$cm->id); |
287 | |
288 | $timeout = "AND (chu.version<>'basic' AND chu.lastping>:timeold) OR (chu.version='basic' AND chu.lastping>:timeoldext)"; |
dd97c328 |
289 | |
290 | foreach ($current as $cm) { |
291 | //count users first |
292 | if (isset($cm->mygroupids)) { |
293 | $groupselect = "AND (chu.groupid IN ({$cm->mygroupids}) OR chu.groupid = 0)"; |
294 | } else { |
295 | $groupselect = ""; |
296 | } |
fd4d41c3 |
297 | |
d3bf6f92 |
298 | if (!$users = $DB->get_records_sql("SELECT u.id, u.firstname, u.lastname, u.email, u.picture |
299 | FROM {course_modules} cm |
300 | JOIN {chat} ch ON ch.id = cm.instance |
301 | JOIN {chat_users} chu ON chu.chatid = ch.id |
302 | JOIN {user} u ON u.id = chu.userid |
303 | WHERE cm.id = :cmid $timeout $groupselect |
304 | GROUP BY u.id, u.firstname, u.lastname, u.email, u.picture", $params)) { |
dd97c328 |
305 | } |
306 | |
307 | $link = $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id; |
308 | $date = userdate($cm->lasttime, $strftimerecent); |
309 | |
310 | echo '<div class="head"><div class="date">'.$date.'</div></div>'; |
311 | echo '<div class="info"><a href="'.$link.'">'.format_string($cm->name,true).'</a></div>'; |
312 | echo '<div class="userlist">'; |
313 | if ($users) { |
314 | echo '<ul>'; |
315 | foreach ($users as $user) { |
316 | echo '<li>'.fullname($user, $viewfullnames).'</li>'; |
317 | } |
318 | echo '</ul>'; |
319 | } |
320 | echo '</div>'; |
321 | } |
b7602a11 |
322 | } |
323 | |
324 | return true; |
1515a89e |
325 | } |
326 | |
8f7dc7f1 |
327 | |
1515a89e |
328 | function chat_cron () { |
329 | /// Function to be run periodically according to the moodle cron |
b5de723d |
330 | /// This function searches for things that need to be done, such |
331 | /// as sending out mail, toggling flags etc ... |
d3bf6f92 |
332 | global $DB; |
1515a89e |
333 | |
fcd3a1ee |
334 | chat_update_chat_times(); |
335 | |
7d792369 |
336 | chat_delete_old_users(); |
337 | |
319038c3 |
338 | /// Delete old messages with a |
339 | /// single SQL query. |
340 | $subselect = "SELECT c.keepdays |
d3bf6f92 |
341 | FROM {chat} c |
342 | WHERE c.id = {chat_messages}.chatid"; |
4388027c |
343 | |
319038c3 |
344 | $sql = "DELETE |
d3bf6f92 |
345 | FROM {chat_messages} |
6e5f40ea |
346 | WHERE ($subselect) > 0 AND timestamp < ( ".time()." -($subselect) * 24 * 3600)"; |
347 | |
348 | $DB->execute($sql); |
349 | |
350 | $sql = "DELETE |
351 | FROM {chat_messages_current} |
352 | WHERE timestamp < ( ".time()." - 8 * 3600)"; |
4388027c |
353 | |
d3bf6f92 |
354 | $DB->execute($sql); |
22a4491a |
355 | |
1515a89e |
356 | return true; |
357 | } |
358 | |
84a2fdd7 |
359 | function chat_get_participants($chatid, $groupid=0) { |
05855091 |
360 | //Returns the users with data in one chat |
361 | //(users with records in chat_messages, students) |
d3bf6f92 |
362 | global $DB; |
05855091 |
363 | |
d3bf6f92 |
364 | $params = array('groupid'=>$groupid, 'chatid'=>$chatid); |
05855091 |
365 | |
84a2fdd7 |
366 | if ($groupid) { |
d3bf6f92 |
367 | $groupselect = " AND (c.groupid=:groupid OR c.groupid='0')"; |
84a2fdd7 |
368 | } else { |
369 | $groupselect = ""; |
370 | } |
371 | |
05855091 |
372 | //Get students |
d3bf6f92 |
373 | $students = $DB->get_records_sql("SELECT DISTINCT u.id, u.id |
374 | FROM {user} u, {chat_messages} c |
375 | WHERE c.chatid = :chatid $groupselect |
376 | AND u.id = c.userid", $params); |
1515a89e |
377 | |
05855091 |
378 | //Return students array (it contains an array of unique users) |
379 | return ($students); |
380 | } |
1515a89e |
381 | |
8496c4af |
382 | function chat_refresh_events($courseid = 0) { |
383 | // This standard function will check all instances of this module |
384 | // and make sure there are up-to-date events created for each of them. |
385 | // If courseid = 0, then every chat event in the site is checked, else |
386 | // only chat events belonging to the course specified are checked. |
387 | // This function is used, in its new format, by restore_refresh_events() |
d3bf6f92 |
388 | global $DB; |
8496c4af |
389 | |
390 | if ($courseid) { |
d3bf6f92 |
391 | if (! $chats = $DB->get_records("chat", array("course"=>$courseid))) { |
8496c4af |
392 | return true; |
393 | } |
394 | } else { |
d3bf6f92 |
395 | if (! $chats = $DB->get_records("chat")) { |
8496c4af |
396 | return true; |
397 | } |
398 | } |
d3bf6f92 |
399 | $moduleid = $DB->get_field('modules', 'id', array('name'=>'chat')); |
8496c4af |
400 | |
401 | foreach ($chats as $chat) { |
402 | $event = NULL; |
d3bf6f92 |
403 | $event->name = $chat->name; |
404 | $event->description = $chat->intro; |
8496c4af |
405 | $event->timestart = $chat->chattime; |
406 | |
d3bf6f92 |
407 | if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'chat', 'instance'=>$chat->id))) { |
8496c4af |
408 | update_event($event); |
409 | |
410 | } else { |
411 | $event->courseid = $chat->course; |
412 | $event->groupid = 0; |
413 | $event->userid = 0; |
414 | $event->modulename = 'chat'; |
415 | $event->instance = $chat->id; |
416 | $event->eventtype = $chat->schedule; |
417 | $event->timeduration = 0; |
d3bf6f92 |
418 | $event->visible = $DB->get_field('course_modules', 'visible', array('module'=>$moduleid, 'instance'=>$chat->id)); |
b5de723d |
419 | |
8496c4af |
420 | add_event($event); |
421 | } |
422 | } |
423 | return true; |
424 | } |
425 | |
516121bd |
426 | |
1515a89e |
427 | ////////////////////////////////////////////////////////////////////// |
428 | /// Functions that require some SQL |
429 | |
a12e11c1 |
430 | function chat_get_users($chatid, $groupid=0, $groupingid=0) { |
d3bf6f92 |
431 | global $DB; |
1515a89e |
432 | |
d3bf6f92 |
433 | $params = array('chatid'=>$chatid, 'groupid'=>$groupid, 'groupingid'=>$groupingid); |
84a2fdd7 |
434 | |
435 | if ($groupid) { |
d3bf6f92 |
436 | $groupselect = " AND (c.groupid=:groupid OR c.groupid='0')"; |
84a2fdd7 |
437 | } else { |
438 | $groupselect = ""; |
439 | } |
6e5f40ea |
440 | |
a12e11c1 |
441 | if (!empty($CFG->enablegroupings) && !(empty($groupingid))) { |
d3bf6f92 |
442 | $groupingjoin = "JOIN {groups_members} gm ON u.id = gm.userid |
443 | JOIN {groupings_groups} gg ON gm.groupid = gg.groupid AND gg.groupingid = :groupingid "; |
6e5f40ea |
444 | |
a12e11c1 |
445 | } else { |
446 | $groupingjoin = ''; |
447 | } |
b5de723d |
448 | |
547ac664 |
449 | return $DB->get_records_sql("SELECT |
450 | DISTINCT u.id, u.firstname, u.lastname, u.picture, c.lastmessageping, c.firstping, u.imagealt |
451 | FROM {chat_users} c JOIN {user} u ON u.id = c.userid $groupingjoin |
452 | WHERE c.chatid = :chatid $groupselect |
453 | ORDER BY c.firstping ASC", $params); |
1515a89e |
454 | } |
455 | |
84a2fdd7 |
456 | function chat_get_latest_message($chatid, $groupid=0) { |
f33e1ed4 |
457 | global $DB; |
1515a89e |
458 | |
d3bf6f92 |
459 | $params = array('chatid'=>$chatid, 'groupid'=>$groupid); |
1515a89e |
460 | |
84a2fdd7 |
461 | if ($groupid) { |
d3bf6f92 |
462 | $groupselect = "AND (groupid=:groupid OR groupid=0)"; |
84a2fdd7 |
463 | } else { |
464 | $groupselect = ""; |
465 | } |
466 | |
547ac664 |
467 | $sql = "SELECT * |
468 | FROM {chat_messages_current} WHERE chatid = :chatid $groupselect |
469 | ORDER BY timestamp DESC"; |
03cedd62 |
470 | |
547ac664 |
471 | // return the lastest one message |
f33e1ed4 |
472 | return $DB->get_record_sql($sql, $params, true); |
1515a89e |
473 | } |
474 | |
5a8625e4 |
475 | |
1515a89e |
476 | ////////////////////////////////////////////////////////////////////// |
516121bd |
477 | // login if not already logged in |
1515a89e |
478 | |
a32c7772 |
479 | function chat_login_user($chatid, $version, $groupid, $course) { |
d3bf6f92 |
480 | global $USER, $DB; |
481 | |
482 | if (($version != 'sockets') and $chatuser = $DB->get_record('chat_users', array('chatid'=>$chatid, 'userid'=>$USER->id, 'groupid'=>$groupid))) { |
7f0483f6 |
483 | // this will update logged user information |
516121bd |
484 | $chatuser->version = $version; |
d96466d2 |
485 | $chatuser->ip = $USER->lastip; |
516121bd |
486 | $chatuser->lastping = time(); |
487 | $chatuser->lang = current_language(); |
1515a89e |
488 | |
d96466d2 |
489 | // Sometimes $USER->lastip is not setup properly |
d13ef2fb |
490 | // during login. Update with current value if possible |
f83edcb1 |
491 | // or provide a dummy value for the db |
d13ef2fb |
492 | if (empty($chatuser->ip)) { |
493 | $chatuser->ip = getremoteaddr(); |
494 | if (empty($chatuser->ip)) { |
f83edcb1 |
495 | $chatuser->ip = ''; |
d13ef2fb |
496 | } |
497 | } |
498 | |
7f0483f6 |
499 | if (($chatuser->course != $course->id) or ($chatuser->userid != $USER->id)) { |
516121bd |
500 | return false; |
501 | } |
d3bf6f92 |
502 | if (!$DB->update_record('chat_users', $chatuser)) { |
516121bd |
503 | return false; |
504 | } |
516121bd |
505 | } else { |
6ee78cee |
506 | $chatuser = new object(); |
516121bd |
507 | $chatuser->chatid = $chatid; |
508 | $chatuser->userid = $USER->id; |
509 | $chatuser->groupid = $groupid; |
510 | $chatuser->version = $version; |
d96466d2 |
511 | $chatuser->ip = $USER->lastip; |
516121bd |
512 | $chatuser->lastping = $chatuser->firstping = $chatuser->lastmessageping = time(); |
513 | $chatuser->sid = random_string(32); |
3dfd307f |
514 | $chatuser->course = $course->id; //caching - needed for current_language too |
515 | $chatuser->lang = current_language(); //caching - to resource intensive to find out later |
516121bd |
516 | |
d96466d2 |
517 | // Sometimes $USER->lastip is not setup properly |
274f0091 |
518 | // during login. Update with current value if possible |
519 | // or provide a dummy value for the db |
520 | if (empty($chatuser->ip)) { |
521 | $chatuser->ip = getremoteaddr(); |
522 | if (empty($chatuser->ip)) { |
523 | $chatuser->ip = ''; |
524 | } |
525 | } |
526 | |
527 | |
d3bf6f92 |
528 | if (!$DB->insert_record('chat_users', $chatuser)) { |
516121bd |
529 | return false; |
530 | } |
531 | |
a32c7772 |
532 | if ($version == 'sockets') { |
533 | // do not send 'enter' message, chatd will do it |
534 | } else { |
6ee78cee |
535 | $message = new object(); |
2ac0d13b |
536 | $message->chatid = $chatuser->chatid; |
537 | $message->userid = $chatuser->userid; |
538 | $message->groupid = $groupid; |
539 | $message->message = 'enter'; |
540 | $message->system = 1; |
541 | $message->timestamp = time(); |
542 | |
7f0483f6 |
543 | if (!$DB->insert_record('chat_messages', $message) || !$DB->insert_record('chat_messages_current', $message)) |
544 | { |
2f52a088 |
545 | print_error('cantinsert', 'chat'); |
2ac0d13b |
546 | } |
516121bd |
547 | } |
1515a89e |
548 | } |
549 | |
550 | return $chatuser->sid; |
551 | } |
552 | |
7d792369 |
553 | function chat_delete_old_users() { |
554 | // Delete the old and in the way |
d3bf6f92 |
555 | global $CFG, $DB; |
b5012f3e |
556 | |
e7fbd0b3 |
557 | $timeold = time() - $CFG->chat_old_ping; |
953eb6f3 |
558 | $timeoldext = time() - ($CFG->chat_old_ping*10); // JSless gui_basic needs much longer timeouts |
a32c7772 |
559 | |
d3bf6f92 |
560 | $query = "(version<>'basic' AND lastping<?) OR (version='basic' AND lastping<?)"; |
561 | $params = array($timeold, $timeoldext); |
7d792369 |
562 | |
d3bf6f92 |
563 | if ($oldusers = $DB->get_records_select('chat_users', $query, $params) ) { |
564 | $DB->delete_records_select('chat_users', $query, $params); |
7d792369 |
565 | foreach ($oldusers as $olduser) { |
6ee78cee |
566 | $message = new object(); |
516121bd |
567 | $message->chatid = $olduser->chatid; |
568 | $message->userid = $olduser->userid; |
569 | $message->groupid = $olduser->groupid; |
570 | $message->message = 'exit'; |
571 | $message->system = 1; |
7d792369 |
572 | $message->timestamp = time(); |
b5de723d |
573 | |
547ac664 |
574 | if (!$DB->insert_record('chat_messages', $message) |
575 | || !$DB->insert_record('chat_messages_current', $message) ) |
576 | { |
2f52a088 |
577 | print_error('cantinsert', 'chat'); |
7d792369 |
578 | } |
579 | } |
580 | } |
581 | } |
1515a89e |
582 | |
22a4491a |
583 | |
fcd3a1ee |
584 | function chat_update_chat_times($chatid=0) { |
585 | /// Updates chat records so that the next chat time is correct |
d3bf6f92 |
586 | global $DB; |
fcd3a1ee |
587 | |
588 | $timenow = time(); |
d3bf6f92 |
589 | |
590 | $params = array('timenow'=>$timenow, 'chatid'=>$chatid); |
591 | |
fcd3a1ee |
592 | if ($chatid) { |
d3bf6f92 |
593 | if (!$chats[] = $DB->get_record_select("chat", "id = :chatid AND chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee |
594 | return; |
595 | } |
596 | } else { |
d3bf6f92 |
597 | if (!$chats = $DB->get_records_select("chat", "chattime <= :timenow AND schedule > 0", $params)) { |
fcd3a1ee |
598 | return; |
599 | } |
600 | } |
601 | |
602 | foreach ($chats as $chat) { |
7626969c |
603 | unset($chat->name); |
604 | unset($chat->intro); |
fcd3a1ee |
605 | switch ($chat->schedule) { |
606 | case 1: // Single event - turn off schedule and disable |
607 | $chat->chattime = 0; |
608 | $chat->schedule = 0; |
609 | break; |
610 | case 2: // Repeat daily |
f0d3bb9e |
611 | while ($chat->chattime <= $timenow) { |
612 | $chat->chattime += 24 * 3600; |
613 | } |
fcd3a1ee |
614 | break; |
615 | case 3: // Repeat weekly |
f0d3bb9e |
616 | while ($chat->chattime <= $timenow) { |
617 | $chat->chattime += 7 * 24 * 3600; |
618 | } |
fcd3a1ee |
619 | break; |
620 | } |
d3bf6f92 |
621 | $DB->update_record("chat", $chat); |
622 | |
623 | $event = new object(); // Update calendar too |
8496c4af |
624 | |
d3bf6f92 |
625 | $cond = "modulename='chat' AND instance = :chatid AND timestart <> :chattime"; |
626 | $params = array('chattime'=>$chat->chattime, 'chatid'=>$chatid); |
627 | |
628 | if ($event->id = $DB->get_field_select('event', 'id', $cond, $params)) { |
8496c4af |
629 | $event->timestart = $chat->chattime; |
630 | update_event($event); |
631 | } |
fcd3a1ee |
632 | } |
633 | } |
634 | |
635 | |
aa5c32fd |
636 | function chat_format_message_manually($message, $courseid, $sender, $currentuser, $chat_lastrow=NULL) { |
72989350 |
637 | global $CFG, $USER; |
1515a89e |
638 | |
6ee78cee |
639 | $output = new object(); |
516121bd |
640 | $output->beep = false; // by default |
641 | $output->refreshusers = false; // by default |
7d792369 |
642 | |
72989350 |
643 | // Use get_user_timezone() to find the correct timezone for displaying this message: |
644 | // It's either the current user's timezone or else decided by some Moodle config setting |
970f144e |
645 | // First, "reset" $USER->timezone (which could have been set by a previous call to here) |
646 | // because otherwise the value for the previous $currentuser will take precedence over $CFG->timezone |
647 | $USER->timezone = 99; |
72989350 |
648 | $tz = get_user_timezone($currentuser->timezone); |
b5de723d |
649 | |
72989350 |
650 | // Before formatting the message time string, set $USER->timezone to the above. |
651 | // This will allow dst_offset_on (called by userdate) to work correctly, otherwise the |
652 | // message times appear off because DST is not taken into account when it should be. |
653 | $USER->timezone = $tz; |
b5de723d |
654 | $message->strtime = userdate($message->timestamp, get_string('strftimemessage', 'chat'), $tz); |
655 | |
656 | $message->picture = print_user_picture($sender->id, 0, $sender->picture, false, true, false); |
582de679 |
657 | if ($courseid) { |
d3981e38 |
658 | $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 |
659 | } |
1515a89e |
660 | |
aa5c32fd |
661 | //Calculate the row class |
662 | if ($chat_lastrow !== NULL) { |
663 | $rowclass = ' class="r'.$chat_lastrow.'" '; |
664 | } else { |
665 | $rowclass = ''; |
666 | } |
667 | |
b5de723d |
668 | // Start processing the message |
1515a89e |
669 | |
b5de723d |
670 | if(!empty($message->system)) { |
671 | // System event |
672 | $output->text = $message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender)); |
aa5c32fd |
673 | $output->html = '<table class="chat-event"><tr'.$rowclass.'><td class="picture">'.$message->picture.'</td><td class="text">'; |
674 | $output->html .= '<span class="event">'.$output->text.'</span></td></tr></table>'; |
6e5f40ea |
675 | $output->basic = '<dl><dt class="event">'.$message->strtime.': '.get_string('message'.$message->message, 'chat', fullname($sender)).'</dt></dl>'; |
7d792369 |
676 | |
516121bd |
677 | if($message->message == 'exit' or $message->message == 'enter') { |
678 | $output->refreshusers = true; //force user panel refresh ASAP |
679 | } |
1515a89e |
680 | return $output; |
681 | } |
682 | |
82a524ef |
683 | // It's not a system event |
b5de723d |
684 | |
685 | $text = $message->message; |
82a524ef |
686 | |
687 | /// Parse the text to clean and filter it |
688 | |
6ee78cee |
689 | $options = new object(); |
82a524ef |
690 | $options->para = false; |
691 | $text = format_text($text, FORMAT_MOODLE, $options, $courseid); |
927a7808 |
692 | |
b5de723d |
693 | // And now check for special cases |
927a7808 |
694 | $special = false; |
695 | |
b5de723d |
696 | if (substr($text, 0, 5) == 'beep ') { |
6e5f40ea |
697 | /// It's a beep! |
927a7808 |
698 | $special = true; |
7d792369 |
699 | $beepwho = trim(substr($text, 5)); |
9f85bed4 |
700 | |
b5de723d |
701 | if ($beepwho == 'all') { // everyone |
702 | $outinfo = $message->strtime.': '.get_string('messagebeepseveryone', 'chat', fullname($sender)); |
703 | $outmain = ''; |
704 | $output->beep = true; // (eventually this should be set to |
7d792369 |
705 | // to a filename uploaded by the user) |
706 | |
82a524ef |
707 | } else if ($beepwho == $currentuser->id) { // current user |
b5de723d |
708 | $outinfo = $message->strtime.': '.get_string('messagebeepsyou', 'chat', fullname($sender)); |
709 | $outmain = ''; |
7d792369 |
710 | $output->beep = true; |
264867fd |
711 | |
0eda0a46 |
712 | } else { //something is not caught? |
7d792369 |
713 | return false; |
714 | } |
b5de723d |
715 | } else if (substr($text, 0, 1) == '/') { /// It's a user command |
1d507186 |
716 | // support some IRC commands |
717 | $pattern = '#(^\/)(\w+).*#'; |
718 | preg_match($pattern, trim($text), $matches); |
719 | $command = $matches[2]; |
720 | switch ($command){ |
721 | case 'me': |
927a7808 |
722 | $special = true; |
b5de723d |
723 | $outinfo = $message->strtime; |
1d507186 |
724 | $outmain = '*** <b>'.$sender->firstname.' '.substr($text, 4).'</b>'; |
725 | break; |
1515a89e |
726 | } |
7f0483f6 |
727 | } elseif (substr($text, 0, 2) == 'To') { |
728 | $pattern = '#To[[:space:]](.*):(.*)#'; |
729 | preg_match($pattern, trim($text), $matches); |
730 | $special = true; |
731 | $outinfo = $message->strtime; |
732 | $outmain = $sender->firstname.' '.get_string('saidto', 'chat').' <i>'.$matches[1].'</i>: '.$matches[2]; |
927a7808 |
733 | } |
9f85bed4 |
734 | |
927a7808 |
735 | if(!$special) { |
b5de723d |
736 | $outinfo = $message->strtime.' '.$sender->firstname; |
7d792369 |
737 | $outmain = $text; |
1515a89e |
738 | } |
264867fd |
739 | |
9f85bed4 |
740 | /// Format the message as a small table |
1515a89e |
741 | |
b5de723d |
742 | $output->text = strip_tags($outinfo.': '.$outmain); |
7d792369 |
743 | |
5379d249 |
744 | $output->html = "<table class=\"chat-message\"><tr$rowclass><td class=\"picture\" valign=\"top\">$message->picture</td><td class=\"text\">"; |
aa5c32fd |
745 | $output->html .= "<span class=\"title\">$outinfo</span>"; |
7d792369 |
746 | if ($outmain) { |
747 | $output->html .= ": $outmain"; |
6e5f40ea |
748 | $output->basic = '<dl><dt class="title">'.$outinfo.':</dt><dd class="text">'.$outmain.'</dd></dl>'; |
6ee78cee |
749 | } else { |
6e5f40ea |
750 | $output->basic = '<dl><dt class="title">'.$outinfo.'</dt></dl>'; |
7d792369 |
751 | } |
aa5c32fd |
752 | $output->html .= "</td></tr></table>"; |
7d792369 |
753 | return $output; |
b5de723d |
754 | } |
755 | |
aa5c32fd |
756 | function chat_format_message($message, $courseid, $currentuser, $chat_lastrow=NULL) { |
b5de723d |
757 | /// Given a message object full of information, this function |
758 | /// formats it appropriately into text and html, then |
759 | /// returns the formatted data. |
d3bf6f92 |
760 | global $DB; |
b5de723d |
761 | |
78c98892 |
762 | static $users; // Cache user lookups |
763 | |
764 | if (isset($users[$message->userid])) { |
765 | $user = $users[$message->userid]; |
d3bf6f92 |
766 | } else if ($user = $DB->get_record('user', array('id'=>$message->userid), 'id,picture,firstname,lastname')) { |
78c98892 |
767 | $users[$message->userid] = $user; |
768 | } else { |
769 | return NULL; |
b5de723d |
770 | } |
aa5c32fd |
771 | return chat_format_message_manually($message, $courseid, $user, $currentuser, $chat_lastrow); |
1515a89e |
772 | } |
773 | |
f3221af9 |
774 | function chat_get_view_actions() { |
775 | return array('view','view all','report'); |
776 | } |
777 | |
778 | function chat_get_post_actions() { |
779 | return array('talk'); |
780 | } |
781 | |
9ca0187e |
782 | function chat_print_overview($courses, &$htmlarray) { |
783 | global $USER, $CFG; |
784 | |
785 | if (empty($courses) || !is_array($courses) || count($courses) == 0) { |
786 | return array(); |
787 | } |
788 | |
789 | if (!$chats = get_all_instances_in_courses('chat',$courses)) { |
790 | return; |
791 | } |
792 | |
793 | $strchat = get_string('modulename', 'chat'); |
794 | $strnextsession = get_string('nextsession', 'chat'); |
9ca0187e |
795 | |
796 | foreach ($chats as $chat) { |
9ca0187e |
797 | if ($chat->chattime and $chat->schedule) { // A chat is scheduled |
a2a37336 |
798 | $str = '<div class="chat overview"><div class="name">'. |
799 | $strchat.': <a '.($chat->visible?'':' class="dimmed"'). |
800 | ' href="'.$CFG->wwwroot.'/mod/chat/view.php?id='.$chat->coursemodule.'">'. |
801 | $chat->name.'</a></div>'; |
802 | $str .= '<div class="info">'.$strnextsession.': '.userdate($chat->chattime).'</div></div>'; |
803 | |
804 | if (empty($htmlarray[$chat->course]['chat'])) { |
805 | $htmlarray[$chat->course]['chat'] = $str; |
806 | } else { |
807 | $htmlarray[$chat->course]['chat'] .= $str; |
808 | } |
9ca0187e |
809 | } |
9ca0187e |
810 | } |
811 | } |
812 | |
0b5a80a1 |
813 | |
814 | /** |
815 | * Implementation of the function for printing the form elements that control |
816 | * whether the course reset functionality affects the chat. |
817 | * @param $mform form passed by reference |
818 | */ |
819 | function chat_reset_course_form_definition(&$mform) { |
820 | $mform->addElement('header', 'chatheader', get_string('modulenameplural', 'chat')); |
821 | $mform->addElement('advcheckbox', 'reset_chat', get_string('removemessages','chat')); |
822 | } |
823 | |
824 | /** |
825 | * Course reset form defaults. |
826 | */ |
827 | function chat_reset_course_form_defaults($course) { |
828 | return array('reset_chat'=>1); |
829 | } |
830 | |
831 | /** |
832 | * Actual implementation of the rest coures functionality, delete all the |
833 | * chat messages for course $data->courseid. |
834 | * @param $data the data submitted from the reset course. |
835 | * @return array status array |
836 | */ |
837 | function chat_reset_userdata($data) { |
d3bf6f92 |
838 | global $CFG, $DB; |
0b5a80a1 |
839 | |
840 | $componentstr = get_string('modulenameplural', 'chat'); |
841 | $status = array(); |
842 | |
843 | if (!empty($data->reset_chat)) { |
844 | $chatessql = "SELECT ch.id |
d3bf6f92 |
845 | FROM {chat} ch |
846 | WHERE ch.course=?"; |
847 | $params = array($data->courseid); |
0b5a80a1 |
848 | |
d3bf6f92 |
849 | $DB->delete_records_select('chat_messages', "chatid IN ($chatessql)", $params); |
6e5f40ea |
850 | $DB->delete_records_select('chat_messages_current', "chatid IN ($chatessql)", $params); |
d3bf6f92 |
851 | $DB->delete_records_select('chat_users', "chatid IN ($chatessql)", $params); |
0b5a80a1 |
852 | $status[] = array('component'=>$componentstr, 'item'=>get_string('removemessages', 'chat'), 'error'=>false); |
853 | } |
854 | |
855 | /// updating dates - shift may be negative too |
856 | if ($data->timeshift) { |
857 | shift_course_mod_dates('chat', array('chattime'), $data->timeshift, $data->courseid); |
858 | $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); |
859 | } |
860 | |
861 | return $status; |
862 | } |
863 | |
f432bebf |
864 | /** |
865 | * Returns all other caps used in module |
866 | */ |
867 | function chat_get_extra_capabilities() { |
868 | return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames'); |
869 | } |
870 | |
47cfd331 |
871 | class chat_portfolio_caller extends portfolio_module_caller_base { |
872 | |
873 | private $chat; |
0d06b6fd |
874 | protected $start; |
875 | protected $end; |
876 | |
877 | public static function expected_callbackargs() { |
878 | return array( |
879 | 'id' => true, |
880 | 'start' => false, |
881 | 'end' => false, |
882 | ); |
883 | } |
884 | |
885 | public function load_data() { |
886 | global $DB; |
47cfd331 |
887 | |
0d06b6fd |
888 | if (!$this->cm = get_coursemodule_from_id('chat', $this->id)) { |
34035201 |
889 | throw new portfolio_caller_exception('invalidid', 'chat'); |
47cfd331 |
890 | } |
891 | $this->chat = $DB->get_record('chat', array('id' => $this->cm->instance)); |
892 | $select = 'chatid = ?'; |
893 | $params = array($this->chat->id); |
0d06b6fd |
894 | if ($this->start && $this->end) { |
47cfd331 |
895 | $select .= ' AND timestamp >= ? AND timestamp <= ?'; |
0d06b6fd |
896 | $params[] = $this->start; |
897 | $params[] = $this->end; |
47cfd331 |
898 | } |
899 | $this->messages = $DB->get_records_select( |
900 | 'chat_messages', |
901 | $select, |
902 | $params, |
903 | 'timestamp ASC' |
904 | ); |
905 | $select .= ' AND userid = ?'; |
0d06b6fd |
906 | $params[] = $this->user->id; |
47cfd331 |
907 | $this->participated = $DB->record_exists_select( |
908 | 'chat_messages', |
909 | $select, |
910 | $params |
911 | ); |
0d06b6fd |
912 | } |
913 | |
a7d90683 |
914 | public static function supported_formats() { |
6be1dcae |
915 | return array(PORTFOLIO_FORMAT_PLAINHTML); |
47cfd331 |
916 | } |
917 | |
918 | public function expected_time() { |
d8606b20 |
919 | return portfolio_expected_time_db(count($this->messages)); |
47cfd331 |
920 | } |
921 | |
922 | public function get_sha1() { |
923 | $str = ''; |
924 | ksort($this->messages); |
925 | foreach ($this->messages as $m) { |
926 | $str .= implode('', (array)$m); |
927 | } |
928 | return sha1($str); |
929 | } |
930 | |
931 | public function check_permissions() { |
932 | $context = get_context_instance(CONTEXT_MODULE, $this->cm->id); |
933 | return has_capability('mod/chat:exportsession', $context) |
934 | || ($this->participated |
935 | && has_capability('mod/chat:exportparticipatedsession', $context)); |
936 | } |
937 | |
938 | public function prepare_package() { |
939 | $content = ''; |
5a04379a |
940 | $lasttime = 0; |
941 | $sessiongap = 5 * 60; // 5 minutes silence means a new session |
47cfd331 |
942 | foreach ($this->messages as $message) { // We are walking FORWARDS through messages |
5a04379a |
943 | $m = clone $message; // grrrrrr - this causes the sha1 to change as chat_format_message changes what it's passed. |
47cfd331 |
944 | $formatmessage = chat_format_message($m, null, $this->user); |
945 | if (!isset($formatmessage->html)) { |
946 | continue; |
947 | } |
5a04379a |
948 | if (empty($lasttime) || (($message->timestamp - $lasttime) > $sessiongap)) { |
949 | $content .= '<hr />'; |
950 | $content .= userdate($message->timestamp); |
951 | } |
47cfd331 |
952 | $content .= $formatmessage->html; |
5a04379a |
953 | $lasttime = $message->timestamp; |
47cfd331 |
954 | } |
955 | $content = preg_replace('/\<img[^>]*\>/', '', $content); |
956 | |
6be1dcae |
957 | $this->exporter->write_new_file($content, clean_filename($this->cm->name . '-session.html'), false); |
47cfd331 |
958 | } |
959 | |
960 | public static function display_name() { |
961 | return get_string('modulename', 'chat'); |
962 | } |
963 | |
964 | public function get_return_url() { |
965 | global $CFG; |
966 | |
967 | return $CFG->wwwroot . '/mod/chat/report.php?id=' |
968 | . $this->cm->id . ((isset($this->start)) |
969 | ? '&start=' . $this->start . '&end=' . $this->end |
970 | : ''); |
971 | } |
972 | } |
973 | |
1515a89e |
974 | ?> |