feat: add questionnaire definitions and their catalog

This commit is contained in:
fromme committed 2026-10-27 16:41:46 +01:00
1 parent 2ec2a4c93f
commit a84275b40e
12 files changed
+1136

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Model\Questionnaire;
use App\Enum\ConditionOperator;
/**
* A question's show_if: it is shown, and can be required, only while this holds.
*/
readonly class Condition
{
/**
* @param string|list<string>|int $value an option key for EQUALS, a list of them for IN,
* a rating for LTE
*/
public function __construct(
public string $question,
public ConditionOperator $operator,
public string|array|int $value,
) {
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Model\Questionnaire;
/**
* One version of a questionnaire as read from config/questionnaires/. Responses store its key and
* version, and their answers are keyed by Question::$key.
*/
readonly class Definition
{
/**
* @param list<Section> $sections
*/
public function __construct(
public string $key,
public int $version,
public string $title,
public ?string $description,
public array $sections,
) {
}
/**
* @return array<string, Question> in the order they are asked, keyed by question key
*/
public function getQuestions(): array
{
$questions = [];
foreach ($this->sections as $section) {
foreach ($section->questions as $question) {
$questions[$question->key] = $question;
}
}
return $questions;
}
public function getQuestion(string $key): ?Question
{
return $this->getQuestions()[$key] ?? null;
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Model\Questionnaire;
readonly class Option
{
public function __construct(
public string $key,
public string $label,
) {
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Model\Questionnaire;
use App\Enum\ChoiceWidget;
use App\Enum\QuestionType;
readonly class Question
{
/**
* @param list<Option> $options only for CHOICE and MULTI
* @param ChoiceWidget|null $widget only for CHOICE
*/
public function __construct(
public string $key,
public string $label,
public QuestionType $type,
public bool $required = false,
public ?string $help = null,
public ?ChoiceWidget $widget = null,
public array $options = [],
public ?Condition $showIf = null,
) {
}
public function getOption(string $key): ?Option
{
foreach ($this->options as $option) {
if ($key === $option->key) {
return $option;
}
}
return null;
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace App\Model\Questionnaire;
readonly class Section
{
/**
* @param list<Question> $questions
*/
public function __construct(
public string $key,
public ?string $title,
public array $questions,
) {
}
}