Skip to content

Commit b0aca85

Browse files
authored
Merge pull request #4674 from nextcloud/fix/ocs-responses
API refactor, fixes and empty basline
2 parents 77b61f5 + 517a73a commit b0aca85

16 files changed

Lines changed: 116 additions & 244 deletions

lib/Controller/BaseApiV2OCSController.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
1515
use OCP\AppFramework\Http\DataResponse;
1616
use OCP\AppFramework\OCS\OCSBadRequestException;
17+
use OCP\AppFramework\OCS\OCSException;
1718
use OCP\AppFramework\OCS\OCSNotFoundException;
1819
use OCP\AppFramework\OCSController;
1920
use OCP\IRequest;
@@ -34,8 +35,11 @@ public function __construct(
3435
}
3536

3637
/**
37-
* @param Closure $callback Callback function
38-
* @psalm-param HttpStatusCode $successStatus HTTP status code for success
38+
* @template TData of array
39+
* @template TStatus of Http::STATUS_*
40+
* @param Closure(): TData $callback
41+
* @param TStatus $successStatus
42+
* @return DataResponse<TStatus, TData, array{}>
3943
*/
4044
#[NoAdminRequired]
4145
protected function response(Closure $callback, int $successStatus = Http::STATUS_OK): DataResponse {
@@ -46,12 +50,10 @@ protected function response(Closure $callback, int $successStatus = Http::STATUS
4650
throw new OCSNotFoundException($e->getMessage());
4751

4852
} catch (Exception $e) {
49-
50-
if ($e->getStatus() === Http::STATUS_NOT_MODIFIED) {
51-
return new DataResponse(statusCode: Http::STATUS_NOT_MODIFIED);
52-
}
53-
54-
throw new OCSBadRequestException($e->getMessage());
53+
throw match ($e->getStatus()) {
54+
Http::STATUS_NOT_MODIFIED => new OCSException($e->getMessage(), Http::STATUS_NOT_MODIFIED),
55+
default => new OCSBadRequestException($e->getMessage()),
56+
};
5557
}
5658
}
5759
}

lib/Controller/CommentApiController.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ public function __construct(
3535
* 200: Returns list of comments
3636
* @param int $pollId Poll id
3737
* @return DataResponse<Http::STATUS_OK, array{comments: list<PollsComment>}, array{}>
38-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
3938
*/
4039
#[CORS]
4140
#[NoAdminRequired]
4241
#[NoCSRFRequired]
4342
#[ApiRoute(verb: 'GET', url: '/api/v1.0/poll/{pollId}/comments')]
4443
public function list(int $pollId): DataResponse {
45-
return $this->response(fn () => ['comments' => $this->commentService->list($pollId)]);
44+
return $this->response(fn () => ['comments' => array_values(array_map(fn ($c) => $c->jsonSerialize(), $this->commentService->list($pollId)))]);
4645
}
4746

4847
/**
@@ -51,43 +50,40 @@ public function list(int $pollId): DataResponse {
5150
* @param int $pollId Poll id
5251
* @param string $comment Comment text to add
5352
* @return DataResponse<Http::STATUS_OK, array{comment: PollsComment}, array{}>
54-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
5553
*/
5654
#[CORS]
5755
#[NoAdminRequired]
5856
#[NoCSRFRequired]
5957
#[ApiRoute(verb: 'POST', url: '/api/v1.0/poll/{pollId}/comment')]
6058
public function add(int $pollId, string $comment): DataResponse {
61-
return $this->response(fn () => ['comment' => $this->commentService->add($comment, $pollId)]);
59+
return $this->response(fn () => ['comment' => $this->commentService->add($comment, $pollId)->jsonSerialize()]);
6260
}
6361

6462
/**
6563
* Delete comment
6664
* 200: Comment deleted
6765
* @param int $commentId Id of comment to delete
6866
* @return DataResponse<Http::STATUS_OK, array{comment: PollsComment}, array{}>
69-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
7067
*/
7168
#[CORS]
7269
#[NoAdminRequired]
7370
#[NoCSRFRequired]
7471
#[ApiRoute(verb: 'DELETE', url: '/api/v1.0/comment/{commentId}')]
7572
public function delete(int $commentId): DataResponse {
76-
return $this->response(fn () => ['comment' => $this->commentService->delete($commentId)]);
73+
return $this->response(fn () => ['comment' => $this->commentService->delete($commentId)->jsonSerialize()]);
7774
}
7875

7976
/**
8077
* Restore comment
8178
* 200: Comment restored
8279
* @param int $commentId Id of comment to restore
8380
* @return DataResponse<Http::STATUS_OK, array{comment: PollsComment}, array{}>
84-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
8581
*/
8682
#[CORS]
8783
#[NoAdminRequired]
8884
#[NoCSRFRequired]
8985
#[ApiRoute(verb: 'POST', url: '/api/v1.0/comment/{commentId}/restore')]
9086
public function restore(int $commentId): DataResponse {
91-
return $this->response(fn () => ['comment' => $this->commentService->restore($commentId)]);
87+
return $this->response(fn () => ['comment' => $this->commentService->restore($commentId)->jsonSerialize()]);
9288
}
9389
}

lib/Controller/OptionApiController.php

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,13 @@ public function __construct(
4444
* 200: Returns list of options
4545
* @param int $pollId Poll id
4646
* @return DataResponse<Http::STATUS_OK, array{options: list<PollsOption>}, array{}>
47-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
4847
*/
4948
#[CORS]
5049
#[NoAdminRequired]
5150
#[NoCSRFRequired]
5251
#[ApiRoute(verb: 'GET', url: '/api/v1.0/poll/{pollId}/options')]
5352
public function list(int $pollId): DataResponse {
54-
return $this->response(fn () => ['options' => $this->optionService->list($pollId)]);
53+
return $this->response(fn () => ['options' => array_values(array_map(fn ($o) => $o->jsonSerialize(), $this->optionService->list($pollId)))]);
5554
}
5655

5756
/**
@@ -62,7 +61,6 @@ public function list(int $pollId): DataResponse {
6261
* @param bool $voteYes Vote yes for this option and for all generated sequence
6362
* @param PollsSequence|null $sequence Sequence of the option
6463
* @return DataResponse<Http::STATUS_CREATED, array{option: PollsOption, repetitions: list<PollsOption>, options: list<PollsOption>, votes: list<PollsVote>}, array{}>
65-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
6664
*/
6765
#[CORS]
6866
#[NoAdminRequired]
@@ -74,16 +72,20 @@ public function add(
7472
bool $voteYes = false,
7573
?array $sequence = null,
7674
): DataResponse {
77-
return $this->response(fn () => array_merge(
78-
$this->optionService->addWithSequenceAndAutoVote(
75+
return $this->response(function () use ($pollId, $option, $voteYes, $sequence): array {
76+
$result = $this->optionService->addWithSequenceAndAutoVote(
7977
$pollId,
8078
SimpleOption::fromArray($option),
8179
$voteYes,
8280
Sequence::fromArray($sequence),
83-
),
84-
['options' => $this->optionService->list($pollId)],
85-
['votes' => $this->voteService->list($pollId)],
86-
), Http::STATUS_CREATED);
81+
);
82+
return [
83+
'option' => $result['option']->jsonSerialize(),
84+
'repetitions' => array_map(fn ($o) => $o->jsonSerialize(), $result['repetitions']),
85+
'options' => array_values(array_map(fn ($o) => $o->jsonSerialize(), $this->optionService->list($pollId))),
86+
'votes' => array_values(array_map(fn ($v) => $v->jsonSerialize(), $this->voteService->list($pollId))),
87+
];
88+
}, Http::STATUS_CREATED);
8789
}
8890

8991
/**
@@ -92,14 +94,13 @@ public function add(
9294
* @param int $pollId Poll id
9395
* @param string $text Options text (newline-separated) for text poll
9496
* @return DataResponse<Http::STATUS_CREATED, array{options: list<PollsOption>}, array{}>
95-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
9697
*/
9798
#[CORS]
9899
#[NoAdminRequired]
99100
#[NoCSRFRequired]
100101
#[ApiRoute(verb: 'POST', url: '/api/v1.0/poll/{pollId}/options')]
101102
public function addBulk(int $pollId, string $text = ''): DataResponse {
102-
return $this->response(fn () => ['options' => $this->optionService->addBulk($pollId, $text)], Http::STATUS_CREATED);
103+
return $this->response(fn () => ['options' => array_values(array_map(fn ($o) => $o->jsonSerialize(), $this->optionService->addBulk($pollId, $text)))], Http::STATUS_CREATED);
103104
}
104105

105106
/**
@@ -112,7 +113,6 @@ public function addBulk(int $pollId, string $text = ''): DataResponse {
112113
* @param string|null $isoTimestamo ISO 8601 timestamp
113114
* @param string|null $isoDuration ISO 8601 duration
114115
* @return DataResponse<Http::STATUS_OK, array{option: PollsOption}, array{}>
115-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
116116
*/
117117
#[CORS]
118118
#[NoAdminRequired]
@@ -124,67 +124,63 @@ public function update(int $optionId, int $timestamp = 0, string $text = '', int
124124
$text,
125125
new DateTimeImmutable($isoTimestamo ?? $timestamp),
126126
new DateInterval($isoDuration ?? $duration),
127-
)]);
127+
)->jsonSerialize()]);
128128
}
129129

130130
/**
131131
* Delete option
132132
* 200: Option deleted
133133
* @param int $optionId Option id
134134
* @return DataResponse<Http::STATUS_OK, array{option: PollsOption}, array{}>
135-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
136135
*/
137136
#[CORS]
138137
#[NoAdminRequired]
139138
#[NoCSRFRequired]
140139
#[ApiRoute(verb: 'DELETE', url: '/api/v1.0/option/{optionId}')]
141140
public function delete(int $optionId): DataResponse {
142-
return $this->response(fn () => ['option' => $this->optionService->delete($optionId)]);
141+
return $this->response(fn () => ['option' => $this->optionService->delete($optionId)->jsonSerialize()]);
143142
}
144143

145144
/**
146145
* Restore option
147146
* 200: Option restored
148147
* @param int $optionId Option id
149148
* @return DataResponse<Http::STATUS_OK, array{option: PollsOption}, array{}>
150-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
151149
*/
152150
#[CORS]
153151
#[NoAdminRequired]
154152
#[NoCSRFRequired]
155153
#[ApiRoute(verb: 'PUT', url: '/api/v1.0/option/{optionId}/restore')]
156154
public function restore(int $optionId): DataResponse {
157-
return $this->response(fn () => ['option' => $this->optionService->delete($optionId, true)]);
155+
return $this->response(fn () => ['option' => $this->optionService->delete($optionId, true)->jsonSerialize()]);
158156
}
159157

160158
/**
161159
* Switch option confirmation
162160
* 200: Option confirmation toggled
163161
* @param int $optionId Option id
164162
* @return DataResponse<Http::STATUS_OK, array{option: PollsOption}, array{}>
165-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
166163
*/
167164
#[CORS]
168165
#[NoAdminRequired]
169166
#[NoCSRFRequired]
170167
#[ApiRoute(verb: 'PUT', url: '/api/v1.0/option/{optionId}/confirm')]
171168
public function confirm(int $optionId): DataResponse {
172-
return $this->response(fn () => ['option' => $this->optionService->confirm($optionId)]);
169+
return $this->response(fn () => ['option' => $this->optionService->confirm($optionId)->jsonSerialize()]);
173170
}
174171

175172
/**
176173
* Set order position for option
177174
* 200: Option order updated
178175
* @param int $optionId Option id
179176
* @param int $order Option's new position
180-
* @return DataResponse<Http::STATUS_OK, array{option: PollsOption}, array{}>
181-
* @psalm-suppress InvalidReturnType InvalidReturnStatement
177+
* @return DataResponse<Http::STATUS_OK, array{options: list<PollsOption>}, array{}>
182178
*/
183179
#[CORS]
184180
#[NoAdminRequired]
185181
#[NoCSRFRequired]
186182
#[ApiRoute(verb: 'PUT', url: '/api/v1.0/option/{optionId}/order/{order}')]
187183
public function setOrder(int $optionId, int $order): DataResponse {
188-
return $this->response(fn () => ['option' => $this->optionService->setOrder($optionId, $order)]);
184+
return $this->response(fn () => ['options' => array_map(fn ($o) => $o->jsonSerialize(), $this->optionService->setOrder($optionId, $order))]);
189185
}
190186
}

0 commit comments

Comments
 (0)