ILIAS  trunk Revision v11.0_alpha-1753-gb21ca8c4367
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilTestQuestionNavigationGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
26 
34 {
35  public const SHOW_DISABLED_COMMANDS = false;
36 
37  public const CSS_CLASS_SUBMIT_BUTTONS = 'ilc_qsubmit_Submit';
38  private \ILIAS\DI\UIServices $ui;
39 
40  private string $edit_solution_command = '';
41  private bool $question_worked_through = false;
42  private string $revert_changes_link_target = '';
43  private bool $discard_solution_button_enabled = false;
44  private string $skip_question_link_target = '';
45  private string $instant_feedback_command = '';
46  private bool $answer_freezing_enabled = false;
47  private bool $force_instant_response_enabled = false;
48  private string $request_hint_command = '';
49  private string $show_hints_command = '';
50  private bool $hint_requests_exist = false;
51  private string $question_mark_link_target = '';
52  private bool $question_marked = false;
53  private bool $anything_rendered = false;
55 
56  public function __construct(
57  protected ilLanguage $lng,
58  protected UIFactory $ui_factory,
59  protected UIRenderer $ui_renderer
60  ) {
61  }
62 
63  public function setEditSolutionCommand(string $edit_solution_command): void
64  {
65  $this->edit_solution_command = $edit_solution_command;
66  }
67 
68  public function setQuestionWorkedThrough(bool $question_worked_through): void
69  {
70  $this->question_worked_through = $question_worked_through;
71  }
72 
73  public function setRevertChangesLinkTarget(string $revert_changes_link_target): void
74  {
75  $this->revert_changes_link_target = $revert_changes_link_target;
76  }
77 
78  public function setDiscardSolutionButtonEnabled(bool $discard_solution_button_enabled): void
79  {
80  $this->discard_solution_button_enabled = $discard_solution_button_enabled;
81  }
82 
83  public function setSkipQuestionLinkTarget(string $skip_question_link_target): void
84  {
85  $this->skip_question_link_target = $skip_question_link_target;
86  }
87 
88  public function setInstantFeedbackCommand(string $instant_feedback_command): void
89  {
90  $this->instant_feedback_command = $instant_feedback_command;
91  }
92 
93  public function setForceInstantResponseEnabled(bool $force_instant_response_enabled): void
94  {
95  $this->force_instant_response_enabled = $force_instant_response_enabled;
96  }
97 
98  public function setAnswerFreezingEnabled(bool $answer_freezing_enabled): void
99  {
100  $this->answer_freezing_enabled = $answer_freezing_enabled;
101  }
102 
103  public function setRequestHintCommand(string $request_hint_command): void
104  {
105  $this->request_hint_command = $request_hint_command;
106  }
107 
108  public function setShowHintsCommand(string $show_hints_command): void
109  {
110  $this->show_hints_command = $show_hints_command;
111  }
112 
113  public function setHintRequestsExist(bool $hint_requests_exist): void
114  {
115  $this->hint_requests_exist = $hint_requests_exist;
116  }
117 
118  public function setQuestionMarkLinkTarget(string $question_mark_link_target): void
119  {
120  $this->question_mark_link_target = $question_mark_link_target;
121  }
122 
123  public function setQuestionMarked(bool $question_marked): void
124  {
125  $this->question_marked = $question_marked;
126  }
127 
128  public function setAnythingRendered(): void
129  {
130  $this->anything_rendered = true;
131  }
132 
133  public function setShowDiscardModalSignal(Signal $signal): void
134  {
135  $this->show_discard_modal_signal = $signal;
136  }
137 
138  private function getShowDiscardModalSignal(): Signal
139  {
140  return $this->show_discard_modal_signal ?? new SignalImplementation('');
141  }
142 
143  public function getActionsHTML(): string
144  {
145  $tpl = $this->getTemplate('actions');
146  $actions = [];
147 
148  if ($this->question_mark_link_target) {
149  $this->renderActionsIcon(
150  $tpl,
151  $this->getQuestionMarkIconSource(),
152  $this->getQuestionMarkIconLabel(),
153  'ilTestMarkQuestionIcon'
154  );
156  $actions[] = $this->ui_factory->button()->shy(
158  ''
159  )->withAdditionalOnLoadCode(
160  static function (string $id) use ($target): string {
161  return "document.getElementById('$id').addEventListener('click', "
162  . '(e) => {'
163  . " il.TestPlayerQuestionEditControl.checkNavigation('{$target}', 'show', e);"
164  . '});';
165  }
166  );
167  }
168 
169  if ($this->skip_question_link_target) {
170  $actions[] = $this->ui_factory->button()->shy(
171  $this->lng->txt('postpone_question'),
173  );
174  }
175 
176  if ($actions !== []) {
177  $actions[] = $this->ui_factory->divider()->horizontal();
178  }
179 
180  $actions[] = $this->ui_factory->button()->shy(
181  $this->lng->txt('tst_revert_changes'),
183  )->withUnavailableAction(!$this->revert_changes_link_target);
184 
185  if ($this->question_worked_through) {
186  $actions[] = $this->ui_factory->button()->shy(
187  $this->lng->txt('discard_answer'),
188  '#'
189  )->withUnavailableAction(!$this->discard_solution_button_enabled)
190  ->withOnClick($this->getShowDiscardModalSignal());
191  }
192 
193  $list = $this->ui_factory->dropdown()->standard($actions)->withLabel($this->lng->txt('actions'));
194  $tpl->setVariable('ACTION_MENU', $this->ui_renderer->render($list));
195 
196  return $tpl->get();
197  }
198 
199  public function getHTML(): string
200  {
201  $tpl = $this->getTemplate('toolbar');
202  if ($this->edit_solution_command) {
203  $this->renderSubmitButton(
204  $tpl,
205  $this->edit_solution_command,
207  );
208  }
209 
210  if ($this->instant_feedback_command === ilTestPlayerCommands::SHOW_INSTANT_RESPONSE) {
212  $tpl,
213  $this->instant_feedback_command,
214  $this->getCheckButtonLabel(),
215  $this->force_instant_response_enabled
216  );
217  }
218 
219  if ($this->request_hint_command) {
220  $this->renderSubmitButton(
221  $tpl,
222  $this->request_hint_command,
224  );
225  }
226 
227  if ($this->show_hints_command) {
228  $this->renderSubmitButton(
229  $tpl,
230  $this->show_hints_command,
231  $this->lng->txt('show_requested_question_hints')
232  );
233  }
234 
235  if ($this->anything_rendered) {
236  $this->parseNavigation($tpl);
237  }
238 
239  return $tpl->get();
240  }
241 
242  private function getEditSolutionButtonLabel(): string
243  {
244  if ($this->question_worked_through) {
245  return $this->lng->txt('edit_answer');
246  }
247 
248  return $this->lng->txt('answer_question');
249  }
250 
251  private function getCheckButtonLabel(): string
252  {
253  if ($this->answer_freezing_enabled) {
254  return $this->lng->txt('submit_and_check');
255  }
256 
257  return $this->lng->txt('check');
258  }
259 
260  private function getRequestHintButtonLabel(): string
261  {
262  if ($this->hint_requests_exist) {
263  return $this->lng->txt('button_request_next_question_hint');
264  }
265 
266  return $this->lng->txt('button_request_question_hint');
267  }
268 
269  private function getQuestionMarkActionLabel(): string
270  {
271  if ($this->question_marked) {
272  return $this->lng->txt('tst_remove_mark');
273  }
274 
275  return $this->lng->txt('tst_question_mark');
276  }
277 
278 
279  private function getQuestionMarkIconLabel(): string
280  {
281  if ($this->question_marked) {
282  return $this->lng->txt('tst_question_marked');
283  }
284 
285  return$this->lng->txt('tst_question_not_marked');
286  }
287 
288  private function getQuestionMarkIconSource(): string
289  {
290  if ($this->question_marked) {
291  return ilUtil::getImagePath('object/marked.svg');
292  }
293 
294  return ilUtil::getImagePath('object/marked_.svg');
295  }
296 
297  private function getTemplate($a_purpose = 'toolbar'): ilTemplate
298  {
299  switch ($a_purpose) {
300  case 'toolbar':
301  return new ilTemplate(
302  'tpl.tst_question_navigation.html',
303  true,
304  true,
305  'components/ILIAS/Test'
306  );
307  default:
308  case 'actions':
309  return new ilTemplate(
310  'tpl.tst_question_actions.html',
311  true,
312  true,
313  'components/ILIAS/Test'
314  );
315  }
316  }
317 
318  private function parseNavigation(ilTemplate $tpl): void
319  {
320  $tpl->setCurrentBlock('question_related_navigation');
321  $tpl->parseCurrentBlock();
322  }
323 
324  private function parseButtonsBlock(ilTemplate $tpl): void
325  {
326  $tpl->setCurrentBlock('buttons');
327  $tpl->parseCurrentBlock();
328  }
329 
330  private function renderButtonInstance(ilTemplate $tpl, Button $button): void
331  {
332  $tpl->setCurrentBlock('button_instance');
333  $tpl->setVariable('BUTTON_INSTANCE', $this->ui_renderer->render($button));
334  $tpl->parseCurrentBlock();
335 
336  $this->parseButtonsBlock($tpl);
337  $this->setAnythingRendered();
338  }
339 
340  private function renderSubmitButton(
341  ilTemplate $tpl,
342  string $command,
343  string $label
344  ): void {
345  $on_load_code = $this->getOnLoadCode($command);
346  $this->renderButtonInstance(
347  $tpl,
348  $this->ui_factory->button()->standard($label, '')->withAdditionalOnLoadCode($on_load_code)
349  );
350  }
351 
352  private function renderInstantFeedbackButton(
353  ilTemplate $tpl,
354  string $command,
355  string $label,
356  bool $is_primary
357  ): void {
358  $on_load_code = $this->getOnLoadCode($command);
359  if ($is_primary) {
360  $this->renderButtonInstance(
361  $tpl,
362  $this->ui_factory->button()->primary($label, '')->withAdditionalOnLoadCode($on_load_code)
363  );
364  return;
365  }
366 
367  $this->renderButtonInstance(
368  $tpl,
369  $this->ui_factory->button()->standard($label, '')->withAdditionalOnLoadCode($on_load_code)
370  );
371  }
372 
373  private function getOnLoadCode(string $command): Closure
374  {
375  return static function ($id) use ($command): string {
376  return "document.getElementById('$id').addEventListener('click', "
377  . '(e) => {'
378  . " e.target.setAttribute('name', 'cmd[$command]');"
379  . ' e.target.form.requestSubmit(e.target);'
380  . '});';
381  };
382  }
383 
384  private function renderActionsIcon(
385  ilTemplate $tpl,
386  string $icon_src,
387  string $label,
388  string $css_class
389  ): void {
390  $tpl->setCurrentBlock('actions_icon');
391  $tpl->setVariable('ICON_SRC', $icon_src);
392  $tpl->setVariable('ICON_TEXT', $label);
393  $tpl->setVariable('ICON_CLASS', $css_class);
394  $tpl->parseCurrentBlock();
395  }
396 }
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
setRevertChangesLinkTarget(string $revert_changes_link_target)
setSkipQuestionLinkTarget(string $skip_question_link_target)
setDiscardSolutionButtonEnabled(bool $discard_solution_button_enabled)
setEditSolutionCommand(string $edit_solution_command)
renderActionsIcon(ilTemplate $tpl, string $icon_src, string $label, string $css_class)
renderButtonInstance(ilTemplate $tpl, Button $button)
setShowHintsCommand(string $show_hints_command)
setForceInstantResponseEnabled(bool $force_instant_response_enabled)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
setAnswerFreezingEnabled(bool $answer_freezing_enabled)
setRequestHintCommand(string $request_hint_command)
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:544
renderSubmitButton(ilTemplate $tpl, string $command, string $label)
__construct(protected ilLanguage $lng, protected UIFactory $ui_factory, protected UIRenderer $ui_renderer)
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
renderInstantFeedbackButton(ilTemplate $tpl, string $command, string $label, bool $is_primary)
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
setInstantFeedbackCommand(string $instant_feedback_command)
setQuestionWorkedThrough(bool $question_worked_through)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
global $lng
Definition: privfeed.php:31
setQuestionMarkLinkTarget(string $question_mark_link_target)