ILIAS  release_8 Revision v8.24
class.ilTestScoringGUI.php
Go to the documentation of this file.
1<?php
2
19include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
20include_once "./Modules/Test/classes/class.ilTestServiceGUI.php";
21
33{
34 public const PART_FILTER_ACTIVE_ONLY = 1;
35 public const PART_FILTER_INACTIVE_ONLY = 2;
36 public const PART_FILTER_ALL_USERS = 3; // default
39 //const PART_FILTER_MANSCORING_PENDING = 6;
40
44 protected $testAccess;
45
54 public function __construct(ilObjTest $a_object)
55 {
56 parent::__construct($a_object);
57 }
58
62 public function getTestAccess(): ilTestAccess
63 {
64 return $this->testAccess;
65 }
66
70 public function setTestAccess($testAccess)
71 {
72 $this->testAccess = $testAccess;
73 }
74
78 protected function buildSubTabs($active_sub_tab = 'man_scoring_by_qst')
79 {
83 global $DIC;
84 $ilTabs = $DIC['ilTabs'];
85
86 $ilTabs->addSubTab('man_scoring_by_qst', $this->lng->txt('tst_man_scoring_by_qst'), $this->ctrl->getLinkTargetByClass('ilTestScoringByQuestionsGUI', 'showManScoringByQuestionParticipantsTable'));
87 $ilTabs->addSubTab('man_scoring', $this->lng->txt('tst_man_scoring_by_part'), $this->ctrl->getLinkTargetByClass('ilTestScoringGUI', 'showManScoringParticipantsTable'));
88 $ilTabs->setSubTabActive($active_sub_tab);
89 }
90
91 private function fetchActiveIdParameter(): int
92 {
93 global $DIC;
94 $ilCtrl = $DIC['ilCtrl'];
95
96 // fetch active_id
97
98 if (!$this->testrequest->isset('active_id') || !(int) $this->testrequest->raw('active_id')) {
99 // allow only write access
100 $this->tpl->setOnScreenMessage('failure', 'no active id given!', true);
101 $ilCtrl->redirectByClass("ilobjtestgui", "infoScreen");
102 } else {
103 $activeId = (int) $this->testrequest->raw('active_id');
104 }
105
106 return $activeId;
107 }
108
109 private function fetchPassParameter($activeId)
110 {
111 // fetch pass nr
112
113 $maxPass = $this->object->_getMaxPass($activeId);
114 if ($this->testrequest->isset("pass") && 0 <= (int) $this->testrequest->raw("pass") && $maxPass >= (int) $this->testrequest->raw("pass")) {
115 $pass = $this->testrequest->raw("pass");
116 } elseif ($this->object->getPassScoring() == SCORE_LAST_PASS) {
117 $pass = $maxPass;
118 } else {
119 $pass = $this->object->_getResultPass($activeId);
120 }
121
122 return $pass;
123 }
124
128 public function executeCommand()
129 {
130 global $DIC; /* @var ILIAS\DI\Container $DIC */
131
132 if (!$this->getTestAccess()->checkScoreParticipantsAccess()) {
134 }
135
136 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
138 // allow only if at least one question type is marked for manual scoring
139 $this->tpl->setOnScreenMessage('failure', $this->lng->txt("manscoring_not_allowed"), true);
140 $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
141 }
142
143 $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_MANUAL_SCORING);
144 $this->buildSubTabs($this->getActiveSubTabId());
145
146 $nextClass = $this->ctrl->getNextClass($this);
147 $command = $this->ctrl->getCmd($this->getDefaultCommand());
148
149 switch ($nextClass) {
150 default:
151 $this->$command();
152 break;
153 }
154 }
155
159 protected function getDefaultCommand(): string
160 {
161 return 'manscoring';
162 }
163
167 protected function getActiveSubTabId(): string
168 {
169 return 'man_scoring';
170 }
171
173 {
174 global $DIC;
175 $tpl = $DIC['tpl'];
176
177 $table = $this->buildManScoringParticipantsTable(true);
178
179 $tpl->setContent($table->getHTML());
180 }
181
183 {
184 $table = $this->buildManScoringParticipantsTable(false);
185
186 $table->resetOffset();
187 $table->writeFilterToSession();
188
190 }
191
193 {
194 $table = $this->buildManScoringParticipantsTable(false);
195
196 $table->resetOffset();
197 $table->resetFilter();
198
200 }
201
203 {
204 global $DIC;
205 $tpl = $DIC['tpl'];
206 $lng = $DIC['lng'];
207
208 $activeId = $this->fetchActiveIdParameter();
209
210 if (!$this->getTestAccess()->checkScoreParticipantsAccessForActiveId($activeId)) {
212 }
213
214 $pass = $this->fetchPassParameter($activeId);
215
216 $contentHTML = '';
217
218 // pass overview table
219 require_once 'Modules/Test/classes/tables/class.ilTestPassManualScoringOverviewTableGUI.php';
220 $table = new ilTestPassManualScoringOverviewTableGUI($this, 'showManScoringParticipantScreen');
221
222 $userId = $this->object->_getUserIdFromActiveId($activeId);
223 $userFullname = $this->object->userLookupFullName($userId, false, true);
224 $tableTitle = sprintf($lng->txt('tst_pass_overview_for_participant'), $userFullname);
225 $table->setTitle($tableTitle);
226
227 $passOverviewData = $this->service->getPassOverviewData($activeId);
228 $table->setData($passOverviewData['passes']);
229
230 $contentHTML .= $table->getHTML() . '<br />';
231
232 // pass scoring form
233
234 if ($form === null) {
235 $questionGuiList = $this->service->getManScoringQuestionGuiList($activeId, $pass);
236 $form = $this->buildManScoringParticipantForm($questionGuiList, $activeId, $pass, true);
237 }
238
239 $contentHTML .= $form->getHTML();
240
241 // set content
242
243 $tpl->setContent($contentHTML);
244 }
245
250 private function saveManScoringParticipantScreen($redirect = true)
251 {
252 global $DIC;
253 $ilCtrl = $DIC['ilCtrl'];
254 $lng = $DIC['lng'];
255
256 $activeId = $this->fetchActiveIdParameter();
257
258 if (!$this->getTestAccess()->checkScoreParticipantsAccessForActiveId($activeId)) {
260 }
261
262 $pass = $this->fetchPassParameter($activeId);
263
264 $questionGuiList = $this->service->getManScoringQuestionGuiList($activeId, $pass);
265 $form = $this->buildManScoringParticipantForm($questionGuiList, $activeId, $pass, false);
266
267 $form->setValuesByPost();
268
269 if (!$form->checkInput()) {
270 $this->tpl->setOnScreenMessage('failure', sprintf($lng->txt('tst_save_manscoring_failed'), $pass + 1));
272 return false;
273 }
274
275 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
276
277 $maxPointsByQuestionId = array();
278 $maxPointsExceeded = false;
279 foreach ($questionGuiList as $questionId => $questionGui) {
280 $reachedPoints = $form->getItemByPostVar("question__{$questionId}__points")->getValue();
281 $maxPoints = assQuestion::_getMaximumPoints($questionId);
282
283 if ($reachedPoints > $maxPoints) {
284 $maxPointsExceeded = true;
285
286 $form->getItemByPostVar("question__{$questionId}__points")->setAlert(sprintf(
287 $lng->txt('tst_manscoring_maxpoints_exceeded_input_alert'),
288 $maxPoints
289 ));
290 }
291
292 $maxPointsByQuestionId[$questionId] = $maxPoints;
293 }
294
295 if ($maxPointsExceeded) {
296 $this->tpl->setOnScreenMessage('failure', sprintf($lng->txt('tst_save_manscoring_failed'), $pass + 1));
298 return false;
299 }
300
301 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
302
303 foreach ($questionGuiList as $questionId => $questionGui) {
304 $reachedPoints = $form->getItemByPostVar("question__{$questionId}__points")->getValue();
305
306 $finalized = (bool) $form->getItemByPostVar("{$questionId}__evaluated")->getchecked();
307
308 // fix #35543: save manual points only if they differ from the existing points
309 // this prevents a question being set to "answered" if only feedback is entered
310 $oldPoints = assQuestion::_getReachedPoints($activeId, $questionId, $pass);
311 if ($reachedPoints != $oldPoints) {
313 $activeId,
314 $questionId,
315 $reachedPoints,
316 $maxPointsByQuestionId[$questionId],
317 $pass,
318 true,
319 $this->object->areObligationsEnabled()
320 );
321 }
322
323 $feedback = ilUtil::stripSlashes(
324 (string) $form->getItemByPostVar("question__{$questionId}__feedback")->getValue(),
325 false,
327 );
328
329 $this->object->saveManualFeedback($activeId, (int) $questionId, (int) $pass, $feedback, $finalized, true);
330
331 $notificationData[$questionId] = array(
332 'points' => $reachedPoints, 'feedback' => $feedback
333 );
334 }
335
336 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
337 include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
339 $this->object->getId(),
341 );
342
343 $manScoringDone = $form->getItemByPostVar("manscoring_done")->getChecked();
344 ilTestService::setManScoringDone($activeId, $manScoringDone);
345
346 $manScoringNotify = $form->getItemByPostVar("manscoring_notify")->getChecked();
347 if ($manScoringNotify) {
348 require_once 'Modules/Test/classes/notifications/class.ilTestManScoringParticipantNotification.php';
349
350 $notification = new ilTestManScoringParticipantNotification(
351 $this->object->_getUserIdFromActiveId($activeId),
352 $this->object->getRefId()
353 );
354
355 $notification->setAdditionalInformation(array(
356 'test_title' => $this->object->getTitle(),
357 'test_pass' => $pass + 1,
358 'questions_gui_list' => $questionGuiList,
359 'questions_scoring_data' => $notificationData
360 ));
361
362 $notification->send();
363 }
364
365 require_once './Modules/Test/classes/class.ilTestScoring.php';
366 $scorer = new ilTestScoring($this->object);
367 $scorer->setPreserveManualScores(true);
368 $scorer->recalculateSolutions();
369
370 if ($this->object->getAnonymity() == 0) {
372 $name_real_or_anon = $user_name['firstname'] . ' ' . $user_name['lastname'];
373 } else {
374 $name_real_or_anon = $lng->txt('anonymous');
375 }
376 $this->tpl->setOnScreenMessage('success', sprintf($lng->txt('tst_saved_manscoring_successfully'), $pass + 1, $name_real_or_anon), true);
377 if ($redirect == true) {
378 $ilCtrl->redirect($this, 'showManScoringParticipantScreen');
379 }
380 return true;
381 }
382
384 {
385 global $DIC;
386 $ilCtrl = $DIC['ilCtrl'];
387
388 $table = $this->buildManScoringParticipantsTable(true);
389
390 if ($this->saveManScoringParticipantScreen(false)) {
391 $participantData = $table->getInternalyOrderedDataValues();
392
393 $nextIndex = null;
394 foreach ($participantData as $index => $participant) {
395 if ($participant['active_id'] == $this->testrequest->raw('active_id')) {
396 $nextIndex = $index + 1;
397 break;
398 }
399 }
400
401 if ($nextIndex && isset($participantData[$nextIndex])) {
402 $ilCtrl->setParameter($this, 'active_id', $participantData[$nextIndex]['active_id']);
403 $ilCtrl->redirect($this, 'showManScoringParticipantScreen');
404 }
405
406 $ilCtrl->redirectByClass("iltestscoringgui", "showManScoringParticipantsTable");
407 }
408 }
409
411 {
412 global $DIC;
413 $ilCtrl = $DIC['ilCtrl'];
414
415 if ($this->saveManScoringParticipantScreen(false)) {
416 $ilCtrl->redirectByClass("iltestscoringgui", "showManScoringParticipantsTable");
417 }
418 }
419
420 private function buildManScoringParticipantForm($questionGuiList, $activeId, $pass, $initValues = false): ilPropertyFormGUI
421 {
422 global $DIC;
423 $ilCtrl = $DIC['ilCtrl'];
424 $lng = $DIC['lng'];
425
426 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
427 require_once 'Services/Form/classes/class.ilFormSectionHeaderGUI.php';
428 require_once 'Services/Form/classes/class.ilCustomInputGUI.php';
429 require_once 'Services/Form/classes/class.ilCheckboxInputGUI.php';
430 require_once 'Services/Form/classes/class.ilTextInputGUI.php';
431 require_once 'Services/Form/classes/class.ilTextAreaInputGUI.php';
432
433 $ilCtrl->setParameter($this, 'active_id', $activeId);
434 $ilCtrl->setParameter($this, 'pass', $pass);
435
436 $form = new ilPropertyFormGUI();
437 $form->setFormAction($ilCtrl->getFormAction($this));
438
439 $form->setTitle(sprintf($lng->txt('manscoring_results_pass'), $pass + 1));
440 $form->setTableWidth('100%');
441
442 foreach ($questionGuiList as $questionId => $questionGUI) {
443 $questionHeader = sprintf($lng->txt('tst_manscoring_question_section_header'), $questionGUI->object->getTitleForHTMLOutput());
444 $questionSolution = $questionGUI->getSolutionOutput($activeId, $pass, false, false, true, false, false, true);
445 $bestSolution = $questionGUI->object->getSuggestedSolutionOutput();
446
447 $feedback = $this->object->getSingleManualFeedback($activeId, $questionId, $pass);
448
449 $disabled = false;
450 if (isset($feedback['finalized_evaluation']) && $feedback['finalized_evaluation'] == 1) {
451 $disabled = true;
452 }
453
454 $sect = new ilFormSectionHeaderGUI();
455 $sect->setTitle($questionHeader . ' [' . $this->lng->txt('question_id_short') . ': ' . $questionGUI->object->getId() . ']');
456 $form->addItem($sect);
457
458 $cust = new ilCustomInputGUI($lng->txt('tst_manscoring_input_question_and_user_solution'));
459 $cust->setHtml($questionSolution);
460 $form->addItem($cust);
461
462 if ($questionGUI instanceof assTextQuestionGUI && $this->object->getAutosave()) {
463 $aresult_output = $questionGUI->getAutoSavedSolutionOutput(
464 $activeId,
465 $pass,
466 false,
467 false,
468 false,
469 false,
470 false,
471 false,
472 false
473 );
474 $cust = new ilCustomInputGUI($this->lng->txt('autosavecontent'));
475 $cust->setHtml($aresult_output);
476 $form->addItem($cust);
477 }
478
479 $text = new ilTextInputGUI($this->lng->txt('tst_change_points_for_question'), "question__{$questionId}__points");
480 if ($initValues) {
481 $text->setValue((string) assQuestion::_getReachedPoints($activeId, $questionId, $pass));
482 }
483 if ($disabled) {
484 $text->setDisabled($disabled);
485 }
486 $form->addItem($text);
487
488 $nonedit = new ilNonEditableValueGUI($lng->txt('tst_manscoring_input_max_points_for_question'), "question__{$questionId}__maxpoints");
489 if ($initValues) {
490 $nonedit->setValue(assQuestion::_getMaximumPoints($questionId));
491 }
492 $form->addItem($nonedit);
493
494 $area = new ilTextAreaInputGUI($lng->txt('set_manual_feedback'), "question__{$questionId}__feedback");
495 $area->setUseRTE(true);
496 if ($initValues) {
497 $area->setValue(ilObjTest::getSingleManualFeedback((int) $activeId, (int) $questionId, (int) $pass)['feedback'] ?? '');
498 }
499 if ($disabled) {
500 $area->setDisabled($disabled);
501 }
502 $form->addItem($area);
503
504 $check = new ilCheckboxInputGUI($lng->txt('finalized_evaluation'), "{$questionId}__evaluated");
505 if ($disabled) {
506 $check->setChecked(true);
507 }
508 $form->addItem($check);
509
510 if (strlen(trim($bestSolution))) {
511 $cust = new ilCustomInputGUI($lng->txt('tst_show_solution_suggested'));
512 $cust->setHtml($bestSolution);
513 $form->addItem($cust);
514 }
515 }
516
517 $sect = new ilFormSectionHeaderGUI();
518 $sect->setTitle($lng->txt('tst_participant'));
519 $form->addItem($sect);
520
521 $check = new ilCheckboxInputGUI($lng->txt('set_manscoring_done'), 'manscoring_done');
522 if ($initValues && ilTestService::isManScoringDone($activeId)) {
523 $check->setChecked(true);
524 }
525 $form->addItem($check);
526
527 $check = new ilCheckboxInputGUI($lng->txt('tst_manscoring_user_notification'), 'manscoring_notify');
528 $form->addItem($check);
529
530 $form->addCommandButton('saveManScoringParticipantScreen', $lng->txt('save'));
531 $form->addCommandButton('saveReturnManScoringParticipantScreen', $lng->txt('save_return'));
532 $form->addCommandButton('saveNextManScoringParticipantScreen', $lng->txt('save_and_next'));
533
534 return $form;
535 }
536
538 {
539 }
540
545 {
546 require_once 'Modules/Test/classes/tables/class.ilTestManScoringParticipantsTableGUI.php';
547 $table = new ilTestManScoringParticipantsTableGUI($this);
548
549 if ($withData) {
550 $participantStatusFilterValue = $table->getFilterItemByPostVar('participant_status')->getValue();
551
552 require_once 'Modules/Test/classes/class.ilTestParticipantList.php';
553 $participant_list = new ilTestParticipantList($this->object);
554
555 $participant_list->initializeFromDbRows(
556 $this->object->getTestParticipantsForManualScoring($participantStatusFilterValue)
557 );
558
559 $filtered_participant_list = $participant_list->getAccessFilteredList(
561 );
562
563 $table->setData($filtered_participant_list->getParticipantsTableRows());
564 }
565
566 return $table;
567 }
568}
$check
Definition: buildRTE.php:81
static _getMaximumPoints(int $question_id)
Returns the maximum points, a learner can reach answering the question.
static _getReachedPoints(int $active_id, int $question_id, int $pass)
static _setReachedPoints(int $active_id, int $question_id, float $points, float $maxpoints, int $pass, bool $manualscoring, bool $obligationsEnabled)
Sets the points, a learner has reached answering the question Additionally objective results are upda...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a checkbox property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getUsedHTMLTagsAsString(string $a_module="")
Returns a string of all allowed HTML tags for text editing.
static _mananuallyScoreableQuestionTypesExists()
Returns the fact wether manually scoreable question types exist or not.
static _getParticipantId($active_id)
Get user id for active id.
static accessViolationRedirect()
static getSingleManualFeedback(int $active_id, int $question_id, int $pass)
static _lookupName(int $a_user_id)
lookup user name
This class represents a property form user interface.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
executeCommand()
execute command
buildManScoringParticipantsTable($withData=false)
saveManScoringParticipantScreen($redirect=true)
__construct(ilObjTest $a_object)
ilTestScoringGUI constructor
buildManScoringParticipantForm($questionGuiList, $activeId, $pass, $initValues=false)
showManScoringParticipantScreen(ilPropertyFormGUI $form=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Service GUI class for tests.
static setManScoringDone($activeId, $manScoringDone)
stores the flag wether manscoring is done for the given test active or not within the global settings...
static isManScoringDone($activeId)
reads the flag wether manscoring is done for the given test active or not from the global settings (s...
This class represents a text area property in a property form.
This class represents a text property in a property form.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
global $DIC
Definition: feed.php:28
const SCORE_LAST_PASS
$index
Definition: metadata.php:145
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc