portal.mkgtu.ru/common/modules/abiturient/controllers/BaseChatController.php

292 lines
9.5 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace common\modules\abiturient\controllers;
use common\components\filesystem\FilterFilename;
use common\models\settings\ChatSettings;
use common\models\User;
use common\modules\abiturient\models\chat\ChatBase;
use common\modules\abiturient\models\chat\ChatFileBase;
use common\modules\abiturient\models\chat\ChatPersonToPerson;
use common\modules\abiturient\models\chat\ChatUserBase;
use common\modules\abiturient\models\chat\EmptyChatUser;
use Throwable;
use Yii;
use yii\base\UserException;
use yii\helpers\ArrayHelper;
use yii\helpers\FileHelper;
use yii\web\Controller;
use yii\web\ForbiddenHttpException;
use yii\web\Response;
use yii\web\ServerErrorHttpException;
class BaseChatController extends Controller
{
public function beforeAction($action)
{
if (!ChatSettings::getValueByName(ChatSettings::ENABLE_CHAT)) {
throw new ForbiddenHttpException('Чат отключён администратором');
}
return parent::beforeAction($action);
}
public function init()
{
parent::init();
$path = realpath(__DIR__);
$path = FileHelper::normalizePath("{$path}/../views/chat");
Yii::setAlias('@chatView', $path);
$path = realpath(__DIR__);
$path = FileHelper::normalizePath("{$path}/../views/chat/_partials");
Yii::setAlias('@chatPartialView', $path);
}
public static function otherUsersClass(): string
{
return ChatUserBase::class;
}
public function getViewPath()
{
return Yii::getAlias('@chatView');
}
public function renderActionIndex(string $viewPath = 'index')
{
$data = $this->processDataActionIndex();
return $this->render(
$viewPath,
$data
);
}
public function processDataActionIndex(): array
{
$user = Yii::$app->user->identity;
$otherUsersClass = static::otherUsersClass();
$availableUsersWithChats = $otherUsersClass::getAvailableUsersWithChats($user);
$availableUsersWithoutChats = $otherUsersClass::getAvailableUsersWithoutChats($user);
return compact([
'user',
'availableUsersWithoutChats',
'availableUsersWithChats',
]);
}
public function actionOpenChat()
{
Yii::$app->response->statusCode = 200;
Yii::$app->response->format = Response::FORMAT_JSON;
$chat = null;
$history = '';
$destinationUser = null;
if (Yii::$app->request->isAjax) {
$thisUser = Yii::$app->user->identity;
$thatUserId = '';
$destinationId = Yii::$app->request->post('destinationId');
if ($destinationId === ChatBase::ID_FOR_NEW_CHAT || $destinationId === ChatBase::ID_FOR_ARCHIVE_CHAT) {
$thatUserId = ChatBase::ID_FOR_NEW_CHAT;
} else {
$thatUser = User::findOne((int)$destinationId);
$thatUserId = $thatUser->id;
}
$chat = ChatPersonToPerson::findChatByIdAndUsersId(
(int)Yii::$app->request->post('chatId'),
[$thisUser->id, $thatUserId]
);
$destinationUser = null;
if ($destinationId !== ChatBase::ID_FOR_NEW_CHAT) {
if (!$thatUser) {
throw new ServerErrorHttpException('Не удалось определить пользователя чата');
}
$otherUsersClass = static::otherUsersClass();
$destinationUser = $otherUsersClass::getOrCreateUser($chat, $thatUser);
} else {
$destinationUser = EmptyChatUser::getOrCreateUser($chat, $thisUser);
}
if ($chat) {
$history = $chat->renderHistory($this, $thisUser);
}
}
return [
'history' => $history,
'chatId' => $chat ? $chat->id : null,
'header' => $destinationUser ? $destinationUser->renderHeader($this) : []
];
}
public function actionSendMessage()
{
$chatId = null;
$blobsUid = [];
Yii::$app->response->statusCode = 200;
Yii::$app->response->format = Response::FORMAT_JSON;
if (Yii::$app->request->isAjax) {
$hasError = false;
$user = Yii::$app->user->identity;
$fileContexts = json_decode(Yii::$app->request->post('fileContexts'), true);
$messageOutput = '';
$messageContext = json_decode(Yii::$app->request->post('messageContext'), true);
if ($messageContext) {
$messageOutput = $messageContext['messageOutput'];
}
$blobsUid = $this->buildBlobsUid($messageContext, $fileContexts);
$chat = null;
try {
$chat = ChatPersonToPerson::getOrCreateChat(
(int)Yii::$app->request->post('chatId'),
json_decode(Yii::$app->request->post('usersIds'))
);
} catch (Throwable $th) {
Yii::error("Ошибка содания чата при отправке сообщения: {$th->getMessage()}", 'BaseChatController.actionSendMessage');
Yii::$app->response->statusCode = 400;
$hasError = true;
}
if (!$hasError && $chat) {
$chatId = $chat->id;
} else {
Yii::$app->response->statusCode = 400;
$hasError = true;
}
if (!$hasError && $messageContext) {
try {
if (!$chat->addMessage($messageOutput, $user->id)) {
Yii::$app->response->statusCode = 400;
$hasError = true;
}
} catch (Throwable $th) {
Yii::error("Ошибка отправки сообщения: {$th->getMessage()}", 'BaseChatController.actionSendMessage');
Yii::$app->response->statusCode = 400;
$hasError = true;
}
}
if (!$hasError && $fileContexts) {
try {
if (!$chat->addFiles($fileContexts, $user->id)) {
Yii::$app->response->statusCode = 400;
}
} catch (Throwable $th) {
Yii::error("Ошибка отправки файла: {$th->getMessage()}", 'BaseChatController.actionSendMessage');
Yii::$app->response->statusCode = 400;
}
}
}
return [
'chatId' => $chatId,
'blobsUid' => $blobsUid,
];
}
private function buildBlobsUid(array $messageContext, array $fileContexts): array
{
$blobsUid = [];
if ($messageContext) {
$tmp = ArrayHelper::getValue($messageContext, 'messageUid');
if ($tmp) {
$blobsUid[] = $tmp;
}
}
if ($fileContexts) {
foreach ($fileContexts as $context) {
$tmp = ArrayHelper::getValue($context, 'fileUid');
if ($tmp) {
$blobsUid[] = $tmp;
}
}
}
return $blobsUid;
}
public function renderActionUpdateChatPeopleList(string $viewPath = '@chatPartialView/chat-people-list')
{
if (Yii::$app->request->isAjax) {
$data = $this->processDataActionIndex();
return $this->renderPartial(
$viewPath,
$data
);
}
return '';
}
public function actionDownload(int $id = null, int $key = null)
{
if (is_null($id) && !is_null($key)) {
$id = $key;
}
if (is_null($id)) {
throw new UserException('Невозможно скачать файл, так как не передан уникальный идентификатор файла.');
}
$file = ChatFileBase::findOne($id);
Yii::$app->response->format = Response::FORMAT_JSON;
if ($file != null) {
$user = Yii::$app->user->identity;
if ($file->checkAccess($user)) {
$abs_path = $file->getAbsPath();
if ($abs_path && file_exists($abs_path)) {
return Yii::$app->response->sendFile(
$abs_path,
FilterFilename::sanitize($file->filename),
[
'mimeType' => $file->getMimeType(),
'inline' => $file->extension === 'pdf'
]
);
}
return Yii::t(
'abiturient/chat/chat-file',
'Текст сообщения об отсутствии файла для файла в чате: `Невозможно получить файл.`'
);
}
return Yii::t(
'abiturient/chat/chat-file',
'Текст сообщения об отсутствии доступа к записи для файла в чате: `У вас нет доступа для скачивания этого файла.`'
);
}
return Yii::t(
'abiturient/chat/chat-file',
'Текст сообщения об записи об таком файле для файла в чате: `Файл не найден.`'
);
}
}