ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilAssQuestionPreviewGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4
19{
20 const CMD_SHOW = 'show';
21 const CMD_RESET = 'reset';
22 const CMD_INSTANT_RESPONSE = 'instantResponse';
23 const CMD_HANDLE_QUESTION_ACTION = 'handleQuestionAction';
24 const CMD_GATEWAY_CONFIRM_HINT_REQUEST = 'gatewayConfirmHintRequest';
25 const CMD_GATEWAY_SHOW_HINT_LIST = 'gatewayShowHintList';
26
27 const TAB_ID_QUESTION_PREVIEW = 'preview';
28
29 const FEEDBACK_FOCUS_ANCHOR = 'focus';
30
34 protected $ctrl;
35
39 protected $tabs;
40
44 protected $tpl;
45
49 protected $lng;
50
54 protected $db;
55
59 protected $user;
60
64 protected $questionGUI;
65
69 protected $questionOBJ;
70
75
79 protected $previewSession;
80
84 protected $hintTracking;
85
87 {
88 $this->ctrl = $ctrl;
89 $this->tabs = $tabs;
90 $this->tpl = $tpl;
91 $this->lng = $lng;
92 $this->db = $db;
93 $this->user = $user;
94 }
95
96 public function initQuestion($questionId, $parentObjId)
97 {
98 require_once 'Modules/TestQuestionPool/classes/class.assQuestion.php';
99
100 $this->questionGUI = assQuestion::instantiateQuestionGUI($questionId);
101 $this->questionOBJ = $this->questionGUI->object;
102
103 $this->questionOBJ->setObjId($parentObjId);
104
105 $this->questionGUI->setQuestionTabs();
106 $this->questionGUI->outAdditionalOutput();
107
108 $this->questionGUI->populateJavascriptFilesRequiredForWorkForm($this->tpl);
109 $this->questionOBJ->setOutputType(OUTPUT_JAVASCRIPT); // TODO: remove including depending stuff
110
111 $this->questionGUI->setTargetGui($this);
112 $this->questionGUI->setQuestionActionCmd(self::CMD_HANDLE_QUESTION_ACTION);
113
114 $this->questionGUI->setRenderPurpose(assQuestionGUI::RENDER_PURPOSE_DEMOPLAY);
115 }
116
117 public function initPreviewSettings($parentRefId)
118 {
119 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewSettings.php';
120 $this->previewSettings = new ilAssQuestionPreviewSettings($parentRefId);
121
122 $this->previewSettings->init();
123 }
124
125 public function initPreviewSession($userId, $questionId)
126 {
127 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewSession.php';
128 $this->previewSession = new ilAssQuestionPreviewSession($userId, $questionId);
129
130 $this->previewSession->init();
131 }
132
133 public function initHintTracking()
134 {
135 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewHintTracking.php';
136 $this->hintTracking = new ilAssQuestionPreviewHintTracking($this->db, $this->previewSession);
137 }
138
139 public function initStyleSheets()
140 {
141 include_once("./Services/Style/Content/classes/class.ilObjStyleSheet.php");
142
143 $this->tpl->setCurrentBlock("ContentStyle");
144 $this->tpl->setVariable("LOCATION_CONTENT_STYLESHEET", ilObjStyleSheet::getContentStylePath(0));
145 $this->tpl->parseCurrentBlock();
146
147 $this->tpl->setCurrentBlock("SyntaxStyle");
148 $this->tpl->setVariable("LOCATION_SYNTAX_STYLESHEET", ilObjStyleSheet::getSyntaxStylePath());
149 $this->tpl->parseCurrentBlock();
150 }
151
152 public function executeCommand()
153 {
154 global $DIC; /* @var \ILIAS\DI\Container $DIC */
155 $ilHelp = $DIC['ilHelp']; /* @var ilHelpGUI $ilHelp */
156 $ilHelp->setScreenIdComponent('qpl');
157
158 $this->tabs->setTabActive(self::TAB_ID_QUESTION_PREVIEW);
159
160 $this->lng->loadLanguageModule('content');
161
162 $nextClass = $this->ctrl->getNextClass($this);
163
164 switch ($nextClass) {
165 case 'ilassquestionhintrequestgui':
166
167 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
168 $gui = new ilAssQuestionHintRequestGUI($this, self::CMD_SHOW, $this->questionGUI, $this->hintTracking);
169
170 $this->ctrl->forwardCommand($gui);
171
172 break;
173
174 case 'ilassspecfeedbackpagegui':
175 case 'ilassgenfeedbackpagegui':
176 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionFeedbackPageObjectCommandForwarder.php';
177 $forwarder = new ilAssQuestionFeedbackPageObjectCommandForwarder($this->questionOBJ, $this->ctrl, $this->tabs, $this->lng);
178 $forwarder->forward();
179 break;
180
181 case 'ilnotegui':
182
183 $notesGUI = new ilNoteGUI($this->questionOBJ->getObjId(), $this->questionOBJ->getId(), 'quest');
184 $notesGUI->enablePublicNotes(true);
185 $notesGUI->enablePublicNotesDeletion(true);
186 $notesPanelHTML = $this->ctrl->forwardCommand($notesGUI);
187 $this->showCmd($notesPanelHTML);
188 break;
189
190
191 default:
192
193 $cmd = $this->ctrl->getCmd(self::CMD_SHOW) . 'Cmd';
194
195 $this->$cmd();
196 }
197 }
198
202 protected function buildPreviewFormAction()
203 {
204 return $this->ctrl->getFormAction($this, self::CMD_SHOW) . '#' . self::FEEDBACK_FOCUS_ANCHOR;
205 }
206
207 protected function isCommentingRequired()
208 {
209 global $DIC; /* @var ILIAS\DI\Container $DIC */
210
211 if ($this->previewSettings->isTestRefId()) {
212 return false;
213 }
214
215 return (bool) $DIC->rbac()->system()->checkAccess('write', (int) $_GET['ref_id']);
216 }
217
218 private function showCmd($notesPanelHTML = '')
219 {
220 $tpl = new ilTemplate('tpl.qpl_question_preview.html', true, true, 'Modules/TestQuestionPool');
221
222 $tpl->setVariable('PREVIEW_FORMACTION', $this->buildPreviewFormAction());
223
225
227
229
230 if ($this->isCommentingRequired()) {
231 $this->questionGUI->addHeaderAction();
232 $this->populateNotesPanel($tpl, $notesPanelHTML);
233 }
234
235 $this->tpl->setContent($tpl->get());
236 }
237
239 {
240 $renderHeader = false;
241 $renderAnchor = false;
242
243 if ($this->isShowReachedPointsRequired()) {
244 $this->populateReachedPointsOutput($tpl);
245 $renderAnchor = true;
246 $renderHeader = true;
247 }
248
249 if ($this->isShowBestSolutionRequired()) {
250 $this->populateSolutionOutput($tpl);
251 $renderAnchor = true;
252 $renderHeader = true;
253 }
254
257 $renderAnchor = true;
258 $renderHeader = true;
259 }
260
262 $renderHeader = true;
263
264 if ($this->questionGUI->hasInlineFeedback()) {
265 $renderAnchor = false;
266 } else {
268 $renderAnchor = true;
269 }
270 }
271
272 if ($renderHeader) {
273 $this->populateInstantResponseHeader($tpl, $renderAnchor);
274 }
275 }
276
277 private function resetCmd()
278 {
279 $this->previewSession->setRandomizerSeed(null);
280 $this->previewSession->setParticipantsSolution(null);
281 $this->previewSession->resetRequestedHints();
282 $this->previewSession->setInstantResponseActive(false);
283
284 ilUtil::sendInfo($this->lng->txt('qst_preview_reset_msg'), true);
285
286 $this->ctrl->redirect($this, self::CMD_SHOW);
287 }
288
289 private function instantResponseCmd()
290 {
291 if ($this->saveQuestionSolution()) {
292 $this->previewSession->setInstantResponseActive(true);
293 } else {
294 $this->previewSession->setInstantResponseActive(false);
295 }
296
297 $this->ctrl->redirect($this, self::CMD_SHOW);
298 }
299
300 private function handleQuestionActionCmd()
301 {
302 $this->questionOBJ->persistPreviewState($this->previewSession);
303 $this->ctrl->redirect($this, self::CMD_SHOW);
304 }
305
307 {
308 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewToolbarGUI.php';
309 $toolbarGUI = new ilAssQuestionPreviewToolbarGUI($this->lng);
310
311 $toolbarGUI->setFormAction($this->ctrl->getFormAction($this, self::CMD_SHOW));
312 $toolbarGUI->setResetPreviewCmd(self::CMD_RESET);
313
314 $toolbarGUI->build();
315
316 $tpl->setVariable('PREVIEW_TOOLBAR', $this->ctrl->getHTML($toolbarGUI));
317 }
318
320 {
321 // FOR WHAT EXACTLY IS THIS USEFUL?
322 $this->ctrl->setReturnByClass('ilAssQuestionPageGUI', 'view');
323 $this->ctrl->setReturnByClass('ilObjQuestionPoolGUI', 'questions');
324
325 include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
326 $pageGUI = new ilAssQuestionPageGUI($this->questionOBJ->getId());
327 $pageGUI->setRenderPageContainer(false);
328 $pageGUI->setEditPreview(true);
329 $pageGUI->setEnabledTabs(false);
330
331 // FOR WHICH SITUATION IS THIS WORKAROUND NECCESSARY? (sure .. imagemaps, but where this can be done?)
332 if (strlen($this->ctrl->getCmd()) == 0 && !isset($_POST['editImagemapForward_x'])) { // workaround for page edit imagemaps, keep in mind
333 $this->ctrl->setCmdClass(get_class($pageGUI));
334 $this->ctrl->setCmd('preview');
335 }
336
337 $this->questionGUI->setPreviewSession($this->previewSession);
338 $this->questionGUI->object->setShuffler($this->getQuestionAnswerShuffler());
339
340 $questionHtml = $this->questionGUI->getPreview(true, $this->isShowSpecificQuestionFeedbackRequired());
341 $this->questionGUI->magicAfterTestOutput();
342
343 if ($this->isShowSpecificQuestionFeedbackRequired() && $this->questionGUI->hasInlineFeedback()) {
344 $questionHtml = $this->questionGUI->buildFocusAnchorHtml() . $questionHtml;
345 }
346
347 $questionHtml .= $this->getQuestionNavigationHtml();
348
349 $pageGUI->setQuestionHTML(array($this->questionOBJ->getId() => $questionHtml));
350
351 //$pageGUI->setHeader($this->questionOBJ->getTitle()); // NO ADDITIONAL HEADER
352 $pageGUI->setPresentationTitle($this->questionOBJ->getTitle());
353
354 //$pageGUI->setTemplateTargetVar("ADM_CONTENT"); // NOT REQUIRED, OR IS?
355
356 $tpl->setVariable('QUESTION_OUTPUT', $pageGUI->preview());
357 }
358
360 {
361 $reachedPoints = $this->questionOBJ->calculateReachedPointsFromPreviewSession($this->previewSession);
362 $maxPoints = $this->questionOBJ->getMaximumPoints();
363
364 $scoreInformation = sprintf(
365 $this->lng->txt("you_received_a_of_b_points"),
366 $reachedPoints,
367 $maxPoints
368 );
369
370 $tpl->setCurrentBlock("reached_points_feedback");
371 $tpl->setVariable("REACHED_POINTS_FEEDBACK", $scoreInformation);
372 $tpl->parseCurrentBlock();
373 }
374
376 {
377 // FOR WHAT EXACTLY IS THIS USEFUL?
378 $this->ctrl->setReturnByClass('ilAssQuestionPageGUI', 'view');
379 $this->ctrl->setReturnByClass('ilObjQuestionPoolGUI', 'questions');
380
381 include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php");
382 $pageGUI = new ilAssQuestionPageGUI($this->questionOBJ->getId());
383
384 $pageGUI->setEditPreview(true);
385 $pageGUI->setEnabledTabs(false);
386
387 // FOR WHICH SITUATION IS THIS WORKAROUND NECCESSARY? (sure .. imagemaps, but where this can be done?)
388 if (strlen($this->ctrl->getCmd()) == 0 && !isset($_POST['editImagemapForward_x'])) { // workaround for page edit imagemaps, keep in mind
389 $this->ctrl->setCmdClass(get_class($pageGUI));
390 $this->ctrl->setCmd('preview');
391 }
392
393 $this->questionGUI->setPreviewSession($this->previewSession);
394
395 $pageGUI->setQuestionHTML(array($this->questionOBJ->getId() => $this->questionGUI->getSolutionOutput(0, null, false, false, true, false, true, false, false)));
396
397 //$pageGUI->setHeader($this->questionOBJ->getTitle()); // NO ADDITIONAL HEADER
398 //$pageGUI->setPresentationTitle($this->questionOBJ->getTitle());
399
400 //$pageGUI->setTemplateTargetVar("ADM_CONTENT"); // NOT REQUIRED, OR IS?
401
402 $output = $this->questionGUI->getSolutionOutput(0, null, false, false, true, false, true, false, false);
403 //$output = $pageGUI->preview();
404 //$output = str_replace('<h1 class="ilc_page_title_PageTitle"></h1>', '', $output);
405
406 $tpl->setCurrentBlock('solution_output');
407 $tpl->setVariable('TXT_CORRECT_SOLUTION', $this->lng->txt('tst_best_solution_is'));
408 $tpl->setVariable('SOLUTION_OUTPUT', $output);
409 $tpl->parseCurrentBlock();
410 }
411
412 private function getQuestionNavigationHtml()
413 {
414 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionRelatedNavigationBarGUI.php';
415 $navGUI = new ilAssQuestionRelatedNavigationBarGUI($this->ctrl, $this->lng);
416
417 $navGUI->setInstantResponseCmd(self::CMD_INSTANT_RESPONSE);
418 $navGUI->setHintRequestCmd(self::CMD_GATEWAY_CONFIRM_HINT_REQUEST);
419 $navGUI->setHintListCmd(self::CMD_GATEWAY_SHOW_HINT_LIST);
420
421 $navGUI->setInstantResponseEnabled($this->previewSettings->isInstantFeedbackNavigationRequired());
422 $navGUI->setHintProvidingEnabled($this->previewSettings->isHintProvidingEnabled());
423
424 $navGUI->setHintRequestsPossible($this->hintTracking->requestsPossible());
425 $navGUI->setHintRequestsExist($this->hintTracking->requestsExist());
426
427 return $this->ctrl->getHTML($navGUI);
428 }
429
431 {
432 if ($this->questionOBJ->isPreviewSolutionCorrect($this->previewSession)) {
433 $feedback = $this->questionGUI->getGenericFeedbackOutputForCorrectSolution();
435 } else {
436 $feedback = $this->questionGUI->getGenericFeedbackOutputForIncorrectSolution();
438 }
439
440 if (strlen($feedback)) {
441 $tpl->setCurrentBlock('instant_feedback_generic');
442 $tpl->setVariable('GENERIC_FEEDBACK', $feedback);
443 $tpl->setVariable('ILC_FB_CSS_CLASS', $cssClass);
444 $tpl->parseCurrentBlock();
445 }
446 }
447
449 {
450 $fb = $this->questionGUI->getSpecificFeedbackOutput(
451 (array) $this->previewSession->getParticipantsSolution()
452 );
453
454 $tpl->setCurrentBlock('instant_feedback_specific');
455 $tpl->setVariable('ANSWER_FEEDBACK', $fb);
456 $tpl->parseCurrentBlock();
457 }
458
459 protected function populateInstantResponseHeader(ilTemplate $tpl, $withFocusAnchor)
460 {
461 if ($withFocusAnchor) {
462 $tpl->setCurrentBlock('inst_resp_id');
463 $tpl->setVariable('INSTANT_RESPONSE_FOCUS_ID', self::FEEDBACK_FOCUS_ANCHOR);
464 $tpl->parseCurrentBlock();
465 }
466
467 $tpl->setCurrentBlock('instant_response_header');
468 $tpl->setVariable('INSTANT_RESPONSE_HEADER', $this->lng->txt('tst_feedback'));
469 $tpl->parseCurrentBlock();
470 }
471
472 private function isShowBestSolutionRequired()
473 {
474 if (!$this->previewSettings->isBestSolutionEnabled()) {
475 return false;
476 }
477
478 return $this->previewSession->isInstantResponseActive();
479 }
480
482 {
483 if (!$this->previewSettings->isGenericFeedbackEnabled()) {
484 return false;
485 }
486
487 return $this->previewSession->isInstantResponseActive();
488 }
489
491 {
492 if (!$this->previewSettings->isSpecificFeedbackEnabled()) {
493 return false;
494 }
495
496 return $this->previewSession->isInstantResponseActive();
497 }
498
500 {
501 if (!$this->previewSettings->isReachedPointsEnabled()) {
502 return false;
503 }
504
505 return $this->previewSession->isInstantResponseActive();
506 }
507
508 public function saveQuestionSolution()
509 {
510 return $this->questionOBJ->persistPreviewState($this->previewSession);
511 }
512
514 {
515 if (!$this->saveQuestionSolution()) {
516 $this->previewSession->setInstantResponseActive(false);
517 $this->showCmd();
518 return;
519 }
520
521 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
522
523 $this->ctrl->redirectByClass(
524 'ilAssQuestionHintRequestGUI',
526 );
527 }
528
529 public function gatewayShowHintListCmd()
530 {
531 if (!$this->saveQuestionSolution()) {
532 $this->previewSession->setInstantResponseActive(false);
533 $this->showCmd();
534 return;
535 }
536
537 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
538
539 $this->ctrl->redirectByClass(
540 'ilAssQuestionHintRequestGUI',
542 );
543 }
544
548 private function getQuestionAnswerShuffler()
549 {
550 require_once 'Services/Randomization/classes/class.ilArrayElementShuffler.php';
551 $shuffler = new ilArrayElementShuffler();
552
553 if (!$this->previewSession->randomizerSeedExists()) {
554 $this->previewSession->setRandomizerSeed($shuffler->buildRandomSeed());
555 }
556
557 $shuffler->setSeed($this->previewSession->getRandomizerSeed());
558
559 return $shuffler;
560 }
561
562 protected function populateNotesPanel(ilTemplate $tpl, $notesPanelHTML)
563 {
564 if (!strlen($notesPanelHTML)) {
565 $notesPanelHTML = $this->questionGUI->getNotesHTML();
566 }
567
568 $tpl->setCurrentBlock('notes_panel');
569 $tpl->setVariable('NOTES_PANEL', $notesPanelHTML);
570 $tpl->parseCurrentBlock();
571 }
572}
user()
Definition: user.php:4
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
static instantiateQuestionGUI($a_question_id)
Creates an instance of a question gui with a given question id.
Question page GUI class.
populateInstantResponseHeader(ilTemplate $tpl, $withFocusAnchor)
initQuestion($questionId, $parentObjId)
__construct(ilCtrl $ctrl, ilTabsGUI $tabs, ilGlobalTemplateInterface $tpl, ilLanguage $lng, ilDBInterface $db, ilObjUser $user)
populateNotesPanel(ilTemplate $tpl, $notesPanelHTML)
This class provides processing control methods.
language handling
Notes GUI class.
static getSyntaxStylePath()
get syntax style path
static getContentStylePath($a_style_id, $add_random=true, $add_token=true)
get content style path
Tabs GUI.
special template class to simplify handling of ITX/PEAR
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
const OUTPUT_JAVASCRIPT
Interface ilDBInterface.
$DIC
Definition: xapitoken.php:46