ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
SettingsTestBehaviour.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
28use ILIAS\Refinery\Factory as Refinery;
29
31{
33
34 public function __construct(
35 protected int $number_of_tries = 0,
36 protected bool $block_after_passed_enabled = false,
37 protected ?string $pass_waiting = null,
38 protected bool $processing_time_enabled = false,
39 protected ?string $processing_time = null,
40 protected bool $reset_processing_time = false,
41 protected int $kiosk_mode = 0,
42 protected bool $examid_in_test_attempt_enabled = false
43 ) {
44 $this->pass_waiting = $this->cleanupPassWaiting($this->pass_waiting);
46 }
47
48 public function toForm(
50 FieldFactory $f,
52 ?array $environment = null
53 ): FormInput {
54 $inputs['limit_attempts'] = $this->getInputLimitAttempts(
55 $lng,
56 $f,
58 $environment
59 );
60 $inputs['force_waiting_between_attempts'] = $this->getInputForceWaitingBetweenAttempts(
61 $lng,
62 $f,
64 $environment
65 );
66 $inputs['time_limit_for_completion'] = $this->getInputTimeLimitForCompletion(
67 $lng,
68 $f,
70 $environment
71 );
72 $inputs['kiosk_mode'] = $this->getInputKioskMode($lng, $f, $refinery);
73
74 $inputs['show_exam_id'] = $f->checkbox(
75 $lng->txt('examid_in_test_pass'),
76 $lng->txt('examid_in_test_pass_desc')
77 )->withValue($this->getExamIdInTestAttemptEnabled());
78
79 return $f->section($inputs, $lng->txt('tst_settings_header_test_run'));
80 }
81
82 private function getInputLimitAttempts(
84 FieldFactory $f,
86 array $environment
87 ): FormInput {
88 $trafo = $refinery->custom()->transformation(
89 static function (?array $vs): array {
90 if ($vs === null) {
91 return [
92 'number_of_available_attempts' => 0,
93 'block_after_passed' => false
94 ];
95 }
96
97 return $vs;
98 }
99 );
100
101 $sub_inputs['number_of_available_attempts'] = $f->numeric($lng->txt('tst_nr_of_tries'));
102 $sub_inputs['block_after_passed'] = $f->checkbox(
103 $lng->txt('tst_block_passes_after_passed'),
104 $lng->txt('tst_block_passes_after_passed_info')
105 );
106
107 if (!$environment['participant_data_exists']) {
108 $sub_inputs['number_of_available_attempts'] =
109 $sub_inputs['number_of_available_attempts']->withRequired(true)
110 ->withAdditionalTransformation($refinery->int()->isGreaterThan(0));
111 }
112
113 $limit_attempts = $f->optionalGroup(
114 $sub_inputs,
115 $lng->txt('tst_limit_nr_of_tries'),
116 $lng->txt('tst_nr_of_tries_desc')
117 )->withValue(null)
118 ->withAdditionalTransformation($trafo);
119
120 if ($this->getNumberOfTries() > 0) {
121 $limit_attempts = $limit_attempts->withValue(
122 [
123 'number_of_available_attempts' => $this->getNumberOfTries(),
124 'block_after_passed' => $this->getBlockAfterPassedEnabled()
125 ]
126 );
127 }
128
129 if (!$environment['participant_data_exists']) {
130 return $limit_attempts;
131 }
132
133 return $limit_attempts->withDisabled(true);
134 }
135
138 FieldFactory $f,
140 array $environment
141 ): FormInput {
142 $constraint = $refinery->custom()->constraint(
143 static function (?string $vs): bool {
144 return $vs !== '0:0:0';
145 },
146 sprintf($lng->txt('not_greater_than'), $lng->txt('tst_pass_waiting_time'), 0)
147 );
148
149 $trafo = $refinery->custom()->transformation(
150 static function (?array $vs): ?string {
151 return $vs === null ? null : implode(':', $vs);
152 }
153 );
154
155 $force_waiting_between_attempts = $f->optionalGroup(
156 $this->getSubInputsForceWaitingBetweenAttempts($lng, $f, $refinery, ),
157 $lng->txt('tst_pass_waiting_enabled'),
158 $lng->txt('tst_pass_waiting_info')
159 )->withValue(null)
160 ->withAdditionalTransformation($trafo);
161
162 if ($this->getPassWaitingEnabled()) {
163 list($days, $hours, $minutes) = explode(':', $this->getPassWaiting());
164 $force_waiting_between_attempts = $force_waiting_between_attempts->withValue(
165 [
166 'days' => $days,
167 'hours' => $hours,
168 'minutes' => $minutes
169 ]
170 );
171 }
172
173 if (!$environment['participant_data_exists']) {
174 return $force_waiting_between_attempts->withAdditionalTransformation($constraint);
175 }
176
177 return $force_waiting_between_attempts->withDisabled(true);
178 }
179
182 FieldFactory $f,
184 ): array {
185 $sub_inputs_force_waiting_between_attempts['days'] = $f->numeric($lng->txt('days'))
186 ->withAdditionalTransformation($refinery->int()->isGreaterThanOrEqual(0))
187 ->withRequired(true)
188 ->withValue(0);
189 $sub_inputs_force_waiting_between_attempts['hours'] = $f->numeric($lng->txt('hours'))
190 ->withAdditionalTransformation($refinery->int()->isGreaterThanOrEqual(0))
191 ->withAdditionalTransformation($refinery->int()->isLessThanOrEqual(24))
192 ->withRequired(true)
193 ->withValue(0);
194 $sub_inputs_force_waiting_between_attempts['minutes'] = $f->numeric($lng->txt('minutes'))
195 ->withAdditionalTransformation($refinery->int()->isGreaterThanOrEqual(0))
196 ->withAdditionalTransformation($refinery->int()->isLessThanOrEqual(60))
197 ->withRequired(true)
198 ->withValue(0);
199
200 return $sub_inputs_force_waiting_between_attempts;
201 }
202
203 private function cleanupPassWaiting(?string $pass_waiting): ?string
204 {
205 if ($pass_waiting === null || $pass_waiting === '') {
206 return null;
207 }
208
209 $pass_waiting_array = array_map(
210 fn(string $v) => strval((int) $v),
211 explode(':', $pass_waiting)
212 );
213 if (count($pass_waiting_array) === 3) {
214 return implode(':', $pass_waiting_array);
215 }
216
217 $month = array_shift($pass_waiting_array);
218 $pass_waiting_array[0] = strval((int) $pass_waiting_array[0] + (int) $month * 31);
219 return implode(':', $pass_waiting_array);
220 }
221
224 FieldFactory $f,
226 array $environment
227 ): FormInput {
228 $trafo = $refinery->custom()->transformation(
229 static function (?array $vs): array {
230 if ($vs === null) {
231 return [
232 'processing_time_limit' => false,
233 'time_limit_for_completion_value' => null,
234 'reset_time_limit_for_completion_by_attempt' => false
235 ];
236 }
237
238 $vs['processing_time_limit'] = true;
239 $vs['time_limit_for_completion_value'] = sprintf(
240 '%02d:%02d:00',
241 floor(
242 $vs['time_limit_for_completion_value'] / 60
243 ),
244 $vs['time_limit_for_completion_value'] % 60
245 );
246 return $vs;
247 }
248 );
249
250 $sub_inputs_time_limit_for_completion['time_limit_for_completion_value'] = $f
251 ->numeric(
252 $lng->txt('tst_processing_time_duration')
253 )
254 ->withRequired(true)
255 ->withAdditionalTransformation($refinery->int()->isGreaterThan(0))
256 ->withValue(self::DEFAULT_PROCESSING_TIME_MINUTES);
257 $sub_inputs_time_limit_for_completion['reset_time_limit_for_completion_by_attempt'] = $f->checkbox(
258 $lng->txt('tst_reset_processing_time'),
259 $lng->txt('tst_reset_processing_time_desc')
260 );
261
262 $time_limit_for_completion = $f->optionalGroup(
263 $sub_inputs_time_limit_for_completion,
264 $lng->txt('tst_processing_time'),
265 $lng->txt('tst_processing_time_desc')
266 )->withValue(null)
267 ->withAdditionalTransformation($trafo);
268
269 if ($this->getProcessingTimeEnabled()) {
270 $time_limit_for_completion = $time_limit_for_completion->withValue(
271 [
272 'time_limit_for_completion_value' => (int) $this->getProcessingTimeAsMinutes(),
273 'reset_time_limit_for_completion_by_attempt' => (bool) $this->getResetProcessingTime()
274 ]
275 );
276 }
277
278 if (!$environment['participant_data_exists']) {
279 return $time_limit_for_completion;
280 }
281
282 return $time_limit_for_completion->withDisabled(true);
283 }
284
285 private function getInputKioskMode(
287 FieldFactory $f,
289 ): FormInput {
290 $trafo = $refinery->custom()->transformation(
291 static function (?array $vs): ?int {
292 if ($vs === null) {
293 return 0;
294 }
295
296 $kiosk_mode = 1;
297
298 if ($vs['show_title'] === true) {
299 $kiosk_mode += 2;
300 }
301
302 if ($vs['show_participant_name'] === true) {
303 $kiosk_mode += 4;
304 }
305
306 return $kiosk_mode;
307 }
308 );
309
310 $sub_inputs_kiosk_mode['show_title'] = $f->checkbox($lng->txt('kiosk_show_title'));
311
312 $sub_inputs_kiosk_mode['show_participant_name'] = $f->checkbox($lng->txt('kiosk_show_participant'));
313
314 $kiosk_mode = $f->optionalGroup(
315 $sub_inputs_kiosk_mode,
316 $lng->txt('kiosk'),
317 $lng->txt('kiosk_description')
318 )->withValue(null)
319 ->withAdditionalTransformation($trafo);
320
321 if (!$this->getKioskMode()) {
322 return $kiosk_mode;
323 }
324
325 return $kiosk_mode->withValue([
326 'show_title' => $this->getShowTitleInKioskMode(),
327 'show_participant_name' => $this->getShowParticipantNameInKioskMode()
328 ]);
329 }
330
331 public function toStorage(): array
332 {
333 return [
334 'nr_of_tries' => ['integer', $this->getNumberOfTries()],
335 'block_after_passed' => ['integer', (int) $this->getBlockAfterPassedEnabled()],
336 'pass_waiting' => ['string', $this->getPassWaiting()],
337 'enable_processing_time' => ['integer', (int) $this->getProcessingTimeEnabled()],
338 'processing_time' => ['string', $this->getProcessingTime()],
339 'reset_processing_time' => ['integer', (int) $this->getResetProcessingTime()],
340 'kiosk' => ['integer', $this->getKioskMode()],
341 'examid_in_test_pass' => ['integer', (int) $this->getExamIdInTestAttemptEnabled()]
342 ];
343 }
344
345 public function toLog(AdditionalInformationGenerator $additional_info): array
346 {
347 $log_array[AdditionalInformationGenerator::KEY_TEST_LIMIT_NR_OF_TRIES] = $this->getNumberOfTries() > 0
348 ? $this->getNumberOfTries() : $additional_info->getEnabledDisabledTagForBool(false);
349 if ($this->getNumberOfTries() > 0) {
350 $log_array[AdditionalInformationGenerator::KEY_TEST_BLOCK_AFTER_PASSED] = $additional_info
351 ->getEnabledDisabledTagForBool($this->getBlockAfterPassedEnabled());
352 }
353
354 $log_array[AdditionalInformationGenerator::KEY_TEST_PASSWAITING_ENABLED] = $this->getPassWaitingEnabled()
355 ? $this->getPassWaiting() : $additional_info->getEnabledDisabledTagForBool(false);
356
357 $log_array[AdditionalInformationGenerator::KEY_TEST_PROCESSING_TIME_ENABLED] = $this->getProcessingTimeEnabled()
358 ? $this->getProcessingTimeAsMinutes() : $additional_info->getEnabledDisabledTagForBool(false);
359 if ($this->getProcessingTimeEnabled()) {
360 $log_array[AdditionalInformationGenerator::KEY_TEST_RESET_PROCESSING_TIME] = $additional_info
361 ->getEnabledDisabledTagForBool($this->getResetProcessingTime());
362 }
363
364 $log_array[AdditionalInformationGenerator::KEY_TEST_KIOSK_ENABLED] = $additional_info
365 ->getEnabledDisabledTagForBool($this->getKioskModeEnabled());
366 if ($this->getKioskModeEnabled()) {
367 $log_array[AdditionalInformationGenerator::KEY_TEST_KIOSK_SHOW_TITLE] = $additional_info
368 ->getEnabledDisabledTagForBool($this->getShowTitleInKioskMode());
369 $log_array[AdditionalInformationGenerator::KEY_TEST_KIOSK_SHOW_PARTICIPANT_NAME] = $additional_info
370 ->getEnabledDisabledTagForBool($this->getShowParticipantNameInKioskMode());
371 }
372
373 $log_array[AdditionalInformationGenerator::KEY_TEST_SHOW_EXAM_ID] = $additional_info
374 ->getEnabledDisabledTagForBool($this->getExamIdInTestAttemptEnabled());
375 return $log_array;
376 }
377
378 public function getNumberOfTries(): int
379 {
380 return $this->number_of_tries;
381 }
382
383 public function withNumberOfTries(int $number_of_tries): self
384 {
385 $clone = clone $this;
386 $clone->number_of_tries = $number_of_tries;
387 return $clone;
388 }
389
390 public function getBlockAfterPassedEnabled(): bool
391 {
392 return $this->block_after_passed_enabled;
393 }
394
395 public function withBlockAfterPassedEnabled(bool $block_after_passed_enabled): self
396 {
397 $clone = clone $this;
398 $clone->block_after_passed_enabled = $block_after_passed_enabled;
399 return $clone;
400 }
401
402 public function getPassWaiting(): ?string
403 {
404 return $this->pass_waiting;
405 }
406
407 public function withPassWaiting(?string $pass_waiting): self
408 {
409 $clone = clone $this;
410 $clone->pass_waiting = $this->cleanupPassWaiting($pass_waiting);
411 return $clone;
412 }
413
414 public function getPassWaitingEnabled(): bool
415 {
416 if ($this->pass_waiting === null) {
417 return false;
418 }
419 if (array_sum(explode(':', $this->pass_waiting)) > 0) {
420 return true;
421 }
422 return false;
423 }
424
425 public function getProcessingTimeEnabled(): bool
426 {
427 return $this->processing_time_enabled;
428 }
429
430 public function withProcessingTimeEnabled(bool $processing_time_enabled): self
431 {
432 $clone = clone $this;
433 $clone->processing_time_enabled = $processing_time_enabled;
434 return $clone;
435 }
436
437 public function getProcessingTime(): ?string
438 {
439 return $this->processing_time;
440 }
441
442 public function withProcessingTime(?string $processing_time): self
443 {
444 $clone = clone $this;
445 $clone->processing_time = $processing_time;
446 return $clone;
447 }
448
450 {
451 if ($this->processing_time !== null && preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches)) {
452 return ((int) $matches[1] * 60) + (int) $matches[2];
453 }
454
455 return self::DEFAULT_PROCESSING_TIME_MINUTES;
456 }
457
458 public function getResetProcessingTime(): bool
459 {
460 return $this->reset_processing_time;
461 }
462
463 public function withResetProcessingTime(bool $reset_processing_time): self
464 {
465 $clone = clone $this;
466 $clone->reset_processing_time = $reset_processing_time;
467 return $clone;
468 }
469
470 public function getKioskMode(): int
471 {
472 return $this->kiosk_mode;
473 }
474
475 public function withKioskMode(int $kiosk_mode): self
476 {
477 $clone = clone $this;
478 $clone->kiosk_mode = $kiosk_mode;
479 return $clone;
480 }
481
482 public function getKioskModeEnabled(): bool
483 {
484 return ($this->kiosk_mode & 1) > 0;
485 }
486
487 public function getShowTitleInKioskMode(): bool
488 {
489 return ($this->kiosk_mode & 2) > 0;
490 }
491
492 public function getShowParticipantNameInKioskMode(): bool
493 {
494 return ($this->kiosk_mode & 4) > 0;
495 }
496
497 public function getExamIdInTestAttemptEnabled(): bool
498 {
499 return $this->examid_in_test_attempt_enabled;
500 }
501
502 public function withExamIdInTestAttemptEnabled(bool $exam_id_in_test_pass_enabled): self
503 {
504 $clone = clone $this;
505 $clone->examid_in_test_attempt_enabled = $exam_id_in_test_pass_enabled;
506 return $clone;
507 }
508
509 public function toExport(): array
510 {
511 return [
512 'nr_of_tries' => $this->getNumberOfTries(),
513 'block_after_passed' => $this->getBlockAfterPassedEnabled(),
514 'pass_waiting' => $this->getPassWaiting(),
515 'enable_processing_time' => $this->getProcessingTimeEnabled(),
516 'processing_time' => $this->getProcessingTime(),
517 'reset_processing_time' => $this->getResetProcessingTime(),
518 'kiosk_mode' => $this->getKioskMode(),
519 'examid_in_test_pass' => $this->getExamIdInTestAttemptEnabled()
520 ];
521 }
522
523 public static function fromExport(array $data): static
524 {
525 return new self(
526 (int) $data['nr_of_tries'],
527 (bool) $data['block_after_passed'],
528 $data['pass_waiting'],
529 (bool) $data['enable_processing_time'],
530 $data['processing_time'],
531 (bool) $data['reset_processing_time'],
532 (int) $data['kiosk_mode'],
533 (bool) $data['examid_in_test_pass']
534 );
535 }
536}
Builds data types.
Definition: Factory.php:36
__construct(protected int $number_of_tries=0, protected bool $block_after_passed_enabled=false, protected ?string $pass_waiting=null, protected bool $processing_time_enabled=false, protected ?string $processing_time=null, protected bool $reset_processing_time=false, protected int $kiosk_mode=0, protected bool $examid_in_test_attempt_enabled=false)
getInputForceWaitingBetweenAttempts(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, array $environment)
toForm(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, ?array $environment=null)
toExport()
Transform the object into a simple, associative array.
getInputTimeLimitForCompletion(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, array $environment)
withExamIdInTestAttemptEnabled(bool $exam_id_in_test_pass_enabled)
getSubInputsForceWaitingBetweenAttempts(\ilLanguage $lng, FieldFactory $f, Refinery $refinery)
static fromExport(array $data)
Creates an instance of the object from an array.
getInputLimitAttempts(\ilLanguage $lng, FieldFactory $f, Refinery $refinery, array $environment)
getInputKioskMode(\ilLanguage $lng, FieldFactory $f, Refinery $refinery)
toLog(AdditionalInformationGenerator $additional_info)
return true
language handling
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This interface allows an object to define its own transformation into a language-neutral,...
Definition: Exportable.php:40
This describes inputs that can be used in forms.
Definition: FormInput.php:33
This is what a factory for input fields looks like.
Definition: Factory.php:31
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
withAdditionalTransformation(Transformation $trafo)
@inheritDoc
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:61
global $lng
Definition: privfeed.php:31
if(!file_exists('../ilias.ini.php'))