diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 2110c671f..e1bd329a3 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -512,7 +512,7 @@ public function newQuestion(int $formId, ?string $type = null, string $text = '' $question = $this->questionMapper->insert($question); - $response = $question->read(); + $response = $this->formsService->getQuestion($question->getId()); $response['options'] = []; $response['accept'] = []; } else { @@ -704,7 +704,7 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { * * @param int $formId Id of the form to reorder * @param array $newOrder Array of Question-Ids in new order. - * @return DataResponse, array{}> + * @return DataResponse>, array{}> * @throws OCSBadRequestException The given array contains duplicates * @throws OCSBadRequestException The length of the given array does not match the number of stored questions * @throws OCSBadRequestException Question doesn\'t belong to given Form @@ -1009,7 +1009,7 @@ public function deleteOption(int $formId, int $questionId, int $optionId): DataR * @param int $formId id of form * @param int $questionId id of question * @param array $newOrder Array of option ids in new order. - * @return DataResponse, array{}> + * @return DataResponse>, array{}> * @throws OCSBadRequestException The given question id doesn't match the form * @throws OCSBadRequestException The given array contains duplicates * @throws OCSBadRequestException The length of the given array does not match the number of stored options @@ -1081,9 +1081,9 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) { $oldOrder = $options[$arrayKey]->getOrder(); // Only set order, if it changed. - if ($oldOrder !== $arrayKey + 1) { + if ($oldOrder !== (int)$arrayKey + 1) { // Set Order. ArrayKey counts from zero, order counts from 1. - $options[$arrayKey]->setOrder($arrayKey + 1); + $options[$arrayKey]->setOrder((int)$arrayKey + 1); } } @@ -1112,7 +1112,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) { * - `csv`: Comma-separated value * - `ods`: OpenDocument Spreadsheet * - `xlsx`: Excel Open XML Spreadsheet - * @return DataResponse|DataDownloadResponse + * @return DataResponse, array{}>|DataDownloadResponse * @throws OCSNotFoundException Could not find form * @throws OCSForbiddenException The current user has no permission to get the results for this form * @@ -1396,7 +1396,7 @@ public function exportSubmissionsToCloud(int $formId, string $path, string $file * @param int $formId id of the form * @param int $questionId id of the question * @param string $shareHash hash of the form share - * @return DataResponse + * @return DataResponse, array{}> * @throws OCSBadRequestException No files provided * @throws OCSBadRequestException Question doesn't belong to the given form * @throws OCSBadRequestException Invalid file provided diff --git a/lib/Controller/ShareApiController.php b/lib/Controller/ShareApiController.php index 1249eeacf..66aa06cc5 100644 --- a/lib/Controller/ShareApiController.php +++ b/lib/Controller/ShareApiController.php @@ -90,12 +90,12 @@ public function __construct( * @param int $formId The form to share * @param int $shareType Nextcloud-ShareType * @param string $shareWith ID of user/group/... to share with. For Empty shareWith and shareType Link, this will be set as RandomID. - * @param array $permissions the permissions granted on the share, defaults to `submit` - * Possible values: - * - `submit` user can submit - * - `results` user can see the results - * - `results_delete` user can see and delete results - * @return DataResponse + * @param list $permissions the permissions granted on the share, defaults to `submit` + * Possible values: + * - `submit` user can submit + * - `results` user can see the results + * - `results_delete` user can see and delete results + * @return DataResponse, array{}> * @throws OCSBadRequestException Invalid shareType * @throws OCSBadRequestException Invalid permission given * @throws OCSBadRequestException Invalid user to share with @@ -231,7 +231,7 @@ public function newShare(int $formId, int $shareType, string $shareWith = '', ar * * @param int $formId of the form * @param int $shareId of the share to update - * @param array{key: string, values: mixed} $keyValuePairs Array of key=>value pairs to update. + * @param array $keyValuePairs Array of key=>value pairs to update. * @return DataResponse * @throws OCSBadRequestException Share doesn't belong to given Form * @throws OCSBadRequestException Invalid permission given @@ -277,7 +277,7 @@ public function updateShare(int $formId, int $shareId, array $keyValuePairs): Da } //Don't allow to change other properties than permissions - if (count($keyValuePairs) > 1 || !key_exists('permissions', $keyValuePairs)) { + if (count($keyValuePairs) > 1 || !array_key_exists('permissions', $keyValuePairs)) { $this->logger->debug('Not allowed to update other properties than permissions'); throw new OCSForbiddenException('Not allowed to update other properties than permissions'); } diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index c77acd061..157596896 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -24,16 +24,6 @@ namespace OCA\Forms; /** - * @psalm-type FormsPartialForm = array{ - * id: int, - * hash: string, - * title: string, - * expires: int, - * permissions: string[], - * partial: bool, - * state: int - * } - * * @psalm-type FormsOption = array{ * id: int, * questionId: int, @@ -41,6 +31,19 @@ * order: ?int * } * + * @psalm-type FormsQuestionExtraSettings = array{ + * allowOtherAnswer?: ?bool, + * allowedFileExtensions?: ?list, + * allowedFileTypes?: ?list, + * maxAllowedFilesCount?: ?int, + * maxFileSize?: ?int, + * optionsLimitMax?: ?int, + * optionsLimitMin?: ?int, + * shuffleOptions?: ?bool, + * validationRegex?: ?string, + * validationType?: ?string + * } + * * @psalm-type FormsQuestion = array{ * id: int, * formId: int, @@ -49,9 +52,10 @@ * isRequired: bool, * text: string, * name: string, - * options: array, - * accept: string[], - * extraSettings: \stdClass + * description: string, + * extraSettings: list|FormsQuestionExtraSettings, + * options: list, + * accept?: ?list * } * * @psalm-type FormsAnswer = array{ @@ -66,13 +70,39 @@ * formId: int, * userId: string, * timestamp: int, - * answers: array, + * answers: list, * userDisplayName: string * } * * @psalm-type FormsSubmissions = array{ - * submissions: array, - * questions: array + * submissions: list, + * questions: list + * } + * + * @psalm-type FormsAccess = array{ + * permitAllUsers: bool, + * showToAllUsers: bool + * } + * + * @psalm-type FormsPermission = "edit"|"results"|"results_delete"|"submit"|"embed" + * + * @psalm-type FormsShare = array{ + * id: int, + * formId: int, + * shareType: int, + * shareWith: string, + * permissions: list, + * displayName: string + * } + * + * @psalm-type FormsPartialForm = array{ + * id: int, + * hash: string, + * title: string, + * expires: int, + * permissions: list, + * partial: true, + * state: int * } * * @psalm-type FormsForm = array{ @@ -82,32 +112,23 @@ * description: string, * ownerId: string, * created: int, - * access: \stdClass, + * access: FormsAccess, * expires: int, * isAnonymous: bool, * submitMultiple: bool, * showExpiration: bool, * canSubmit: bool, - * permissions: string[], - * questions: array, + * permissions: list, + * questions: list, * state: int, - * shares: string[], - * submissions: array, + * shares: list, + * submissions: list, * } * * @psalm-type FormsUploadedFile = array{ * uploadedFileId: int, * fileName: string * } - * - * @psalm-type FormsShare = array{ - * id: int, - * formId: int, - * shareType: int, - * shareWith: string, - * permissions: string[], - * displayName: string - * } */ class ResponseDefinitions { } diff --git a/openapi.json b/openapi.json index 5e94ba642..5d74d2eed 100644 --- a/openapi.json +++ b/openapi.json @@ -20,6 +20,21 @@ } }, "schemas": { + "Access": { + "type": "object", + "required": [ + "permitAllUsers", + "showToAllUsers" + ], + "properties": { + "permitAllUsers": { + "type": "boolean" + }, + "showToAllUsers": { + "type": "boolean" + } + } + }, "Answer": { "type": "object", "required": [ @@ -115,8 +130,7 @@ "format": "int64" }, "access": { - "type": "object", - "additionalProperties": true + "$ref": "#/components/schemas/Access" }, "expires": { "type": "integer", @@ -137,7 +151,7 @@ "permissions": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Permission" } }, "questions": { @@ -244,11 +258,14 @@ "permissions": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Permission" } }, "partial": { - "type": "boolean" + "type": "boolean", + "enum": [ + true + ] }, "state": { "type": "integer", @@ -256,6 +273,16 @@ } } }, + "Permission": { + "type": "string", + "enum": [ + "edit", + "results", + "results_delete", + "submit", + "embed" + ] + }, "Question": { "type": "object", "required": [ @@ -266,9 +293,9 @@ "isRequired", "text", "name", - "options", - "accept", - "extraSettings" + "description", + "extraSettings", + "options" ], "properties": { "id": { @@ -295,6 +322,20 @@ "name": { "type": "string" }, + "description": { + "type": "string" + }, + "extraSettings": { + "anyOf": [ + { + "type": "array", + "maxItems": 0 + }, + { + "$ref": "#/components/schemas/QuestionExtraSettings" + } + ] + }, "options": { "type": "array", "items": { @@ -303,13 +344,65 @@ }, "accept": { "type": "array", + "nullable": true, "items": { "type": "string" } + } + } + }, + "QuestionExtraSettings": { + "type": "object", + "properties": { + "allowOtherAnswer": { + "type": "boolean", + "nullable": true }, - "extraSettings": { - "type": "object", - "additionalProperties": true + "allowedFileExtensions": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "allowedFileTypes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "maxAllowedFilesCount": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "maxFileSize": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "optionsLimitMax": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "optionsLimitMin": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "shuffleOptions": { + "type": "boolean", + "nullable": true + }, + "validationRegex": { + "type": "string", + "nullable": true + }, + "validationType": { + "type": "string", + "nullable": true } } }, @@ -342,7 +435,7 @@ "permissions": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Permission" } }, "displayName": { @@ -1417,40 +1510,6 @@ } ], "responses": { - "200": { - "description": "the question ids of the given form in the new order", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int64" - } - } - } - } - } - } - } - } - }, "400": { "description": "One question has already been marked as deleted", "content": { @@ -2297,40 +2356,6 @@ } ], "responses": { - "200": { - "description": "the options of the question in the new order", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int64" - } - } - } - } - } - } - } - } - }, "400": { "description": "This option is not part of the given question", "content": { @@ -2858,7 +2883,10 @@ "$ref": "#/components/schemas/OCSMeta" }, "data": { - "$ref": "#/components/schemas/Submissions" + "type": "array", + "items": { + "$ref": "#/components/schemas/Submissions" + } } } } @@ -3643,7 +3671,10 @@ "$ref": "#/components/schemas/OCSMeta" }, "data": { - "$ref": "#/components/schemas/UploadedFile" + "type": "array", + "items": { + "$ref": "#/components/schemas/UploadedFile" + } } } } @@ -3774,7 +3805,7 @@ "permissions": { "type": "array", "default": [], - "description": "the permissions granted on the share, defaults to `submit`\n Possible values:\n - `submit` user can submit\n - `results` user can see the results\n - `results_delete` user can see and delete results", + "description": "the permissions granted on the share, defaults to `submit`\n Possible values:\n - `submit` user can submit\n - `results` user can see the results\n - `results_delete` user can see and delete results", "items": { "type": "string" } @@ -3828,7 +3859,10 @@ "$ref": "#/components/schemas/OCSMeta" }, "data": { - "$ref": "#/components/schemas/Share" + "type": "array", + "items": { + "$ref": "#/components/schemas/Share" + } } } } @@ -3949,17 +3983,8 @@ "keyValuePairs": { "type": "object", "description": "Array of key=>value pairs to update.", - "required": [ - "key", - "values" - ], - "properties": { - "key": { - "type": "string" - }, - "values": { - "type": "object" - } + "additionalProperties": { + "type": "object" } } }