Skip to content

Commit d06b955

Browse files
committed
fix(polls): Split draft model from normal polls
Signed-off-by: Joas Schilling <[email protected]>
1 parent 3225a1c commit d06b955

File tree

12 files changed

+191
-87
lines changed

12 files changed

+191
-87
lines changed

lib/Controller/PollController.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
/**
3737
* @psalm-import-type TalkPoll from ResponseDefinitions
38+
* @psalm-import-type TalkPollDraft from ResponseDefinitions
3839
*/
3940
class PollController extends AEnvironmentAwareController {
4041

@@ -134,7 +135,7 @@ public function createPoll(string $question, array $options, int $resultMode, in
134135
*
135136
* Required capability: `talk-polls-drafts`
136137
*
137-
* @return DataResponse<Http::STATUS_OK, list<TalkPoll>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>
138+
* @return DataResponse<Http::STATUS_OK, list<TalkPollDraft>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>
138139
*
139140
* 200: Poll returned
140141
* 403: User is not a moderator
@@ -153,7 +154,7 @@ public function getAllDraftPolls(): DataResponse {
153154
$polls = $this->pollService->getDraftsForRoom($this->room->getId());
154155
$data = [];
155156
foreach ($polls as $poll) {
156-
$data[] = $this->renderPoll($poll);
157+
$data[] = $poll->renderAsDraft();
157158
}
158159

159160
return new DataResponse($data);
@@ -346,7 +347,7 @@ public function closePoll(int $pollId): DataResponse {
346347
* @throws JsonException
347348
*/
348349
protected function renderPoll(Poll $poll, array $votedSelf = [], array $detailedVotes = []): array {
349-
$data = $poll->asArray();
350+
$data = $poll->renderAsPoll();
350351

351352
$canSeeSummary = !empty($votedSelf) && $poll->getResultMode() === Poll::MODE_PUBLIC;
352353

lib/Federation/Proxy/TalkV1/Controller/PollController.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
/**
2222
* @psalm-import-type TalkPoll from ResponseDefinitions
23+
* @psalm-import-type TalkPollDraft from ResponseDefinitions
2324
*/
2425
class PollController {
2526
public function __construct(
@@ -29,7 +30,7 @@ public function __construct(
2930
}
3031

3132
/**
32-
* @return DataResponse<Http::STATUS_OK, list<TalkPoll>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>
33+
* @return DataResponse<Http::STATUS_OK, list<TalkPollDraft>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>
3334
* @throws CannotReachRemoteException
3435
*
3536
* 200: Polls returned
@@ -49,7 +50,7 @@ public function getDraftsForRoom(Room $room, Participant $participant): DataResp
4950
return new DataResponse([], $status);
5051
}
5152

52-
/** @var list<TalkPoll> $list */
53+
/** @var list<TalkPollDraft> $list */
5354
$list = $this->proxy->getOCSData($proxy);
5455

5556
$data = [];

lib/Federation/Proxy/TalkV1/UserConverter.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
/**
1919
* @psalm-import-type TalkChatMessageWithParent from ResponseDefinitions
2020
* @psalm-import-type TalkPoll from ResponseDefinitions
21+
* @psalm-import-type TalkPollDraft from ResponseDefinitions
2122
* @psalm-import-type TalkReaction from ResponseDefinitions
2223
*/
2324
class UserConverter {
@@ -137,9 +138,12 @@ public function convertMessages(Room $room, array $messages): array {
137138
}
138139

139140
/**
141+
* @template T of TalkPoll|TalkPollDraft
140142
* @param Room $room
141-
* @param TalkPoll $poll
142-
* @return TalkPoll
143+
* @param TalkPoll|TalkPollDraft $poll
144+
* @psalm-param T $poll
145+
* @return TalkPoll|TalkPollDraft
146+
* @psalm-return T
143147
*/
144148
public function convertPoll(Room $room, array $poll): array {
145149
$poll = $this->convertAttendee($room, $poll, 'actorType', 'actorId', 'actorDisplayName');

lib/Model/Poll.php

+13-5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @method int getMaxVotes()
3838
*
3939
* @psalm-import-type TalkPoll from ResponseDefinitions
40+
* @psalm-import-type TalkPollDraft from ResponseDefinitions
4041
*/
4142
class Poll extends Entity {
4243
public const STATUS_OPEN = 0;
@@ -75,25 +76,32 @@ public function __construct() {
7576
/**
7677
* @return TalkPoll
7778
*/
78-
public function asArray(): array {
79+
public function renderAsPoll(): array {
80+
$data = $this->renderAsDraft();
7981
$votes = json_decode($this->getVotes(), true, 512, JSON_THROW_ON_ERROR);
8082

8183
// Because PHP is turning arrays with sequent numeric keys "{"0":x,"1":y,"2":z}" into "[x,y,z]"
8284
// when json_encode() is used we have to prefix the keys with a string,
8385
// to prevent breaking in the mobile apps.
84-
$prefixedVotes = [];
86+
$data['votes'] = [];
8587
foreach ($votes as $option => $count) {
86-
$prefixedVotes['option-' . $option] = $count;
88+
$data['votes']['option-' . $option] = $count;
8789
}
90+
$data['numVoters'] = $this->getNumVoters();
8891

92+
return $data;
93+
}
94+
95+
/**
96+
* @return TalkPollDraft
97+
*/
98+
public function renderAsDraft(): array {
8999
return [
90100
'id' => $this->getId(),
91101
// The room id is not needed on the API level but only internally for optimising database queries
92102
// 'roomId' => $this->getRoomId(),
93103
'question' => $this->getQuestion(),
94104
'options' => json_decode($this->getOptions(), true, 512, JSON_THROW_ON_ERROR),
95-
'votes' => $prefixedVotes,
96-
'numVoters' => $this->getNumVoters(),
97105
'actorType' => $this->getActorType(),
98106
'actorId' => $this->getActorId(),
99107
'actorDisplayName' => $this->getDisplayName(),

lib/Model/PollMapper.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public function getDraftsByRoomId(int $roomId): array {
3636
$query->select('*')
3737
->from($this->getTableName())
3838
->where($query->expr()->eq('room_id', $query->createNamedParameter($roomId, IQueryBuilder::PARAM_INT)))
39-
->andWhere($query->expr()->eq('status', $query->createNamedParameter(Poll::STATUS_DRAFT, IQueryBuilder::PARAM_INT)));
39+
->andWhere($query->expr()->eq('status', $query->createNamedParameter(Poll::STATUS_DRAFT, IQueryBuilder::PARAM_INT)))
40+
->orderBy('id', 'ASC');
4041

4142
return $this->findEntities($query);
4243
}

lib/ResponseDefinitions.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -197,18 +197,21 @@
197197
* optionId: int,
198198
* }
199199
*
200-
* @psalm-type TalkPoll = array{
200+
* @psalm-type TalkPollDraft = array{
201201
* actorDisplayName: string,
202202
* actorId: string,
203203
* actorType: string,
204-
* details?: TalkPollVote[],
205204
* id: int,
206205
* maxVotes: int,
207-
* numVoters?: int,
208206
* options: string[],
209207
* question: string,
210208
* resultMode: int,
211209
* status: int,
210+
* }
211+
*
212+
* @psalm-type TalkPoll = TalkPollDraft&array{
213+
* details?: TalkPollVote[],
214+
* numVoters?: int,
212215
* votedSelf?: int[],
213216
* votes?: array<string, int>,
214217
* }

openapi-full.json

+37-25
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,42 @@
842842
}
843843
},
844844
"Poll": {
845+
"allOf": [
846+
{
847+
"$ref": "#/components/schemas/PollDraft"
848+
},
849+
{
850+
"type": "object",
851+
"properties": {
852+
"details": {
853+
"type": "array",
854+
"items": {
855+
"$ref": "#/components/schemas/PollVote"
856+
}
857+
},
858+
"numVoters": {
859+
"type": "integer",
860+
"format": "int64"
861+
},
862+
"votedSelf": {
863+
"type": "array",
864+
"items": {
865+
"type": "integer",
866+
"format": "int64"
867+
}
868+
},
869+
"votes": {
870+
"type": "object",
871+
"additionalProperties": {
872+
"type": "integer",
873+
"format": "int64"
874+
}
875+
}
876+
}
877+
}
878+
]
879+
},
880+
"PollDraft": {
845881
"type": "object",
846882
"required": [
847883
"actorDisplayName",
@@ -864,12 +900,6 @@
864900
"actorType": {
865901
"type": "string"
866902
},
867-
"details": {
868-
"type": "array",
869-
"items": {
870-
"$ref": "#/components/schemas/PollVote"
871-
}
872-
},
873903
"id": {
874904
"type": "integer",
875905
"format": "int64"
@@ -878,10 +908,6 @@
878908
"type": "integer",
879909
"format": "int64"
880910
},
881-
"numVoters": {
882-
"type": "integer",
883-
"format": "int64"
884-
},
885911
"options": {
886912
"type": "array",
887913
"items": {
@@ -898,20 +924,6 @@
898924
"status": {
899925
"type": "integer",
900926
"format": "int64"
901-
},
902-
"votedSelf": {
903-
"type": "array",
904-
"items": {
905-
"type": "integer",
906-
"format": "int64"
907-
}
908-
},
909-
"votes": {
910-
"type": "object",
911-
"additionalProperties": {
912-
"type": "integer",
913-
"format": "int64"
914-
}
915927
}
916928
}
917929
},
@@ -8904,7 +8916,7 @@
89048916
"data": {
89058917
"type": "array",
89068918
"items": {
8907-
"$ref": "#/components/schemas/Poll"
8919+
"$ref": "#/components/schemas/PollDraft"
89088920
}
89098921
}
89108922
}

openapi.json

+37-25
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,42 @@
729729
}
730730
},
731731
"Poll": {
732+
"allOf": [
733+
{
734+
"$ref": "#/components/schemas/PollDraft"
735+
},
736+
{
737+
"type": "object",
738+
"properties": {
739+
"details": {
740+
"type": "array",
741+
"items": {
742+
"$ref": "#/components/schemas/PollVote"
743+
}
744+
},
745+
"numVoters": {
746+
"type": "integer",
747+
"format": "int64"
748+
},
749+
"votedSelf": {
750+
"type": "array",
751+
"items": {
752+
"type": "integer",
753+
"format": "int64"
754+
}
755+
},
756+
"votes": {
757+
"type": "object",
758+
"additionalProperties": {
759+
"type": "integer",
760+
"format": "int64"
761+
}
762+
}
763+
}
764+
}
765+
]
766+
},
767+
"PollDraft": {
732768
"type": "object",
733769
"required": [
734770
"actorDisplayName",
@@ -751,12 +787,6 @@
751787
"actorType": {
752788
"type": "string"
753789
},
754-
"details": {
755-
"type": "array",
756-
"items": {
757-
"$ref": "#/components/schemas/PollVote"
758-
}
759-
},
760790
"id": {
761791
"type": "integer",
762792
"format": "int64"
@@ -765,10 +795,6 @@
765795
"type": "integer",
766796
"format": "int64"
767797
},
768-
"numVoters": {
769-
"type": "integer",
770-
"format": "int64"
771-
},
772798
"options": {
773799
"type": "array",
774800
"items": {
@@ -785,20 +811,6 @@
785811
"status": {
786812
"type": "integer",
787813
"format": "int64"
788-
},
789-
"votedSelf": {
790-
"type": "array",
791-
"items": {
792-
"type": "integer",
793-
"format": "int64"
794-
}
795-
},
796-
"votes": {
797-
"type": "object",
798-
"additionalProperties": {
799-
"type": "integer",
800-
"format": "int64"
801-
}
802814
}
803815
}
804816
},
@@ -8791,7 +8803,7 @@
87918803
"data": {
87928804
"type": "array",
87938805
"items": {
8794-
"$ref": "#/components/schemas/Poll"
8806+
"$ref": "#/components/schemas/PollDraft"
87958807
}
87968808
}
87978809
}

0 commit comments

Comments
 (0)