Skip to content

Commit 0319a73

Browse files
Chartman123Koc
authored andcommitted
fix backend code and API docs
Signed-off-by: Christian Hartmann <chris-hartmann@gmx.de>
1 parent 2ca219c commit 0319a73

File tree

6 files changed

+116
-53
lines changed

6 files changed

+116
-53
lines changed

docs/API_v3.md

+3
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ Get all Submissions to a Form
653653
| Parameter | Type | Description |
654654
|-----------|---------|-------------|
655655
| _formId_ | Integer | ID of the form to get the submissions for |
656+
- Parameters:
657+
| Parameter | Type | Description |
658+
|------------------|----------|-------------|
656659
| _query_ | String | Phrase for full text search |
657660
| _limit_ | Integer | How many items to get |
658661
| _offset_ | Integer | How many items to skip for a pagination |

lib/Controller/ApiController.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,10 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) {
11321132
* Get all the submissions of a given form
11331133
*
11341134
* @param int $formId of the form
1135-
* @param ?string $fileFormat the file format that should be used for the download. Defaults to `null`
1135+
* @param ?string $query (optional) A search query to filter submissions
1136+
* @param ?int $limit (optional) The maximum number of submissions to retrieve. Defaults to `null`
1137+
* @param int $offset (optional) The offset for pagination. Defaults to `0`
1138+
* @param ?string $fileFormat (optional) The file format that should be used for the download. Defaults to `null`
11361139
* Possible values:
11371140
* - `csv`: Comma-separated value
11381141
* - `ods`: OpenDocument Spreadsheet
@@ -1147,7 +1150,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) {
11471150
#[NoAdminRequired()]
11481151
#[BruteForceProtection(action: 'form')]
11491152
#[ApiRoute(verb: 'GET', url: '/api/v3/forms/{formId}/submissions')]
1150-
public function getSubmissions(int $formId, ?string $query = null, int $limit = 20, int $offset = 0, ?string $fileFormat = null): DataResponse|DataDownloadResponse {
1153+
public function getSubmissions(int $formId, ?string $query = null, ?int $limit = null, int $offset = 0, ?string $fileFormat = null): DataResponse|DataDownloadResponse {
11511154
$form = $this->getFormIfAllowed($formId, Constants::PERMISSION_RESULTS);
11521155

11531156
if ($fileFormat !== null) {

lib/Db/SubmissionMapper.php

+66-47
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
namespace OCA\Forms\Db;
99

10-
use OC\DB\QueryBuilder\QueryFunction;
1110
use OCP\AppFramework\Db\DoesNotExistException;
1211
use OCP\AppFramework\Db\QBMapper;
1312
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -30,35 +29,43 @@ public function __construct(
3029
}
3130

3231
/**
33-
* @param int $formId
34-
* @param ?string $query
35-
* @param int $limit
36-
* @param int $offset
37-
* @throws DoesNotExistException if not found
38-
* @return Submission[]
32+
* Retrieves a list of submissions for a specific form.
33+
*
34+
* @param int $formId The ID of the form whose submissions are being retrieved.
35+
* @param ?string $query An optional search query to filter the submissions.
36+
* @param ?int $limit The maximum number of submissions to retrieve, default: all submissions
37+
* @param int $offset The number of submissions to skip before starting to retrieve, default: 0
38+
*
39+
* @throws DoesNotExistException If no submissions are found for the given form ID.
40+
*
41+
* @return Submission[] An array of Submission objects.
3942
*/
40-
public function findByForm(int $formId, ?string $query = null, int $limit = 20, int $offset = 0): array {
43+
public function findByForm(int $formId, ?string $query = null, ?int $limit = null, int $offset = 0): array {
4144
$qb = $this->db->getQueryBuilder();
4245

43-
if ($query) {
44-
$qb->select('MAX(submissions.id) AS id, MAX(submissions.form_id) AS form_id, MAX(submissions.user_id) AS user_id, MAX(submissions.timestamp) AS timestamp')
45-
->join('submissions', $this->answerMapper->getTableName(), 'answers', $qb->expr()->eq('submissions.id', 'answers.submission_id'))
46-
->where($qb->expr()->like('answers.text', $qb->createNamedParameter('%' . $query . '%')))
47-
->groupBy('submissions.id');
48-
} else {
49-
$qb->select('*');
50-
}
51-
52-
$qb->from($this->getTableName(), 'submissions')
53-
->andWhere(
54-
$qb->expr()->eq('form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT))
46+
// Select all columns from the submissions table
47+
$qb->selectDistinct('submissions.*')
48+
->from($this->getTableName(), 'submissions')
49+
->where(
50+
$qb->expr()->eq('submissions.form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT))
5551
)
56-
//Newest submissions first
57-
->orderBy('timestamp', 'DESC')
58-
->setMaxResults($limit)
59-
->setFirstResult($offset);
60-
61-
//var_dump($qb->getSQL());exit;
52+
// Newest submissions first
53+
->orderBy('submissions.timestamp', 'DESC')
54+
->setFirstResult($offset)
55+
->setMaxResults($limit);
56+
57+
// If a query is provided, join the answers table and filter by the query text
58+
if (!is_null($query) && $query !== '') {
59+
$qb->join(
60+
'submissions',
61+
$this->answerMapper->getTableName(),
62+
'answers',
63+
$qb->expr()->eq('submissions.id', 'answers.submission_id')
64+
)
65+
->andWhere(
66+
$qb->expr()->like('answers.text', $qb->createNamedParameter('%' . $query . '%'))
67+
);
68+
}
6269

6370
return $this->findEntities($qb);
6471
}
@@ -100,49 +107,61 @@ public function hasFormSubmissionsByUser(Form $form, string $userId): bool {
100107
}
101108

102109
/**
103-
* Count submissions by form
104-
* @param int $formId ID of the form to count submissions
105-
* @throws \Exception
110+
* Counts the number of submissions associated with a specific form.
111+
*
112+
* @param int $formId The ID of the form for which submissions are to be counted.
113+
* @param ?string $searchString An optional search string to filter submissions by their answers.
114+
* @return int The total number of submissions for the specified form.
115+
* @throws \Exception If an error occurs during the count operation.
106116
*/
107117
public function countSubmissions(int $formId, ?string $searchString = null): int {
108118
return $this->countSubmissionsWithFilters($formId, null, -1, $searchString);
109119
}
110120

111121
/**
112-
* Count submissions by form with optional filters
113-
* @param int $formId ID of the form to count submissions
114-
* @param string|null $userId optionally limit submissions to the one of that user
115-
* @param int $limit allows to limit the query selection. If -1, the restriction is ignored
116-
* @throws \Exception
122+
* Count submissions by form with optional filters.
123+
*
124+
* @param int $formId The ID of the form for which submissions are to be counted.
125+
* @param string|null $userId Optionally limit submissions to those made by the specified user.
126+
* @param int $limit The maximum number of submissions to count. If -1, no limit is applied.
127+
* @param string|null $searchString An optional search string to filter submissions by their answers.
128+
*
129+
* @return int The total number of submissions matching the specified filters.
130+
*
131+
* @throws \Exception If an error occurs during the count operation.
117132
*/
118133
protected function countSubmissionsWithFilters(int $formId, ?string $userId = null, int $limit = -1, ?string $searchString = null): int {
119134
$qb = $this->db->getQueryBuilder();
120135

121-
if ($searchString) {
122-
$query = $qb->select(new QueryFunction('COUNT(DISTINCT submissions.id) AS num_submissions'))
123-
->join('submissions', $this->answerMapper->getTableName(), 'answers', $qb->expr()->eq('submissions.id', 'answers.submission_id'))
124-
->andWhere($qb->expr()->like('answers.text', $qb->createNamedParameter('%' . $searchString . '%')));
125-
} else {
126-
$query = $qb->select($qb->func()->count('*', 'num_submissions'));
127-
}
128-
129-
$query
136+
$query = $qb->select('submissions.id')
130137
->from($this->getTableName(), 'submissions')
131-
->where($qb->expr()->eq('form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT)));
138+
->where($qb->expr()->eq('submissions.form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT)))
139+
->groupBy('submissions.id');
132140

133141
if (!is_null($userId)) {
134-
$query->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
142+
$query->andWhere($qb->expr()->eq('submissions.user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
143+
}
144+
145+
if (!is_null($searchString) && $searchString !== '') {
146+
$query->join(
147+
'submissions',
148+
$this->answerMapper->getTableName(),
149+
'answers',
150+
$qb->expr()->eq('submissions.id', 'answers.submission_id')
151+
)
152+
->andWhere(
153+
$qb->expr()->like('answers.text', $qb->createNamedParameter('%' . $searchString . '%'))
154+
);
135155
}
136156

137157
if ($limit !== -1) {
138158
$query->setMaxResults($limit);
139159
}
140160

141161
$result = $query->executeQuery();
142-
$row = $result->fetch();
143162
$result->closeCursor();
144163

145-
return (int)($row['num_submissions'] ?? 0);
164+
return $result->rowCount();
146165
}
147166

148167
/**

lib/ResponseDefinitions.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
*
7171
* @psalm-type FormsSubmissions = array{
7272
* submissions: list<FormsSubmission>,
73-
* questions: list<FormsQuestion>
73+
* questions: list<FormsQuestion>,
74+
* totalSubmissionsCount: int
7475
* }
7576
*
7677
* @psalm-type FormsAccess = array{

lib/Service/SubmissionService.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ private function getAnswers(int $submissionId): array {
9191
* Get all submissions of a form
9292
*
9393
* @param int $formId the form id
94+
* @param ?string $query optional search query to filter submissions
95+
* @param ?int $limit the maximum number of submissions to return
96+
* @param int $offset the number of submissions to skip
9497
* @return list<array{
9598
* id: int,
9699
* formId: int,
@@ -99,7 +102,7 @@ private function getAnswers(int $submissionId): array {
99102
* answers: list<FormsAnswer>,
100103
* }>
101104
*/
102-
public function getSubmissions(int $formId, ?string $query = null, int $limit = 20, int $offset = 0): array {
105+
public function getSubmissions(int $formId, ?string $query = null, ?int $limit = null, int $offset = 0): array {
103106
$submissionList = [];
104107
try {
105108
$submissionEntities = $this->submissionMapper->findByForm($formId, $query, $limit, $offset);

openapi.json

+36-2
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,8 @@
548548
"type": "object",
549549
"required": [
550550
"submissions",
551-
"questions"
551+
"questions",
552+
"totalSubmissionsCount"
552553
],
553554
"properties": {
554555
"submissions": {
@@ -562,6 +563,10 @@
562563
"items": {
563564
"$ref": "#/components/schemas/Question"
564565
}
566+
},
567+
"totalSubmissionsCount": {
568+
"type": "integer",
569+
"format": "int64"
565570
}
566571
}
567572
},
@@ -2975,10 +2980,39 @@
29752980
"format": "int64"
29762981
}
29772982
},
2983+
{
2984+
"name": "query",
2985+
"in": "query",
2986+
"description": "(optional) A search query to filter submissions",
2987+
"schema": {
2988+
"type": "string",
2989+
"nullable": true
2990+
}
2991+
},
2992+
{
2993+
"name": "limit",
2994+
"in": "query",
2995+
"description": "(optional) The maximum number of submissions to retrieve. Defaults to `null`",
2996+
"schema": {
2997+
"type": "integer",
2998+
"format": "int64",
2999+
"nullable": true
3000+
}
3001+
},
3002+
{
3003+
"name": "offset",
3004+
"in": "query",
3005+
"description": "(optional) The offset for pagination. Defaults to `0`",
3006+
"schema": {
3007+
"type": "integer",
3008+
"format": "int64",
3009+
"default": 0
3010+
}
3011+
},
29783012
{
29793013
"name": "fileFormat",
29803014
"in": "query",
2981-
"description": "the file format that should be used for the download. Defaults to `null` Possible values: - `csv`: Comma-separated value - `ods`: OpenDocument Spreadsheet - `xlsx`: Excel Open XML Spreadsheet",
3015+
"description": "(optional) The file format that should be used for the download. Defaults to `null` Possible values: - `csv`: Comma-separated value - `ods`: OpenDocument Spreadsheet - `xlsx`: Excel Open XML Spreadsheet",
29823016
"schema": {
29833017
"type": "string",
29843018
"nullable": true

0 commit comments

Comments
 (0)