/[drupal]/contributions/modules/chatroom/chatroom.module
ViewVC logotype

Contents of /contributions/modules/chatroom/chatroom.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.67 - (show annotations) (download) (as text)
Fri Nov 6 16:56:18 2009 UTC (3 weeks ago) by justinrandell
Branch: MAIN
Changes since 1.66: +793 -173 lines
File MIME type: text/x-php
sync up HEAD with 6.x-2 BETA 1
1 <?php
2 // $Id: chatroom.module,v 1.63.2.40 2009/11/06 16:40:11 justinrandell Exp $
3
4 require_once dirname(__FILE__) . '/chatroom.forms.inc';
5 require_once dirname(__FILE__) . '/chatroom.theme.inc';
6
7 /**
8 * @file
9 * Enable chat room support in Drupal.
10 */
11
12 /**
13 * Implementation of hook_help().
14 */
15 function chatroom_help($path, $arg) {
16 switch ($path) {
17 case 'admin/help#chatroom':
18 return '<p />';
19 }
20 }
21
22 /**
23 * Implementation of hook_help().
24 */
25 function chatroom_init() {
26 global $user;
27
28 if ($user->uid > 0) {
29 if ($invites = chatroom_chat_get_user_invites($user)) {
30 chatroom_chat_notify_user_of_invites($user, $invites);
31 }
32 }
33 }
34
35 /**
36 * Notify a user of pending chat invites.
37 *
38 * @param mixed $chat_user
39 * @param mixed $invites
40 * @return void
41 */
42 function chatroom_chat_notify_user_of_invites($chat_user, $invites) {
43 foreach (module_implements('chatroom_chat_invites_notify') as $module) {
44 $function = $module . '_chatroom_chat_invites_notify';
45 $function($chat_user, $invites);
46 }
47 $sql = "UPDATE {chatroom_chat_invite} SET notified = 1 WHERE cciid IN (" . db_placeholders(array_keys($invites)) . ')';
48 db_query($sql, array_keys($invites));
49 }
50
51 /**
52 * Implementation of hook_chatroom_chat_invites_notify().
53 *
54 * @param mixed $chat_user
55 * @param mixed $invites
56 * @return void
57 */
58 function chatroom_chatroom_chat_invites_notify($chat_user, $invites) {
59 foreach ($invites as $invite) {
60 $chat_path = 'node/' . $invite->nid;
61 if ($_GET['q'] != $chat_path) {
62 $link = l($invite->title, 'node/' . $invite->nid);
63 $message = t("You have been invited to the chat !link by user '%name'", array('!link' => $link, '%name' => $invite->name));
64 drupal_set_message($message);
65 }
66 }
67 }
68
69 /**
70 * Get any pending invites for a user.
71 *
72 * @param mixed $chat_user
73 * @return array
74 */
75 function chatroom_chat_get_user_invites($chat_user) {
76 $sql = "SELECT cci.cciid, n.title, u.name, u.uid, cci.nid
77 FROM {chatroom_chat_invite} cci
78 INNER JOIN {node} n ON n.nid = cci.nid
79 INNER JOIN {users} u ON u.uid = cci.inviter_uid
80 WHERE cci.invitee_uid = %d
81 AND cci.accepted = 0
82 AND cci.notified = 0";
83 $result = db_query($sql, $chat_user->uid);
84
85 $invites = array();
86 while ($invite = db_fetch_object($result)) {
87 $invites[$invite->cciid] = $invite;
88 }
89 return $invites;
90 }
91
92 /**
93 * Implementation of hook_access().
94 */
95 function chatroom_chat_access($op, $node, $account) {
96 if (user_access('administer chats', $account)) {
97 return TRUE;
98 }
99 if ($op == 'view') {
100 return user_access('access chats', $account) && chatroom_chat_user_has_access($node, $account);
101 }
102 if ($op == 'create') {
103 return user_access('create chats', $account);
104 }
105 if ($op == 'update' || $op == 'delete') {
106 if (user_access('edit own chats', $account) && ($account->uid == $node->uid)) {
107 return TRUE;
108 }
109 }
110 return FALSE;
111 }
112
113 /**
114 * Implementation of hook_access().
115 */
116 function chatroom_access($op, $node, $account) {
117 if (user_access('administer chat rooms', $account)) {
118 return TRUE;
119 }
120 if ($op == 'view') {
121 return user_access('access chat rooms', $account);
122 }
123 if ($op == 'create') {
124 return user_access('create chat rooms', $account);
125 }
126 if ($op == 'update' || $op == 'delete') {
127 if (user_access('edit own chat rooms', $account) && ($account->uid == $node->uid)) {
128 return TRUE;
129 }
130 }
131 return FALSE;
132 }
133
134 /**
135 * Implementation of hook_perm().
136 */
137 function chatroom_perm() {
138 return array('access chats', 'access chat rooms', 'create chat rooms', 'edit own chats', 'edit own chat rooms', 'administer chats', 'administer chat rooms', 'create chats');
139 }
140
141 /**
142 * Implementation of hook_menu().
143 */
144 function chatroom_menu() {
145 $items['chatroom/ajax/user/invite/%node'] = array(
146 'description' => t('Invite a user to a chat.'),
147 'page callback' => 'chatroom_chat_ajax_user_invite',
148 'page arguments' => array(4),
149 'access callback' => TRUE,
150 );
151 $items['chatroom/ajax/user/add/%node'] = array(
152 'description' => t('Add a user to a private chat.'),
153 'page callback' => 'chatroom_chat_ajax_user_add',
154 'page arguments' => array(4),
155 'access callback' => TRUE,
156 );
157 $items['chatroom/ajax/user/remove/%node'] = array(
158 'description' => t('Remove a user from a private chat.'),
159 'page callback' => 'chatroom_chat_ajax_user_remove',
160 'page arguments' => array(4),
161 'access callback' => TRUE,
162 );
163 $items['chatroom/popout/redirect/%node'] = array(
164 'description' => t('Configure global settings for chat rooms and chats.'),
165 'page callback' => 'chatroom_popout_redirect',
166 'page arguments' => array(3),
167 'access callback' => TRUE,
168 );
169 $items['chatroom/user/autocomplete'] = array(
170 'title' => 'Chat room',
171 'page callback' => 'chatroom_user_autocomplete',
172 'access callback' => TRUE,
173 'type' => MENU_CALLBACK,
174 );
175 $items['admin/settings/chatroom'] = array(
176 'title' => 'Chat room',
177 'description' => t('Configure global settings for chat rooms and chats.'),
178 'page callback' => 'drupal_get_form',
179 'page arguments' => array('chatroom_admin_settings'),
180 'access arguments' => array('administer chat rooms'),
181 );
182 $items['chatroom/access-denied/%node/%'] = array(
183 'type' => MENU_CALLBACK,
184 'page callback' => 'chatroom_access_denied',
185 'page arguments' => array(2, 3),
186 'access arguments' => array('access chat rooms'),
187 );
188 $items['chatroom/chat/post/message/%node/%'] = array(
189 'page callback' => 'chatroom_chat_post_message',
190 'page arguments' => array(4, 5),
191 'access arguments' => array('access chat rooms'),
192 'type' => MENU_CALLBACK,
193 );
194 $items['chatroom/chat/get/latest/messages/%node/%'] = array(
195 'page callback' => 'chatroom_chat_get_latest_messages',
196 'page arguments' => array(5, 6),
197 'access arguments' => array('access chat rooms'),
198 'type' => MENU_CALLBACK,
199 );
200 return $items;
201 }
202
203 /**
204 * Implementation of hook_node_info().
205 */
206 function chatroom_node_info() {
207 return array(
208 'chatroom' => array(
209 'name' => t('Chat room'),
210 'module' => 'chatroom',
211 'description' => t('A chat room provides access to chats and chat archives.'),
212 ),
213 'chat' => array(
214 'name' => t('Chat'),
215 'module' => 'chatroom_chat',
216 'description' => t('A chat provides the chat interface.'),
217 ),
218 );
219 }
220
221 /**
222 * Implementation of hook_insert().
223 */
224 function chatroom_insert($node) {
225 cache_clear_all('chatroom_room_list', 'cache');
226 $chatroom = array(
227 'nid' => $node->nid,
228 'poll_freq' => $node->poll_freq,
229 'idle_freq' => $node->idle_freq,
230 'kicked_out_message' => $node->kicked_out_message,
231 'banned_message' => $node->banned_message,
232 'module' => isset($node->module) ? $node->module : 'chatroom',
233 'previous_messages_display_count' => $node->previous_messages_display_count,
234 'popout' => $node->popout,
235 'profile_picture' => $node->profile_picture,
236 );
237 drupal_write_record('chatroom', $chatroom);
238 }
239
240 /**
241 * Implementation of hook_update().
242 */
243 function chatroom_update($node) {
244 cache_clear_all('chatroom_room_list', 'cache');
245 $chatroom = array(
246 'nid' => $node->nid,
247 'poll_freq' => $node->poll_freq,
248 'idle_freq' => $node->idle_freq,
249 'kicked_out_message' => $node->kicked_out_message,
250 'banned_message' => $node->banned_message,
251 'module' => isset($node->module) ? $node->module : 'chatroom',
252 'previous_messages_display_count' => $node->previous_messages_display_count,
253 'popout' => $node->popout,
254 'profile_picture' => $node->profile_picture,
255 );
256 drupal_write_record('chatroom', $chatroom, 'nid');
257 }
258
259 /**
260 * Implementation of hook_delete().
261 */
262 function chatroom_delete(&$node) {
263 cache_clear_all('chatroom_room_list', 'cache');
264 db_query('DELETE FROM {chatroom} WHERE nid = %d', $node->nid);
265 db_query("DELETE FROM {chatroom_chat} WHERE crid = %d", $node->nid);
266 db_query('DELETE FROM {chatroom_ban_list} WHERE nid = %d', $node->nid);
267 if (!empty($node->chats)) {
268 $ccids = implode(',', array_keys($node->chats));
269 db_query('DELETE FROM {chatroom_msg} WHERE ccid IN (%s)', $ccids);
270 db_query('DELETE FROM {chatroom_online_list} WHERE ccid IN (%s)', $ccids);
271 }
272 }
273
274 /**
275 * Implementation of hook_load().
276 */
277 function chatroom_load($node) {
278 $room = new StdClass();
279 if ($room->chatroom = db_fetch_object(db_query('SELECT * FROM {chatroom} WHERE nid = %d', $node->nid))) {
280 $room->chatroom->banned_users = chatroom_get_banned_users($node);
281 // If the user is banned, don't load chats.
282 if (chatroom_is_banned_user($node)) {
283 return $chatroom;
284 }
285 $room->chatroom->chats = chatroom_load_chats($node->nid);
286 }
287 return $room;
288 }
289
290 /**
291 * Load chats for a given chatroom.
292 *
293 * @param mixed $nid
294 * @return array - a list of chats.
295 */
296 function chatroom_load_chats($nid) {
297 $chats = array();
298 $cmids = array();
299
300 $sql = "SELECT cc.*, n.title, 0 last_cmid, 0 msg_count, NULL last_msg
301 FROM {chatroom_chat} cc
302 INNER JOIN {node} n ON n.nid = cc.nid
303 WHERE cc.crid = %d";
304 $result = db_query($sql, $nid);
305 while ($chat = db_fetch_object($result)) {
306 $chats[$chat->nid] = $chat;
307 }
308
309 // Load the message count info.
310 if (!empty($chats)) {
311 $ccids = array_keys($chats);
312 $sql = "SELECT ccid, COUNT(*) msg_count, MAX(cmid) last_cmid
313 FROM {chatroom_msg}
314 WHERE ccid IN (" . db_placeholders($ccids) . ")
315 GROUP BY ccid";
316 $result = db_query($sql, $ccids);
317 while ($count = db_fetch_object($result)) {
318 $chats[$count->ccid]->msg_count = $count->msg_count;
319 $chats[$count->ccid]->last_cmid = $count->last_cmid;
320 $cmids[] = $count->last_cmid;
321 }
322 }
323
324 // Fetch the last message if there is one.
325 if (!empty($cmids)) {
326 // Note we join on the session not the uid, because anon users all have
327 // the same uid.
328 $sql = "SELECT cm.*, u.name, col.guest_id
329 FROM {chatroom_msg} cm
330 INNER JOIN {chatroom_chat_online_list} col ON col.sid = cm.sid
331 INNER JOIN {users} u ON u.uid = col.uid
332 WHERE cm.cmid IN (" . db_placeholders($cmids) . ")";
333 $result = db_query($sql, $cmids);
334 while ($message = db_fetch_object($result)) {
335 $chats[$message->ccid]->last_msg = $message;
336 }
337 }
338 return $chats;
339 }
340
341 /**
342 * Chatroom chat node hook functions.
343 */
344 /**
345 * Implementation of hook_insert().
346 */
347 function chatroom_chat_insert($node) {
348 cache_clear_all('chatroom_chat_list', 'cache');
349 $chat = array(
350 'nid' => $node->nid,
351 'crid' => isset($node->crid) ? $node->crid : 0,
352 'poll_freq' => $node->poll_freq,
353 'idle_freq' => $node->idle_freq,
354 'kicked_out_message' => $node->kicked_out_message,
355 'banned_message' => $node->banned_message,
356 'module' => isset($node->module) ? $node->module : 'chatroom',
357 'previous_messages_display_count' => $node->previous_messages_display_count,
358 'popout' => $node->popout,
359 'private' => $node->private,
360 'profile_picture' => isset($node->profile_picture) ? $node->profile_picture : '',
361 );
362 drupal_write_record('chatroom_chat', $chat);
363 }
364
365 /**
366 * Implementation of hook_update().
367 */
368 function chatroom_chat_update($node) {
369 cache_clear_all('chatroom_chat_list', 'cache');
370 $chat = array(
371 'nid' => $node->nid,
372 'crid' => isset($node->crid) ? $node->crid : 0,
373 'poll_freq' => $node->poll_freq,
374 'idle_freq' => $node->idle_freq,
375 'kicked_out_message' => $node->kicked_out_message,
376 'banned_message' => $node->banned_message,
377 'module' => isset($node->module) ? $node->module : 'chatroom',
378 'previous_messages_display_count' => $node->previous_messages_display_count,
379 'popout' => $node->popout,
380 'private' => $node->private,
381 'profile_picture' => $node->profile_picture,
382 );
383 drupal_write_record('chatroom_chat', $chat, 'nid');
384 }
385
386 /**
387 * Write a row for each uid for the given chat to allow access.
388 *
389 * @param mixed $node
390 * @return void
391 */
392 function chatroom_chat_set_user_list($node) {
393 db_query("DELETE FROM {chatroom_chat_user} WHERE nid = %d", $node->nid);
394 foreach ($node->chat->allowed_uids as $uid) {
395 $row = array('uid' => $uid, 'nid' => $node->nid);
396 drupal_write_record('chatroom_chat_user', $row);
397 }
398 }
399
400 /**
401 * Implementation of hook_delete().
402 */
403 function chatroom_chat_delete(&$node) {
404 cache_clear_all('chatroom_chat_list', 'cache');
405 db_query('DELETE FROM {chatroom_chat} WHERE nid = %d', $node->nid);
406 db_query('DELETE FROM {chatroom_chat_online_list} WHERE ccid = %d', $node->nid);
407 }
408
409 /**
410 * Implementation of hook_load().
411 */
412 function chatroom_chat_load($node) {
413 $chat = new StdClass();
414 if ($chat->chat = db_fetch_object(db_query("SELECT * FROM {chatroom_chat} WHERE nid = %d", $node->nid))) {
415 $chat->chat->chatroom = node_load($chat->chat->crid);
416 $chat->chat->latest_msg = chatroom_chat_get_latest_message($node->nid);
417 $chat->chat->msg_count = chatroom_chat_get_message_count($node->nid);
418 if ($chat->chat->private) {
419 $chat->chat->allowed_uids = chatroom_chat_load_allowed_uids($node);
420 }
421 return $chat;
422 }
423 }
424
425 /**
426 * Load a list of uids allowed in this chat.
427 *
428 * @param mixed $node
429 * @return array
430 */
431 function chatroom_chat_load_allowed_uids($node) {
432 $uids = array();
433 $result = db_query('SELECT uid FROM {chatroom_chat_user} WHERE nid = %d', $node->nid);
434 while ($uid = db_result($result)) {
435 $uids[] = $uid;
436 }
437 return $uids;
438 }
439
440 /**
441 * Get the latest message id for a given chat.
442 *
443 * @param mixed $chat_id
444 */
445 function chatroom_chat_get_latest_message($chat_id) {
446 $sql = "SELECT cm.*, u.name
447 FROM {chatroom_msg} cm
448 INNER JOIN {users} u ON u.uid = cm.uid
449 WHERE ccid = %d
450 ORDER BY cmid
451 DESC LIMIT 1";
452 return db_fetch_object(db_query($sql, $chat_id));
453 }
454
455 /**
456 * Get the message count for a chat.
457 */
458 function chatroom_chat_get_message_count($chat_id) {
459 $sql = "SELECT COUNT(*) FROM {chatroom_msg} WHERE ccid = %d";
460 return db_result(db_query($sql, $chat_id));
461 }
462
463 /**
464 * Implementation of hook_view().
465 */
466 function chatroom_view($node, $teaser = FALSE, $page = FALSE) {
467 $node = node_prepare($node);
468 if (!$teaser && $page) {
469 // if the user is banned, just tell them why
470 if (chatroom_is_banned_user($node)) {
471 $node->content['body']['#value'] = !empty($node->banned_message) ? $node->banned_message : t('You have been banned from %chatroom.', array('%chatroom' => $node->title));
472 }
473 else {
474 // if the user can create chats, show the form
475 if (user_access('create chats')) {
476 $node->content['add_chat'] = array(
477 '#value' => drupal_get_form('chatroom_create_chat_form', $node),
478 '#weight' => 1,
479 );
480 }
481
482 // if there are some chats, build some tables to display them
483 if (!empty($node->chatroom->chats)) {
484 foreach ($node->chatroom->chats as $chat) {
485 if ($chat->when_archived) {
486 $rows['archived'][] = array(
487 array('data' => l($chat->title, "node/$chat->nid")),
488 array('data' => isset($chat->msg_count) ? $chat->msg_count : 0),
489 array('data' => t('Archived on !date.', array('!date' => format_date($chat->when_archived, 'medium')))),
490 );
491 }
492 else {
493 $rows['open'][] = array(
494 array('data' => l($chat->title, "node/$chat->nid")),
495 array('data' => isset($chat->msg_count) ? $chat->msg_count : 0),
496 array('data' => $chat->last_msg ? theme('chatroom_latest_message', $chat->last_msg) : ('No messages.')),
497 );
498 }
499 }
500 if (!empty($rows['open'])) {
501 $node->content['open_chats']['#weight'] = 2;
502 $node->content['open_chats']['title'] = array(
503 '#value' => '<h2>'. t('Open chats in this room') .'</h2>',
504 '#weight' => 0,
505 );
506 $node->content['open_chats']['table'] = array(
507 '#value' => theme('table', array(t('Chat name'), t('Message count'), t('Last message')), $rows['open']),
508 '#weight' => 1,
509 );
510 }
511 if (!empty($rows['archived'])) {
512 $node->content['archived_chats']['#weight'] = 3;
513 $node->content['archived_chats']['header'] = array(
514 '#value' => '<h2>'. t('Archived chats in this room') .'</h2>',
515 '#weight' => 0,
516 );
517 $node->content['archived_chats']['table'] = array(
518 '#value' => theme('table', array(t('Chat name'), t('Message count'), t('When archived')), $rows['archived']),
519 '#weight' => 1,
520 );
521 }
522 }
523 }
524 }
525 else {
526 $node->content['teaser'] = array('#value' => theme('chatroom_teaser', $node));
527 }
528 return $node;
529 }
530
531 /**
532 * Implementation of hook_view().
533 */
534 function chatroom_chat_view($node, $teaser = FALSE, $page = FALSE) {
535 $node = node_prepare($node);
536 if (!$teaser && $page) {
537 drupal_add_css(drupal_get_path('module', 'chatroom') .'/chatroom.css');
538
539 $bc = drupal_get_breadcrumb();
540 if ($node->chat->chatroom) {
541 $bc[] = l($node->chat->chatroom->title, "node/{$node->chat->chatroom->nid}");
542 }
543 $bc[] = l($node->title, "node/$node->nid");
544 drupal_set_breadcrumb($bc);
545
546 // Display a message if the user is banned.
547 if (chatroom_is_banned_user($node)) {
548 $content = theme('chatroom_chat_banned_user', $node);
549 }
550 elseif (!isset($node->chat->when_archived)) {
551 if (!chatroom_chat_register_user($node)) {
552 chatroom_update_last_seen_time($node, session_id());
553 }
554 $node->chat->users = chatroom_load_online_users($node);
555 chatroom_add_js($node);
556 $content = theme('chatroom_chat', $node);
557 }
558 else {
559 $content = theme('chatroom_chat_archive', $node);
560 if (user_access('administer chat rooms')) {
561 $content .= drupal_get_form('chatroom_unarchive_chat_form', $node->nid);
562 }
563 }
564 $node->content['chatroom_chat_interface'] = array('#value' => $content);
565 }
566 else {
567 $node->content['teaser'] = array('#value' => theme('chatroom_chat_teaser', $node));
568 }
569 return $node;
570 }
571
572 /**
573 * Gets a list of banned users for a given chat room.
574 */
575 function chatroom_get_banned_users($room) {
576 $banned_users = array();
577 $result = db_query("
578 SELECT bl.uid, u.name FROM {chatroom_ban_list} bl
579 INNER JOIN {users} u ON u.uid = bl.uid
580 WHERE bl.nid = %d
581 ", $room->nid);
582 while ($user = db_fetch_object($result)) {
583 $banned_users[$user->uid] = $user;
584 }
585 return $banned_users;
586 }
587
588 /**
589 * Unarchive old chat.
590 */
591 function chatroom_unarchive_chat($chat_id) {
592 $result = db_query('UPDATE {chatroom_chat} SET when_archived = NULL WHERE nid = %d', $chat_id);
593 return $result;
594 }
595
596 /**
597 * Archive a chat.
598 */
599 function chatroom_archive_chat($chat_id) {
600 $result = db_query('UPDATE {chatroom_chat} SET when_archived = %d WHERE nid = %d', time(), $chat_id);
601 return $result;
602 }
603
604 /**
605 * Implementation of hook_block().
606 */
607 function chatroom_block($op = 'list', $delta = 0, $edit = array()) {
608 $block_name = $delta == 0 ? 'chats' : ($delta == 1 ? 'chatrooms' : '');
609 switch ($op) {
610 case 'list':
611 $blocks[0] = array(
612 'info' => t('Chat room: active chats'),
613 'cache' => BLOCK_CACHE_GLOBAL,
614 'visibility' => 0,
615 );
616 $blocks[1] = array(
617 'info' => t('Chat room: active chat rooms'),
618 'cache' => BLOCK_CACHE_GLOBAL,
619 'visibility' => 0,
620 );
621 return $blocks;
622
623 case 'configure':
624 switch ($delta) {
625 case 0:
626 $items = t('chats');
627 break;
628 case 1:
629 $items = t('chat rooms');
630 }
631 if (isset($items)) {
632 $form["chatroom_block_$block_name"] = array(
633 '#type' => 'select',
634 '#title' => t('Number of !items to display', array('!items' => $items)),
635 '#default_value' => variable_get("chatroom_block_$block_name", 5),
636 '#options' => drupal_map_assoc(range(1, 15))
637 );
638 return $form;
639 }
640 break;
641
642 case 'save':
643 variable_set("chatroom_block_$block_name", $edit["chatroom_block_$block_name"]);
644 break;
645
646 case 'view':
647 switch ($block_name) {
648 case 'chats':
649 if (user_access('access chats')) {
650 return theme('chatroom_block_chats');
651 }
652
653 case 'chatrooms':
654 if (user_access('access chat rooms')) {
655 return theme('chatroom_block_chatrooms');
656 }
657 }
658 break;
659 }
660 }
661
662 /**
663 * Get a list of active rooms.
664 */
665 function chatroom_get_active_chatrooms($start = NULL, $end = NULL) {
666 if ($cache = cache_get('chatroom_room_list')) {
667 return $cache->data;
668 }
669 $result = db_query("SELECT nid FROM {node} WHERE type = 'chatroom' AND status = 1");
670 $chatrooms = array();
671 while ($nid = db_result($result)) {
672 $chatrooms[] = node_load($nid);
673 }
674 drupal_alter('chatroom_room_list', $chatrooms);
675 cache_set('chatroom_room_list', $chatrooms);
676 return $chatrooms;
677 }
678
679 /**
680 * Get a list of active chats.
681 */
682 function chatroom_get_active_chats() {
683 if ($cache = cache_get('chatroom_chat_list')) {
684 return $cache->data;
685 }
686 $chats = array();
687 $sql = "SELECT nid FROM {node} WHERE type = 'chat' AND status = 1";
688 $result = db_query($sql);
689 while ($nid = db_result($result)) {
690 $chats[] = node_load($nid);
691 }
692 drupal_alter('chatroom_chat_list', $chatrooms);
693 cache_set('chatroom_chat_list', $chats);
694 return $chats;
695 }
696
697 /**
698 * Display a page for a user kicked out or banned from a chat.
699 *
700 * @param mixed $node
701 * @param mixed $type
702 */
703 function chatroom_access_denied($node, $type) {
704 if ($type == 'banned') {
705 $content = theme('chatroom_chat_banned_user', $node);
706 }
707 else {
708 $content = theme('chatroom_chat_kicked_user', $node);
709 }
710 return $content;
711 }
712
713 /**
714 * Move old messages to archive.
715 */
716 function chatroom_archive_old_msgs($chat_id) {
717 db_query("UPDATE {chatroom_msg} set archived = 1 WHERE ccid = %d", $chat_id);
718 }
719
720 /**
721 * Update an invite and set it to accepted.
722 *
723 * @param mixed $node
724 * @param mixed $chat_user
725 * @return void
726 */
727 function chatroom_chat_accept_invite($node, $chat_user) {
728 $sql = "UPDATE {chatroom_chat_invite} SET accepted = 1 WHERE nid = %d AND initee_uid = %d";
729 db_query($sql, $node->nid, $chat_user->uid);
730 foreach (module_implements('chatroom_chat_invite_accepted') as $module) {
731 $function = $module . '_chatroom_chat_invite_accepted';
732 $function($node, $chat_user);
733 }
734 }
735
736 /**
737 * Check to see if a user has an invite to the given chat.
738 *
739 * @param mixed $node
740 * @param mixed $chat_user
741 * @return boolean
742 */
743 function chatroom_chat_user_has_invite($node, $chat_user) {
744 $sql = "SELECT nid FROM {chatroom_chat_invite} WHERE invitee_uid = %d AND nid = %d";
745 return db_result(db_query($sql, $chat_user->uid, $node->nid));
746 }
747
748 /**
749 * Register a user in a chat.
750 */
751 function chatroom_chat_register_user($node) {
752 global $user;
753
754 $session_id = session_id();
755 if (!db_result(db_query("SELECT sid FROM {chatroom_chat_online_list} WHERE ccid = %d AND sid = '%s'", $node->nid, $session_id))) {
756
757 if (chatroom_chat_user_has_invite($node, $user)) {
758 chatroom_accept_invite($node, $user);
759 }
760
761 $params = array($node->nid, $user->uid, $session_id, time());
762 if ($user->uid) {
763 $sql = "INSERT INTO {chatroom_chat_online_list} (ccid, uid, sid, last_seen_time) VALUES (%d, %d, '%s', %d)";
764 }
765 else {
766 $sql = "INSERT INTO {chatroom_chat_online_list} (ccid, uid, sid, guest_id, last_seen_time)
767 SELECT %d, %d, '%s', COALESCE(MAX(guest_id) + 1, 1), %d
768 FROM {chatroom_chat_online_list}
769 WHERE ccid = %d";
770 $params[] = $node->nid;
771 }
772 return db_query($sql, $params);
773 }
774 return FALSE;
775 }
776
777 /**
778 * Add settings to chat page.
779 */
780 function chatroom_add_js($node) {
781 global $user;
782 $js = array(
783 'pollInterval' => (int) isset($node->chat) ? $node->chat->poll_freq : 1,
784 'idleInterval' => (int) $node->chat->idle_freq,
785 'chatId' => (int) $node->nid,
786 'popoutParams' => chatroom_get_popout_params($node),
787 'cacheDirectory' => variable_get('chatroom_cache_directory', '/tmp'),
788 'postMessagePath' => 'chatroom/chat/post/message',
789 'chatPath' => 'node/' . $node->nid,
790 'successiveCacheHits' => 0,
791 'skipCacheCheckCount' => 5,
792 'latestMsgId' => $node->chat->latest_msg ? $node->chat->latest_msg->cmid : 0,
793 'accessDeniedPath' => 'chatroom/access-denied',
794 'viewAsPopout' => $node->chat->popout,
795 'popoutRedirect' => 'chatroom/popout/redirect',
796 );
797
798 if (variable_get('configurable_timezones', 1) && $user->uid && drupal_strlen($user->timezone)) {
799 $js['timezone'] = $user->timezone;
800 }
801 else {
802 $js['timezone'] = variable_get('date_default_timezone', 0);
803 }
804 if (isset($node->chat, $node->chat->latest_msg_id)) {
805 $js['latestMsgId'] = $node->chat->latest_msg_id;
806 }
807
808 // Allow modules to alter the js settings sent down for a chat.
809 drupal_alter('chatroom_js_settings', $js);
810
811 drupal_add_js(drupal_get_path('module', 'chatroom') . '/chatroom.js');
812 drupal_add_js(array('chatroom' => $js), 'setting');
813 }
814
815 /**
816 * Get messages for a given chat.
817 *
818 * @param $chat_id
819 * The chat id.
820 * @param $last_cmid
821 * Only load messages with cmids greater than this value.
822 * @param $limit
823 * Default: FALSE.
824 * @return array $messages
825 */
826 function chatroom_chat_load_messages($chat_id, $last_cmid = 0, $limit = FALSE) {
827 $sql = "SELECT cm.*, u.name, 0 guest_id
828 FROM {chatroom_msg} cm
829 INNER JOIN {users} u ON u.uid = cm.uid
830 WHERE cm.ccid = %d
831 AND cm.cmid > %d
832 ORDER BY cm.cmid ASC";
833 $args = array($chat_id, $last_cmid);
834 if ($limit) {
835 $sql .= ' LIMIT %d';
836 $args[] = $limit;
837 }
838 $result = db_query($sql, $args);
839
840 $messages = array();
841 $guest_sids = array();
842 while ($message = db_fetch_object($result)) {
843 if ($message->uid == 0 && !in_array($message->sid, $guest_sids)) {
844 $guest_sids[] = $message->sid;
845 $message->name = variable_get('chatroom_guest_user_prefix', 'guest-');
846 }
847 $messages[$message->cmid] = $message;
848 }
849
850 if (!empty($guest_sids)) {
851 $sql = "SELECT sid, guest_id FROM {chatroom_chat_online_list} WHERE sid IN (" . db_placeholders($guest_sids, 'varchar') . ")";
852 $result = db_query($sql, $guest_sids);
853 while ($guest = db_fetch_object($result)) {
854 foreach ($messages as $message) {
855 if ($message->sid == $guest->sid) {
856 $messages[$message->cmid]->guest_id = $guest->guest_id;
857 $messages[$message->cmid]->name .= $guest->guest_id;
858 }
859 }
860 }
861 }
862 return $messages;
863 }
864
865 /**
866 * Load online users for the given chat.
867 */
868 function chatroom_load_online_users($chat) {
869 global $user;
870
871 $sql = "SELECT col.*, u.name, u.picture
872 FROM {chatroom_chat_online_list} col
873 LEFT JOIN {users} u ON u.uid = col.uid
874 WHERE col.ccid = %d
875 AND col.last_seen_time >= %d
876 ORDER BY u.name ASC";
877 $sql = db_rewrite_sql($sql, 'col', 'sid', array('chatroom_chat_online_list' => TRUE));
878 $result = db_query($sql, $chat->nid, time() - variable_get('chatroom_online_list_timeout', 10));
879 $chat_users = array();
880 $logged_in_users = array();
881 while ($chat_user = db_fetch_object($result)) {
882 if ($chat_user->uid == 0) {
883 $chat_user->name = variable_get('chatroom_guest_user_prefix', 'guest-') . $u->guest_id;
884 }
885 else if (in_array($chat_user->uid, $logged_in_users)) {
886 continue;
887 }
888 if ($chat_user->uid != 0) {
889 $logged_in_users[] = $chat_user->uid;
890 }
891 $chat_users[$chat_user->sid] = $chat_user;
892 }
893 return $chat_users;
894 }
895
896 /**
897 * updates chat's cache file modified time
898 */
899 function chatroom_chat_update_cache($chat_id, $latest_msg_id) {
900 $cache_file = variable_get('chatroom_cache_directory', '/tmp') . '/chatroom.chat.' . $chat_id . '.cache';
901 file_put_contents($cache_file, "$latest_msg_id\n");
902 }
903
904 /**
905 * Check if the current user is banned from the chat room.
906 */
907 function chatroom_is_banned_user($room) {
908 global $user;
909 // If the node is already loaded, check the ban list. Otherwise, query the
910 // database.
911 if (isset($room->banned_list) && is_array($room->banned_list)) {
912 return in_array($user->uid, array_keys($room->banned_list));
913 }
914 else {
915 return db_result(db_query("SELECT nid FROM {chatroom_ban_list} WHERE nid = %d AND uid = %d", $room->nid, $user->uid));
916 }
917 }
918
919 /**
920 * Get the latest messages for a chat, and send back to the client.
921 */
922 function chatroom_chat_get_latest_messages($node, $last_msg_id, $command_response = FALSE) {
923 global $user;
924
925 if ($node->chat->private && $node->uid != $user->uid && !in_array($user->uid, $node->chat->allowed_uids)) {
926 drupal_json(array('data' => array('accessDenied' => 'kicked', 'messages' => array())));
927 return;
928 }
929
930 if (chatroom_chat_is_banned_user($user, $node)) {
931 drupal_json(array('data' => array('accessDenied' => 'banned', 'messages' => array())));
932 return;
933 }
934
935 if (chatroom_chat_is_kicked_user($user, $node)) {
936 print drupal_json(array('data' => array('accessDenied' => 'kicked', 'messages' => array())));
937 return;
938 }
939
940 $response['messages'] = array();
941 if ($node->chat->when_archived) {
942 $response['archived'] = $node->chat->when_archived;
943 drupal_set_message(t('This chat has been archived.'));
944 }
945 else {
946 chatroom_update_last_seen_time($node, session_id());
947
948 foreach (chatroom_chat_load_messages($node->nid, $last_msg_id) as $message) {
949 if ($message->msg_type == 'private_message' && $user->uid != $message->recipien_uid) {
950 continue;
951 }
952 $msg = new StdClass();
953 $msg->html = theme('chatroom_message', $message, $node);
954 $msg->text = strip_tags($message->msg);
955 $msg->name = $message->name;
956 $msg->cmid = $message->cmid;
957 $msg->type = $message->msg_type;
958 $response['messages'][] = $msg;
959 $latest_msg_id = $message->cmid;
960 }
961 if (isset($latest_msg_id)) {
962 chatroom_chat_update_cache($node->nid, $latest_msg_id);
963 }
964
965 $response['usersHtml'] = theme('chatroom_user_list', chatroom_load_online_users($node), $node);
966 if (is_object($command_response)) {
967 $response['commandResponse'] = $command_response;
968 }
969 }
970 drupal_json(array('data' => $response));
971 }
972
973 /**
974 * Posted messages are handled here.
975 *
976 * @return void
977 */
978 function chatroom_chat_post_message($node, $last_msg_id) {
979 global $user;
980
981 // Check we have a message posted.
982 if (!isset($_POST['message'])) {
983 exit;
984 }
985
986 if ($node->chat->private && $node->uid != $user->uid && !in_array($user->uid, $node->chat->allowed_uids)) {
987 drupal_json(array('data' => array('accessDenied' => 'kicked', 'messages' => array())));
988 return;
989 }
990
991 if (chatroom_chat_is_banned_user($user, $node)) {
992 print drupal_json(array('data' => array('accessDenied' => 'banned', 'messages' => array())));
993 return;
994 }
995
996 if (chatroom_chat_is_kicked_user($user, $node)) {
997 print drupal_json(array('data' => array('accessDenied' => 'kicked', 'messages' => array())));
998 return;
999 }
1000
1001 $message = array(
1002 'ccid' => $node->chat->nid,
1003 'uid' => $user->uid,
1004 'msg' => $_POST['message'],
1005 'sid' => session_id(),
1006 'msg_type' => chatroom_chat_get_message_type($_POST['message']),
1007 'recipient_uid' => 0,
1008 'modified' => time(),
1009 );
1010 if ($message['msg_type'] == 'command') {
1011 $result = chatroom_chat_call_command($message, $node);
1012 }
1013 else {
1014 $result = chatroom_chat_save_message($message, $node);
1015 }
1016 chatroom_chat_get_latest_messages($node, $last_msg_id, $result);
1017 }
1018
1019 /**
1020 * Write a message into a chat, and allow any interested modules to react.
1021 *
1022 * @param array $message
1023 * @param StdClass $node
1024 * @return boolean
1025 */
1026 function chatroom_chat_save_message($message, $node) {
1027 drupal_alter('chatroom_chat_msg', $message);
1028 if (drupal_write_record('chatroom_msg', $message)) {
1029 $node->chat->latest_msg_id = $message['cmid'];
1030 foreach (module_implements('chat_msg_saved') as $module) {
1031 $function = $module . '_chat_msg_saved';
1032 $function($message, $node);
1033 }
1034 return $message['cmid'];
1035 }
1036 return FALSE;
1037 }
1038
1039 /**
1040 * Implementation of hook_chat_commands().
1041 */
1042 function chatroom_chat_commands() {
1043 return array(
1044 'kick' => array(
1045 'callback' => 'chatroom_command_kick_user',
1046 ),
1047 'ban' => array(
1048 'callback' => 'chatroom_command_ban_user',
1049 ),
1050 'msg' => array(
1051 'callback' => 'chatroom_command_msg_user',
1052 ),
1053 );
1054 }
1055
1056 /**
1057 * Implementation of hook_chat_command_api().
1058 *
1059 * This hook allows other modules to react to commands defined by other
1060 * modules. This hook is only fired after the module that defines the
1061 * command has run its callback code for the given command.
1062 *
1063 * The return value from a modules' callback are stored in the command
1064 * object in $command->callback_result.
1065 */
1066 function chatroom_chat_command_api($command, $node) {
1067 watchdog('chatroom', __FUNCTION__ . ' invoked with command %command for chat %chat.', array('%command' => $command->name, '%chat' => $node->title));
1068 }
1069
1070 /**
1071 * Ban a user from a chat.
1072 *
1073 * @param mixed $command
1074 * @param mixed $node
1075 * @return boolean
1076 */
1077 function chatroom_command_ban_user($command, $node) {
1078 global $user;
1079 if ($user_to_ban = chatroom_get_user_from_command_arg($command->args[0])) {
1080 if (chatroom_ban_user($node, $user_to_ban, $user)) {
1081 $params = array(
1082 '!banned_username' => $user_to_ban->name,
1083 '!chat' => $node->title,
1084 '!chat_admin_username' => $user->name,
1085 );
1086 $response = new StdClass();
1087 $response->name = 'banned';
1088 $response->msg = t('User !banned_username banned from chat !chat by !chat_admin_username.', $params);
1089 return $response;
1090 }
1091 }
1092 return FALSE;
1093 }
1094
1095 /**
1096 * Respond to a command to kick a user out of a chat.
1097 *
1098 * @param mixed $command
1099 * @param mixed $node
1100 * @return boolean
1101 */
1102 function chatroom_command_kick_user($command, $node) {
1103 global $user;
1104 if ($user_to_kick = chatroom_get_user_from_command_arg($command->args[0])) {
1105 if (chatroom_kick_user($node, $user_to_kick, $user)) {
1106 $params = array(
1107 '!kicked_username' => $user_to_kick->name,
1108 '!chat' => $node->title,
1109 '!chat_admin_username' => $user->name,
1110 );
1111 $response = new StdClass();
1112 $response->name = 'kicked';
1113 $response->msg = t('User !kicked_username kicked out of chat !chat by !chat_admin_username.', $params);
1114 return $response;
1115 }
1116 }
1117 return FALSE;
1118 }
1119
1120 /**
1121 * Respond to a command to send a message to a specific user in a chat.
1122 *
1123 * @param mixed $command
1124 * @param mixed $node
1125 * @return boolean
1126 */
1127 function chatroom_command_msg_user($command, $node) {
1128 global $user;
1129
1130 // The second arg is the message, so if there isn't one, just bail.
1131 if (count($command->args) < 2) {
1132 return FALSE;
1133 }
1134 if ($to_user = chatroom_get_user_from_command_arg(array_shift($command->args))) {
1135 return chatroom_msg_user($node, $to_user, $user, implode(' ', $command->args));
1136 }
1137 return FALSE;
1138 }
1139
1140 /**
1141 * Ban a user from a chat.
1142 *
1143 * @param mixed $node
1144 * @param mixed $user_to_ban
1145 * @param mixed $chat_admin_user
1146 * @return boolean
1147 */
1148 function chatroom_ban_user($node, $user_to_ban, $chat_admin_user) {
1149 if ($user_to_ban->uid == $chat_admin_user->uid) {
1150 return FALSE;
1151 }
1152 if (user_access('administer chats', $chat_admin_user) || $node->uid == $chat_admin_user->uid) {
1153 $ban_data = array(
1154 'nid' => $node->nid,
1155 'uid' => $user_to_ban->uid,
1156 'admin_uid' => $chat_admin_user->uid,
1157 'modified' => time(),
1158 );
1159