ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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");
253  $stylesheet = ilObjStyleSheet::getContentStylePath(0);
254  $this->DIC->ui()->mainTemplate()->setVariable("LOCATION_CONTENT_STYLESHEET", $stylesheet);
255  $this->DIC->ui()->mainTemplate()->parseCurrentBlock();
256 
257  $this->DIC->ui()->mainTemplate()->setCurrentBlock("SyntaxStyle");
258  $stylesheet = ilObjStyleSheet::getSyntaxStylePath();
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 }
static getContentStylePath($a_style_id, $add_random=true, $add_token=true)
get content style path
addHiddenItem($a_post_var, $a_value)
Add hidden item.
exit
Definition: login.php:29
This class represents a property form user interface.
buildQuestionCorrectionForm(assQuestionGUI $questionGUI)
$type
addHiddenItemsFromArray(ilConfirmationGUI $gui, $array, $curPath=array())
$_GET["client_id"]
Abstract basic class which is to be extended by the concrete assessment question type classes...
Class ChatMainBarProvider .
static getQuestionTypeByTypeId($type_id)
getTestId()
Gets the database id of the additional test data.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
setQuestionRemoveRowButtonEnabled(bool $questionRemoveRowButtonEnabled)
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
static accessViolationRedirect()
Question page GUI class.
if($format !==null) $name
Definition: metadata.php:230
This class represents a hidden form property in a property form.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
setCorrectionTabsContext(assQuestionGUI $questionGUI, $activeTabId)
$lng
Class HTTPServicesTest.
Interface ilObjAnswerScoringAdjustable.
getSolutions(assQuestion $question)
allowedInAdjustment(\assQuestionGUI $question_object)
Returns if the question type is allowed for adjustments in the global test administration.
setRenderPageContainer($a_val)
Set render page container.
getQuestionType()
Returns the question type string.
static getSyntaxStylePath()
get syntax style path
Basic GUI class for assessment questions.
$txt
Definition: error.php:13
Class ilTestScoring.
supportsAdjustment(\assQuestionGUI $question_object)
Returns if the given question object support scoring adjustment.
populatePageTitleAndDescription(assQuestionGUI $questionGUI)
__construct(\ILIAS\DI\Container $DIC, ilObjTest $testOBJ)
ilTestCorrectionsGUI constructor.
Interface ilObjQuestionScoringAdjustable.
getRefId()
get reference id public
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$response
$_POST["username"]
static instantiateQuestionGUI($a_question_id)
Creates an instance of a question gui with a given question id.
showQuestion(ilPropertyFormGUI $form=null)
Confirmation screen class.