19declare(strict_types=1);
42 protected int $question_title_output_mode,
43 protected bool $autosave_enabled,
44 protected int $autosave_interval,
45 protected bool $shuffle_questions,
46 protected bool $instant_feedback_points_enabled,
47 protected bool $instant_feedback_generic_enabled,
48 protected bool $instant_feedback_specific_enabled,
49 protected bool $instant_feedback_solution_enabled,
50 protected bool $force_instant_feedback_on_next_question,
51 protected bool $lock_answer_on_instant_feedback,
52 protected bool $lock_answer_on_next_question
65 ?array $environment =
null
68 $lng->txt(
'tst_title_output'),
69 $lng->txt(
'tst_title_output_info')
70 )->withOption(
'0',
$lng->txt(
'tst_title_output_full'))
71 ->withOption(
'1',
$lng->txt(
'tst_title_output_hide_points'))
72 ->withOption(
'3',
$lng->txt(
'tst_title_output_only_points'))
73 ->withOption(
'2',
$lng->txt(
'tst_title_output_no_title'))
79 $inputs[
'shuffle_questions'] =
$f->checkbox(
80 $lng->txt(
'tst_shuffle_questions'),
81 $lng->txt(
'tst_shuffle_questions_description')
84 if ($environment[
'participant_data_exists']) {
85 $inputs[
'shuffle_questions'] =
$inputs[
'shuffle_questions']->withDisabled(
true);
91 $section =
$f->section(
$inputs,
$lng->txt(
'tst_presentation_properties'))
103 static function (?array $vs): array {
106 'autosave_enabled' =>
false,
107 'autosave_interval' => self::DEFAULT_AUTOSAVE_INTERVAL
112 'autosave_enabled' =>
true,
113 'autosave_interval' => $vs[
'autosave_interval'] * 1000
117 $sub_inputs_autosave[
'autosave_interval'] =
$f->numeric(
$lng->txt(
'autosave_ival'),
$lng->txt(
'seconds'))
119 ->withAdditionalTransformation(
$refinery->int()->isGreaterThan(0))
121 $this->getAutosaveInterval() !== 0
122 ? $this->getAutosaveInterval() / 1000
126 $autosave_input =
$f->optionalGroup(
127 $sub_inputs_autosave,
128 $lng->txt(
'autosave'),
129 $lng->txt(
'autosave_info')
131 ->withAdditionalTransformation($trafo);
133 if (!$this->getAutosaveEnabled()) {
134 return $autosave_input;
137 return $autosave_input->withValue([
'autosave_interval' => $this->getAutosaveInterval() / 1000]);
147 fn(?array $vs) => $vs === null
148 || $vs[
'enabled_feedback_types'][
'instant_feedback_specific'] === null
149 && $vs[
'enabled_feedback_types'][
'instant_feedback_generic'] === null
150 && $vs[
'enabled_feedback_types'][
'instant_feedback_points'] === null
151 && $vs[
'enabled_feedback_types'][
'instant_feedback_solution'] === null
152 && $vs[
'feedback_trigger'] === null
154 $vs[
'enabled_feedback_types'][
'instant_feedback_specific'] ===
true
155 || $vs[
'enabled_feedback_types'][
'instant_feedback_generic'] ===
true
156 || $vs[
'enabled_feedback_types'][
'instant_feedback_points'] ===
true
157 || $vs[
'enabled_feedback_types'][
'instant_feedback_solution'] ===
true
159 && $vs[
'feedback_trigger'] !==
'',
160 $lng->txt(
'select_at_least_one_feedback_type_and_trigger')
162 $trafo =
$refinery->custom()->transformation(
163 static function (?array $vs): array {
166 'enabled_feedback_types' => [
167 'instant_feedback_specific' =>
false,
168 'instant_feedback_generic' =>
false,
169 'instant_feedback_points' =>
false,
170 'instant_feedback_solution' => false
172 'feedback_on_next_question' => false
176 $vs[
'feedback_on_next_question'] = $vs[
'feedback_trigger'] ===
'1';
181 $instant_feedback =
$f->optionalGroup(
182 $this->getSubInputInstantFeedback(
$lng,
$f, $environment),
183 $lng->txt(
'tst_instant_feedback'),
184 $lng->txt(
'tst_instant_feedback_desc')
186 ->withAdditionalTransformation($constraint)
187 ->withAdditionalTransformation($trafo);
189 if ($this->isAnyInstantFeedbackOptionEnabled()) {
190 $instant_feedback = $instant_feedback->withValue(
192 'enabled_feedback_types' => [
193 'instant_feedback_specific' => (
bool) $this->getInstantFeedbackSpecificEnabled(),
194 'instant_feedback_generic' => (
bool) $this->getInstantFeedbackGenericEnabled(),
195 'instant_feedback_points' => (
bool) $this->getInstantFeedbackPointsEnabled(),
196 'instant_feedback_solution' => (
bool) $this->getInstantFeedbackSolutionEnabled()
198 'feedback_trigger' => ($this->getForceInstantFeedbackOnNextQuestion() ?
'1' :
'0')
203 if (!$environment[
'participant_data_exists']) {
204 return $instant_feedback;
207 return $instant_feedback->withDisabled(
true);
215 $feedback_options = [
216 'instant_feedback_points' =>
$f->checkbox(
217 $lng->txt(
'tst_instant_feedback_results'),
218 $lng->txt(
'tst_instant_feedback_results_desc')
220 'instant_feedback_generic' =>
$f->checkbox(
221 $lng->txt(
'tst_instant_feedback_answer_generic'),
222 $lng->txt(
'tst_instant_feedback_answer_generic_desc')
224 'instant_feedback_specific' =>
$f->checkbox(
225 $lng->txt(
'tst_instant_feedback_answer_specific'),
226 $lng->txt(
'tst_instant_feedback_answer_specific_desc')
228 'instant_feedback_solution' =>
$f->checkbox(
229 $lng->txt(
'tst_instant_feedback_solution'),
230 $lng->txt(
'tst_instant_feedback_solution_desc')
234 $sub_inputs_feedback[
'enabled_feedback_types'] =
$f->group(
236 $lng->txt(
'tst_instant_feedback_contents')
239 $sub_inputs_feedback[
'feedback_trigger'] =
$f->radio(
240 $lng->txt(
'tst_instant_feedback_trigger')
243 $lng->txt(
'tst_instant_feedback_trigger_manual'),
244 $lng->txt(
'tst_instant_feedback_trigger_manual_desc')
247 $lng->txt(
'tst_instant_feedback_trigger_forced'),
248 $lng->txt(
'tst_instant_feedback_trigger_forced_desc')
251 if (!$environment[
'participant_data_exists']) {
252 $sub_inputs_feedback[
'feedback_trigger'] = $sub_inputs_feedback[
'feedback_trigger']
253 ->withRequired(
true);
255 return $sub_inputs_feedback;
267 static fn(?array $vs): bool => $vs === null || array_filter($vs[1]) !== [],
268 $lng->txt(
'select_at_least_one_lock_answer_type')
271 $group1 =
$f->group([],
$lng->txt(
'tst_answer_fixation_none'));
275 'lock_answer_on_instant_feedback' =>
$f->checkbox(
276 $lng->txt(
'tst_answer_fixation_on_instant_feedback'),
277 $lng->txt(
'tst_answer_fixation_on_instant_feedback_desc')
279 'lock_answer_on_next_question' =>
$f->checkbox(
280 $lng->txt(
'tst_answer_fixation_on_followup_question'),
281 $lng->txt(
'tst_answer_fixation_on_followup_question_desc')
284 $lng->txt(
'tst_answer_fixation'),
285 $lng->txt(
'tst_answer_fixation_on_instantfb_or_followupqst_desc')
286 )->withRequired(
true);
288 return $f->switchableGroup(
289 [self::ANSWER_FIXATION_NONE => $group1, self::ANSWER_FIXATION_ON_IFB_OR_FUQST => $group2],
290 $lng->txt(
'tst_answer_fixation_handling')
292 ->withAdditionalTransformation($constraint)
293 ->withAdditionalTransformation($this->getTransformationLockAnswers(
$refinery))
294 ->withValue($this->getAnswerFixationSettingsAsFormValue())
295 ->withDisabled($environment[
'participant_data_exists']);
300 return $refinery->custom()->transformation(
301 static fn(?array $v): array => ($v[0] ??
null) === self::ANSWER_FIXATION_ON_IFB_OR_FUQST
303 : [
'lock_answer_on_instant_feedback' =>
false,
'lock_answer_on_next_question' =>
false]
312 function ($vs): bool {
313 if ($vs[
'shuffle_questions'] ===
true
314 && $vs[
'lock_answers'][
'lock_answer_on_next_question']) {
319 $lng->txt(
'tst_settings_conflict_shuffle_and_lock'),
326 'title_output' => [
'integer', $this->getQuestionTitleOutputMode()],
327 'autosave' => [
'integer', (
int) $this->getAutosaveEnabled()],
328 'autosave_ival' => [
'integer', $this->getAutosaveInterval()],
329 'shuffle_questions' => [
'integer', (
int) $this->getShuffleQuestions()],
330 'answer_feedback_points' => [
'integer', (
int) $this->getInstantFeedbackPointsEnabled()],
331 'answer_feedback' => [
'integer', (
int) $this->getInstantFeedbackGenericEnabled()],
332 'specific_feedback' => [
'integer', (
int) $this->getInstantFeedbackSpecificEnabled()],
333 'instant_verification' => [
'integer', (
int) $this->getInstantFeedbackSolutionEnabled()],
334 'force_inst_fb' => [
'integer', (
int) $this->getForceInstantFeedbackOnNextQuestion()],
335 'inst_fb_answer_fixation' => [
'integer', (
int) $this->getLockAnswerOnInstantFeedbackEnabled()],
336 'follow_qst_answer_fixation' => [
'integer', (
int) $this->getLockAnswerOnNextQuestionEnabled()]
343 switch ($this->getQuestionTitleOutputMode()) {
345 $log_array[AdditionalInformationGenerator::KEY_TEST_TITLE_PRESENTATION] = $additional_info
349 $log_array[AdditionalInformationGenerator::KEY_TEST_TITLE_PRESENTATION] = $additional_info
353 $log_array[AdditionalInformationGenerator::KEY_TEST_TITLE_PRESENTATION] = $additional_info
357 $log_array[AdditionalInformationGenerator::KEY_TEST_TITLE_PRESENTATION] = $additional_info
361 $log_array[AdditionalInformationGenerator::KEY_TEST_AUTOSAVE_ENABLED] = $this->getAutosaveEnabled()
363 $log_array[AdditionalInformationGenerator::KEY_TEST_SHUFFLE_QUESTIONS] = $additional_info
366 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_ENABLED] = $additional_info
368 if ($this->isAnyInstantFeedbackOptionEnabled()) {
369 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_SHOW_POINTS] = $additional_info
371 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_SHOW_GENERIC] = $additional_info
373 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_SHOW_SPECIFIC] = $additional_info
375 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_SHOW_SOLUTION] = $additional_info
377 $log_array[AdditionalInformationGenerator::KEY_TEST_FEEDBACK_TRIGGER] = $this->getForceInstantFeedbackOnNextQuestion()
379 : $additional_info->
getTagForLangVar(
'tst_instant_feedback_trigger_manual');
382 $lock_answers = $additional_info->
getTagForLangVar(
'tst_answer_fixation_none');
383 if ($this->getLockAnswerOnInstantFeedbackEnabled()
384 && $this->getLockAnswerOnNextQuestionEnabled()) {
385 $lock_answers = $additional_info->
getTagForLangVar(
'tst_answer_fixation_on_instantfb_or_followupqst');
386 } elseif ($this->getLockAnswerOnInstantFeedbackEnabled()) {
387 $lock_answers = $additional_info->
getTagForLangVar(
'tst_answer_fixation_on_instant_feedback');
388 } elseif ($this->getLockAnswerOnNextQuestionEnabled()) {
389 $lock_answers = $additional_info->
getTagForLangVar(
'tst_answer_fixation_on_followup_question');
391 $log_array[AdditionalInformationGenerator::KEY_TEST_LOCK_ANSWERS_MODE] = $lock_answers;
398 return $this->question_title_output_mode;
403 $clone = clone $this;
404 $clone->question_title_output_mode = $question_title_output_mode;
410 return $this->autosave_enabled;
415 $clone = clone $this;
416 $clone->autosave_enabled = $autosave_enabled;
422 return $this->autosave_interval;
427 $clone = clone $this;
428 $clone->autosave_interval = $autosave_interval;
434 return $this->shuffle_questions;
439 $clone = clone $this;
440 $clone->shuffle_questions = $shuffle_questions;
446 return $this->instant_feedback_points_enabled;
451 $clone = clone $this;
452 $clone->instant_feedback_points_enabled = $instant_feedback_points_enabled;
458 return $this->instant_feedback_generic_enabled;
463 $clone = clone $this;
464 $clone->instant_feedback_generic_enabled = $instant_feedback_generic_enabled;
470 return $this->instant_feedback_specific_enabled;
475 $clone = clone $this;
476 $clone->instant_feedback_specific_enabled = $instant_feedback_specific_enabled;
482 return $this->instant_feedback_solution_enabled;
487 $clone = clone $this;
488 $clone->instant_feedback_solution_enabled = $instant_feedback_solution_enabled;
494 return $this->getInstantFeedbackPointsEnabled()
495 || $this->getInstantFeedbackGenericEnabled()
496 || $this->getInstantFeedbackSpecificEnabled()
497 || $this->getInstantFeedbackSolutionEnabled();
502 return $this->force_instant_feedback_on_next_question;
507 $clone = clone $this;
508 $clone->force_instant_feedback_on_next_question = $force_instant_feedback_on_next_question;
514 return $this->lock_answer_on_instant_feedback;
519 $clone = clone $this;
520 $clone->lock_answer_on_instant_feedback = $lock_answer_on_instant_feedback;
526 return $this->lock_answer_on_next_question;
531 $clone = clone $this;
532 $clone->lock_answer_on_next_question = $lock_answer_on_next_question;
538 if ($this->getLockAnswerOnInstantFeedbackEnabled() || $this->getLockAnswerOnNextQuestionEnabled()) {
540 0 => self::ANSWER_FIXATION_ON_IFB_OR_FUQST,
542 'lock_answer_on_instant_feedback' => $this->getLockAnswerOnInstantFeedbackEnabled(),
543 'lock_answer_on_next_question' => $this->getLockAnswerOnNextQuestionEnabled()
548 return [0 => self::ANSWER_FIXATION_NONE, 1 => []];
getLockAnswerOnNextQuestionEnabled()
withLockAnswerOnNextQuestionEnabled(bool $lock_answer_on_next_question)
withInstantFeedbackGenericEnabled(bool $instant_feedback_generic_enabled)
getInstantFeedbackGenericEnabled()
withAutosaveInterval(int $autosave_interval)
withAutosaveEnabled(bool $autosave_enabled)
getQuestionTitleOutputMode()
__construct(int $test_id, protected int $question_title_output_mode, protected bool $autosave_enabled, protected int $autosave_interval, protected bool $shuffle_questions, protected bool $instant_feedback_points_enabled, protected bool $instant_feedback_generic_enabled, protected bool $instant_feedback_specific_enabled, protected bool $instant_feedback_solution_enabled, protected bool $force_instant_feedback_on_next_question, protected bool $lock_answer_on_instant_feedback, protected bool $lock_answer_on_next_question)
withLockAnswerOnInstantFeedbackEnabled(bool $lock_answer_on_instant_feedback)
const DEFAULT_AUTOSAVE_INTERVAL
getInputAutosave(\ilLanguage $lng, FieldFactory $f, Refinery $refinery)
withForceInstantFeedbackOnNextQuestion(bool $force_instant_feedback_on_next_question)
withInstantFeedbackSpecificEnabled(bool $instant_feedback_specific_enabled)
getInputInstantFeedback(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, array $environment)
getLockAnswerOnInstantFeedbackEnabled()
getInstantFeedbackPointsEnabled()
toForm(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, ?array $environment=null)
withInstantFeedbackPointsEnabled(bool $instant_feedback_points_enabled)
withShuffleQuestions(bool $shuffle_questions)
const ANSWER_FIXATION_NONE
getShuffleAndLockAnswersConstraint(\ilLanguage $lng, Refinery $refinery)
getInstantFeedbackSpecificEnabled()
withQuestionTitleOutputMode(int $question_title_output_mode)
toLog(AdditionalInformationGenerator $additional_info)
getInstantFeedbackSolutionEnabled()
isAnyInstantFeedbackOptionEnabled()
getSubInputInstantFeedback(\ilLanguage $lng, FieldFactory $f, array $environment)
getAnswerFixationSettingsAsFormValue()
getForceInstantFeedbackOnNextQuestion()
const ANSWER_FIXATION_ON_IFB_OR_FUQST
getInputLockAnswers(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, array $environment)
getTransformationLockAnswers(Refinery $refinery)
withInstantFeedbackSolutionEnabled(bool $instant_feedback_solution_enabled)
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
A constraint encodes some resrtictions on values.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if(!file_exists('../ilias.ini.php'))