ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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_MAIL_NOTIFICATION_CONTENT_TYPE = 'tst_finish_notification';
103 public const KEY_TEST_ALWAYS_SEND_NOTIFICATION = 'tst_finish_notification_content_type';
104 public const KEY_TEST_TAXONOMIES_ENABLED = 'tst_activate_skill_service';
105 public const KEY_TEST_HIDE_INFO_TAB = 'tst_hide_info_tab';
106
107 public const KEY_SCORING_COUNT_SYSTEM = 'tst_text_count_system';
108 public const KEY_SCORING_SCORE_CUTTING = 'tst_score_cutting';
109 public const KEY_SCORING_PASS_SCORING = 'tst_pass_scoring';
110 public const KEY_SCORING_REPORTING = 'tst_results_access_setting';
111 public const KEY_SCORING_REPORTING_SHOW_STATUS = 'tst_results_grading_opt_show_status';
112 public const KEY_SCORING_REPORTING_SHOW_MARK = 'tst_results_grading_opt_show_mark';
113 public const KEY_SCORING_REPORTING_SHOW_DETAILS = 'tst_results_grading_opt_show_details';
114 public const KEY_SCORING_DELETION_ALLOWED = 'tst_pass_deletion';
115 public const KEY_SCORING_SOLUTION_SHOW_BEST_SOLUTION = 'tst_results_print_best_solution';
116 public const KEY_SCORING_SOLUTION_SHOW_FEEDBACK = 'tst_show_solution_feedback';
117 public const KEY_SCORING_SOLUTION_SHOW_SUGGESTED = 'tst_show_solution_suggested';
118 public const KEY_SCORING_SOLUTION_SHOW_PRINTVIEW = 'tst_show_solution_printview';
119 public const KEY_SCORING_SOLUTION_SHOW_ANSWERS_ONLY = 'tst_hide_pagecontents';
120 public const KEY_SCORING_SOLUTION_SHOW_SIGNATRUE = 'tst_show_solution_signature';
121 public const KEY_SCORING_SOLUTION_SHOW_EXAM_ID = 'examid_in_test_res';
122 public const KEY_SCORING_HIGHSCORE_ENABLED = 'tst_highscore_enabled';
123 public const KEY_SCORING_HIGHSCORE_MODE = 'tst_highscore_mode';
124 public const KEY_SCORING_HIGHSCORE_SHOW_TOP_NUM = 'tst_highscore_top_num';
125 public const KEY_SCORING_HIGHSCORE_SHOW_ANON = 'tst_highscore_anon';
126 public const KEY_SCORING_HIGHSCORE_SHOW_ACHIEVED_TS = 'tst_highscore_achieved_ts';
127 public const KEY_SCORING_HIGHSCORE_SHOW_SCORE = 'tst_highscore_score';
128 public const KEY_SCORING_HIGHSCORE_SHOW_PERCENTAGE = 'tst_highscore_percentage';
129 public const KEY_SCORING_HIGHSCORE_SHOW_WTIME = 'tst_highscore_wtime';
130
131 public const KEY_PASS = 'pass';
132 public const KEY_PAX_ANSWER = 'answer';
133
134 public const KEY_QUESTION_SHUFFLE_ANSWER_OPTIONS = 'shuffle_answers';
135 public const KEY_QUESTION_FEEDBACK_ON_INCOMPLETE = 'feedback_incomplete_solution';
136 public const KEY_QUESTION_FEEDBACK_ON_COMPLETE = 'feedback_complete_solution';
137 public const KEY_QUESTION_ANSWER_OPTION = 'answer';
138 public const KEY_QUESTION_ANSWER_OPTIONS = 'answers';
139 public const KEY_QUESTION_CORRECT_ANSWER_OPTIONS = 'correct_answers';
140 public const KEY_QUESTION_LONGMENU_TEXT = 'lmtext';
141 public const KEY_QUESTION_KPRIM_OPTION_LABEL = 'option_label';
142 public const KEY_QUESTION_REACHABLE_POINTS = 'points';
143 public const KEY_QUESTION_TEXT_MATCHING_METHOD = 'matching_method';
144 public const KEY_QUESTION_FORMULA_VARIABLES = 'variables';
145 public const KEY_QUESTION_FORMULA_RESULTS = 'results';
146 public const KEY_QUESTION_FORMULA_VARIABLE = 'variable';
147 public const KEY_QUESTION_FORMULA_RESULT = 'result';
148 public const KEY_QUESTION_FORMULA_PRECISION = 'precision';
149 public const KEY_QUESTION_FORMULA_INTPRECISION = 'intprecision';
150 public const KEY_QUESTION_FORMULA_TOLERANCE = 'tolerance';
151 public const KEY_QUESTION_FORMULA_UNIT = 'unit';
152 public const KEY_QUESTION_FORMULA_RESULT_TYPE = 'result_type_selection';
153 public const KEY_QUESTION_FORMULA_FORMULA = 'formula';
154 public const KEY_QUESTION_ORDERING_NESTING_TYPE = 'qst_use_nested_answers';
155 public const KEY_QUESTION_ANSWER_OPTION_IMAGE = 'image';
156 public const KEY_QUESTION_ANSWER_OPTION_ORDER = 'order';
157 public const KEY_QUESTION_ANSWER_OPTION_CORRECTNESS = 'correctness';
158 public const KEY_QUESTION_POINTS_CHECKED = 'points_checked';
159 public const KEY_QUESTION_POINTS_UNCHECKED = 'points_unchecked';
160 public const KEY_QUESTION_IMAGEMAP_IMAGE = 'image';
161 public const KEY_QUESTION_IMAGEMAP_MODE = 'tst_imap_qst_mode';
162 public const KEY_QUESTION_IMAGEMAP_ANSWER_OPTION_COORDS = 'coordinates';
164 public const KEY_QUESTION_TEXTSIZE = 'textsize';
165 public const KEY_QUESTION_UPLOAD_MAXSIZE = 'maxsize';
166 public const KEY_QUESTION_UPLOAD_ALLOWED_EXTENSIONS = 'allowedextensions';
167 public const KEY_QUESTION_UPLOAD_COMPLETION_BY_SUBMISSION = 'ass_completion_by_submission';
168 public const KEY_QUESTION_ERRORTEXT_ERRORTEXT = 'assErrorText';
169 public const KEY_QUESTION_MAXCHARS = 'maxchars';
170 public const KEY_QUESTION_LOWER_LIMIT = 'range_lower_limit';
171 public const KEY_QUESTION_UPPER_LIMIT = 'range_upper_limit';
172 public const KEY_QUESTION_MATCHING_TERM = 'term';
173 public const KEY_QUESTION_MATCHING_TERMS = 'terms';
174 public const KEY_QUESTION_MATCHING_DEFINITION = 'definition';
175 public const KEY_QUESTION_MATCHING_DEFINITIONS = 'definitions';
176 public const KEY_QUESTION_CLOZE_CLOZETEXT = 'cloze_text';
177 public const KEY_QUESTION_CLOZE_GAPS = 'gaps';
178 public const KEY_QUESTION_CLOZE_GAP_TYPE = 'type';
179 public const KEY_QUESTION_KPRIM_SCORE_PARTIAL_SOLUTION_ENABLED = 'score_partsol_enabled';
180 public const KEY_QUESTION_TEXT_WORDCOUNT_ENABLED = 'qst_essay_wordcounter_enabled';
181 public const KEY_QUESTION_TEXT_SCORING_MODE = 'essay_scoring_mode';
182
183 private const TAG_NONE = '{{ none }}';
184 private const TAG_TRUE = '{{ true }}';
185 private const TAG_FALSE = '{{ false }}';
186 private const TAG_ENABLED = '{{ enabled }}';
187 private const TAG_DISABLED = '{{ disabled }}';
188 private const TAG_CHECKED = '{{ checked }}';
189 private const TAG_UNCHECKED = '{{ unchecked }}';
190
191 private const VALID_TAGS = [
192 'none',
193 'enabled',
194 'disabled',
195 'true',
196 'false',
197 'checked',
198 'unchecked',
199 'seconds',
200 'redirect_always',
201 'gap',
202 'points',
203 'type',
204 'answers_select',
205 'answers_text_box',
206 'tst_finish_notification_simple',
207 'tst_finish_notification_advanced',
208 'test_question_set_type_fixed',
209 'tst_title_output_full',
210 'tst_title_output_hide_points',
211 'tst_title_output_no_title',
212 'tst_title_output_only_points',
213 'tst_instant_feedback_trigger_forced',
214 'tst_instant_feedback_trigger_manual',
215 'tst_answer_fixation_none',
216 'tst_answer_fixation_on_instantfb_or_followupqst',
217 'tst_answer_fixation_on_instant_feedback',
218 'tst_answer_fixation_on_followup_question',
219 'tst_highscore_own_table',
220 'tst_highscore_top_table',
221 'tst_highscore_all_tables',
222 'tst_results_access_setting',
223 'tst_results_access_finished',
224 'tst_results_access_always',
225 'tst_results_access_setting',
226 'tst_results_access_passed',
227 'tst_count_partial_solutions',
228 'tst_count_correct_solutions',
229 'tst_score_cut_question',
230 'tst_score_cut_test',
231 'tst_pass_last_pass',
232 'tst_pass_best_pass',
233 'tst_inp_quest_amount_cfg_mode_pool',
234 'tst_imap_qst_mode_mc',
235 'tst_imap_qst_mode_sc',
236 'option_label_right_wrong',
237 'option_label_plus_minus',
238 'option_label_applicable_or_not',
239 'option_label_adequate_or_not',
240 'option_label_custom',
241 'qpl_qst_inp_matching_mode_one_on_one',
242 'qpl_qst_inp_matching_mode_all_on_all',
243 'essay_scoring_mode_without_keywords',
244 'essay_scoring_mode_keyword_relation_any',
245 'essay_scoring_mode_keyword_relation_all',
246 'essay_scoring_mode_keyword_relation_one',
247 'qst_nested_nested_answers_off',
248 'qst_nested_nested_answers_on',
249 'oq_btn_use_order_pictures',
250 'oq_btn_use_order_terms',
251 ];
252
257 private const LEGACY_TAGS = [];
258
259 private array $tags;
260
261 public function __construct(
262 private readonly \Mustache_Engine $mustache,
263 private readonly \ilLanguage $lng,
264 private readonly UIFactory $ui_factory,
265 private readonly Refinery $refinery,
266 private readonly GeneralQuestionPropertiesRepository $questions_repo
267 ) {
268 $lng->loadLanguageModule('assessment');
269 $lng->loadLanguageModule('crs');
270 $this->tags = $this->buildTags();
271 }
272
273 public function parseForTable(
274 array $additional_info,
275 array $environment
276 ): DescriptiveListing {
284 return $this->ui_factory->listing()->descriptive(
285 array_combine(
286 array_map(
287 fn(string $k): string => $this->getCorrectedTranslationForKey($k) . ' ',
288 array_keys($additional_info)
289 ),
290 array_map(
291 fn(string $k): string => $this->parseValue($k, $additional_info[$k], $environment),
292 array_keys($additional_info)
293 )
294 )
295 );
296 }
297
298 public function parseForExport(
299 array $additional_info,
300 array $environment
301 ): string {
302 return implode(
303 '; ',
304 array_map(
305 fn(string $k) => "{$this->getCorrectedTranslationForKey($k)}: {$this->parseValue($k, $additional_info[$k] ?? '', $environment)}",
306 array_keys($additional_info)
307 )
308 );
309 }
310
311 public function getTrueFalseTagForBool(bool $bool): string
312 {
313 return $bool ? self::TAG_TRUE : self::TAG_FALSE;
314 }
315
316 public function getEnabledDisabledTagForBool(bool $bool): string
317 {
318 return $bool ? self::TAG_ENABLED : self::TAG_DISABLED;
319 }
320
321 public function getCheckedUncheckedTagForBool(bool $bool): string
322 {
323 return $bool ? self::TAG_CHECKED : self::TAG_UNCHECKED;
324 }
325
326 public function getNoneTag(): string
327 {
328 return self::TAG_NONE;
329 }
330
331 public function getTagForLangVar(string $lang_var): string
332 {
333 return "{{ {$lang_var} }}";
334 }
335
336 private function getCorrectedTranslationForKey(string $key): string
337 {
338 $lang_var = $key;
339 if (array_key_exists($key, self::LEGACY_TAGS)) {
340 $lang_var = self::LEGACY_TAGS[$key];
341 }
342
343 return $this->lng->exists($lang_var) ? $this->lng->txt($lang_var) : $key;
344 }
345
346 private function parseValue(
347 int|string $key,
348 string|int|float|array $value,
349 array $environment
350 ): string {
351 switch ($key) {
352 case self::KEY_USER:
353 return \ilUserUtil::getNamePresentation(
354 $value,
355 false,
356 false,
357 '',
358 true
359 );
360 case self::KEY_USERS:
361 return $this->buildListOfUsers($value);
362 case self::KEY_QUESTION_TYPE:
363 return $this->lng->txt($value);
364 case self::KEY_QUESTIONS:
365 return implode(
366 ', ',
367 array_map(
368 fn(int $usr): string => $this->questions_repo
369 ->getForQuestionId($usr)?->getTitle() ?? $this->lng->txt('deleted'),
370 $value
371 )
372 );
373 case self::KEY_QUESTION_ID:
374 if (is_int($value)) {
375 return $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
376 $this->questions_repo->getForQuestionId($value)?->getTitle() ?? $this->lng->txt('deleted')
377 );
378 }
379 //no break
380 default:
381 return $this->buildDefaultValueString($value, $environment);
382 }
383 }
384
385 private function buildListOfUsers(array $user_ids): string
386 {
387 return implode(
388 ', ',
389 array_map(
390 static fn(int $usr): string => \ilUserUtil::getNamePresentation(
391 $usr,
392 false,
393 false,
394 '',
395 true
396 ),
397 $user_ids
398 )
399 );
400 }
401
402 private function buildDefaultValueString(
403 string|int|float|array $value,
404 array $environment
405 ): string {
406 if (is_int($value)
407 || is_float($value)) {
408 return (string) $value;
409 }
410 if (is_array($value)) {
411 return $this->buildValueStringFromArray($value, $environment);
412 }
413 if ($value === '') {
414 return $this->lng->txt('none');
415 }
416 if (strpos($value, '+0000') !== false
417 && ($date = \DateTimeImmutable::createFromFormat(self::DATE_STORAGE_FORMAT, $value)) !== false) {
418 return $date
419 ->setTimezone($environment['timezone'])
420 ->format($environment['date_format']);
421 }
422 return $this->mustache->render(
423 $this->refinery->string()->stripTags()->transform($value),
424 $this->tags
425 );
426 }
427
428 private function buildValueStringFromArray(array $value, array $environment): string
429 {
430 return array_reduce(
431 array_keys($value),
432 function ($c, $k) use ($value, $environment): string {
433 $label = $k;
434 if (is_string($k)) {
435 $label = $this->getCorrectedTranslationForKey($k);
436 }
437 if ($c !== '') {
438 $c .= ', ';
439 }
440 return "{$c}{$label}: {$this->parseValue($k, $value[$k], $environment)}";
441 },
442 ''
443 );
444 }
445
446 private function buildTags(): array
447 {
448 return array_combine(
449 self::VALID_TAGS,
450 array_map(
451 fn(string $v): string => $this->lng->txt($v),
452 self::VALID_TAGS
453 )
454 ) + array_reduce(
455 array_keys(self::LEGACY_TAGS),
456 function (array $c, string $k): array {
457 $c[$k] = $this->lng->txt(self::LEGACY_TAGS[$k]);
458 return $c;
459 },
460 []
461 );
462 }
463}
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'))