Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse {
* @param int $formId id of the form
* @param int $questionId id of the question
* @param list<string> $optionTexts the new option text
* @param string|null $optionType the new option type (e.g. 'row')
* @param string|null $optionType the new option type (e.g. 'row'), defaults to 'choice'
* @return DataResponse<Http::STATUS_CREATED, list<FormsOption>, array{}> Returns a DataResponse containing the added options
* @throws OCSBadRequestException This question is not part ot the given form
* @throws OCSForbiddenException This form is archived and can not be modified
Expand All @@ -908,7 +908,7 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse {
#[NoAdminRequired()]
#[BruteForceProtection(action: 'form')]
#[ApiRoute(verb: 'POST', url: '/api/v3/forms/{formId}/questions/{questionId}/options')]
public function newOption(int $formId, int $questionId, array $optionTexts, ?string $optionType = null): DataResponse {
public function newOption(int $formId, int $questionId, array $optionTexts, ?string $optionType = 'choice'): DataResponse {
$this->logger->debug('Adding new options: formId: {formId}, questionId: {questionId}, text: {text}, optionType: {optionType}', [
'formId' => $formId,
'questionId' => $questionId,
Expand Down
67 changes: 67 additions & 0 deletions lib/Migration/Version050300Date20260716000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Forms\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

/**
* Gives the option_type column a 'choice' default and backfills existing
* rows that were stored without a type. Options created through the API
* without an explicit optionType previously kept a null type, which the
* frontend does not render.
*/
class Version050300Date20260716000000 extends SimpleMigrationStep {

public function __construct(
protected IDBConnection $db,
) {
}

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$table = $schema->getTable('forms_v2_options');
$changed = false;

if ($table->hasColumn('option_type')) {
$column = $table->getColumn('option_type');
if ($column->getDefault() === null) {
$column->setDefault('choice');
$changed = true;
}
}

return $changed ? $schema : null;
}

/**
* @param IOutput $output
* @param Closure(): ISchemaWrapper $schemaClosure
* @param array $options
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
$qbUpdate = $this->db->getQueryBuilder();

$qbUpdate->update('forms_v2_options')
->set('option_type', $qbUpdate->createNamedParameter('choice'))
->where($qbUpdate->expr()->isNull('option_type'))
->executeStatement();
}
}
4 changes: 2 additions & 2 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2702,8 +2702,8 @@
"optionType": {
"type": "string",
"nullable": true,
"default": null,
"description": "the new option type (e.g. 'row')"
"default": "choice",
"description": "the new option type (e.g. 'row'), defaults to 'choice'"
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions tests/Integration/Api/ApiV3Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -497,17 +497,17 @@ public static function dataGetFullForm() {
[
'text' => 'Option 1',
'order' => 1,
'optionType' => null,
'optionType' => 'choice',
],
[
'text' => 'Option 2',
'order' => 2,
'optionType' => null,
'optionType' => 'choice',
],
[
'text' => '',
'order' => 3,
'optionType' => null,
'optionType' => 'choice',
]
],
'accept' => [],
Expand Down Expand Up @@ -1027,7 +1027,9 @@ public static function dataCreateNewOption() {
// 'questionId' => Done dynamically below.
'text' => 'A new Option.',
'order' => 4,
'optionType' => null,
// Non-grid questions default to the 'choice' option type
// when none is provided.
'optionType' => 'choice',
]
]
];
Expand Down
Loading