123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- <?php
- /* For licensing terms, see /license.txt */
- use ChamiloSession as Session;
- /**
- * Class Chat.
- *
- * @todo ChamiloSession instead of $_SESSION
- *
- * @package chamilo.library.chat
- */
- class Chat extends Model
- {
- public $columns = [
- 'id',
- 'from_user',
- 'to_user',
- 'message',
- 'sent',
- 'recd',
- ];
- public $window_list = [];
- /**
- * The contructor sets the chat table name and the window_list attribute.
- */
- public function __construct()
- {
- parent::__construct();
- $this->table = Database::get_main_table(TABLE_MAIN_CHAT);
- $this->window_list = Session::read('window_list');
- Session::write('window_list', $this->window_list);
- }
- /**
- * Get user chat status.
- *
- * @return int 0 if disconnected, 1 if connected
- */
- public function getUserStatus()
- {
- // ofaj
- return 1;
- $status = UserManager::get_extra_user_data_by_field(
- api_get_user_id(),
- 'user_chat_status',
- false,
- true
- );
- return $status['user_chat_status'];
- }
- /**
- * Set user chat status.
- *
- * @param int $status 0 if disconnected, 1 if connected
- */
- public function setUserStatus($status)
- {
- UserManager::update_extra_field_value(
- api_get_user_id(),
- 'user_chat_status',
- $status
- );
- }
- /**
- * @param int $currentUserId
- * @param int $userId
- * @param bool $latestMessages
- *
- * @return array
- */
- public function getLatestChat($currentUserId, $userId, $latestMessages)
- {
- $items = $this->getPreviousMessages(
- $currentUserId,
- $userId,
- 0,
- $latestMessages
- );
- return array_reverse($items);
- }
- /**
- * @return string
- */
- public function getContacts()
- {
- $html = SocialManager::listMyFriendsBlock(
- api_get_user_id(),
- '',
- true
- );
- echo $html;
- }
- /**
- * @param array $chatHistory
- * @param int $latestMessages
- *
- * @return mixed
- */
- public function getAllLatestChats($chatHistory, $latestMessages = 5)
- {
- $currentUserId = api_get_user_id();
- if (empty($chatHistory)) {
- return [];
- }
- $chats = [];
- foreach ($chatHistory as $userId => $time) {
- $total = $this->getCountMessagesExchangeBetweenUsers($userId, $currentUserId);
- $start = $total - $latestMessages;
- if ($start < 0) {
- $start = 0;
- }
- $items = $this->getMessages($userId, $currentUserId, $start, $latestMessages);
- $chats[$userId]['items'] = $items;
- $chats[$userId]['window_user_info'] = api_get_user_info($userId);
- }
- return $chats;
- }
- /**
- * Starts a chat session and returns JSON array of status and chat history.
- *
- * @return bool (prints output in JSON format)
- */
- public function startSession()
- {
- // ofaj
- $chat = new Chat();
- $chat->setUserStatus(1);
- $chatList = Session::read('openChatBoxes');
- $chats = $this->getAllLatestChats($chatList);
- $return = [
- 'user_status' => $this->getUserStatus(),
- 'me' => get_lang('Me'),
- 'user_id' => api_get_user_id(),
- 'items' => $chats,
- ];
- echo json_encode($return);
- return true;
- }
- /**
- * @param int $fromUserId
- * @param int $toUserId
- *
- * @return int
- */
- public function getCountMessagesExchangeBetweenUsers($fromUserId, $toUserId)
- {
- $row = Database::select(
- 'count(*) as count',
- $this->table,
- [
- 'where' => [
- '(from_user = ? AND to_user = ?) OR (from_user = ? AND to_user = ?) ' => [
- $fromUserId,
- $toUserId,
- $toUserId,
- $fromUserId,
- ],
- ],
- ],
- 'first'
- );
- return (int) $row['count'];
- }
- /**
- * @param int $fromUserId
- * @param int $toUserId
- * @param int $visibleMessages
- * @param int $previousMessageCount messages to show
- *
- * @return array
- */
- public function getPreviousMessages(
- $fromUserId,
- $toUserId,
- $visibleMessages = 1,
- $previousMessageCount = 5,
- $orderBy = ''
- ) {
- $toUserId = (int) $toUserId;
- $fromUserId = (int) $fromUserId;
- $visibleMessages = (int) $visibleMessages;
- $previousMessageCount = (int) $previousMessageCount;
- $total = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $toUserId);
- $show = $total - $visibleMessages;
- if ($show < $previousMessageCount) {
- $show = $previousMessageCount;
- }
- $from = $show - $previousMessageCount;
- if ($from < 0) {
- return [];
- }
- return $this->getMessages($fromUserId, $toUserId, $from, $previousMessageCount, $orderBy);
- }
- /**
- * @param int $fromUserId
- * @param int $toUserId
- * @param int $start
- * @param int $end
- * @param string $orderBy
- *
- * @return array
- */
- public function getMessages($fromUserId, $toUserId, $start, $end, $orderBy = '')
- {
- $toUserId = (int) $toUserId;
- $fromUserId = (int) $fromUserId;
- $start = (int) $start;
- $end = (int) $end;
- if (empty($toUserId) || empty($fromUserId)) {
- return [];
- }
- $orderBy = Database::escape_string($orderBy);
- if (empty($orderBy)) {
- $orderBy = 'ORDER BY id ASC';
- }
- $sql = "SELECT * FROM ".$this->table."
- WHERE
- (
- to_user = $toUserId AND
- from_user = $fromUserId
- )
- OR
- (
- from_user = $toUserId AND
- to_user = $fromUserId
- )
- $orderBy
- LIMIT $start, $end
- ";
- $result = Database::query($sql);
- $rows = Database::store_result($result);
- $fromUserInfo = api_get_user_info($fromUserId, true);
- $toUserInfo = api_get_user_info($toUserId, true);
- $users = [
- $fromUserId => $fromUserInfo,
- $toUserId => $toUserInfo,
- ];
- $items = [];
- $rows = array_reverse($rows);
- foreach ($rows as $chat) {
- $fromUserId = $chat['from_user'];
- $userInfo = $users[$fromUserId];
- $toUserInfo = $users[$toUserId];
- $items[$chat['id']] = [
- 'id' => $chat['id'],
- 'message' => Security::remove_XSS($chat['message']),
- 'date' => api_strtotime($chat['sent'], 'UTC'),
- 'recd' => $chat['recd'],
- 'from_user_info' => $userInfo,
- 'to_user_info' => $toUserInfo,
- ];
- $_SESSION['openChatBoxes'][$fromUserId] = api_strtotime($chat['sent'], 'UTC');
- }
- return $items;
- }
- /**
- * Refreshes the chat windows (usually called every x seconds through AJAX).
- */
- public function heartbeat()
- {
- $chatHistory = Session::read('chatHistory');
- $currentUserId = api_get_user_id();
- // update current chats
- if (!empty($chatHistory) && is_array($chatHistory)) {
- foreach ($chatHistory as $fromUserId => &$data) {
- $userInfo = api_get_user_info($fromUserId, true);
- $count = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $currentUserId);
- $chatItems = $this->getLatestChat($fromUserId, $currentUserId, 5);
- $data['window_user_info'] = $userInfo;
- $data['items'] = $chatItems;
- $data['total_messages'] = $count;
- }
- }
- $sql = "SELECT * FROM ".$this->table."
- WHERE
- to_user = '".$currentUserId."' AND recd = 0
- ORDER BY id ASC";
- $result = Database::query($sql);
- $chatList = [];
- while ($chat = Database::fetch_array($result, 'ASSOC')) {
- $chatList[$chat['from_user']][] = $chat;
- }
- foreach ($chatList as $fromUserId => $messages) {
- $userInfo = api_get_user_info($fromUserId, true);
- $count = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $currentUserId);
- $chatItems = $this->getLatestChat($fromUserId, $currentUserId, 5);
- // Cleaning tsChatBoxes
- unset($_SESSION['tsChatBoxes'][$fromUserId]);
- foreach ($messages as $chat) {
- $_SESSION['openChatBoxes'][$fromUserId] = api_strtotime($chat['sent'], 'UTC');
- }
- $chatHistory[$fromUserId] = [
- 'window_user_info' => $userInfo,
- 'total_messages' => $count,
- 'items' => $chatItems,
- ];
- }
- Session::write('chatHistory', $chatHistory);
- $sql = "UPDATE ".$this->table."
- SET recd = 1
- WHERE to_user = $currentUserId AND recd = 0";
- Database::query($sql);
- echo json_encode(['items' => $chatHistory]);
- }
- /**
- * Saves into session the fact that a chat window exists with the given user.
- *
- * @param int $userId
- */
- public function saveWindow($userId)
- {
- $this->window_list[$userId] = true;
- Session::write('window_list', $this->window_list);
- }
- /**
- * Sends a message from one user to another user.
- *
- * @param int $fromUserId The ID of the user sending the message
- * @param int $to_user_id The ID of the user receiving the message
- * @param string $message Message
- * @param bool $printResult Optional. Whether print the result
- * @param bool $sanitize Optional. Whether sanitize the message
- */
- public function send(
- $fromUserId,
- $to_user_id,
- $message,
- $printResult = true,
- $sanitize = true
- ) {
- $relation = SocialManager::get_relation_between_contacts($fromUserId, $to_user_id);
- if ($relation == USER_RELATION_TYPE_FRIEND) {
- $now = api_get_utc_datetime();
- $user_info = api_get_user_info($to_user_id, true);
- $this->saveWindow($to_user_id);
- $_SESSION['openChatBoxes'][$to_user_id] = api_strtotime($now, 'UTC');
- if ($sanitize) {
- $messagesan = $this->sanitize($message);
- } else {
- $messagesan = $message;
- }
- if (!isset($_SESSION['chatHistory'][$to_user_id])) {
- $_SESSION['chatHistory'][$to_user_id] = [];
- }
- $item = [
- 's' => '1',
- 'f' => $fromUserId,
- 'm' => $messagesan,
- 'date' => api_strtotime($now, 'UTC'),
- 'username' => get_lang('Me'),
- ];
- $_SESSION['chatHistory'][$to_user_id]['items'][] = $item;
- $_SESSION['chatHistory'][$to_user_id]['user_info']['user_name'] = $user_info['complete_name'];
- $_SESSION['chatHistory'][$to_user_id]['user_info']['online'] = $user_info['user_is_online'];
- $_SESSION['chatHistory'][$to_user_id]['user_info']['avatar'] = $user_info['avatar_small'];
- $_SESSION['chatHistory'][$to_user_id]['user_info']['user_id'] = $user_info['user_id'];
- unset($_SESSION['tsChatBoxes'][$to_user_id]);
- $params = [];
- $params['from_user'] = (int) $fromUserId;
- $params['to_user'] = (int) $to_user_id;
- $params['message'] = $message;
- $params['sent'] = api_get_utc_datetime();
- if (!empty($fromUserId) && !empty($to_user_id)) {
- $messageId = $this->save($params);
- if ($printResult) {
- echo $messageId;
- exit;
- }
- }
- }
- if ($printResult) {
- echo '0';
- exit;
- }
- }
- /**
- * Close a specific chat box (user ID taken from $_POST['chatbox']).
- *
- * @param int $userId
- */
- public function closeWindow($userId)
- {
- if (empty($userId)) {
- return false;
- }
- $list = Session::read('openChatBoxes');
- if (isset($list[$userId])) {
- unset($list[$userId]);
- Session::write('openChatBoxes', $list);
- }
- $list = Session::read('chatHistory');
- if (isset($list[$userId])) {
- unset($list[$userId]);
- Session::write('chatHistory', $list);
- }
- return true;
- }
- /**
- * Close chat - disconnects the user.
- */
- public function close()
- {
- Session::erase('tsChatBoxes');
- Session::erase('openChatBoxes');
- Session::erase('chatHistory');
- Session::erase('window_list');
- }
- /**
- * Filter chat messages to avoid XSS or other JS.
- *
- * @param string $text Unfiltered message
- *
- * @return string Filtered message
- */
- public function sanitize($text)
- {
- $text = htmlspecialchars($text, ENT_QUOTES);
- $text = str_replace("\n\r", "\n", $text);
- $text = str_replace("\r\n", "\n", $text);
- $text = str_replace("\n", "<br>", $text);
- return $text;
- }
- /**
- * SET Disable Chat.
- *
- * @param bool $status to disable chat
- */
- public static function setDisableChat($status = true)
- {
- Session::write('disable_chat', $status);
- }
- /**
- * Disable Chat - disable the chat.
- *
- * @return bool - return true if setDisableChat status is true
- */
- public static function disableChat()
- {
- $status = Session::read('disable_chat');
- if (!empty($status)) {
- if ($status == true) {
- Session::write('disable_chat', null);
- return true;
- }
- }
- return false;
- }
- /**
- * @return bool
- */
- public function isChatBlockedByExercises()
- {
- $currentExercises = Session::read('current_exercises');
- if (!empty($currentExercises)) {
- foreach ($currentExercises as $attempt_status) {
- if ($attempt_status == true) {
- return true;
- }
- }
- }
- return false;
- }
- }
|