Types\YesNoType::class, 'yes_no_conditional' => Types\YesNoConditionalType::class, 'single_choice' => Types\SingleChoiceType::class, 'multi_choice' => Types\MultiChoiceType::class, 'date_time_slots' => Types\DateTimeSlotsType::class, 'scale' => Types\ScaleType::class, 'text' => Types\TextType::class, 'ranking' => Types\RankingType::class, ]; /** @var array|null */ private ?array $types = null; /** @return array keyed by type key */ public function all(): array { if ($this->types === null) { $this->types = []; foreach (timebank_config('polls.question_types') ?? self::DEFAULT_TYPES as $key => $class) { $type = app($class); if (!$type instanceof QuestionType) { throw new InvalidArgumentException("Poll question type [$key] must implement " . QuestionType::class); } if ($type->key() !== $key) { throw new InvalidArgumentException("Poll question type [$key] reports key [{$type->key()}]"); } $this->types[$key] = $type; } } return $this->types; } public function has(string $key): bool { return isset($this->all()[$key]); } public function get(string $key): QuestionType { if (!$this->has($key)) { throw new InvalidArgumentException("Unknown or disabled poll question type [$key]"); } return $this->all()[$key]; } /** @return array key => translated label, for the editor's type select */ public function options(): array { return array_map(fn (QuestionType $type) => $type->label(), $this->all()); } }