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