ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
AdditionalInformationGenerator.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
25use ILIAS\UI\Factory as UIFactory;
26use ILIAS\UI\Component\Listing\Descriptive as DescriptiveListing;
28
30{
31 public const DATE_STORAGE_FORMAT = \DateTimeInterface::ISO8601;
32 public const KEY_USER = 'user';
33 public const KEY_USERS = 'users';
34 public const KEY_QUESTION_ID = 'id';
35 public const KEY_QUESTION_ORDER = 'order';
36 public const KEY_QUESTIONS = 'questions';
37 public const KEY_ANON_IDS = 'anonymous';
38
39 public const KEY_EVAL_FINALIZED = 'finalized_evaluation';
40 public const KEY_FEEDBACK = 'tst_feedback';
41 public const KEY_QUESTION_TITLE = 'question_title';
42 public const KEY_QUESTION_TEXT = 'tst_question';
43 public const KEY_QUESTION_TYPE = 'tst_question_type';
44 public const KEY_HOMOGENEOUS_SCORING = 'tst_inp_all_quest_points_equal_per_pool_desc';
45 public const KEY_QUESTION_AMOUNT_TYPE = 'tst_inp_quest_amount_cfg_mode';
46 public const KEY_QUESTION_AMOUNT_PER_TEST = 'tst_inp_quest_amount_per_test';
47 public const KEY_QUESTION_AMOUNT_PER_POOL = 'tst_inp_quest_amount_per_source_pool';
48 public const KEY_SOURCE_POOL = 'obj_qpl';
49 public const KEY_SOURCE_TAXONOMY_FILTER = 'tst_inp_source_pool_filter_tax';
50 public const KEY_SOURCE_TYPE_FILTER = 'tst_filter_question_type';
51 public const KEY_SOURCE_LIFECYCLE_FILTER = 'qst_lifecycle';
52 public const KEY_REACHED_POINTS = 'tst_reached_points';
53 public const KEY_MARK_SHORT_NAME = 'tst_mark_short_form';
54 public const KEY_MARK_OFFICIAL_NAME = 'tst_mark_official_form';
55 public const KEY_MARK_MINIMUM_LEVEL = 'tst_mark_minimum_level';
56 public const KEY_MARK_IS_PASSING = 'tst_mark_passed';
57
58 public const KEY_TEST_TITLE = 'title';
59 public const KEY_TEST_DESCRIPTION = 'description';
60 public const KEY_TEST_ONLINE = 'online';
61 public const KEY_TEST_QUESTION_SET_TYPE = 'test_question_set_type';
62 public const KEY_TEST_ANONYMITY = 'tst_anonymity';
63 public const KEY_TEST_INTRODUCTION_ENABLED = 'tst_introduction';
64 public const KEY_TEST_CONDITIONS_ENABLED = 'tst_conditions_checkbox_enabled';
65 public const KEY_TEST_START_TIME = 'tst_starting_time';
66 public const KEY_TEST_END_TIME = 'tst_ending_time';
67 public const KEY_TEST_PASSWORD = 'tst_password';
68 public const KEY_TEST_IP_RANGE = 'ip_range_label';
69 public const KEY_TEST_FIXED_PARTICIPANTS = 'participants_invitation';
70 public const KEY_TEST_LIMIT_NR_OF_TRIES = 'tst_limit_nr_of_tries';
71 public const KEY_TEST_BLOCK_AFTER_PASSED = 'tst_block_passes_after_passed';
72 public const KEY_TEST_PASSWAITING_ENABLED = 'tst_pass_waiting_enabled';
73 public const KEY_TEST_PROCESSING_TIME_ENABLED = 'tst_processing_time_duration';
74 public const KEY_TEST_RESET_PROCESSING_TIME = 'tst_reset_processing_time';
75 public const KEY_TEST_ADDED_PROCESSING_TIME = 'minutes';
76 public const KEY_TEST_KIOSK_ENABLED = 'kiosk';
77 public const KEY_TEST_KIOSK_SHOW_TITLE = 'kiosk_show_title';
78 public const KEY_TEST_KIOSK_SHOW_PARTICIPANT_NAME = 'kiosk_show_participant';
79 public const KEY_TEST_SHOW_EXAM_ID = 'examid_in_test_pass';
80 public const KEY_TEST_TITLE_PRESENTATION = 'tst_title_output';
81 public const KEY_TEST_AUTOSAVE_ENABLED = 'autosave';
82 public const KEY_TEST_SHUFFLE_QUESTIONS = 'tst_shuffle_questions';
83 public const KEY_TEST_FEEDBACK_ENABLED = 'tst_instant_feedback';
84 public const KEY_TEST_FEEDBACK_SHOW_POINTS = 'tst_instant_feedback_results';
85 public const KEY_TEST_FEEDBACK_SHOW_GENERIC = 'tst_instant_feedback_answer_generic';
86 public const KEY_TEST_FEEDBACK_SHOW_SPECIFIC = 'tst_instant_feedback_answer_specific';
87 public const KEY_TEST_FEEDBACK_SHOW_SOLUTION = 'tst_instant_feedback_solution';
88 public const KEY_TEST_FEEDBACK_TRIGGER = 'tst_instant_feedback_trigger';
89 public const KEY_TEST_LOCK_ANSWERS_MODE = 'tst_answer_fixation_handling';
90 public const KEY_TEST_USE_PREVIOUS_ANSWERS_ENABELD = 'tst_use_previous_answers';
91 public const KEY_TEST_SUSPEND_ALLOWED = 'tst_show_cancel';
92 public const KEY_TEST_POSTPONED_MOVE_TO_END = 'tst_postpone';
93 public const KEY_TEST_OVERVIEW_ENABLED = 'tst_show_summary';
94 public const KEY_TEST_OVERVIEW_SHOW_START = 'tst_list_of_questions_start';
95 public const KEY_TEST_OVERVIEW_SHOW_END = 'tst_list_of_questions_end';
96 public const KEY_TEST_OVERVIEW_SHOW_DESCRIPTION = 'tst_list_of_questions_with_description';
97 public const KEY_TEST_QUESTION_MARKING_ENABLED = 'question_marking';
98 public const KEY_TEST_QUESTION_LIST_ENABLED = 'tst_enable_questionlist';
99 public const KEY_TEST_ANSWER_OVERVIEW_ENABLED = 'enable_examview';
100 public const KEY_TEST_CONCLUDING_REMARKS_ENABLED = 'final_statement';
101 public const KEY_TEST_REDIRECT_MODE = 'redirect_after_finishing_tst';
102 public const KEY_TEST_REDIRECT_URL = 'redirection_url';
103 public const KEY_TEST_TAXONOMIES_ENABLED = 'tst_activate_skill_service';
104 public const KEY_TEST_HIDE_INFO_TAB = 'tst_hide_info_tab';
105
106 public const KEY_SCORING_COUNT_SYSTEM = 'tst_text_count_system';
107 public const KEY_SCORING_SCORE_CUTTING = 'tst_score_cutting';
108 public const KEY_SCORING_PASS_SCORING = 'tst_pass_scoring';
109 public const KEY_SCORING_REPORTING = 'tst_results_access_setting';
110 public const KEY_SCORING_REPORTING_SHOW_STATUS = 'tst_results_grading_opt_show_status';
111 public const KEY_SCORING_REPORTING_SHOW_MARK = 'tst_results_grading_opt_show_mark';
112 public const KEY_SCORING_REPORTING_SHOW_DETAILS = 'tst_results_grading_opt_show_details';
113 public const KEY_SCORING_DELETION_ALLOWED = 'tst_pass_deletion';
114 public const KEY_SCORING_SOLUTION_SHOW_BEST_SOLUTION = 'tst_results_print_best_solution';
115 public const KEY_SCORING_SOLUTION_SHOW_FEEDBACK = 'tst_show_solution_feedback';
116 public const KEY_SCORING_SOLUTION_SHOW_SUGGESTED = 'tst_show_solution_suggested';
117 public const KEY_SCORING_SOLUTION_SHOW_PRINTVIEW = 'tst_show_solution_printview';
118 public const KEY_SCORING_SOLUTION_SHOW_ANSWERS_ONLY = 'tst_hide_pagecontents';
119 public const KEY_SCORING_SOLUTION_SHOW_SIGNATRUE = 'tst_show_solution_signature';
120 public const KEY_SCORING_SOLUTION_SHOW_EXAM_ID = 'examid_in_test_res';
121 public const KEY_SCORING_HIGHSCORE_ENABLED = 'tst_highscore_enabled';
122 public const KEY_SCORING_HIGHSCORE_MODE = 'tst_highscore_mode';
123 public const KEY_SCORING_HIGHSCORE_SHOW_TOP_NUM = 'tst_highscore_top_num';
124 public const KEY_SCORING_HIGHSCORE_SHOW_ANON = 'tst_highscore_anon';
125 public const KEY_SCORING_HIGHSCORE_SHOW_ACHIEVED_TS = 'tst_highscore_achieved_ts';
126 public const KEY_SCORING_HIGHSCORE_SHOW_SCORE = 'tst_highscore_score';
127 public const KEY_SCORING_HIGHSCORE_SHOW_PERCENTAGE = 'tst_highscore_percentage';
128 public const KEY_SCORING_HIGHSCORE_SHOW_WTIME = 'tst_highscore_wtime';
129
130 public const KEY_PASS = 'pass';
131 public const KEY_PAX_ANSWER = 'answer';
132
133 public const KEY_QUESTION_SHUFFLE_ANSWER_OPTIONS = 'shuffle_answers';
134 public const KEY_QUESTION_FEEDBACK_ON_INCOMPLETE = 'feedback_incomplete_solution';
135 public const KEY_QUESTION_FEEDBACK_ON_COMPLETE = 'feedback_complete_solution';
136 public const KEY_QUESTION_ANSWER_OPTION = 'answer';
137 public const KEY_QUESTION_ANSWER_OPTIONS = 'answers';
138 public const KEY_QUESTION_CORRECT_ANSWER_OPTIONS = 'correct_answers';
139 public const KEY_QUESTION_LONGMENU_TEXT = 'lmtext';
140 public const KEY_QUESTION_KPRIM_OPTION_LABEL = 'option_label';
141 public const KEY_QUESTION_REACHABLE_POINTS = 'points';
142 public const KEY_QUESTION_TEXT_MATCHING_METHOD = 'matching_method';
143 public const KEY_QUESTION_FORMULA_VARIABLES = 'variables';
144 public const KEY_QUESTION_FORMULA_RESULTS = 'results';
145 public const KEY_QUESTION_FORMULA_VARIABLE = 'variable';
146 public const KEY_QUESTION_FORMULA_RESULT = 'result';
147 public const KEY_QUESTION_FORMULA_PRECISION = 'precision';
148 public const KEY_QUESTION_FORMULA_INTPRECISION = 'intprecision';
149 public const KEY_QUESTION_FORMULA_TOLERANCE = 'tolerance';
150 public const KEY_QUESTION_FORMULA_UNIT = 'unit';
151 public const KEY_QUESTION_FORMULA_RESULT_TYPE = 'result_type_selection';
152 public const KEY_QUESTION_FORMULA_FORMULA = 'formula';
153 public const KEY_QUESTION_ORDERING_NESTING_TYPE = 'qst_use_nested_answers';
154 public const KEY_QUESTION_ANSWER_OPTION_IMAGE = 'image';
155 public const KEY_QUESTION_ANSWER_OPTION_ORDER = 'order';
156 public const KEY_QUESTION_ANSWER_OPTION_CORRECTNESS = 'correctness';
157 public const KEY_QUESTION_POINTS_CHECKED = 'points_checked';
158 public const KEY_QUESTION_POINTS_UNCHECKED = 'points_unchecked';
159 public const KEY_QUESTION_IMAGEMAP_IMAGE = 'image';
160 public const KEY_QUESTION_IMAGEMAP_MODE = 'tst_imap_qst_mode';
161 public const KEY_QUESTION_IMAGEMAP_ANSWER_OPTION_COORDS = 'coordinates';
163 public const KEY_QUESTION_TEXTSIZE = 'textsize';
164 public const KEY_QUESTION_UPLOAD_MAXSIZE = 'maxsize';
165 public const KEY_QUESTION_UPLOAD_ALLOWED_EXTENSIONS = 'allowedextensions';
166 public const KEY_QUESTION_UPLOAD_COMPLETION_BY_SUBMISSION = 'ass_completion_by_submission';
167 public const KEY_QUESTION_ERRORTEXT_ERRORTEXT = 'assErrorText';
168 public const KEY_QUESTION_MAXCHARS = 'maxchars';
169 public const KEY_QUESTION_LOWER_LIMIT = 'range_lower_limit';
170 public const KEY_QUESTION_UPPER_LIMIT = 'range_upper_limit';
171 public const KEY_QUESTION_MATCHING_TERM = 'term';
172 public const KEY_QUESTION_MATCHING_TERMS = 'terms';
173 public const KEY_QUESTION_MATCHING_DEFINITION = 'definition';
174 public const KEY_QUESTION_MATCHING_DEFINITIONS = 'definitions';
175 public const KEY_QUESTION_CLOZE_CLOZETEXT = 'cloze_text';
176 public const KEY_QUESTION_CLOZE_GAPS = 'gaps';
177 public const KEY_QUESTION_CLOZE_GAP_TYPE = 'type';
178 public const KEY_QUESTION_KPRIM_SCORE_PARTIAL_SOLUTION_ENABLED = 'score_partsol_enabled';
179 public const KEY_QUESTION_TEXT_WORDCOUNT_ENABLED = 'qst_essay_wordcounter_enabled';
180 public const KEY_QUESTION_TEXT_SCORING_MODE = 'essay_scoring_mode';
181
182 private const TAG_NONE = '{{ none }}';
183 private const TAG_TRUE = '{{ true }}';
184 private const TAG_FALSE = '{{ false }}';
185 private const TAG_ENABLED = '{{ enabled }}';
186 private const TAG_DISABLED = '{{ disabled }}';
187 private const TAG_CHECKED = '{{ checked }}';
188 private const TAG_UNCHECKED = '{{ unchecked }}';
189
190 private const VALID_TAGS = [
191 'none',
192 'enabled',
193 'disabled',
194 'true',
195 'false',
196 'checked',
197 'unchecked',
198 'seconds',
199 'redirect_always',
200 'gap',
201 'points',
202 'type',
203 'answers_select',
204 'answers_text_box',
205 'test_question_set_type_fixed',
206 'tst_title_output_full',
207 'tst_title_output_hide_points',
208 'tst_title_output_no_title',
209 'tst_title_output_only_points',
210 'tst_instant_feedback_trigger_forced',
211 'tst_instant_feedback_trigger_manual',
212 'tst_answer_fixation_none',
213 'tst_answer_fixation_on_instantfb_or_followupqst',
214 'tst_answer_fixation_on_instant_feedback',
215 'tst_answer_fixation_on_followup_question',
216 'tst_highscore_own_table',
217 'tst_highscore_top_table',
218 'tst_highscore_all_tables',
219 'tst_results_access_setting',
220 'tst_results_access_finished',
221 'tst_results_access_always',
222 'tst_results_access_setting',
223 'tst_results_access_passed',
224 'tst_count_partial_solutions',
225 'tst_count_correct_solutions',
226 'tst_score_cut_question',
227 'tst_score_cut_test',
228 'tst_pass_last_pass',
229 'tst_pass_best_pass',
230 'tst_inp_quest_amount_cfg_mode_pool',
231 'tst_imap_qst_mode_mc',
232 'tst_imap_qst_mode_sc',
233 'option_label_right_wrong',
234 'option_label_plus_minus',
235 'option_label_applicable_or_not',
236 'option_label_adequate_or_not',
237 'option_label_custom',
238 'qpl_qst_inp_matching_mode_one_on_one',
239 'qpl_qst_inp_matching_mode_all_on_all',
240 'essay_scoring_mode_without_keywords',
241 'essay_scoring_mode_keyword_relation_any',
242 'essay_scoring_mode_keyword_relation_all',
243 'essay_scoring_mode_keyword_relation_one',
244 'qst_nested_nested_answers_off',
245 'qst_nested_nested_answers_on',
246 'oq_btn_use_order_pictures',
247 'oq_btn_use_order_terms',
248 ];
249
254 private const LEGACY_TAGS = [];
255
256 private array $tags;
257
258 public function __construct(
259 private readonly TemplateEngineInterface $template_engine,
260 private readonly \ilLanguage $lng,
261 private readonly UIFactory $ui_factory,
262 private readonly Refinery $refinery,
263 private readonly GeneralQuestionPropertiesRepository $questions_repo
264 ) {
265 $lng->loadLanguageModule('assessment');
266 $lng->loadLanguageModule('crs');
267 $this->tags = $this->buildTags();
268 }
269
270 public function parseForTable(
271 array $additional_info,
272 array $environment
273 ): DescriptiveListing {
281 return $this->ui_factory->listing()->descriptive(
282 array_combine(
283 array_map(
284 fn(string $k): string => $this->getCorrectedTranslationForKey($k) . ' ',
285 array_keys($additional_info)
286 ),
287 array_map(
288 fn(string $k): string => $this->parseValue($k, $additional_info[$k], $environment),
289 array_keys($additional_info)
290 )
291 )
292 );
293 }
294
295 public function parseForExport(
296 array $additional_info,
297 array $environment
298 ): string {
299 return implode(
300 '; ',
301 array_map(
302 fn(string $k) => "{$this->getCorrectedTranslationForKey($k)}: {$this->parseValue($k, $additional_info[$k] ?? '', $environment)}",
303 array_keys($additional_info)
304 )
305 );
306 }
307
308 public function getTrueFalseTagForBool(bool $bool): string
309 {
310 return $bool ? self::TAG_TRUE : self::TAG_FALSE;
311 }
312
313 public function getEnabledDisabledTagForBool(bool $bool): string
314 {
315 return $bool ? self::TAG_ENABLED : self::TAG_DISABLED;
316 }
317
318 public function getCheckedUncheckedTagForBool(bool $bool): string
319 {
320 return $bool ? self::TAG_CHECKED : self::TAG_UNCHECKED;
321 }
322
323 public function getNoneTag(): string
324 {
325 return self::TAG_NONE;
326 }
327
328 public function getTagForLangVar(string $lang_var): string
329 {
330 return "{{ {$lang_var} }}";
331 }
332
333 private function getCorrectedTranslationForKey(string $key): string
334 {
335 $lang_var = $key;
336 if (array_key_exists($key, self::LEGACY_TAGS)) {
337 $lang_var = self::LEGACY_TAGS[$key];
338 }
339
340 return $this->lng->exists($lang_var) ? $this->lng->txt($lang_var) : $key;
341 }
342
343 private function parseValue(
344 int|string $key,
345 string|int|float|array $value,
346 array $environment
347 ): string {
348 switch ($key) {
349 case self::KEY_USER:
350 return \ilUserUtil::getNamePresentation(
351 $value,
352 false,
353 false,
354 '',
355 true
356 );
357 case self::KEY_USERS:
358 return $this->buildListOfUsers($value);
359 case self::KEY_QUESTION_TYPE:
360 return $this->lng->txt($value);
361 case self::KEY_QUESTIONS:
362 return implode(
363 ', ',
364 array_map(
365 fn(int $usr): string => $this->questions_repo
366 ->getForQuestionId($usr)?->getTitle() ?? $this->lng->txt('deleted'),
367 $value
368 )
369 );
370 case self::KEY_QUESTION_ID:
371 if (is_int($value)) {
372 return $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
373 $this->questions_repo->getForQuestionId($value)?->getTitle() ?? $this->lng->txt('deleted')
374 );
375 }
376 //no break
377 default:
378 return $this->buildDefaultValueString($value, $environment);
379 }
380 }
381
382 private function buildListOfUsers(array $user_ids): string
383 {
384 return implode(
385 ', ',
386 array_map(
387 static fn(int $usr): string => \ilUserUtil::getNamePresentation(
388 $usr,
389 false,
390 false,
391 '',
392 true
393 ),
394 $user_ids
395 )
396 );
397 }
398
399 private function buildDefaultValueString(
400 string|int|float|array $value,
401 array $environment
402 ): string {
403 if (is_int($value)
404 || is_float($value)) {
405 return (string) $value;
406 }
407 if (is_array($value)) {
408 return $this->buildValueStringFromArray($value, $environment);
409 }
410 if ($value === '') {
411 return $this->lng->txt('none');
412 }
413 if (strpos($value, '+0000') !== false
414 && ($date = \DateTimeImmutable::createFromFormat(self::DATE_STORAGE_FORMAT, $value)) !== false) {
415 return $date
416 ->setTimezone($environment['timezone'])
417 ->format($environment['date_format']);
418 }
419 return $this->template_engine->render(
420 $this->refinery->string()->stripTags()->transform($value),
421 $this->tags
422 );
423 }
424
425 private function buildValueStringFromArray(array $value, array $environment): string
426 {
427 return array_reduce(
428 array_keys($value),
429 function ($c, $k) use ($value, $environment): string {
430 $label = $k;
431 if (is_string($k)) {
432 $label = $this->getCorrectedTranslationForKey($k);
433 }
434 if ($c !== '') {
435 $c .= ', ';
436 }
437 return "{$c}{$label}: {$this->parseValue($k, $value[$k], $environment)}";
438 },
439 ''
440 );
441 }
442
443 private function buildTags(): array
444 {
445 return array_combine(
446 self::VALID_TAGS,
447 array_map(
448 fn(string $v): string => $this->lng->txt($v),
449 self::VALID_TAGS
450 )
451 ) + array_reduce(
452 array_keys(self::LEGACY_TAGS),
453 function (array $c, string $k): array {
454 $c[$k] = $this->lng->txt(self::LEGACY_TAGS[$k]);
455 return $c;
456 },
457 []
458 );
459 }
460}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
buildDefaultValueString(string|int|float|array $value, array $environment)
parseForTable(array $additional_info, array $environment)
parseForExport(array $additional_info, array $environment)
__construct(private readonly TemplateEngineInterface $template_engine, private readonly \ilLanguage $lng, private readonly UIFactory $ui_factory, private readonly Refinery $refinery, private readonly GeneralQuestionPropertiesRepository $questions_repo)
parseValue(int|string $key, string|int|float|array $value, array $environment)
language handling
static getNamePresentation( $a_user_id, bool $a_user_image=false, bool $a_profile_link=false, string $a_profile_back_link='', bool $a_force_first_lastname=false, bool $a_omit_login=false, bool $a_sortable=true, bool $a_return_data_array=false, $a_ctrl_path=null)
Default behaviour is:
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface for template engine functionality used in Mail and related components.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $lng
Definition: privfeed.php:31
if(!file_exists('../ilias.ini.php'))