diff --git a/appinfo/info.xml b/appinfo/info.xml index 35537e25c..c3a607365 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -17,7 +17,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m ]]> - 3.99.5 + 3.99.6 agpl Daniel Calviño Sánchez diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index 10d3038fd..6db4af642 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -76,6 +76,9 @@ class ChatManager { $this->commentsManager->save($comment); + // Update last_message + $chat->setLastMessage($comment); + $this->notifier->notifyMentionedUsers($chat, $comment); return $comment; } diff --git a/lib/Chat/CommentsManager.php b/lib/Chat/CommentsManager.php index 85cb24ab8..5e4015725 100644 --- a/lib/Chat/CommentsManager.php +++ b/lib/Chat/CommentsManager.php @@ -29,6 +29,14 @@ use OCP\DB\QueryBuilder\IQueryBuilder; class CommentsManager extends Manager { + /** + * @param array $data + * @return IComment + */ + public function getCommentFromData(array $data): IComment { + return new Comment($this->normalizeDatabaseData($data)); + } + /** * @param string $objectType * @param string $objectId diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index e4d97dfe4..514fdf8ce 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -38,6 +38,7 @@ use OCA\Spreed\TalkSession; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; +use OCP\Comments\IComment; use OCP\IL10N; use OCP\ILogger; use OCP\IRequest; @@ -115,7 +116,7 @@ class RoomController extends OCSController { * @return DataResponse */ public function getRooms() { - $rooms = $this->manager->getRoomsForParticipant($this->userId); + $rooms = $this->manager->getRoomsForParticipant($this->userId, true); $return = []; foreach ($rooms as $room) { @@ -249,35 +250,35 @@ class RoomController extends OCSController { $room->cleanGuestParticipants(); } - $lastMessageFromHistory = $this->chatManager->getHistory($room->getId(), 0, 1); - $lastMessage = []; + $lastMessage = $room->getLastMessage(); + if ($lastMessage instanceof IComment) { - if (!empty($lastMessageFromHistory)) { - - list($message, $messageParameters) = $this->richMessageHelper->getRichMessage($lastMessageFromHistory[0]); + list($message, $messageParameters) = $this->richMessageHelper->getRichMessage($lastMessage); $displayName = ''; - $actorId = $lastMessageFromHistory[0]->getActorId(); - $actorType = $lastMessageFromHistory[0]->getActorType(); + $actorId = $lastMessage->getActorId(); + $actorType = $lastMessage->getActorType(); if ($actorType === 'users') { $user = $this->userManager->get($actorId); $displayName = $user instanceof IUser ? $user->getDisplayName() : ''; } else if ($actorType === 'guests') { $guestNames = !empty($actorId) ? $this->guestManager->getNamesBySessionHashes([$actorId]) : []; - $displayName = isset($guestNames[$actorId]) ? $guestNames[$actorId] : ''; + $displayName = $guestNames[$actorId] ?? ''; } $lastMessage = [ - 'id' => $lastMessageFromHistory[0]->getId(), + 'id' => $lastMessage->getId(), 'actorType' => $actorType, 'actorId' => $actorId, 'actorDisplayName' => $displayName, - 'timestamp' => $lastMessageFromHistory[0]->getCreationDateTime()->getTimestamp(), + 'timestamp' => $lastMessage->getCreationDateTime()->getTimestamp(), 'message' => $message, 'messageParameters' => $messageParameters, ]; + } else { + $lastMessage = []; } $roomData = array_merge($roomData, [ diff --git a/lib/Manager.php b/lib/Manager.php index bd9a2ab69..27e5340d0 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -22,6 +22,7 @@ namespace OCA\Spreed; +use OCA\Spreed\Chat\CommentsManager; use OCA\Spreed\Exceptions\RoomNotFoundException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; @@ -39,6 +40,8 @@ class Manager { private $config; /** @var ISecureRandom */ private $secureRandom; + /** @var CommentsManager */ + private $commentsManager; /** @var EventDispatcherInterface */ private $dispatcher; /** @var IHasher */ @@ -50,13 +53,15 @@ class Manager { * @param IDBConnection $db * @param IConfig $config * @param ISecureRandom $secureRandom + * @param CommentsManager $commentsManager * @param EventDispatcherInterface $dispatcher * @param IHasher $hasher */ - public function __construct(IDBConnection $db, IConfig $config, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher) { + public function __construct(IDBConnection $db, IConfig $config, ISecureRandom $secureRandom, CommentsManager $commentsManager, EventDispatcherInterface $dispatcher, IHasher $hasher) { $this->db = $db; $this->config = $config; $this->secureRandom = $secureRandom; + $this->commentsManager = $commentsManager; $this->dispatcher = $dispatcher; $this->hasher = $hasher; } @@ -89,7 +94,12 @@ class Manager { $lastActivity = new \DateTime($row['last_activity']); } - return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->hasher, (int) $row['id'], (int) $row['type'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity); + $lastMessage = null; + if (!empty($row['comment_id'])) { + $lastMessage = $this->commentsManager->getCommentFromData(array_merge($row, ['id' => $row['comment_id']])); + } + + return new Room($this, $this->db, $this->secureRandom, $this->dispatcher, $this->hasher, (int) $row['id'], (int) $row['type'], $row['token'], $row['name'], $row['password'], (int) $row['active_guests'], $activeSince, $lastActivity, $lastMessage); } /** @@ -103,11 +113,12 @@ class Manager { /** * @param string $participant + * @param bool $includeLastMessage * @return Room[] */ - public function getRoomsForParticipant($participant) { + public function getRoomsForParticipant($participant, $includeLastMessage = false) { $query = $this->db->getQueryBuilder(); - $query->select('*') + $query->select('r.*')->addSelect('p.*') ->from('talk_rooms', 'r') ->leftJoin('r', 'talk_participants', 'p', $query->expr()->andX( $query->expr()->eq('p.user_id', $query->createNamedParameter($participant)), @@ -115,6 +126,12 @@ class Manager { )) ->where($query->expr()->isNotNull('p.user_id')); + if ($includeLastMessage) { + $query->leftJoin('r','comments', 'c', $query->expr()->eq('r.last_message', 'c.id')); + $query->selectAlias('c.id', 'comment_id'); + $query->addSelect('c.actor_id', 'c.actor_type', 'c.message', 'c.creation_timestamp'); + } + $result = $query->execute(); $rooms = []; while ($row = $result->fetch()) { diff --git a/lib/Migration/Version3003Date20180718133519.php b/lib/Migration/Version3003Date20180718133519.php new file mode 100644 index 000000000..ef0964987 --- /dev/null +++ b/lib/Migration/Version3003Date20180718133519.php @@ -0,0 +1,88 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Spreed\Migration; + +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\IDBConnection; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version3003Date20180718133519 extends SimpleMigrationStep { + + /** @var IDBConnection */ + protected $connection; + + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + } + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + * @since 13.0.0 + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('talk_rooms'); + + if (!$table->hasColumn('last_message')) { + $table->addColumn('last_message', Type::BIGINT, [ + 'notnull' => false, + 'default' => 0, + ]); + } + + return $schema; + } + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @since 13.0.0 + */ + public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { + $update = $this->connection->getQueryBuilder(); + $update->update('talk_rooms') + ->set('last_message', $update->createParameter('message')) + ->where($update->expr()->eq('id', $update->createParameter('room'))); + + $query = $this->connection->getQueryBuilder(); + $query->selectAlias($query->createFunction('MAX(' . $query->getColumnName('id') . ')'), 'message') + ->addSelect('object_id') + ->from('comments') + ->where($query->expr()->eq('object_type', $query->createNamedParameter('chat'))) + ->groupBy('object_id'); + + $result = $query->execute(); + while ($row = $result->fetch()) { + $update->setParameter('message', $row['message']) + ->setParameter('room', $row['object_id']); + $update->execute(); + } + $result->closeCursor(); + } +} diff --git a/lib/Room.php b/lib/Room.php index aec6cb776..23adba481 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -27,6 +27,7 @@ namespace OCA\Spreed; use OCA\Spreed\Exceptions\InvalidPasswordException; use OCA\Spreed\Exceptions\ParticipantNotFoundException; +use OCP\Comments\IComment; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUser; @@ -68,6 +69,8 @@ class Room { private $activeSince; /** @var \DateTime|null */ private $lastActivity; + /** @var IComment|null */ + private $lastMessage; /** @var string */ protected $currentUser; @@ -90,8 +93,9 @@ class Room { * @param int $activeGuests * @param \DateTime|null $activeSince * @param \DateTime|null $lastActivity + * @param IComment|null $lastMessage */ - public function __construct(Manager $manager, IDBConnection $db, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher, $id, $type, $token, $name, $password, $activeGuests, \DateTime $activeSince = null, \DateTime $lastActivity = null) { + public function __construct(Manager $manager, IDBConnection $db, ISecureRandom $secureRandom, EventDispatcherInterface $dispatcher, IHasher $hasher, $id, $type, $token, $name, $password, $activeGuests, \DateTime $activeSince = null, \DateTime $lastActivity = null, IComment $lastMessage = null) { $this->manager = $manager; $this->db = $db; $this->secureRandom = $secureRandom; @@ -105,6 +109,7 @@ class Room { $this->activeGuests = $activeGuests; $this->activeSince = $activeSince; $this->lastActivity = $lastActivity; + $this->lastMessage = $lastMessage; } /** @@ -156,6 +161,13 @@ class Room { return $this->lastActivity; } + /** + * @return IComment|null + */ + public function getLastMessage() { + return $this->lastMessage; + } + /** * @return bool */ @@ -369,6 +381,14 @@ class Room { return true; } + public function setLastMessage(IComment $message) { + $query = $this->db->getQueryBuilder(); + $query->update('talk_rooms') + ->set('last_message', $query->createNamedParameter((int) $message->getId())) + ->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT))); + $query->execute(); + } + /** * @return bool */