Skip to content

Commit

Permalink
feat: Allow to reorder options for "multiple" question type
Browse files Browse the repository at this point in the history
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux authored and Chartman123 committed Sep 24, 2024
1 parent b40ef76 commit 4af0d6c
Show file tree
Hide file tree
Showing 9 changed files with 464 additions and 164 deletions.
385 changes: 267 additions & 118 deletions appinfo/routes.php

Large diffs are not rendered by default.

68 changes: 40 additions & 28 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ This file contains the API-Documentation. For more information on the returned D

Returns condensed objects of all Forms beeing owned by the authenticated user.

- Endpoint: `/api/v2.4/forms`
- Endpoint: `/api/v2.5/forms`
- Method: `GET`
- Parameters: None
- Response: Array of condensed Form Objects, sorted as newest first.
Expand Down Expand Up @@ -98,7 +98,7 @@ Returns condensed objects of all Forms beeing owned by the authenticated user.

Returns condensed objects of all Forms, that are shared & shown to the authenticated user and that have not expired yet.

- Endpoint: `/api/v2.4/shared_forms`
- Endpoint: `/api/v2.5/shared_forms`
- Method: `GET`
- Parameters: None
- Response: Array of condensed Form Objects, sorted as newest first, similar to [List owned Forms](#list-owned-forms).
Expand All @@ -111,7 +111,7 @@ See above, 'List owned forms'

Returns a single partial form object, corresponding to owned/shared form-listings.

- Endpoint: `/api/v2.4/partial_form/{hash}`
- Endpoint: `/api/v2.5/partial_form/{hash}`
- Method: `GET`
- Url-Parameter:
| Parameter | Type | Description |
Expand All @@ -135,7 +135,7 @@ Returns a single partial form object, corresponding to owned/shared form-listing

### Create a new Form

- Endpoint: `/api/v2.4/form`
- Endpoint: `/api/v2.5/form`
- Method: `POST`
- Parameters: None
- Response: The new form object, similar to requesting an existing form.
Expand All @@ -148,7 +148,7 @@ See next section, 'Request full data of a form'

Returns the full-depth object of the requested form (without submissions).

- Endpoint: `/api/v2.4/form/{id}`
- Endpoint: `/api/v2.5/form/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand Down Expand Up @@ -243,7 +243,7 @@ Returns the full-depth object of the requested form (without submissions).

Creates a clone of a form (without submissions).

- Endpoint: `/api/v2.4/form/clone/{id}`
- Endpoint: `/api/v2.5/form/clone/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -259,7 +259,7 @@ See section 'Request full data of a form'.

Update a single or multiple properties of a form-object. Concerns **only** the Form-Object, properties of Questions, Options and Submissions, as well as their creation or deletion, are handled separately.

- Endpoint: `/api/v2.4/form/update`
- Endpoint: `/api/v2.5/form/update`
- Method: `PATCH`
- _Method: `POST` deprecated_
- Parameters:
Expand All @@ -278,7 +278,7 @@ Update a single or multiple properties of a form-object. Concerns **only** the F

Transfer the ownership of a form to another user

- Endpoint: `/api/v2.4/form/transfer`
- Endpoint: `/api/v2.5/form/transfer`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand All @@ -294,7 +294,7 @@ Transfer the ownership of a form to another user

### Delete a form

- Endpoint: `/api/v2.4/form/{id}`
- Endpoint: `/api/v2.5/form/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -308,7 +308,7 @@ Transfer the ownership of a form to another user

### Link a form to a file

- Endpoint: `/api/v2.4/form/link/{fileFormat}`
- Endpoint: `/api/v2.5/form/link/{fileFormat}`
- Url-Parameter:
| Parameter | Type | Description |
|--------------|---------|--------------|
Expand All @@ -332,7 +332,7 @@ Transfer the ownership of a form to another user

### Unlink file from form

- Endpoint: `/api/v2.4/form/unlink`
- Endpoint: `/api/v2.5/form/unlink`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand All @@ -346,7 +346,7 @@ Contains only manipulative question-endpoints. To retrieve questions, request th

### Create a new question

- Endpoint: `/api/v2.4/question`
- Endpoint: `/api/v2.5/question`
- Method: `POST`
- Parameters:
| Parameter | Type | Optional | Description |
Expand Down Expand Up @@ -374,7 +374,7 @@ Contains only manipulative question-endpoints. To retrieve questions, request th

Update a single or multiple properties of a question-object.

- Endpoint: `/api/v2.4/question/update`
- Endpoint: `/api/v2.5/question/update`
- Method: `PATCH`
- _Method: `POST` deprecated_
- Parameters:
Expand All @@ -393,7 +393,7 @@ Update a single or multiple properties of a question-object.

Reorders all Questions of a single form

- Endpoint: `/api/v2.4/question/reorder`
- Endpoint: `/api/v2.5/question/reorder`
- Method: `PUT`
- _Method: `POST` deprecated_
- Parameters:
Expand All @@ -420,7 +420,7 @@ Reorders all Questions of a single form

### Delete a question

- Endpoint: `/api/v2.4/question/{id}`
- Endpoint: `/api/v2.5/question/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -436,7 +436,7 @@ Reorders all Questions of a single form

Creates a clone of a question with all its options.

- Endpoint: `/api/v2.4/question/clone/{id}`
- Endpoint: `/api/v2.5/question/clone/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -454,7 +454,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the

### Create a new Option

- Endpoint: `/api/v2.4/option`
- Endpoint: `/api/v2.5/option`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand All @@ -475,7 +475,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the

Update a single or all properties of an option-object

- Endpoint: `/api/v2.4/option/update`
- Endpoint: `/api/v2.5/option/update`
- Method: `PATCH`
- _Method: `POST` deprecated_
- Parameters:
Expand All @@ -489,10 +489,22 @@ Update a single or all properties of an option-object
```
"data": 7
```
### Reorder options
- Endpoint: `/api/v2.5/question/{id}/options`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
| _id_ | Integer | ID of the question to reorder options for |
- Parameters:
| Parameter | Type | Description |
|-----------|---------|-------------|
| _order_ | Array | Ordered array of option IDs, the options will be reordered according to their position in this array |
- Method: `PATCH`
- Response: **Status-Code OK**.

### Delete an option

- Endpoint: `/api/v2.4/option/{id}`
- Endpoint: `/api/v2.5/option/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -508,7 +520,7 @@ Update a single or all properties of an option-object

### Add a new Share

- Endpoint: `/api/v2.4/share`
- Endpoint: `/api/v2.5/share`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand All @@ -532,7 +544,7 @@ Update a single or all properties of an option-object

### Delete a Share

- Endpoint: `/api/v2.4/share/{id}`
- Endpoint: `/api/v2.5/share/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand All @@ -546,7 +558,7 @@ Update a single or all properties of an option-object

### Update a Share

- Endpoint: `/api/v2.4/share/update`
- Endpoint: `/api/v2.5/share/update`
- Parameters:
| Parameter | Type | Description |
|------------------|----------|-------------|
Expand All @@ -569,7 +581,7 @@ Update a single or all properties of an option-object

Get all Submissions to a Form

- Endpoint: `/api/v2.4/submissions/{hash}`
- Endpoint: `/api/v2.5/submissions/{hash}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand Down Expand Up @@ -668,7 +680,7 @@ Get all Submissions to a Form

Returns all submissions to the form in form of a csv-file.

- Endpoint: `/api/v2.4/submissions/export/{hash}`
- Endpoint: `/api/v2.5/submissions/export/{hash}`
- Url-Parameter:
| Parameter | Type | Description |
|--------------|---------|-------------|
Expand All @@ -687,7 +699,7 @@ Returns all submissions to the form in form of a csv-file.

Creates a csv file and stores it to the cloud, resp. Files-App.

- Endpoint: `/api/v2.4/submissions/export`
- Endpoint: `/api/v2.5/submissions/export`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand All @@ -705,7 +717,7 @@ Creates a csv file and stores it to the cloud, resp. Files-App.

Delete all Submissions to a form

- Endpoint: `/api/v2.4/submissions/{formId}`
- Endpoint: `/api/v2.5/submissions/{formId}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand Down Expand Up @@ -739,7 +751,7 @@ Upload a files to answer before form submitting

Store Submission to Database

- Endpoint: `/api/v2.4/submission/insert`
- Endpoint: `/api/v2.5/submission/insert`
- Method: `POST`
- Parameters:
| Parameter | Type | Description |
Expand Down Expand Up @@ -771,7 +783,7 @@ Store Submission to Database
### Delete a single Submission
- Endpoint: `/api/v2.4/submission/{id}`
- Endpoint: `/api/v2.5/submission/{id}`
- Url-Parameter:
| Parameter | Type | Description |
|-----------|---------|-------------|
Expand Down
53 changes: 52 additions & 1 deletion lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,7 @@ public function cloneQuestionLegacy(int $id): DataResponse {
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/
public function newOptionLegacy(int $questionId, string $text): DataResponse {
public function newOptionLegacy(int $questionId, string $text, int|null $order = null): DataResponse {
$this->logger->debug('Adding new option: questionId: {questionId}, text: {text}', [
'questionId' => $questionId,
'text' => $text,
Expand Down Expand Up @@ -1979,6 +1979,9 @@ public function newOptionLegacy(int $questionId, string $text): DataResponse {

$option->setQuestionId($questionId);
$option->setText($text);
if ($order !== null) {
$option->setOrder($order);
}

$option = $this->optionMapper->insert($option);

Expand Down Expand Up @@ -2085,11 +2088,59 @@ public function deleteOptionLegacy(int $id): DataResponse {

$this->optionMapper->delete($option);

// Reorder the remaining options
$options = array_values($this->optionMapper->findByQuestion($question->getId()));
foreach ($options as $order => $option) {
$option->setOrder($order);
$this->optionMapper->update($option);
}

$this->formsService->setLastUpdatedTimestamp($form->getId());

return new DataResponse($id);
}

/**
* Reorder options for a given question
* @param int $id The question ID
* @param int[] $order Order to use
*/
public function reorderOptions(int $id, array $order) {
try {
/** @var int[] */
$order = array_flip(array_values($order));
} catch (\Error $e) {
throw new OCSBadRequestException('Invalid order parameter');
}

try {
$question = $this->questionMapper->findById($id);
$form = $this->formMapper->findById($question->getFormId());
} catch (IMapperException $e) {
$this->logger->debug('Could not find form or question', ['exception' => $e]);
throw new OCSNotFoundException('Could not find question');
}

if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user');
throw new OCSForbiddenException();
}

if ($this->formsService->isFormArchived($form)) {
$this->logger->debug('This form is archived and can not be modified');
throw new OCSForbiddenException();
}

$options = $this->optionMapper->findByQuestion($id);

foreach ($options as $option) {
$option->setOrder($order[$option->getId()] ?? 0);
$this->optionMapper->update($option);
}

return new DataResponse([]);
}

/**
* @CORS
* @NoAdminRequired
Expand Down
19 changes: 13 additions & 6 deletions lib/Db/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,37 @@
use OCP\AppFramework\Db\Entity;

/**
* @method int getQuestionId()
* @method void setQuestionId(int $value)
* @method int|float getQuestionId()
* @method void setQuestionId(int|float $value)
* @method string getText()
* @method void setText(string $value)
* @method int getOrder();
* @method void setOrder(int $value)
*/
class Option extends Entity {

/** @var int */
protected $questionId;
/** @var string */
protected $text;
// For 32bit PHP long integers, like IDs, are represented by floats
protected int|float|null $questionId;
protected string|null $text;
protected int|null $order;

/**
* Option constructor.
*/
public function __construct() {
$this->questionId = null;
$this->text = null;
$this->order = null;
$this->addType('questionId', 'integer');
$this->addType('order', 'integer');
$this->addType('text', 'string');
}

public function read(): array {
return [
'id' => $this->getId(),
'questionId' => $this->getQuestionId(),
'order' => $this->getOrder(),
'text' => (string)$this->getText(),
];
}
Expand Down
Loading

0 comments on commit 4af0d6c

Please sign in to comment.