Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion lib/Chat/ChatManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@
use OC\Memcache\NullCache;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\ChatParticipantEvent;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Poll;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\AttachmentService;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\Service\PollService;
use OCA\Talk\Service\RoomService;
use OCA\Talk\Share\RoomShareProvider;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Collaboration\Reference\IReferenceManager;
use OCP\Comments\IComment;
Expand Down Expand Up @@ -357,6 +358,60 @@ public function unshareFileOnMessageDelete(Room $room, Participant $participant,
$this->shareManager->deleteShare($share);
}

/**
* @param Room $room
* @param Participant $participant
* @param array $messageData
* @throws ShareNotFound
*/
public function removePollOnMessageDelete(Room $room, Participant $participant, array $messageData, \DateTime $deletionTime): void {
if (!isset($messageData['message'], $messageData['parameters']['objectType'], $messageData['parameters']['objectId'])
|| $messageData['message'] !== 'object_shared'
|| $messageData['parameters']['objectType'] !== 'talk-poll') {
// Not a poll share
return;
}

try {
$poll = $this->pollService->getPoll($room->getId(), (int)$messageData['parameters']['objectId']);
} catch (DoesNotExistException $e) {
return;
}

if ($poll->getStatus() === Poll::STATUS_CLOSED) {
$closingMessages = $this->commentsManager->searchForObjects(
json_encode([
'message' => 'poll_closed',
'parameters' => [
'poll' => [
'type' => 'talk-poll',
'id' => $poll->getId(),
'name' => $poll->getQuestion(),
],
],
], JSON_THROW_ON_ERROR),
'chat',
[(string) $room->getId()],
'system',
0
);
foreach ($closingMessages as $closingMessage) {
$this->deleteMessage($room, $closingMessage, $participant, $deletionTime);
}
}

if (!$participant->hasModeratorPermissions(false)) {
$attendee = $participant->getAttendee();
if (!($attendee->getActorType() === $poll->getActorType()
&& $attendee->getActorId() === $poll->getActorId())) {
// Only moderators or the poll creator can delete it
return;
}
}

$this->pollService->deleteByPollId($poll->getId());
}

/**
* @param Room $chat
* @param IComment $comment
Expand All @@ -369,6 +424,7 @@ public function deleteMessage(Room $chat, IComment $comment, Participant $partic
if ($comment->getVerb() === self::VERB_OBJECT_SHARED) {
$messageData = json_decode($comment->getMessage(), true);
$this->unshareFileOnMessageDelete($chat, $participant, $messageData);
$this->removePollOnMessageDelete($chat, $participant, $messageData, $deletionTime);
}

$comment->setMessage(
Expand Down
9 changes: 9 additions & 0 deletions lib/Model/PollMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,13 @@ public function deleteByRoomId(int $roomId): void {

$query->executeStatement();
}

public function deleteByPollId(int $pollId): void {
$query = $this->db->getQueryBuilder();

$query->delete($this->getTableName())
->where($query->expr()->eq('id', $query->createNamedParameter($pollId, IQueryBuilder::PARAM_INT)));

$query->executeStatement();
}
}
9 changes: 9 additions & 0 deletions lib/Model/VoteMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ public function deleteByRoomId(int $roomId): void {
$query->executeStatement();
}

public function deleteByPollId(int $pollId): void {
$query = $this->db->getQueryBuilder();

$query->delete($this->getTableName())
->where($query->expr()->eq('poll_id', $query->createNamedParameter($pollId, IQueryBuilder::PARAM_INT)));

$query->executeStatement();
}

public function deleteVotesByActor(int $pollId, string $actorType, string $actorId): void {
$query = $this->db->getQueryBuilder();

Expand Down
5 changes: 5 additions & 0 deletions lib/Service/PollService.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ public function deleteByRoomId(int $roomId): void {
$this->pollMapper->deleteByRoomId($roomId);
}

public function deleteByPollId(int $pollId): void {
$this->voteMapper->deleteByPollId($pollId);
$this->pollMapper->deleteByPollId($pollId);
}

public function updateDisplayNameForActor(string $actorType, string $actorId, string $displayName): void {
$update = $this->connection->getQueryBuilder();
$update->update('talk_polls')
Expand Down
8 changes: 5 additions & 3 deletions tests/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -1614,9 +1614,11 @@ public function userSeesPollInRoom(string $user, string $question, string $ident
$this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/poll/' . self::$identifierToToken[$identifier] . '/' . self::$questionToPollId[$question]);
$this->assertStatusCode($this->response, $statusCode);

$expected = $this->preparePollExpectedData($formData->getRowsHash());
$response = $this->getDataFromResponse($this->response);
$this->assertPollEquals($expected, $response);
if ($statusCode === '200' || $formData instanceof TableNode) {
$expected = $this->preparePollExpectedData($formData->getRowsHash());
$response = $this->getDataFromResponse($this->response);
$this->assertPollEquals($expected, $response);
}
}

/**
Expand Down
63 changes: 63 additions & 0 deletions tests/integration/features/chat-2/poll.feature
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,66 @@ Feature: chat-2/poll
| status | closed |
| votedSelf | [] |
| details | [{"actorType":"deleted_users","actorId":"deleted_users","actorDisplayName":"","optionId":0}] |

Scenario: Deleting the poll message removes all details
Given user "participant1" creates room "room" (v4)
| roomType | 2 |
| roomName | room |
And user "participant1" adds user "participant2" to room "room" with 200 (v4)
And user "participant2" creates a poll in room "room" with 201
| question | What is the question? |
| options | ["Where are you?","How much is the fish?"] |
| resultMode | public |
| maxVotes | unlimited |
And user "participant1" sees the following messages in room "room" with 200 (v1)
| room | actorType | actorId | actorDisplayName | message | messageParameters |
| room | users | participant2 | participant2-displayname | {object} | "IGNORE" |
And user "participant1" deletes message "{object}" from room "room" with 200 (v1)
And user "participant1" votes for options "[1]" on poll "What is the question?" in room "room" with 404
And user "participant2" votes for options "[0]" on poll "What is the question?" in room "room" with 404
And user "participant1" closes poll "What is the question?" in room "room" with 404
And user "participant2" closes poll "What is the question?" in room "room" with 404
Then user "participant1" sees poll "What is the question?" in room "room" with 404
Then user "participant2" sees poll "What is the question?" in room "room" with 404
And user "participant1" sees the following messages in room "room" with 200 (v1)
| room | actorType | actorId | actorDisplayName | message | messageParameters |
| room | users | participant2 | participant2-displayname | Message deleted by you | "IGNORE" |

Scenario: Deleting a closed poll message removes also the close message
Given user "participant1" creates room "room" (v4)
| roomType | 2 |
| roomName | room |
And user "participant1" adds user "participant2" to room "room" with 200 (v4)
And user "participant2" creates a poll in room "room" with 201
| question | What is the question? |
| options | ["Where are you?","How much is the fish?"] |
| resultMode | public |
| maxVotes | unlimited |
And user "participant1" sees the following messages in room "room" with 200 (v1)
| room | actorType | actorId | actorDisplayName | message | messageParameters |
| room | users | participant2 | participant2-displayname | {object} | "IGNORE" |
And user "participant2" closes poll "What is the question?" in room "room" with 200
| id | POLL_ID(What is the question?) |
| question | What is the question? |
| options | ["Where are you?","How much is the fish?"] |
| votes | [] |
| numVoters | 0 |
| resultMode | public |
| maxVotes | unlimited |
| actorType | users |
| actorId | participant2 |
| actorDisplayName | participant2-displayname |
| status | closed |
| votedSelf | [] |
| details | [] |
And user "participant1" deletes message "{object}" from room "room" with 200 (v1)
And user "participant1" votes for options "[1]" on poll "What is the question?" in room "room" with 404
And user "participant2" votes for options "[0]" on poll "What is the question?" in room "room" with 404
And user "participant1" closes poll "What is the question?" in room "room" with 404
And user "participant2" closes poll "What is the question?" in room "room" with 404
Then user "participant1" sees poll "What is the question?" in room "room" with 404
Then user "participant2" sees poll "What is the question?" in room "room" with 404
And user "participant1" sees the following messages in room "room" with 200 (v1)
| room | actorType | actorId | actorDisplayName | message | messageParameters |
| room | users | participant2 | participant2-displayname | Message deleted by you | "IGNORE" |
| room | users | participant2 | participant2-displayname | Message deleted by you | "IGNORE" |