YetiForceCompany/YetiForceCRM

View on GitHub
modules/Chat/actions/ChatAjax.php

Summary

Maintainability
D
1 day
Test Coverage
F
24%
<?php

/**
 * Action to get Chat data.
 *
 * @package Action
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 * @author    Arkadiusz Adach <a.adach@yetiforce.com>
 * @author    Tomasz Poradzewski <t.poradzewski@yetiforce.com>
 * @author    Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
 */
class Chat_ChatAjax_Action extends \App\Controller\Action
{
    use \App\Controller\ExposeMethod;

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
        $this->exposeMethod('getChatConfig');
        $this->exposeMethod('getMessages');
        $this->exposeMethod('getMoreMessages');
        $this->exposeMethod('getRoomsMessages');
        $this->exposeMethod('getUnread');
        $this->exposeMethod('getHistory');
        $this->exposeMethod('getRooms');
        $this->exposeMethod('getRoomsUnpinned');
        $this->exposeMethod('getRecordRoom');
        $this->exposeMethod('getRoomPrivateUnpinnedUsers');
        $this->exposeMethod('send');
        $this->exposeMethod('search');
        $this->exposeMethod('addPrivateRoom');
        $this->exposeMethod('archivePrivateRoom');
        $this->exposeMethod('addParticipant');
    }

    /** {@inheritdoc} */
    public function isSessionExtend(App\Request $request)
    {
        return false;
    }

    /** {@inheritdoc} */
    public function checkPermission(App\Request $request)
    {
        $userPrivileges = \Users_Privileges_Model::getCurrentUserPrivilegesModel();
        if (!$userPrivileges->hasModulePermission($request->getModule()) || $userPrivileges->getId() !== $userPrivileges->getRealId()) {
            throw new \App\Exceptions\NoPermitted('ERR_NOT_ACCESSIBLE', 406);
        }
    }

    /**
     * Get chat init data.
     *
     * @param App\Request $request
     *
     * @return void
     */
    public function getChatConfig(App\Request $request)
    {
        $userRealID = \App\User::getCurrentUserRealId();
        $userRoomPin = \App\Config::module('Chat', 'userRoomPin');
        if (!$userRoomPin) {
            \App\Chat::pinAllUsers($userRealID);
        }
        $result = [
            'config' => [
                'isChatAllowed' => $userRealID === \App\User::getCurrentUserId(),
                'isAdmin' => \Users_Privileges_Model::getCurrentUserPrivilegesModel()->isAdminUser(),
                'isDefaultSoundNotification' => \App\Config::module('Chat', 'DEFAULT_SOUND_NOTIFICATION'),
                'refreshMessageTime' => \App\Config::module('Chat', 'REFRESH_MESSAGE_TIME'),
                'refreshRoomTime' => \App\Config::module('Chat', 'REFRESH_ROOM_TIME'),
                'defaultRoom' => \App\Chat::getDefaultRoom(),
                'dynamicAddingRooms' => \App\Config::module('Chat', 'dynamicAddingRooms'),
                'draggableButton' => false,
                'maxLengthMessage' => \App\Config::module('Chat', 'MAX_LENGTH_MESSAGE'),
                'refreshTimeGlobal' => \App\Config::module('Chat', 'REFRESH_TIME_GLOBAL'),
                'showNumberOfNewMessages' => \App\Config::module('Chat', 'SHOW_NUMBER_OF_NEW_MESSAGES'),
                'showRoleName' => \App\Config::module('Users', 'SHOW_ROLE_NAME'),
                'activeRoomTypes' => \App\Chat::getActiveRoomTypes(),
                'userRoomPin' => $userRoomPin
            ],
            'roomList' => \App\Chat::getRoomsByUser(),
            'currentRoom' => \App\Chat::getCurrentRoom()
        ];
        if ($result['config']['dynamicAddingRooms']) {
            $result['config']['chatModules'] = \App\Chat::getChatModules();
        }
        $response = new Vtiger_Response();
        $response->setResult($result);
        $response->emit();
    }

    /**
     * Get messages from chat.
     *
     * @param \App\Request $request
     */
    public function getMessages(App\Request $request)
    {
        $response = new Vtiger_Response();
        $response->setResult($this->setMessagesResult($request));
        $response->emit();
    }

    /**
     *    Set messages result.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\IllegalValue
     */
    public function setMessagesResult(App\Request $request)
    {
        if ($request->has('roomType') && $request->has('recordId')) {
            $roomType = $request->getByType('roomType');
            $recordId = $request->getInteger('recordId');
            if (!$request->getBoolean('recordRoom')) {
                \App\Chat::setCurrentRoom($roomType, $recordId);
            }
        } else {
            $currentRoom = \App\Chat::getCurrentRoom();
            if (!$currentRoom || !isset($currentRoom['roomType']) || !isset($currentRoom['recordId'])) {
                return false;
            }
            $roomType = $currentRoom['roomType'];
            $recordId = $currentRoom['recordId'];
        }
        $chat = \App\Chat::getInstance($roomType, $recordId);
        if (!$chat->isRoomExists()) {
            throw new \App\Exceptions\IllegalValue('ERR_NOT_ALLOWED_VALUE', 406);
        }
        $chatEntries = $chat->getEntries($request->has('lastId') ? $request->getInteger('lastId') : 0);
        $isNextPage = $this->isNextPage(\count($chatEntries));
        if ($isNextPage) {
            array_shift($chatEntries);
        }
        $result = [];
        $roomList = \App\Chat::getRoomsByUser();
        if (!isset($roomList[$roomType][$recordId])) {
            $defaultRoom = \App\Chat::setCurrentRoomDefault();
            $roomType = $defaultRoom['roomType'];
            $recordId = $defaultRoom['recordId'];
        }
        $roomList[$roomType][$recordId]['chatEntries'] = $chatEntries;
        $roomList[$roomType][$recordId]['participants'] = $chat->getParticipants();
        if (!$request->has('lastId')) {
            $result['currentRoom'] = \App\Chat::getCurrentRoom();
            $roomList[$roomType][$recordId]['showMoreButton'] = $isNextPage;
        }
        $result['roomList'] = $roomList;

        if (App\Config::module('Chat', 'SHOW_NUMBER_OF_NEW_MESSAGES')) {
            $result['amountOfNewMessages'] = \App\Chat::getNumberOfNewMessages();
        }
        return $result;
    }

    /**
     * Get rooms messages from chat.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\IllegalValue
     */
    public function getRoomsMessages(App\Request $request)
    {
        $result = [];
        $roomList = \App\Chat::getRoomsByUser();
        $areNewEntries = false;

        foreach ($request->getArray('rooms') as $room) {
            $recordId = $room['recordid'];
            $roomType = $room['roomType'];
            $chat = \App\Chat::getInstance($roomType, $recordId);
            if (!$chat->isRoomExists()) {
                throw new \App\Exceptions\IllegalValue('ERR_NOT_ALLOWED_VALUE', 406);
            }
            if ('private' === $roomType && !$chat->isPrivateRoomAllowed($recordId)) {
                continue;
            }
            $lastEntries = !empty($room['chatEntries']) ? array_pop($room['chatEntries']) : false;
            $chatEntries = $chat->getEntries($lastEntries ? $lastEntries['id'] : 0);
            $isNextPage = $this->isNextPage(\count($chatEntries));
            if ($isNextPage) {
                array_shift($chatEntries);
            }
            $roomList[$roomType][$recordId]['showMoreButton'] = $isNextPage;
            $roomList[$roomType][$recordId]['chatEntries'] = $chatEntries;
            $roomList[$roomType][$recordId]['participants'] = $chat->getParticipants();
            if (!$areNewEntries) {
                $areNewEntries = \count($chatEntries) > 0;
            }
        }
        $result['roomList'] = $roomList;
        $result['areNewEntries'] = $areNewEntries;
        if (App\Config::module('Chat', 'SHOW_NUMBER_OF_NEW_MESSAGES')) {
            $result['amountOfNewMessages'] = \App\Chat::getNumberOfNewMessages($roomList);
        }
        $response = new Vtiger_Response();
        $response->setResult($result);
        $response->emit();
    }

    /**
     * Get more messages from chat.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\AppException
     * @throws \App\Exceptions\IllegalValue
     * @throws \yii\db\Exception
     */
    public function getMoreMessages(App\Request $request)
    {
        $chat = \App\Chat::getInstance($request->getByType('roomType'), $request->getInteger('recordId'));
        $chatEntries = $chat->getEntries($request->getInteger('lastId'), '<');
        $isNextPage = $this->isNextPage(\count($chatEntries));
        if ($isNextPage) {
            array_shift($chatEntries);
        }
        $response = new Vtiger_Response();
        $response->setResult([
            'currentRoom' => \App\Chat::getCurrentRoom(),
            'chatEntries' => $chatEntries,
            'showMoreButton' => $isNextPage,
        ]);
        $response->emit();
    }

    /**
     * Send message function.
     *
     * @param \App\Request $request
     */
    public function send(App\Request $request)
    {
        $roomType = $request->getByType('roomType');
        $recordId = $request->getInteger('recordId');
        $chat = \App\Chat::getInstance($roomType, $recordId);
        if (!$chat->isRoomExists()) {
            throw new \App\Exceptions\IllegalValue('ERR_NOT_ALLOWED_VALUE', 406);
        }
        if ('private' === $roomType && !$chat->isPrivateRoomAllowed($recordId)) {
            $defaultRoom = \App\Chat::setCurrentRoomDefault();
            $result = [
                'message' => 'JS_CHAT_ROOM_NOT_ALLOWED',
                'data' => $this->setMessagesResult(new App\Request(['roomType' => $defaultRoom['roomType'], 'recordId' => $defaultRoom['recordId']]))
            ];
        } else {
            $chat->addMessage(\App\Utils\Completions::encodeAll($request->getForHtml('message')));
            $chatEntries = $chat->getEntries($request->isEmpty('mid') ? null : $request->getInteger('mid'));
            $isNextPage = $this->isNextPage(\count($chatEntries));
            if ($isNextPage) {
                array_shift($chatEntries);
            }
            $result = [
                'chatEntries' => $chatEntries,
                'participants' => $chat->getParticipants(),
                'showMoreButton' => $isNextPage
            ];
        }
        $response = new Vtiger_Response();
        $response->setResult($result);
        $response->emit();
    }

    /**
     * Search meassages.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\IllegalValue
     */
    public function search(App\Request $request)
    {
        $roomType = $request->getByType('roomType');
        $recordId = $request->getInteger('recordId');
        $chat = \App\Chat::getInstance($roomType, $recordId);
        $searchVal = $request->getByType('searchVal', 'Text');
        if (!$request->isEmpty('mid')) {
            $chatEntries = $chat->getEntries($request->getInteger('mid'), '<', $searchVal);
        } else {
            $chatEntries = $chat->getEntries(null, '>', $searchVal);
        }
        $isNextPage = $this->isNextPage(\count($chatEntries));
        if ($isNextPage) {
            array_shift($chatEntries);
        }
        $response = new Vtiger_Response();
        $response->setResult([
            'chatEntries' => $chatEntries,
            'showMoreButton' => $isNextPage
        ]);
        $response->emit();
    }

    /**
     * Add private room.
     *
     * @param \App\Request $request
     */
    public function addPrivateRoom(App\Request $request)
    {
        $chat = \App\Chat::getInstance();
        $chat->createPrivateRoom($request->getByType('name', 'Text'));
        $response = new Vtiger_Response();
        $response->setResult(\App\Chat::getRoomsByUser());
        $response->emit();
    }

    /**
     * Archive rooms.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\IllegalValue
     */
    public function archivePrivateRoom(App\Request $request)
    {
        $recordId = $request->getInteger('recordId');
        $chat = \App\Chat::getInstance('private', $recordId);
        if (!$chat->isRoomModerator($recordId)) {
            throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
        }
        if (\App\Chat::getCurrentRoom()['recordId'] === $recordId) {
            \App\Chat::setCurrentRoomDefault();
        }
        $chat->archivePrivateRoom($recordId);
        $response = new Vtiger_Response();
        $response->setResult(true);
        $response->emit();
    }

    /**
     * Add participant.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\AppException
     */
    public function addParticipant(App\Request $request)
    {
        $recordId = $request->getInteger('recordId');
        $chat = \App\Chat::getInstance('private', $recordId);
        if (!$chat->isRoomModerator($recordId)) {
            throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
        }
        $alreadyInvited = $chat->addParticipantToPrivate($request->getInteger('userId'));
        if ($alreadyInvited) {
            $result = ['message' => 'JS_CHAT_PARTICIPANT_INVITED'];
        } else {
            $result = $chat->getParticipants();
        }
        $response = new Vtiger_Response();
        $response->setResult($result);
        $response->emit();
    }

    /**
     * Get all unread messages.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\AppException
     */
    public function getUnread(App\Request $request)
    {
        $unreadMessages = [];
        foreach (\App\Chat::getActiveRoomTypes() as $roomType) {
            $unreadMessages[$roomType] = \App\Chat::getUnreadByType($roomType);
        }
        $response = new Vtiger_Response();
        $response->setResult($unreadMessages);
        $response->emit();
    }

    /**
     * Get history.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\AppException
     * @throws \App\Exceptions\IllegalValue
     */
    public function getHistory(App\Request $request)
    {
        $chat = \App\Chat::getInstance();
        $groupHistory = $request->getByType('groupHistory', 2);
        if (!\in_array($groupHistory, \App\Chat::ALLOWED_ROOM_TYPES)) {
            throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
        }
        if ($request->isEmpty('mid')) {
            $chatEntries = $chat->getHistoryByType($groupHistory);
        } else {
            $chatEntries = $chat->getHistoryByType($groupHistory, $request->getInteger('mid'));
        }
        $isNextPage = $this->isNextPage(\count($chatEntries));
        if ($isNextPage) {
            array_shift($chatEntries);
        }
        $response = new Vtiger_Response();
        $response->setResult([
            'chatEntries' => $chatEntries,
            'showMoreButton' => $isNextPage
        ]);
        $response->emit();
    }

    /**
     * Get rooms function.
     *
     * @param \App\Request $request
     */
    public function getRooms(App\Request $request)
    {
        $response = new Vtiger_Response();
        $response->setResult([
            'roomList' => \App\Chat::getRoomsByUser()
        ]);
        $response->emit();
    }

    /**
     * Get rooms unpinned.
     *
     * @param App\Request $request
     *
     * @return void
     */
    public function getRoomsUnpinned(App\Request $request)
    {
        $roomType = $request->getByType('roomType');
        $methodName = 'getRooms' . ucfirst($roomType) . 'Unpinned';
        $response = new Vtiger_Response();
        $response->setResult(\App\Chat::{$methodName}());
        $response->emit();
    }

    /**
     * Show chat for record.
     *
     * @param \App\Request $request
     *
     * @throws \App\Exceptions\NoPermittedToRecord
     */
    public function getRecordRoom(App\Request $request)
    {
        $recordId = $request->getInteger('id');
        $recordModel = Vtiger_Record_Model::getInstanceById($recordId);
        if (!$recordModel->isViewable()) {
            throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
        }
        $chat = \App\Chat::getInstance('crm', $recordId);
        $chatEntries = $chat->getEntries();
        $response = new Vtiger_Response();
        $response->setResult([
            'roomList' => [
                'crm' => [
                    $recordId => [
                        'roomType' => 'crm',
                        'recordid' => $recordId,
                        'active' => true,
                        'recordRoom' => true,
                        'chatEntries' => $chatEntries,
                        'participants' => $chat->getParticipants(),
                        'showMoreButton' => \count($chatEntries) > \App\Config::module('Chat', 'CHAT_ROWS_LIMIT')
                    ]
                ]
            ]
        ]);
        $response->emit();
    }

    /**
     * Get room private unpinned users.
     *
     * @param \App\Request $request
     */
    public function getRoomPrivateUnpinnedUsers(App\Request $request)
    {
        $response = new Vtiger_Response();
        $response->setResult(\App\Chat::getRoomPrivateUnpinnedUsers($request->getInteger('roomId')));
        $response->emit();
    }

    /**
     * Check if there are more messages.
     *
     * @param int $numberOfMessages
     *
     * @return bool
     */
    private function isNextPage(int $numberOfMessages): bool
    {
        return $numberOfMessages >= \App\Config::module('Chat', 'CHAT_ROWS_LIMIT') + 1;
    }
}