6161 * @psalm-import-type FormsPartialForm from ResponseDefinitions
6262 * @psalm-import-type FormsQuestion from ResponseDefinitions
6363 * @psalm-import-type FormsQuestionType from ResponseDefinitions
64+ * @psalm-import-type FormsQuestionGridSubType from ResponseDefinitions
6465 * @psalm-import-type FormsSubmission from ResponseDefinitions
6566 * @psalm-import-type FormsSubmissions from ResponseDefinitions
6667 * @psalm-import-type FormsUploadedFile from ResponseDefinitions
@@ -445,6 +446,7 @@ public function getQuestion(int $formId, int $questionId): DataResponse {
445446 *
446447 * @param int $formId the form id
447448 * @param FormsQuestionType $type the new question type
449+ * @param FormsQuestionGridSubType $subtype the new question subtype
448450 * @param string $text the new question title
449451 * @param ?int $fromId (optional) id of the question that should be cloned
450452 * @return DataResponse<Http::STATUS_CREATED, FormsQuestion, array{}>
@@ -461,7 +463,7 @@ public function getQuestion(int $formId, int $questionId): DataResponse {
461463 #[NoAdminRequired()]
462464 #[BruteForceProtection(action: 'form ' )]
463465 #[ApiRoute(verb: 'POST ' , url: '/api/v3/forms/{formId}/questions ' )]
464- public function newQuestion (int $ formId , ?string $ type = null , string $ text = '' , ?int $ fromId = null ): DataResponse {
466+ public function newQuestion (int $ formId , ?string $ type = null , ? string $ subtype = null , string $ text = '' , ?int $ fromId = null ): DataResponse {
465467 $ form = $ this ->formsService ->getFormIfAllowed ($ formId , Constants::PERMISSION_EDIT );
466468 $ this ->formsService ->obtainFormLock ($ form );
467469
@@ -505,7 +507,7 @@ public function newQuestion(int $formId, ?string $type = null, string $text = ''
505507 $ question ->setText ($ text );
506508 $ question ->setDescription ('' );
507509 $ question ->setIsRequired (false );
508- $ question ->setExtraSettings ([]);
510+ $ question ->setExtraSettings ($ subtype ? [ ' questionType ' => $ subtype ] : []);
509511
510512 $ question = $ this ->questionMapper ->insert ($ question );
511513
@@ -820,6 +822,7 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse {
820822 * @param int $formId id of the form
821823 * @param int $questionId id of the question
822824 * @param list<string> $optionTexts the new option text
825+ * @param string|null $optionType the new option type (e.g. 'row')
823826 * @return DataResponse<Http::STATUS_CREATED, list<FormsOption>, array{}> Returns a DataResponse containing the added options
824827 * @throws OCSBadRequestException This question is not part ot the given form
825828 * @throws OCSForbiddenException This form is archived and can not be modified
@@ -833,11 +836,12 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse {
833836 #[NoAdminRequired()]
834837 #[BruteForceProtection(action: 'form ' )]
835838 #[ApiRoute(verb: 'POST ' , url: '/api/v3/forms/{formId}/questions/{questionId}/options ' )]
836- public function newOption (int $ formId , int $ questionId , array $ optionTexts ): DataResponse {
837- $ this ->logger ->debug ('Adding new options: formId: {formId}, questionId: {questionId}, text: {text} ' , [
839+ public function newOption (int $ formId , int $ questionId , array $ optionTexts, ? string $ optionType = null ): DataResponse {
840+ $ this ->logger ->debug ('Adding new options: formId: {formId}, questionId: {questionId}, text: {text}, optionType: {optionType} ' , [
838841 'formId ' => $ formId ,
839842 'questionId ' => $ questionId ,
840843 'text ' => $ optionTexts ,
844+ 'optionType ' => $ optionType ,
841845 ]);
842846
843847 $ form = $ this ->formsService ->getFormIfAllowed ($ formId , Constants::PERMISSION_EDIT );
@@ -863,7 +867,7 @@ public function newOption(int $formId, int $questionId, array $optionTexts): Dat
863867 }
864868
865869 // Retrieve all options sorted by 'order'. Takes the order of the last array-element and adds one.
866- $ options = $ this ->optionMapper ->findByQuestion ($ questionId );
870+ $ options = $ this ->optionMapper ->findByQuestion ($ questionId, $ optionType );
867871 $ lastOption = array_pop ($ options );
868872 if ($ lastOption ) {
869873 $ optionOrder = $ lastOption ->getOrder () + 1 ;
@@ -878,6 +882,7 @@ public function newOption(int $formId, int $questionId, array $optionTexts): Dat
878882 $ option ->setQuestionId ($ questionId );
879883 $ option ->setText ($ text );
880884 $ option ->setOrder ($ optionOrder ++);
885+ $ option ->setOptionType ($ optionType );
881886
882887 try {
883888 $ option = $ this ->optionMapper ->insert ($ option );
@@ -1034,6 +1039,7 @@ public function deleteOption(int $formId, int $questionId, int $optionId): DataR
10341039 * @param int $formId id of form
10351040 * @param int $questionId id of question
10361041 * @param list<int> $newOrder Array of option ids in new order.
1042+ * @param string|null $optionType the new option type (e.g. 'row')
10371043 * @return DataResponse<Http::STATUS_OK, array<string, FormsOrder>, array{}>
10381044 * @throws OCSBadRequestException The given question id doesn't match the form
10391045 * @throws OCSBadRequestException The given array contains duplicates
@@ -1050,7 +1056,7 @@ public function deleteOption(int $formId, int $questionId, int $optionId): DataR
10501056 #[NoAdminRequired()]
10511057 #[BruteForceProtection(action: 'form ' )]
10521058 #[ApiRoute(verb: 'PATCH ' , url: '/api/v3/forms/{formId}/questions/{questionId}/options ' )]
1053- public function reorderOptions (int $ formId , int $ questionId , array $ newOrder) {
1059+ public function reorderOptions (int $ formId , int $ questionId , array $ newOrder, ? string $ optionType = null ): DataResponse {
10541060 $ form = $ this ->formsService ->getFormIfAllowed ($ formId , Constants::PERMISSION_EDIT );
10551061 $ this ->formsService ->obtainFormLock ($ form );
10561062
@@ -1077,7 +1083,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) {
10771083 throw new OCSBadRequestException ('The given array contains duplicates ' );
10781084 }
10791085
1080- $ options = $ this ->optionMapper ->findByQuestion ($ questionId );
1086+ $ options = $ this ->optionMapper ->findByQuestion ($ questionId, $ optionType );
10811087
10821088 if (sizeof ($ options ) !== sizeof ($ newOrder )) {
10831089 $ this ->logger ->debug ('The length of the given array does not match the number of stored options ' );
@@ -1691,6 +1697,22 @@ public function uploadFiles(int $formId, int $questionId, string $shareHash = ''
16911697 * @param string[]|array<array{uploadedFileId: string, uploadedFileName: string}> $answerArray
16921698 */
16931699 private function storeAnswersForQuestion (Form $ form , $ submissionId , array $ question , array $ answerArray ): void {
1700+ if ($ question ['type ' ] === Constants::ANSWER_TYPE_GRID ) {
1701+ if (!$ answerArray ) {
1702+ return ;
1703+ }
1704+
1705+ $ answerEntity = new Answer ();
1706+ $ answerEntity ->setSubmissionId ($ submissionId );
1707+ $ answerEntity ->setQuestionId ($ question ['id ' ]);
1708+
1709+ $ answerText = json_encode ($ answerArray );
1710+ $ answerEntity ->setText ($ answerText );
1711+ $ this ->answerMapper ->insert ($ answerEntity );
1712+
1713+ return ;
1714+ }
1715+
16941716 foreach ($ answerArray as $ answer ) {
16951717 $ answerEntity = new Answer ();
16961718 $ answerEntity ->setSubmissionId ($ submissionId );
0 commit comments