portal.mkgtu.ru/common/modules/abiturient/models/chat/ChatPersonToPerson.php

286 lines
7.4 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace common\modules\abiturient\models\chat;
use common\models\errors\RecordNotValid;
use common\models\User;
use Throwable;
use Yii;
use yii\db\ActiveQuery;
use yii\web\ServerErrorHttpException;
class ChatPersonToPerson extends ChatBase
{
public static function getOrCreateChat(int $chatId, $userIds): ChatBase
{
if (count($userIds) != 2) {
throw new ServerErrorHttpException('Количество активных пользователей чата должно быть строго два');
}
$chat = static::findChatByIdAndUsersId($chatId, $userIds);
if (!$chat) {
$chat = static::createNewChat($userIds);
}
if (
$chat instanceof ChatPersonToPerson &&
$chat->canStartingOrOpenAgain
) {
$chat->statusTransition();
ChatHistoryBase::managerStartingChat($chat);
ChatHistoryBase::abitOpenAgainChat($chat);
if (!$chat->save()) {
throw new RecordNotValid($chat);
}
if ($chat->status == static::STATUS_OPEN_AGAIN) {
$chat->connectWithLastPerson();
}
}
return $chat;
}
public static function findChatByIdAndUsersId(int $chatId, array $userIds): ?ChatBase
{
$tnFirstChatUser = 'firstChatUser';
$tnSecondChatUser = 'secondChatUser';
$thChatBase = ChatBase::tableName();
[
$secondChatUserId,
$firstChatUserId,
] = $userIds;
if ($secondChatUserId == $firstChatUserId) {
return null;
}
if ($firstChatUserId === static::ID_FOR_NEW_CHAT || $secondChatUserId === static::ID_FOR_NEW_CHAT) {
$realId = $firstChatUserId === static::ID_FOR_NEW_CHAT ? $secondChatUserId : $firstChatUserId;
$chat = ChatPersonToPerson::findChatByOnlyAbiturientId($chatId, $realId);
if (!$chat) {
return ChatPersonToEmpty::getOrCreateChat($chatId, $realId);
}
return $chat;
}
$chat = static::find()
->joinWith("chatUsers {$tnFirstChatUser}")
->joinWith("chatUsers {$tnSecondChatUser}")
->andWhere([
"{$thChatBase}.id" => $chatId,
"{$tnFirstChatUser}.user_id" => $firstChatUserId,
"{$tnSecondChatUser}.user_id" => $secondChatUserId,
"{$tnFirstChatUser}.archive" => false,
"{$tnSecondChatUser}.archive" => false,
])
->one();
if (!$chat && ChatPersonToEmpty::isExists($chatId, $userIds)) {
$chat = ChatPersonToPerson::find()
->andWhere(["{$thChatBase}.id" => $chatId])
->one();
}
return $chat;
}
public static function findChatUsersId(array $userIds): ?ChatPersonToPerson
{
$tnFirstChatUser = 'firstChatUser';
$tnSecondChatUser = 'secondChatUser';
[
$secondChatUserId,
$firstChatUserId,
] = $userIds;
if ($secondChatUserId == $firstChatUserId) {
return null;
}
$chat = static::find()
->joinWith("chatUsers {$tnFirstChatUser}")
->joinWith("chatUsers {$tnSecondChatUser}")
->andWhere([
"{$tnFirstChatUser}.user_id" => $firstChatUserId,
"{$tnSecondChatUser}.user_id" => $secondChatUserId,
"{$tnFirstChatUser}.archive" => false,
"{$tnSecondChatUser}.archive" => false,
])
->one();
return $chat;
}
public function endChat(int $chatUserId): bool
{
$chatUser = $this->getChatUsers()
->andWhere(['user_id' => $chatUserId])
->one();
if ($chatUser) {
if (!$chatUser->makeArchive()) {
throw new ServerErrorHttpException('Возникла ошибка архивирования пользователя чата');
}
}
ChatHistoryBase::managerEndingChat($this);
$this->status = static::STATUS_ENDING;
if (!$this->save()) {
throw new RecordNotValid($this);
}
return true;
}
public function connectWithLastPerson(): bool
{
$thisUserId = Yii::$app->user->identity->id;
$tnChatUserBase = ChatUserBase::tableName();
$chatUser = $this->getChatUsers()
->andWhere(['!=', "{$tnChatUserBase}.user_id", $thisUserId])
->orderBy(["{$tnChatUserBase}.updated_at" => SORT_DESC])
->one();
if ($chatUser) {
if (!$chatUser->makeActive()) {
throw new ServerErrorHttpException('Возникла ошибка активирования пользователя чата');
}
}
return true;
}
public function redirectChat(User $thisUser, User $otherManager): bool
{
$chatUserToArchive = $this->getChatUsers()
->andWhere([
'archive' => false,
'user_id' => $thisUser->id,
])
->orderBy(['updated_at' => SORT_DESC])
->one();
if ($chatUserToArchive) {
$chatUserToConnect = $this->getOrCreateChatUserByUserId($otherManager->id);
$transaction = Yii::$app->db->beginTransaction();
try {
if (!$chatUserToArchive->makeArchive() || !$chatUserToConnect->makeActive()) {
throw new ServerErrorHttpException('Не удалось произвести переадресацию чата, на другого пользователя');
}
$transaction->commit();
} catch (Throwable $th) {
$transaction->rollBack();
Yii::error("Возникла ошибка при перенаправлении чата: {$th->getMessage()}", 'ChatPersonToPerson.redirectChat');
return false;
}
ChatHistoryBase::managerRedirectChat($this);
return true;
}
throw new ServerErrorHttpException('Для данного чат не найдена ни одного пользователя');
}
public static function findChatByOnlyAbiturientIdQuery(int $chatId, int $userId): ActiveQuery
{
$tnChatUser = ChatUserBase::tableName();
$thChatBase = ChatBase::tableName();
$subQuery = static::find()
->select("{$thChatBase}.id")
->joinWith('chatUsers')
->andWhere([
"{$thChatBase}.id" => $chatId,
"{$tnChatUser}.archive" => false,
])
->andWhere(['!=', "{$tnChatUser}.user_id", $userId]);
return static::find()
->joinWith('chatUsers')
->andWhere([
"{$thChatBase}.id" => $chatId,
"{$tnChatUser}.user_id" => $userId,
"{$tnChatUser}.archive" => false,
])
->andWhere(['IN', "{$thChatBase}.id", $subQuery]);
}
public static function findChatByOnlyAbiturientId(int $chatId, int $userId): ?ChatPersonToEmpty
{
return static::findChatByOnlyAbiturientIdQuery($chatId, $userId)->one();
}
}