ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilTestCorrectionsGUI.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
4
14{
18 protected $DIC;
19
23 protected $testOBJ;
24
28 protected $testAccess;
29
35 public function __construct(\ILIAS\DI\Container $DIC, ilObjTest $testOBJ)
36 {
37 $this->DIC = $DIC;
38 $this->testOBJ = $testOBJ;
39
40 $this->testAccess = new ilTestAccess($testOBJ->getRefId(), $testOBJ->getTestId());
41 }
42
43 public function executeCommand()
44 {
45 if (!$this->testAccess->checkCorrectionsAccess()) {
47 }
48
49 if (isset($_GET['eqid']) && (int) $_GET["eqid"] && isset($_GET['eqpl']) && (int) $_GET["eqpl"]) {
50 $this->DIC->ctrl()->setParameter($this, 'qid', (int) $_GET["eqid"]);
51 $this->DIC->ctrl()->redirect($this, 'showQuestion');
52 }
53
54 if (isset($_GET['removeQid']) && (int) $_GET['removeQid']) {
55 $this->DIC->ctrl()->setParameter($this, 'qid', (int) $_GET['removeQid']);
56 $this->DIC->ctrl()->redirect($this, 'confirmQuestionRemoval');
57 }
58
59 if ((int) $_GET['qid'] && !$this->checkQuestion((int) $_GET['qid'])) {
61 }
62
63 $this->DIC->ctrl()->saveParameter($this, 'qid');
64
65 switch ($this->DIC->ctrl()->getNextClass($this)) {
66 default:
67
68 $command = $this->DIC->ctrl()->getCmd('showQuestionList');
69 $this->{$command}();
70 }
71 }
72
73 protected function showQuestionList()
74 {
75 $this->DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_CORRECTION);
76
77 $ui = $this->DIC->ui();
78
79 if ($this->testOBJ->isFixedTest()) {
80 $table_gui = new ilTestQuestionsTableGUI(
81 $this,
82 'showQuestionList',
83 $this->testOBJ->getRefId()
84 );
85
86 $table_gui->setQuestionTitleLinksEnabled(true);
87 $table_gui->setQuestionRemoveRowButtonEnabled(true);
88 $table_gui->init();
89
90 $table_gui->setData($this->getQuestions());
91
92 $rendered_gui_component = $table_gui->getHTML();
93 } else {
94 $lng = $this->DIC->language();
95 $txt = $lng->txt('tst_corrections_incompatible_question_set_type');
96
97 $infoBox = $ui->factory()->messageBox()->info($txt);
98
99 $rendered_gui_component = $ui->renderer()->render($infoBox);
100 }
101
102 $ui->mainTemplate()->setContent($rendered_gui_component);
103 }
104
105 protected function showQuestion(ilPropertyFormGUI $form = null)
106 {
107 $questionGUI = $this->getQuestion((int) $_GET['qid']);
108
109 $this->setCorrectionTabsContext($questionGUI, 'question');
110
111 if ($form === null) {
112 $form = $this->buildQuestionCorrectionForm($questionGUI);
113 }
114
115 $this->populatePageTitleAndDescription($questionGUI);
116 $this->DIC->ui()->mainTemplate()->setContent($form->getHTML());
117 }
118
119 protected function saveQuestion()
120 {
121 $questionGUI = $this->getQuestion((int) $_GET['qid']);
122
123 $form = $this->buildQuestionCorrectionForm($questionGUI);
124
125 $form->setValuesByPost();
126
127 if (!$form->checkInput()) {
128 $questionGUI->prepareReprintableCorrectionsForm($form);
129
130 $this->showQuestion($form);
131 return;
132 }
133
134 $questionGUI->saveCorrectionsFormProperties($form);
135 $questionGUI->object->setPoints($questionGUI->object->getMaximumPoints());
136 $questionGUI->object->saveToDb();
137
138 $scoring = new ilTestScoring($this->testOBJ);
139 $scoring->setPreserveManualScores(false);
140 $scoring->setQuestionId($questionGUI->object->getId());
141 $scoring->recalculateSolutions();
142
143 $this->DIC->ctrl()->redirect($this, 'showQuestion');
144 }
145
146 protected function buildQuestionCorrectionForm(assQuestionGUI $questionGUI)
147 {
148 $form = new ilPropertyFormGUI();
149 $form->setFormAction($this->DIC->ctrl()->getFormAction($this));
150 $form->setId('tst_question_correction');
151
152 $form->setTitle($this->DIC->language()->txt('tst_corrections_qst_form'));
153
154 $hiddenQid = new ilHiddenInputGUI('qid');
155 $hiddenQid->setValue($questionGUI->object->getId());
156 $form->addItem($hiddenQid);
157
158 $questionGUI->populateCorrectionsFormProperties($form);
159
160 $scoring = new ilTestScoring($this->testOBJ);
161 $scoring->setQuestionId($questionGUI->object->getId());
162
163 if ($scoring->getNumManualScorings()) {
164 $form->addCommandButton('confirmManualScoringReset', $this->DIC->language()->txt('save'));
165 } else {
166 $form->addCommandButton('saveQuestion', $this->DIC->language()->txt('save'));
167 }
168
169 return $form;
170 }
171
172 protected function addHiddenItemsFromArray(ilConfirmationGUI $gui, $array, $curPath = array())
173 {
174 foreach ($array as $name => $value) {
175 if ($name == 'cmd' && !count($curPath)) {
176 continue;
177 }
178
179 if (count($curPath)) {
180 $name = "[{$name}]";
181 }
182
183 if (is_array($value)) {
184 $nextPath = array_merge($curPath, array($name));
185 $this->addHiddenItemsFromArray($gui, $value, $nextPath);
186 } else {
187 $postVar = implode('', $curPath) . $name;
188 $gui->addHiddenItem($postVar, $value);
189 }
190 }
191 }
192
193 protected function confirmManualScoringReset()
194 {
195 $questionGUI = $this->getQuestion((int) $_GET['qid']);
196
197 $this->setCorrectionTabsContext($questionGUI, 'question');
198
199 $scoring = new ilTestScoring($this->testOBJ);
200 $scoring->setQuestionId($questionGUI->object->getId());
201
202 $confirmation = sprintf(
203 $this->DIC->language()->txt('tst_corrections_manscore_reset_warning'),
204 $scoring->getNumManualScorings(),
205 $questionGUI->object->getTitle(),
206 $questionGUI->object->getId()
207 );
208
209 $gui = new ilConfirmationGUI();
210 $gui->setHeaderText($confirmation);
211 $gui->setFormAction($this->DIC->ctrl()->getFormAction($this));
212 $gui->setCancel($this->DIC->language()->txt('cancel'), 'showQuestion');
213 $gui->setConfirm($this->DIC->language()->txt('confirm'), 'saveQuestion');
214
215 $this->addHiddenItemsFromArray($gui, $_POST);
216
217 $this->DIC->ui()->mainTemplate()->setContent($gui->getHTML());
218 }
219
220 protected function showSolution()
221 {
222 $questionGUI = $this->getQuestion((int) $_GET['qid']);
223
224 $this->setCorrectionTabsContext($questionGUI, 'solution');
225
226 $pageGUI = new ilAssQuestionPageGUI($questionGUI->object->getId());
227 $pageGUI->setRenderPageContainer(false);
228 $pageGUI->setEditPreview(true);
229 $pageGUI->setEnabledTabs(false);
230
231 $solutionHTML = $questionGUI->getSolutionOutput(
232 0,
233 null,
234 false,
235 false,
236 true,
237 false,
238 true,
239 false,
240 true
241 );
242
243 $pageGUI->setQuestionHTML(array($questionGUI->object->getId() => $solutionHTML));
244 $pageGUI->setPresentationTitle($questionGUI->object->getTitle());
245
246 $tpl = new ilTemplate('tpl.tst_corrections_solution_presentation.html', true, true, 'Modules/Test');
247 $tpl->setVariable('SOLUTION_PRESENTATION', $pageGUI->preview());
248
249 $this->populatePageTitleAndDescription($questionGUI);
250
251 $this->DIC->ui()->mainTemplate()->setContent($tpl->get());
252 $this->DIC->ui()->mainTemplate()->addCss('Modules/Test/templates/default/ta.css');
253
254 $this->DIC->ui()->mainTemplate()->setCurrentBlock("ContentStyle");
256 $this->DIC->ui()->mainTemplate()->setVariable("LOCATION_CONTENT_STYLESHEET", $stylesheet);
257 $this->DIC->ui()->mainTemplate()->parseCurrentBlock();
258
259 $this->DIC->ui()->mainTemplate()->setCurrentBlock("SyntaxStyle");
261 $this->DIC->ui()->mainTemplate()->setVariable("LOCATION_SYNTAX_STYLESHEET", $stylesheet);
262 $this->DIC->ui()->mainTemplate()->parseCurrentBlock();
263 }
264
265 protected function showAnswerStatistic()
266 {
267 $questionGUI = $this->getQuestion((int) $_GET['qid']);
268 $solutions = $this->getSolutions($questionGUI->object);
269
270 $this->setCorrectionTabsContext($questionGUI, 'answers');
271
272 $tablesHtml = '';
273
274 foreach ($questionGUI->getSubQuestionsIndex() as $subQuestionIndex) {
275 $table = $questionGUI->getAnswerFrequencyTableGUI(
276 $this,
277 'showAnswerStatistic',
278 $solutions,
279 $subQuestionIndex
280 );
281
282 $tablesHtml .= $table->getHTML() . $table->getAdditionalHtml();
283 }
284
285 $this->populatePageTitleAndDescription($questionGUI);
286 $this->DIC->ui()->mainTemplate()->setContent($tablesHtml);
287 $this->DIC->ui()->mainTemplate()->addCss('Modules/Test/templates/default/ta.css');
288 }
289
290 protected function addAnswerAsynch()
291 {
292 $response = new stdClass();
293
294 $form = new ilAddAnswerModalFormGUI();
295 $form->build();
296 $form->setValuesByPost();
297
298 if (!$form->checkInput()) {
299 $uid = md5($form->getInput('answer'));
300
301 $form->setId($uid);
302 $form->setFormAction($this->DIC->ctrl()->getFormAction($this, 'addAnswerAsynch'));
303
304 $alert = $this->DIC->ui()->factory()->messageBox()->failure(
305 $this->DIC->language()->txt('form_input_not_valid')
306 );
307
308 $bodyTpl = new ilTemplate('tpl.tst_corr_addanswermodal.html', true, true, 'Modules/TestQuestionPool');
309 $bodyTpl->setVariable('MESSAGE', $this->DIC->ui()->renderer()->render($alert));
310 $bodyTpl->setVariable('FORM', $form->getHTML());
311 $bodyTpl->setVariable('BODY_UID', $uid);
312
313 $response->result = false;
314 $response->html = $bodyTpl->get();
315
316 echo json_encode($response);
317 exit;
318 }
319
320 $qid = (int) $form->getInput('qid');
321
322 if (!$this->checkQuestion($qid)) {
323 $response->html = '';
324 $response->result = false;
325
326 echo json_encode($response);
327 exit;
328 }
329
330 $questionGUI = $this->getQuestion($qid);
331
332 $qIndex = (int) $form->getInput('qindex');
333 $points = (float) $form->getInput('points');
334 $answerOption = $form->getInput('answer');
335
336 if ($questionGUI->object->isAddableAnswerOptionValue($qIndex, $answerOption)) {
337 $questionGUI->object->addAnswerOptionValue($qIndex, $answerOption, $points);
338 $questionGUI->object->saveToDb();
339 }
340
341 $scoring = new ilTestScoring($this->testOBJ);
342 $scoring->setPreserveManualScores(true);
343 $scoring->recalculateSolutions();
344
345 $response->result = true;
346
347 echo json_encode($response);
348 exit;
349 }
350
351 protected function confirmQuestionRemoval()
352 {
353 $this->DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_CORRECTION);
354
355 $questionGUI = $this->getQuestion((int) $_GET['qid']);
356
357 $confirmation = sprintf(
358 $this->DIC->language()->txt('tst_corrections_qst_remove_confirmation'),
359 $questionGUI->object->getTitle(),
360 $questionGUI->object->getId()
361 );
362
363 $buttons = array(
364 $this->DIC->ui()->factory()->button()->standard(
365 $this->DIC->language()->txt('confirm'),
366 $this->DIC->ctrl()->getLinkTarget($this, 'performQuestionRemoval')
367 ),
368 $this->DIC->ui()->factory()->button()->standard(
369 $this->DIC->language()->txt('cancel'),
370 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestionList')
371 )
372 );
373
374 $this->DIC->ui()->mainTemplate()->setContent($this->DIC->ui()->renderer()->render(
375 $this->DIC->ui()->factory()->messageBox()->confirmation($confirmation)->withButtons($buttons)
376 ));
377 }
378
379 protected function performQuestionRemoval()
380 {
381 global $DIC; /* @var ILIAS\DI\Container $DIC */
382
383 $questionGUI = $this->getQuestion((int) $_GET['qid']);
384 $scoring = new ilTestScoring($this->testOBJ);
385
386 $participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
387 $participantData->load($this->testOBJ->getTestId());
388
389 // remove question solutions
390 $questionGUI->object->removeAllExistingSolutions();
391
392 // remove test question results
393 $scoring->removeAllQuestionResults($questionGUI->object->getId());
394
395 // remove question from test and reindex remaining questions
396 $this->testOBJ->removeQuestion($questionGUI->object->getId());
397 $reindexedSequencePositionMap = $this->testOBJ->reindexFixedQuestionOrdering();
398 $this->testOBJ->loadQuestions();
399
400 // remove questions from all sequences
401 $this->testOBJ->removeQuestionFromSequences(
402 $questionGUI->object->getId(),
403 $participantData->getActiveIds(),
404 $reindexedSequencePositionMap
405 );
406
407 // update pass and test results
408 $scoring->updatePassAndTestResults($participantData->getActiveIds());
409
410 // trigger learning progress
411 ilLPStatusWrapper::_refreshStatus($this->testOBJ->getId(), $participantData->getUserIds());
412
413 // finally delete the question itself
414 $questionGUI->object->delete($questionGUI->object->getId());
415
416 // check for empty test and set test offline
417 if (!count($this->testOBJ->getTestQuestions())) {
418 $this->testOBJ->setOnline(false);
419 $this->testOBJ->saveToDb(true);
420 }
421
422 $this->DIC->ctrl()->setParameter($this, 'qid', '');
423 $this->DIC->ctrl()->redirect($this, 'showQuestionList');
424 }
425
426 protected function setCorrectionTabsContext(assQuestionGUI $questionGUI, $activeTabId)
427 {
428 $this->DIC->tabs()->clearTargets();
429 $this->DIC->tabs()->clearSubTabs();
430
431 $this->DIC->tabs()->setBackTarget(
432 $this->DIC->language()->txt('back'),
433 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestionList')
434 );
435
436 $this->DIC->tabs()->addTab(
437 'question',
438 $this->DIC->language()->txt('tst_corrections_tab_question'),
439 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestion')
440 );
441
442 $this->DIC->tabs()->addTab(
443 'solution',
444 $this->DIC->language()->txt('tst_corrections_tab_solution'),
445 $this->DIC->ctrl()->getLinkTarget($this, 'showSolution')
446 );
447
448 if ($questionGUI->isAnswerFreuqencyStatisticSupported()) {
449 $this->DIC->tabs()->addTab(
450 'answers',
451 $this->DIC->language()->txt('tst_corrections_tab_statistics'),
452 $this->DIC->ctrl()->getLinkTarget($this, 'showAnswerStatistic')
453 );
454 }
455
456 $this->DIC->tabs()->activateTab($activeTabId);
457 }
458
462 protected function populatePageTitleAndDescription(assQuestionGUI $questionGUI)
463 {
464 $this->DIC->ui()->mainTemplate()->setTitle($questionGUI->object->getTitle());
465 $this->DIC->ui()->mainTemplate()->setDescription($questionGUI->outQuestionType());
466 }
467
472 protected function checkQuestion($qId)
473 {
474 if (!$this->testOBJ->isTestQuestion($qId)) {
475 return false;
476 }
477
478 $questionGUI = $this->getQuestion($qId);
479
480 if (!$this->supportsAdjustment($questionGUI)) {
481 return false;
482 }
483
484 if (!$this->allowedInAdjustment($questionGUI)) {
485 return false;
486 }
487
488 return true;
489 }
490
495 protected function getQuestion($qId)
496 {
497 $question = assQuestion::instantiateQuestionGUI($qId);
498 $question->object->setObjId($this->testOBJ->getId());
499
500 return $question;
501 }
502
503 protected function getSolutions(assQuestion $question)
504 {
505 $solutionRows = array();
506
507 foreach ($this->testOBJ->getParticipants() as $activeId => $participantData) {
508 $passesSelector = new ilTestPassesSelector($this->DIC->database(), $this->testOBJ);
509 $passesSelector->setActiveId($activeId);
510 $passesSelector->loadLastFinishedPass();
511
512 foreach ($passesSelector->getClosedPasses() as $pass) {
513 foreach ($question->getSolutionValues($activeId, $pass) as $row) {
514 $solutionRows[] = $row;
515 }
516 }
517 }
518
519 return $solutionRows;
520 }
521
525 protected function getQuestions() : array
526 {
527 $questions = array();
528
529 foreach ($this->testOBJ->getTestQuestions() as $questionData) {
530 $questionGUI = $this->getQuestion($questionData['question_id']);
531
532 if (!$this->supportsAdjustment($questionGUI)) {
533 continue;
534 }
535
536 if (!$this->allowedInAdjustment($questionGUI)) {
537 continue;
538 }
539
540 $questions[] = $questionData;
541 }
542
543 return $questions;
544 }
545
553 protected function supportsAdjustment(\assQuestionGUI $question_object)
554 {
555 return ($question_object instanceof ilGuiQuestionScoringAdjustable
556 || $question_object instanceof ilGuiAnswerScoringAdjustable)
557 && ($question_object->object instanceof ilObjQuestionScoringAdjustable
558 || $question_object->object instanceof ilObjAnswerScoringAdjustable);
559 }
560
567 protected function allowedInAdjustment(\assQuestionGUI $question_object)
568 {
569 $setting = new ilSetting('assessment');
570 $types = explode(',', $setting->get('assessment_scoring_adjustment'));
571 require_once './Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php';
572 $type_def = array();
573 foreach ($types as $type) {
575 }
576
577 $type = $question_object->getQuestionType();
578 if (in_array($type, $type_def)) {
579 return true;
580 }
581 return false;
582 }
583}
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Basic GUI class for assessment questions.
getQuestionType()
Returns the question type string.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
Abstract basic class which is to be extended by the concrete assessment question type classes.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static instantiateQuestionGUI($a_question_id)
Creates an instance of a question gui with a given question id.
Question page GUI class.
Confirmation screen class.
setConfirm($a_txt, $a_cmd, $a_id="")
Set confirmation button command and text.
setFormAction($a_form_action)
setCancel($a_txt, $a_cmd, $a_id="")
Set cancel button command and text.
setHeaderText($a_headertext)
Set Set header text.
addHiddenItem($a_post_var, $a_value)
Add hidden item.
getHTML()
Get confirmation screen HTML.
This class represents a hidden form property in a property form.
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
static getQuestionTypeByTypeId($type_id)
static getSyntaxStylePath()
get syntax style path
static getContentStylePath($a_style_id, $add_random=true, $add_token=true)
get content style path
static accessViolationRedirect()
This class represents a property form user interface.
ILIAS Setting Class.
special template class to simplify handling of ITX/PEAR
populatePageTitleAndDescription(assQuestionGUI $questionGUI)
supportsAdjustment(\assQuestionGUI $question_object)
Returns if the given question object support scoring adjustment.
allowedInAdjustment(\assQuestionGUI $question_object)
Returns if the question type is allowed for adjustments in the global test administration.
showQuestion(ilPropertyFormGUI $form=null)
getSolutions(assQuestion $question)
addHiddenItemsFromArray(ilConfirmationGUI $gui, $array, $curPath=array())
buildQuestionCorrectionForm(assQuestionGUI $questionGUI)
setCorrectionTabsContext(assQuestionGUI $questionGUI, $activeTabId)
__construct(\ILIAS\DI\Container $DIC, ilObjTest $testOBJ)
ilTestCorrectionsGUI constructor.
Class ilTestScoring.
$txt
Definition: error.php:13
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
Interface ilObjAnswerScoringAdjustable.
Interface ilObjQuestionScoringAdjustable.
exit
Definition: login.php:29
if($format !==null) $name
Definition: metadata.php:230
Class HTTPServicesTest.
Class ChatMainBarProvider \MainMenu\Provider.
$type
$response
$lng
if(isset($_FILES['img_file']['size']) && $_FILES['img_file']['size'] > 0) $tpl