ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilTestScoringGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
5include_once "./Modules/Test/classes/class.ilTestServiceGUI.php";
6
18{
21 const PART_FILTER_ALL_USERS = 3; // default
24 //const PART_FILTER_MANSCORING_PENDING = 6;
25
29 protected $testAccess;
30
39 public function __construct(ilObjTest $a_object)
40 {
41 parent::__construct($a_object);
42 }
43
47 public function getTestAccess()
48 {
49 return $this->testAccess;
50 }
51
55 public function setTestAccess($testAccess)
56 {
57 $this->testAccess = $testAccess;
58 }
59
63 protected function buildSubTabs($active_sub_tab = 'man_scoring_by_qst')
64 {
68 global $DIC;
69 $ilTabs = $DIC['ilTabs'];
70
71 $ilTabs->addSubTab('man_scoring_by_qst', $this->lng->txt('tst_man_scoring_by_qst'), $this->ctrl->getLinkTargetByClass('ilTestScoringByQuestionsGUI', 'showManScoringByQuestionParticipantsTable'));
72 $ilTabs->addSubTab('man_scoring', $this->lng->txt('tst_man_scoring_by_part'), $this->ctrl->getLinkTargetByClass('ilTestScoringGUI', 'showManScoringParticipantsTable'));
73 $ilTabs->setSubTabActive($active_sub_tab);
74 }
75
76 private function fetchActiveIdParameter()
77 {
78 global $DIC;
79 $ilCtrl = $DIC['ilCtrl'];
80
81 // fetch active_id
82
83 if (!isset($_GET['active_id']) || !(int) $_GET['active_id']) {
84 // allow only write access
85 ilUtil::sendFailure('no active id given!', true);
86 $ilCtrl->redirectByClass("ilobjtestgui", "infoScreen");
87 } else {
88 $activeId = (int) $_GET['active_id'];
89 }
90
91 return $activeId;
92 }
93
94 private function fetchPassParameter($activeId)
95 {
96 // fetch pass nr
97
98 $maxPass = $this->object->_getMaxPass($activeId);
99 if (isset($_GET["pass"]) && 0 <= (int) $_GET["pass"] && $maxPass >= (int) $_GET["pass"]) {
100 $pass = $_GET["pass"];
101 } elseif ($this->object->getPassScoring() == SCORE_LAST_PASS) {
102 $pass = $maxPass;
103 } else {
104 $pass = $this->object->_getResultPass($activeId);
105 }
106
107 return $pass;
108 }
109
113 public function executeCommand()
114 {
115 global $DIC; /* @var ILIAS\DI\Container $DIC */
116
117 if (!$this->getTestAccess()->checkScoreParticipantsAccess()) {
119 }
120
121 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
123 // allow only if at least one question type is marked for manual scoring
124 ilUtil::sendFailure($this->lng->txt("manscoring_not_allowed"), true);
125 $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
126 }
127
129 $this->buildSubTabs($this->getActiveSubTabId());
130
131 $nextClass = $this->ctrl->getNextClass($this);
132 $command = $this->ctrl->getCmd($this->getDefaultCommand());
133
134 switch ($nextClass) {
135 default:
136 $this->$command();
137 break;
138 }
139 }
140
144 protected function getDefaultCommand()
145 {
146 return 'manscoring';
147 }
148
152 protected function getActiveSubTabId()
153 {
154 return 'man_scoring';
155 }
156
158 {
159 global $DIC;
160 $tpl = $DIC['tpl'];
161
162 $table = $this->buildManScoringParticipantsTable(true);
163
164 $tpl->setContent($table->getHTML());
165 }
166
168 {
169 $table = $this->buildManScoringParticipantsTable(false);
170
171 $table->resetOffset();
172 $table->writeFilterToSession();
173
175 }
176
178 {
179 $table = $this->buildManScoringParticipantsTable(false);
180
181 $table->resetOffset();
182 $table->resetFilter();
183
185 }
186
188 {
189 global $DIC;
190 $tpl = $DIC['tpl'];
191 $lng = $DIC['lng'];
192
193 $activeId = $this->fetchActiveIdParameter();
194
195 if (!$this->getTestAccess()->checkScoreParticipantsAccessForActiveId($activeId)) {
197 }
198
199 $pass = $this->fetchPassParameter($activeId);
200
201 $contentHTML = '';
202
203 // pass overview table
204 require_once 'Modules/Test/classes/tables/class.ilTestPassManualScoringOverviewTableGUI.php';
205 $table = new ilTestPassManualScoringOverviewTableGUI($this, 'showManScoringParticipantScreen');
206
207 $userId = $this->object->_getUserIdFromActiveId($activeId);
208 $userFullname = $this->object->userLookupFullName($userId, false, true);
209 $tableTitle = sprintf($lng->txt('tst_pass_overview_for_participant'), $userFullname);
210 $table->setTitle($tableTitle);
211
212 $passOverviewData = $this->service->getPassOverviewData($activeId);
213 $table->setData($passOverviewData['passes']);
214
215 $contentHTML .= $table->getHTML() . '<br />';
216
217 // pass scoring form
218
219 if ($form === null) {
220 $questionGuiList = $this->service->getManScoringQuestionGuiList($activeId, $pass);
221 $form = $this->buildManScoringParticipantForm($questionGuiList, $activeId, $pass, true);
222 }
223
224 $contentHTML .= $form->getHTML();
225
226 // set content
227
228 $tpl->setContent($contentHTML);
229 }
230
235 private function saveManScoringParticipantScreen($redirect = true)
236 {
237 global $DIC;
238 $ilCtrl = $DIC['ilCtrl'];
239 $lng = $DIC['lng'];
240
241 $activeId = $this->fetchActiveIdParameter();
242
243 if (!$this->getTestAccess()->checkScoreParticipantsAccessForActiveId($activeId)) {
245 }
246
247 $pass = $this->fetchPassParameter($activeId);
248
249 $questionGuiList = $this->service->getManScoringQuestionGuiList($activeId, $pass);
250 $form = $this->buildManScoringParticipantForm($questionGuiList, $activeId, $pass, false);
251
252 $form->setValuesByPost();
253
254 if (!$form->checkInput()) {
255 ilUtil::sendFailure(sprintf($lng->txt('tst_save_manscoring_failed'), $pass + 1));
257 return false;
258 }
259
260 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
261
262 $maxPointsByQuestionId = array();
263 $maxPointsExceeded = false;
264 foreach ($questionGuiList as $questionId => $questionGui) {
265 $reachedPoints = $form->getItemByPostVar("question__{$questionId}__points")->getValue();
266 $maxPoints = assQuestion::_getMaximumPoints($questionId);
267
268 if ($reachedPoints > $maxPoints) {
269 $maxPointsExceeded = true;
270
271 $form->getItemByPostVar("question__{$questionId}__points")->setAlert(sprintf(
272 $lng->txt('tst_manscoring_maxpoints_exceeded_input_alert'),
273 $maxPoints
274 ));
275 }
276
277 $maxPointsByQuestionId[$questionId] = $maxPoints;
278 }
279
280 if ($maxPointsExceeded) {
281 ilUtil::sendFailure(sprintf($lng->txt('tst_save_manscoring_failed'), $pass + 1));
283 return false;
284 }
285
286 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
287
288 foreach ($questionGuiList as $questionId => $questionGui) {
289 $reachedPoints = $form->getItemByPostVar("question__{$questionId}__points")->getValue();
290
291 $finalized = (bool) $form->getItemByPostVar("{$questionId}__evaluated")->getchecked();
292
293 // fix #35543: save manual points only if they differ from the existing points
294 // this prevents a question being set to "answered" if only feedback is entered
295 $oldPoints = assQuestion::_getReachedPoints($activeId, $questionId, $pass);
296 if ($reachedPoints != $oldPoints) {
298 $activeId,
299 $questionId,
300 $reachedPoints,
301 $maxPointsByQuestionId[$questionId],
302 $pass,
303 1,
304 $this->object->areObligationsEnabled()
305 );
306 }
307
308 $feedback = ilUtil::stripSlashes(
309 $form->getItemByPostVar("question__{$questionId}__feedback")->getValue(),
310 false,
312 );
313
314 $this->object->saveManualFeedback($activeId, $questionId, $pass, $feedback, $finalized, true);
315
316 $notificationData[$questionId] = array(
317 'points' => $reachedPoints, 'feedback' => $feedback
318 );
319 }
320
321 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
322 include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
324 $this->object->getId(),
326 );
327
328 $manScoringDone = $form->getItemByPostVar("manscoring_done")->getChecked();
329 ilTestService::setManScoringDone($activeId, $manScoringDone);
330
331 $manScoringNotify = $form->getItemByPostVar("manscoring_notify")->getChecked();
332 if ($manScoringNotify) {
333 require_once 'Modules/Test/classes/notifications/class.ilTestManScoringParticipantNotification.php';
334
335 $notification = new ilTestManScoringParticipantNotification(
336 $this->object->_getUserIdFromActiveId($activeId),
337 $this->object->getRefId()
338 );
339
340 $notification->setAdditionalInformation(array(
341 'test_title' => $this->object->getTitle(),
342 'test_pass' => $pass + 1,
343 'questions_gui_list' => $questionGuiList,
344 'questions_scoring_data' => $notificationData
345 ));
346
347 $notification->send();
348 }
349
350 require_once './Modules/Test/classes/class.ilTestScoring.php';
351 $scorer = new ilTestScoring($this->object);
352 $scorer->setPreserveManualScores(true);
353 $scorer->recalculateSolutions();
354
355 if ($this->object->getAnonymity() == 0) {
357 $name_real_or_anon = $user_name['firstname'] . ' ' . $user_name['lastname'];
358 } else {
359 $name_real_or_anon = $lng->txt('anonymous');
360 }
361 ilUtil::sendSuccess(sprintf($lng->txt('tst_saved_manscoring_successfully'), $pass + 1, $name_real_or_anon), true);
362 if ($redirect == true) {
363 $ilCtrl->redirect($this, 'showManScoringParticipantScreen');
364 } else {
365 return true;
366 }
367 }
368
370 {
371 global $DIC;
372 $ilCtrl = $DIC['ilCtrl'];
373
374 $table = $this->buildManScoringParticipantsTable(true);
375
376 if ($this->saveManScoringParticipantScreen(false)) {
377 $participantData = $table->getInternalyOrderedDataValues();
378
379 $nextIndex = null;
380 foreach ($participantData as $index => $participant) {
381 if ($participant['active_id'] == $_GET['active_id']) {
382 $nextIndex = $index + 1;
383 break;
384 }
385 }
386
387 if ($nextIndex && isset($participantData[$nextIndex])) {
388 $ilCtrl->setParameter($this, 'active_id', $participantData[$nextIndex]['active_id']);
389 $ilCtrl->redirect($this, 'showManScoringParticipantScreen');
390 }
391
392 $ilCtrl->redirectByClass("iltestscoringgui", "showManScoringParticipantsTable");
393 }
394 }
395
397 {
398 global $DIC;
399 $ilCtrl = $DIC['ilCtrl'];
400
401 if ($this->saveManScoringParticipantScreen(false)) {
402 $ilCtrl->redirectByClass("iltestscoringgui", "showManScoringParticipantsTable");
403 }
404 }
405
406 private function buildManScoringParticipantForm($questionGuiList, $activeId, $pass, $initValues = false)
407 {
408 global $DIC;
409 $ilCtrl = $DIC['ilCtrl'];
410 $lng = $DIC['lng'];
411
412 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
413 require_once 'Services/Form/classes/class.ilFormSectionHeaderGUI.php';
414 require_once 'Services/Form/classes/class.ilCustomInputGUI.php';
415 require_once 'Services/Form/classes/class.ilCheckboxInputGUI.php';
416 require_once 'Services/Form/classes/class.ilTextInputGUI.php';
417 require_once 'Services/Form/classes/class.ilTextAreaInputGUI.php';
418
419 $ilCtrl->setParameter($this, 'active_id', $activeId);
420 $ilCtrl->setParameter($this, 'pass', $pass);
421
422 $form = new ilPropertyFormGUI();
423 $form->setFormAction($ilCtrl->getFormAction($this));
424
425 $form->setTitle(sprintf($lng->txt('manscoring_results_pass'), $pass + 1));
426 $form->setTableWidth('100%');
427
429 foreach ($questionGuiList as $questionId => $questionGUI) {
430 $questionHeader = sprintf($lng->txt('tst_manscoring_question_section_header'), $questionGUI->object->getTitle());
431 $questionSolution = $questionGUI->getSolutionOutput($activeId, $pass, false, false, true, false, false, true);
432 $bestSolution = $questionGUI->object->getSuggestedSolutionOutput();
433 $feedback = $this->object->getSingleManualFeedback($activeId, $questionId, $pass);
434 $disabled = false;
435 if (isset($feedback['finalized_evaluation']) && $feedback['finalized_evaluation'] == 1) {
436 $disabled = true;
437 }
438
439 $sect = new ilFormSectionHeaderGUI();
440 $sect->setTitle($questionHeader . ' [' . $this->lng->txt('question_id_short') . ': ' . $questionGUI->object->getId() . ']');
441 $form->addItem($sect);
442
443 $cust = new ilCustomInputGUI($lng->txt('tst_manscoring_input_question_and_user_solution'));
444 $cust->setHtml($questionSolution);
445 $form->addItem($cust);
446
447 if ($questionGUI->supportsIntermediateSolutionOutput() && $questionGUI->hasIntermediateSolution($activeId, $pass)) {
448 $questionGUI->setUseIntermediateSolution(true);
449 $intermediateSolution = $questionGUI->getSolutionOutput($activeId, $pass, false, false, true, false, false, true);
450 $questionGUI->setUseIntermediateSolution(false);
451 $cust = new ilCustomInputGUI($lng->txt('autosavecontent'));
452 $cust->setHtml($intermediateSolution);
453 $form->addItem($cust);
454 }
455
456 $text = new ilTextInputGUI($lng->txt('tst_change_points_for_question'), "question__{$questionId}__points");
457 if ($initValues) {
458 $text->setValue(assQuestion::_getReachedPoints($activeId, $questionId, $pass));
459 }
460 if($disabled){
461 $text->setDisabled($disabled);
462 }
463 $form->addItem($text);
464
465 $nonedit = new ilNonEditableValueGUI($lng->txt('tst_manscoring_input_max_points_for_question'), "question__{$questionId}__maxpoints");
466 if ($initValues) {
467 $nonedit->setValue(assQuestion::_getMaximumPoints($questionId));
468 }
469 $form->addItem($nonedit);
470
471 $area = new ilTextAreaInputGUI($lng->txt('set_manual_feedback'), "question__{$questionId}__feedback");
472 $area->setUseRTE(true);
473 if ($initValues) {
474 $area->setValue($this->object->getSingleManualFeedback($activeId, $questionId, $pass)['feedback']);
475 }
476 if($disabled){
477 $area->setDisabled($disabled);
478 }
479 $form->addItem($area);
480
481 $check = new ilCheckboxInputGUI($lng->txt('finalized_evaluation'), "{$questionId}__evaluated");
482 if ($disabled) {
483 $check->setChecked(true);
484 }
485 $form->addItem($check);
486
487 if (strlen(trim($bestSolution))) {
488 $cust = new ilCustomInputGUI($lng->txt('tst_show_solution_suggested'));
489 $cust->setHtml($bestSolution);
490 $form->addItem($cust);
491 }
492 }
493
494 $sect = new ilFormSectionHeaderGUI();
495 $sect->setTitle($lng->txt('tst_participant'));
496 $form->addItem($sect);
497
498 $check = new ilCheckboxInputGUI($lng->txt('set_manscoring_done'), 'manscoring_done');
499 if ($initValues && ilTestService::isManScoringDone($activeId)) {
500 $check->setChecked(true);
501 }
502 $form->addItem($check);
503
504 $check = new ilCheckboxInputGUI($lng->txt('tst_manscoring_user_notification'), 'manscoring_notify');
505 $form->addItem($check);
506
507 $form->addCommandButton('saveManScoringParticipantScreen', $lng->txt('save'));
508 $form->addCommandButton('saveReturnManScoringParticipantScreen', $lng->txt('save_return'));
509 $form->addCommandButton('saveNextManScoringParticipantScreen', $lng->txt('save_and_next'));
510
511 return $form;
512 }
513
515 {
516 }
517
521 private function buildManScoringParticipantsTable($withData = false)
522 {
523 require_once 'Modules/Test/classes/tables/class.ilTestManScoringParticipantsTableGUI.php';
524 $table = new ilTestManScoringParticipantsTableGUI($this);
525
526 if ($withData) {
527 $participantStatusFilterValue = $table->getFilterItemByPostVar('participant_status')->getValue();
528
529 require_once 'Modules/Test/classes/class.ilTestParticipantList.php';
530 $participantList = new ilTestParticipantList($this->object);
531
532 $participantList->initializeFromDbRows(
533 $this->object->getTestParticipantsForManualScoring($participantStatusFilterValue)
534 );
535
536 $participantList = $participantList->getAccessFilteredList(
538 );
539
540 $table->setData($participantList->getParticipantsTableRows());
541 }
542
543 return $table;
544 }
545}
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
static _getReachedPoints($active_id, $question_id, $pass=null)
Returns the points, a learner has reached answering the question.
static _getMaximumPoints($question_id)
Returns the maximum points, a learner can reach answering the question.
static _setReachedPoints($active_id, $question_id, $points, $maxpoints, $pass, $manualscoring, $obligationsEnabled)
Sets the points, a learner has reached answering the question Additionally objective results are upda...
This class represents a checkbox property in a property form.
This class represents a custom property in a property form.
This class represents a section header in a property form.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
This class represents a non editable value in a property form.
static _getUsedHTMLTagsAsString($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 _lookupName($a_user_id)
lookup user name
This class represents a property form user interface.
Scoring class for tests.
executeCommand()
execute command
buildManScoringParticipantsTable($withData=false)
saveManScoringParticipantScreen($redirect=true)
__construct(ilObjTest $a_object)
ilTestScoringGUI constructor
showManScoringParticipantScreen(ilPropertyFormGUI $form=null)
Class ilTestScoring.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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 sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
global $DIC
Definition: goto.php:24
const SCORE_LAST_PASS
$index
Definition: metadata.php:128
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc