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