ILIAS  release_7 Revision v7.30-3-g800a261c036
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->setQuestionRemoveRowButtonEnabled(true);
87 $table_gui->init();
88
89 $table_gui->setData($this->getQuestions());
90
91 $rendered_gui_component = $table_gui->getHTML();
92 } else {
93 $lng = $this->DIC->language();
94 $txt = $lng->txt('tst_corrections_incompatible_question_set_type');
95
96 $infoBox = $ui->factory()->messageBox()->info($txt);
97
98 $rendered_gui_component = $ui->renderer()->render($infoBox);
99 }
100
101 $ui->mainTemplate()->setContent($rendered_gui_component);
102 }
103
104 protected function showQuestion(ilPropertyFormGUI $form = null)
105 {
106 $questionGUI = $this->getQuestion((int) $_GET['qid']);
107
108 $this->setCorrectionTabsContext($questionGUI, 'question');
109
110 if ($form === null) {
111 $form = $this->buildQuestionCorrectionForm($questionGUI);
112 }
113
114 $this->populatePageTitleAndDescription($questionGUI);
115 $this->DIC->ui()->mainTemplate()->setContent($form->getHTML());
116 }
117
118 protected function saveQuestion()
119 {
120 $questionGUI = $this->getQuestion((int) $_GET['qid']);
121
122 $form = $this->buildQuestionCorrectionForm($questionGUI);
123
124 $form->setValuesByPost();
125
126 if (!$form->checkInput()) {
127 $questionGUI->prepareReprintableCorrectionsForm($form);
128
129 $this->showQuestion($form);
130 return;
131 }
132
133 $questionGUI->saveCorrectionsFormProperties($form);
134 $questionGUI->object->setPoints($questionGUI->object->getMaximumPoints());
135 $questionGUI->object->saveToDb();
136
137 $scoring = new ilTestScoring($this->testOBJ);
138 $scoring->setPreserveManualScores(false);
139 $scoring->setQuestionId($questionGUI->object->getId());
140 $scoring->recalculateSolutions();
141
142 $this->DIC->ctrl()->redirect($this, 'showQuestion');
143 }
144
145 protected function buildQuestionCorrectionForm(assQuestionGUI $questionGUI)
146 {
147 $form = new ilPropertyFormGUI();
148 $form->setFormAction($this->DIC->ctrl()->getFormAction($this));
149 $form->setId('tst_question_correction');
150
151 $form->setTitle($this->DIC->language()->txt('tst_corrections_qst_form'));
152
153 $hiddenQid = new ilHiddenInputGUI('qid');
154 $hiddenQid->setValue($questionGUI->object->getId());
155 $form->addItem($hiddenQid);
156
157 $questionGUI->populateCorrectionsFormProperties($form);
158
159 $scoring = new ilTestScoring($this->testOBJ);
160 $scoring->setQuestionId($questionGUI->object->getId());
161
162 if ($scoring->getNumManualScorings()) {
163 $form->addCommandButton('confirmManualScoringReset', $this->DIC->language()->txt('save'));
164 } else {
165 $form->addCommandButton('saveQuestion', $this->DIC->language()->txt('save'));
166 }
167
168 return $form;
169 }
170
171 protected function addHiddenItemsFromArray(ilConfirmationGUI $gui, $array, $curPath = array())
172 {
173 foreach ($array as $name => $value) {
174 if ($name == 'cmd' && !count($curPath)) {
175 continue;
176 }
177
178 if (count($curPath)) {
179 $name = "[{$name}]";
180 }
181
182 if (is_array($value)) {
183 $nextPath = array_merge($curPath, array($name));
184 $this->addHiddenItemsFromArray($gui, $value, $nextPath);
185 } else {
186 $postVar = implode('', $curPath) . $name;
187 $gui->addHiddenItem($postVar, $value);
188 }
189 }
190 }
191
192 protected function confirmManualScoringReset()
193 {
194 $questionGUI = $this->getQuestion((int) $_GET['qid']);
195
196 $this->setCorrectionTabsContext($questionGUI, 'question');
197
198 $scoring = new ilTestScoring($this->testOBJ);
199 $scoring->setQuestionId($questionGUI->object->getId());
200
201 $confirmation = sprintf(
202 $this->DIC->language()->txt('tst_corrections_manscore_reset_warning'),
203 $scoring->getNumManualScorings(),
204 $questionGUI->object->getTitle(),
205 $questionGUI->object->getId()
206 );
207
208 $gui = new ilConfirmationGUI();
209 $gui->setHeaderText($confirmation);
210 $gui->setFormAction($this->DIC->ctrl()->getFormAction($this));
211 $gui->setCancel($this->DIC->language()->txt('cancel'), 'showQuestion');
212 $gui->setConfirm($this->DIC->language()->txt('confirm'), 'saveQuestion');
213
214 $this->addHiddenItemsFromArray($gui, $_POST);
215
216 $this->DIC->ui()->mainTemplate()->setContent($gui->getHTML());
217 }
218
219 protected function showSolution()
220 {
221 $questionGUI = $this->getQuestion((int) $_GET['qid']);
222
223 $this->setCorrectionTabsContext($questionGUI, 'solution');
224
225 $pageGUI = new ilAssQuestionPageGUI($questionGUI->object->getId());
226 $pageGUI->setRenderPageContainer(false);
227 $pageGUI->setEditPreview(true);
228 $pageGUI->setEnabledTabs(false);
229
230 $solutionHTML = $questionGUI->getSolutionOutput(
231 0,
232 null,
233 false,
234 false,
235 true,
236 false,
237 true,
238 false,
239 true
240 );
241
242 $pageGUI->setQuestionHTML(array($questionGUI->object->getId() => $solutionHTML));
243 $pageGUI->setPresentationTitle($questionGUI->object->getTitle());
244
245 $tpl = new ilTemplate('tpl.tst_corrections_solution_presentation.html', true, true, 'Modules/Test');
246 $tpl->setVariable('SOLUTION_PRESENTATION', $pageGUI->preview());
247
248 $this->populatePageTitleAndDescription($questionGUI);
249
250 $this->DIC->ui()->mainTemplate()->setContent($tpl->get());
251
252 $this->DIC->ui()->mainTemplate()->setCurrentBlock("ContentStyle");
254 $this->DIC->ui()->mainTemplate()->setVariable("LOCATION_CONTENT_STYLESHEET", $stylesheet);
255 $this->DIC->ui()->mainTemplate()->parseCurrentBlock();
256
257 $this->DIC->ui()->mainTemplate()->setCurrentBlock("SyntaxStyle");
259 $this->DIC->ui()->mainTemplate()->setVariable("LOCATION_SYNTAX_STYLESHEET", $stylesheet);
260 $this->DIC->ui()->mainTemplate()->parseCurrentBlock();
261 }
262
263 protected function showAnswerStatistic()
264 {
265 $questionGUI = $this->getQuestion((int) $_GET['qid']);
266 $solutions = $this->getSolutions($questionGUI->object);
267
268 $this->setCorrectionTabsContext($questionGUI, 'answers');
269
270 $tablesHtml = '';
271
272 foreach ($questionGUI->getSubQuestionsIndex() as $subQuestionIndex) {
273 $table = $questionGUI->getAnswerFrequencyTableGUI(
274 $this,
275 'showAnswerStatistic',
276 $solutions,
277 $subQuestionIndex
278 );
279
280 $tablesHtml .= $table->getHTML() . $table->getAdditionalHtml();
281 }
282
283 $this->populatePageTitleAndDescription($questionGUI);
284 $this->DIC->ui()->mainTemplate()->setContent($tablesHtml);
285 }
286
287 protected function addAnswerAsynch()
288 {
289 $response = new stdClass();
290
291 $form = new ilAddAnswerModalFormGUI();
292 $form->build();
293 $form->setValuesByPost();
294
295 if (!$form->checkInput()) {
296 $uid = md5($form->getInput('answer'));
297
298 $form->setId($uid);
299 $form->setFormAction($this->DIC->ctrl()->getFormAction($this, 'addAnswerAsynch'));
300
301 $alert = $this->DIC->ui()->factory()->messageBox()->failure(
302 $this->DIC->language()->txt('form_input_not_valid')
303 );
304
305 $bodyTpl = new ilTemplate('tpl.tst_corr_addanswermodal.html', true, true, 'Modules/TestQuestionPool');
306 $bodyTpl->setVariable('MESSAGE', $this->DIC->ui()->renderer()->render($alert));
307 $bodyTpl->setVariable('FORM', $form->getHTML());
308 $bodyTpl->setVariable('BODY_UID', $uid);
309
310 $response->result = false;
311 $response->html = $bodyTpl->get();
312
313 echo json_encode($response);
314 exit;
315 }
316
317 $qid = (int) $form->getInput('qid');
318
319 if (!$this->checkQuestion($qid)) {
320 $response->html = '';
321 $response->result = false;
322
323 echo json_encode($response);
324 exit;
325 }
326
327 $questionGUI = $this->getQuestion($qid);
328
329 $qIndex = (int) $form->getInput('qindex');
330 $points = (float) $form->getInput('points');
331 $answerOption = $form->getInput('answer');
332
333 if ($questionGUI->object->isAddableAnswerOptionValue($qIndex, $answerOption)) {
334 $questionGUI->object->addAnswerOptionValue($qIndex, $answerOption, $points);
335 $questionGUI->object->saveToDb();
336 }
337
338 $scoring = new ilTestScoring($this->testOBJ);
339 $scoring->setPreserveManualScores(true);
340 $scoring->recalculateSolutions();
341
342 $response->result = true;
343
344 echo json_encode($response);
345 exit;
346 }
347
348 protected function confirmQuestionRemoval()
349 {
350 $this->DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_CORRECTION);
351
352 $questionGUI = $this->getQuestion((int) $_GET['qid']);
353
354 $confirmation = sprintf(
355 $this->DIC->language()->txt('tst_corrections_qst_remove_confirmation'),
356 $questionGUI->object->getTitle(),
357 $questionGUI->object->getId()
358 );
359
360 $buttons = array(
361 $this->DIC->ui()->factory()->button()->standard(
362 $this->DIC->language()->txt('confirm'),
363 $this->DIC->ctrl()->getLinkTarget($this, 'performQuestionRemoval')
364 ),
365 $this->DIC->ui()->factory()->button()->standard(
366 $this->DIC->language()->txt('cancel'),
367 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestionList')
368 )
369 );
370
371 $this->DIC->ui()->mainTemplate()->setContent($this->DIC->ui()->renderer()->render(
372 $this->DIC->ui()->factory()->messageBox()->confirmation($confirmation)->withButtons($buttons)
373 ));
374 }
375
376 protected function performQuestionRemoval()
377 {
378 global $DIC; /* @var ILIAS\DI\Container $DIC */
379
380 $questionGUI = $this->getQuestion((int) $_GET['qid']);
381 $scoring = new ilTestScoring($this->testOBJ);
382
383 $participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
384 $participantData->load($this->testOBJ->getTestId());
385
386 // remove question solutions
387 $questionGUI->object->removeAllExistingSolutions();
388
389 // remove test question results
390 $scoring->removeAllQuestionResults($questionGUI->object->getId());
391
392 // remove question from test and reindex remaining questions
393 $this->testOBJ->removeQuestion($questionGUI->object->getId());
394 $reindexedSequencePositionMap = $this->testOBJ->reindexFixedQuestionOrdering();
395 $this->testOBJ->loadQuestions();
396
397 // remove questions from all sequences
398 $this->testOBJ->removeQuestionFromSequences(
399 $questionGUI->object->getId(),
400 $participantData->getActiveIds(),
401 $reindexedSequencePositionMap
402 );
403
404 // update pass and test results
405 $scoring->updatePassAndTestResults($participantData->getActiveIds());
406
407 // trigger learning progress
408 ilLPStatusWrapper::_refreshStatus($this->testOBJ->getId(), $participantData->getUserIds());
409
410 // finally delete the question itself
411 $questionGUI->object->delete($questionGUI->object->getId());
412
413 // check for empty test and set test offline
414 if (!count($this->testOBJ->getTestQuestions())) {
415 $this->testOBJ->setOnline(false);
416 $this->testOBJ->saveToDb(true);
417 }
418
419 $this->DIC->ctrl()->setParameter($this, 'qid', '');
420 $this->DIC->ctrl()->redirect($this, 'showQuestionList');
421 }
422
423 protected function setCorrectionTabsContext(assQuestionGUI $questionGUI, $activeTabId)
424 {
425 $this->DIC->tabs()->clearTargets();
426 $this->DIC->tabs()->clearSubTabs();
427
428 $this->DIC->help()->setScreenIdComponent("tst");
429 $this->DIC->help()->setScreenId("scoringadjust");
430 $this->DIC->help()->setSubScreenId($activeTabId);
431
432
433 $this->DIC->tabs()->setBackTarget(
434 $this->DIC->language()->txt('back'),
435 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestionList')
436 );
437
438 $this->DIC->tabs()->addTab(
439 'question',
440 $this->DIC->language()->txt('tst_corrections_tab_question'),
441 $this->DIC->ctrl()->getLinkTarget($this, 'showQuestion')
442 );
443
444 $this->DIC->tabs()->addTab(
445 'solution',
446 $this->DIC->language()->txt('tst_corrections_tab_solution'),
447 $this->DIC->ctrl()->getLinkTarget($this, 'showSolution')
448 );
449
450 if ($questionGUI->isAnswerFreuqencyStatisticSupported()) {
451 $this->DIC->tabs()->addTab(
452 'answers',
453 $this->DIC->language()->txt('tst_corrections_tab_statistics'),
454 $this->DIC->ctrl()->getLinkTarget($this, 'showAnswerStatistic')
455 );
456 }
457
458 $this->DIC->tabs()->activateTab($activeTabId);
459 }
460
464 protected function populatePageTitleAndDescription(assQuestionGUI $questionGUI)
465 {
466 $this->DIC->ui()->mainTemplate()->setTitle($questionGUI->object->getTitle());
467 $this->DIC->ui()->mainTemplate()->setDescription($questionGUI->outQuestionType());
468 }
469
474 protected function checkQuestion($qId)
475 {
476 if (!$this->testOBJ->isTestQuestion($qId)) {
477 return false;
478 }
479
480 $questionGUI = $this->getQuestion($qId);
481
482 if (!$this->supportsAdjustment($questionGUI)) {
483 return false;
484 }
485
486 if (!$this->allowedInAdjustment($questionGUI)) {
487 return false;
488 }
489
490 return true;
491 }
492
497 protected function getQuestion($qId)
498 {
499 $question = assQuestion::instantiateQuestionGUI($qId);
500 $question->object->setObjId($this->testOBJ->getId());
501
502 return $question;
503 }
504
505 protected function getSolutions(assQuestion $question)
506 {
507 $solutionRows = array();
508
509 foreach ($this->testOBJ->getParticipants() as $activeId => $participantData) {
510 $passesSelector = new ilTestPassesSelector($this->DIC->database(), $this->testOBJ);
511 $passesSelector->setActiveId($activeId);
512 $passesSelector->loadLastFinishedPass();
513
514 foreach ($passesSelector->getClosedPasses() as $pass) {
515 foreach ($question->getSolutionValues($activeId, $pass) as $row) {
516 $solutionRows[] = $row;
517 }
518 }
519 }
520
521 return $solutionRows;
522 }
523
527 protected function getQuestions() : array
528 {
529 $questions = array();
530
531 foreach ($this->testOBJ->getTestQuestions() as $questionData) {
532 $questionGUI = $this->getQuestion($questionData['question_id']);
533
534 if (!$this->supportsAdjustment($questionGUI)) {
535 continue;
536 }
537
538 if (!$this->allowedInAdjustment($questionGUI)) {
539 continue;
540 }
541
542 $questions[] = $questionData;
543 }
544
545 return $questions;
546 }
547
555 protected function supportsAdjustment(\assQuestionGUI $question_object)
556 {
557 return ($question_object instanceof ilGuiQuestionScoringAdjustable
558 || $question_object instanceof ilGuiAnswerScoringAdjustable)
559 && ($question_object->object instanceof ilObjQuestionScoringAdjustable
560 || $question_object->object instanceof ilObjAnswerScoringAdjustable);
561 }
562
569 protected function allowedInAdjustment(\assQuestionGUI $question_object)
570 {
571 $setting = new ilSetting('assessment');
572 $types = explode(',', $setting->get('assessment_scoring_adjustment'));
573 require_once './Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php';
574 $type_def = array();
575 foreach ($types as $type) {
577 }
578
579 $type = $question_object->getQuestionType();
580 if (in_array($type, $type_def)) {
581 return true;
582 }
583 return false;
584 }
585}
$_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.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
exit
Definition: login.php:29
if($format !==null) $name
Definition: metadata.php:230
Class HTTPServicesTest.
Class ChatMainBarProvider \MainMenu\Provider.
$type
$response
$lng