1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once 'Modules/Test/classes/class.ilTestSettingsGUI.php';
5
6/**
7 * GUI class that manages the editing of general test settings/properties
8 * shown on "general" subtab
9 *
10 * @author		Björn Heyser <bheyser@databay.de>
11 * @version		$Id$
12 *
13 * @package		Modules/Test
14 *
15 * @ilCtrl_Calls ilObjTestSettingsScoringResultsGUI: ilPropertyFormGUI, ilConfirmationGUI
16 */
17class ilObjTestSettingsScoringResultsGUI extends ilTestSettingsGUI
18{
19    /**
20     * command constants
21     */
22    const CMD_SHOW_FORM = 'showForm';
23    const CMD_SAVE_FORM = 'saveForm';
24    const CMD_CONFIRMED_SAVE_FORM = 'confirmedSaveForm';
25
26    /** @var ilCtrl $ctrl */
27    protected $ctrl = null;
28
29    /** @var ilAccess $access */
30    protected $access = null;
31
32    /** @var ilLanguage $lng */
33    protected $lng = null;
34
35    /** @var ilGlobalTemplateInterface $tpl */
36    protected $tpl = null;
37
38    /** @var ilTree $tree */
39    protected $tree = null;
40
41    /** @var ilDBInterface $db */
42    protected $db = null;
43
44    /** @var ilPluginAdmin $pluginAdmin */
45    protected $pluginAdmin = null;
46
47    /** @var ilObjTest $testOBJ */
48    protected $testOBJ = null;
49
50    /** @var ilObjTestGUI $testGUI */
51    protected $testGUI = null;
52
53    /** @var ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory Factory for question set config. */
54    private $testQuestionSetConfigFactory = null;
55
56    /**
57     * object instance for currently active settings template
58     *
59     * @var $settingsTemplate ilSettingsTemplate
60     */
61    protected $settingsTemplate = null;
62
63    /**
64     * Constructor
65     *
66     * @param ilCtrl          $ctrl
67     * @param ilAccessHandler $access
68     * @param ilLanguage      $lng
69     * @param ilTemplate      $tpl
70     * @param ilDBInterface   $db
71     * @param ilObjTestGUI    $testGUI
72     *
73     * @return \ilObjTestSettingsGeneralGUI
74     */
75    public function __construct(
76        ilCtrl $ctrl,
77        ilAccessHandler $access,
78        ilLanguage $lng,
79        ilTree $tree,
80        ilDBInterface $db,
81        ilPluginAdmin $pluginAdmin,
82        ilObjTestGUI $testGUI
83    ) {
84        global $DIC; /* @var ILIAS\DI\Container $DIC */
85
86        $this->ctrl = $ctrl;
87        $this->access = $access;
88        $this->lng = $lng;
89        $this->tpl = $DIC->ui()->mainTemplate();
90        $this->tree = $tree;
91        $this->db = $db;
92        $this->pluginAdmin = $pluginAdmin;
93
94        $this->testGUI = $testGUI;
95        $this->testOBJ = $testGUI->object;
96
97        require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
98        $this->testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($this->tree, $this->db, $this->pluginAdmin, $this->testOBJ);
99
100        $templateId = $this->testOBJ->getTemplate();
101
102        if ($templateId) {
103            include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
104            $this->settingsTemplate = new ilSettingsTemplate($templateId, ilObjAssessmentFolderGUI::getSettingsTemplateConfig());
105        }
106    }
107
108    /**
109     * Command Execution
110     */
111    public function executeCommand()
112    {
113        // allow only write access
114
115        if (!$this->access->checkAccess('write', '', $this->testGUI->ref_id)) {
116            ilUtil::sendInfo($this->lng->txt('cannot_edit_test'), true);
117            $this->ctrl->redirect($this->testGUI, 'infoScreen');
118        }
119
120        global $DIC; /* @var ILIAS\DI\Container $DIC */
121
122        $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_SETTINGS);
123
124        // process command
125
126        $nextClass = $this->ctrl->getNextClass();
127
128        switch ($nextClass) {
129            default:
130                $cmd = $this->ctrl->getCmd(self::CMD_SHOW_FORM) . 'Cmd';
131                $this->$cmd();
132        }
133    }
134
135    private function showFormCmd(ilPropertyFormGUI $form = null)
136    {
137        //$this->tpl->addJavascript("./Services/JavaScript/js/Basic.js");
138
139        if ($form === null) {
140            $form = $this->buildForm();
141        }
142
143        $this->tpl->setContent($this->ctrl->getHTML($form));
144    }
145
146    private function confirmedSaveFormCmd()
147    {
148        return $this->saveFormCmd(true);
149    }
150
151    private function saveFormCmd($isConfirmedSave = false)
152    {
153        $form = $this->buildForm();
154
155        // form validation and initialisation
156
157        $errors = !$form->checkInput(); // ALWAYS CALL BEFORE setValuesByPost()
158        $form->setValuesByPost(); // NEVER CALL THIS BEFORE checkInput()
159
160        // return to form when any form validation errors exist
161
162        if ($errors) {
163            ilUtil::sendFailure($this->lng->txt('form_input_not_valid'));
164            return $this->showFormCmd($form);
165        }
166
167        // check for required confirmation and redirect if neccessary
168
169        if (!$isConfirmedSave && $this->isScoreRecalculationRequired($form)) {
170            return $this->showConfirmation($form);
171        }
172
173        // saving the form leads to isScoreRecalculationRequired($form)
174        // returning false, so remember whether recalculation is needed
175
176        $recalcRequired = $this->isScoreRecalculationRequired($form);
177
178        // perform save
179
180        $this->performSaveForm($form);
181
182        if ($recalcRequired) {
183            $this->testOBJ->recalculateScores(true);
184        }
185
186        // redirect to form output
187
188        ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
189        $this->ctrl->redirect($this, self::CMD_SHOW_FORM);
190    }
191
192    private function performSaveForm(ilPropertyFormGUI $form)
193    {
194        $this->saveScoringSettingsFormSection($form);
195        $this->saveResultSummarySettings($form);
196        $this->saveResultDetailsSettings($form);
197        $this->saveResultMiscOptionsSettings($form);
198
199        // store settings to db
200        $this->testOBJ->saveToDb(true);
201    }
202
203    private function showConfirmation(ilPropertyFormGUI $form)
204    {
205        require_once 'Services/Utilities/classes/class.ilConfirmationGUI.php';
206        $confirmation = new ilConfirmationGUI();
207
208        $confirmation->setHeaderText($this->lng->txt('tst_trigger_result_refreshing'));
209
210        $confirmation->setFormAction($this->ctrl->getFormAction($this));
211        $confirmation->setCancel($this->lng->txt('cancel'), self::CMD_SHOW_FORM);
212        $confirmation->setConfirm($this->lng->txt('confirm'), self::CMD_CONFIRMED_SAVE_FORM);
213
214        foreach ($form->getInputItemsRecursive() as $key => $item) {
215            //vd("$key // {$item->getType()} // ".json_encode($_POST[$item->getPostVar()]));
216
217            switch ($item->getType()) {
218                case 'section_header':
219
220                    break;
221
222                case 'datetime':
223
224                    $datetime = $item->getDate();
225                    if ($datetime instanceof ilDateTime) {
226                        list($date, $time) = explode(' ', $datetime->get(IL_CAL_DATETIME));
227                        if (!($date instanceof ilDate)) {
228                            $confirmation->addHiddenItem($item->getPostVar(), $date . ' ' . $time);
229                        } else {
230                            $confirmation->addHiddenItem($item->getPostVar(), $date);
231                        }
232                    } else {
233                        $confirmation->addHiddenItem($item->getPostVar(), '');
234                    }
235
236                    break;
237
238                case 'duration':
239
240                    $confirmation->addHiddenItem("{$item->getPostVar()}[MM]", (int) $item->getMonths());
241                    $confirmation->addHiddenItem("{$item->getPostVar()}[dd]", (int) $item->getDays());
242                    $confirmation->addHiddenItem("{$item->getPostVar()}[hh]", (int) $item->getHours());
243                    $confirmation->addHiddenItem("{$item->getPostVar()}[mm]", (int) $item->getMinutes());
244                    $confirmation->addHiddenItem("{$item->getPostVar()}[ss]", (int) $item->getSeconds());
245
246                    break;
247
248                case 'checkboxgroup':
249
250                    if (is_array($item->getValue())) {
251                        foreach ($item->getValue() as $option) {
252                            $confirmation->addHiddenItem("{$item->getPostVar()}[]", $option);
253                        }
254                    }
255
256                    break;
257
258                case 'checkbox':
259
260                    if ($item->getChecked()) {
261                        $confirmation->addHiddenItem($item->getPostVar(), 1);
262                    }
263
264                    break;
265
266                default:
267
268                    $confirmation->addHiddenItem($item->getPostVar(), $item->getValue());
269            }
270        }
271
272        $this->tpl->setContent($this->ctrl->getHTML($confirmation));
273    }
274
275    private function buildForm()
276    {
277        include_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
278        $form = new ilPropertyFormGUI();
279        $form->setFormAction($this->ctrl->getFormAction($this));
280        $form->setTableWidth('100%');
281        $form->setId('test_scoring_results');
282
283        $this->addScoringSettingsFormSection($form);
284        $this->addResultSummarySettingsFormSection($form);
285        $this->addResultDetailsSettingsFormSection($form);
286        $this->addMiscSettingsFormSection($form);
287
288        // remove items when using template
289        if ($this->settingsTemplate) {
290            foreach ($this->settingsTemplate->getSettings() as $id => $item) {
291                if ($item["hide"]) {
292                    $form->removeItemByPostVar($id);
293                }
294            }
295        }
296
297        $form->addCommandButton(self::CMD_SAVE_FORM, $this->lng->txt('save'));
298
299        return $form;
300    }
301
302    private function addScoringSettingsFormSection(ilPropertyFormGUI $form)
303    {
304        $fields = array(
305            'count_system', 'mc_scoring', 'score_cutting', 'pass_scoring', 'pass_deletion_allowed'
306        );
307
308        if ($this->isSectionHeaderRequired($fields)) {
309            // scoring settings
310            $header = new ilFormSectionHeaderGUI();
311            $header->setTitle($this->lng->txt('test_scoring'));
312            $form->addItem($header);
313        }
314
315        // scoring system
316        $count_system = new ilRadioGroupInputGUI($this->lng->txt('tst_text_count_system'), 'count_system');
317        $count_system->addOption($opt = new ilRadioOption($this->lng->txt('tst_count_partial_solutions'), 0, ''));
318        $opt->setInfo($this->lng->txt('tst_count_partial_solutions_desc'));
319        $count_system->addOption($opt = new ilRadioOption($this->lng->txt('tst_count_correct_solutions'), 1, ''));
320        $opt->setInfo($this->lng->txt('tst_count_correct_solutions_desc'));
321        $count_system->setValue($this->testOBJ->getCountSystem());
322        $form->addItem($count_system);
323
324        // mc questions
325        $mc_scoring = new ilRadioGroupInputGUI($this->lng->txt('tst_score_mcmr_questions'), 'mc_scoring');
326        $mc_scoring->addOption($opt = new ilRadioOption($this->lng->txt('tst_score_mcmr_zero_points_when_unanswered'), 0, ''));
327        $opt->setInfo($this->lng->txt('tst_score_mcmr_zero_points_when_unanswered_desc'));
328        $mc_scoring->addOption($opt = new ilRadioOption($this->lng->txt('tst_score_mcmr_use_scoring_system'), 1, ''));
329        $opt->setInfo($this->lng->txt('tst_score_mcmr_use_scoring_system_desc'));
330        $mc_scoring->setValue($this->testOBJ->getMCScoring());
331        // fau: testNav - set the deprecated mc scoring option to disabled
332        $mc_scoring->setDisabled(true);
333        // fau.
334        $form->addItem($mc_scoring);
335
336        // score cutting
337        $score_cutting = new ilRadioGroupInputGUI($this->lng->txt('tst_score_cutting'), 'score_cutting');
338        $score_cutting->addOption($opt = new ilRadioOption($this->lng->txt('tst_score_cut_question'), 0, ''));
339        $opt->setInfo($this->lng->txt('tst_score_cut_question_desc'));
340        $score_cutting->addOption($opt = new ilRadioOption($this->lng->txt('tst_score_cut_test'), 1, ''));
341        $opt->setInfo($this->lng->txt('tst_score_cut_test_desc'));
342        $score_cutting->setValue($this->testOBJ->getScoreCutting());
343        $form->addItem($score_cutting);
344
345        // pass scoring
346        $pass_scoring = new ilRadioGroupInputGUI($this->lng->txt('tst_pass_scoring'), 'pass_scoring');
347        $pass_scoring->addOption($opt = new ilRadioOption($this->lng->txt('tst_pass_last_pass'), 0, ''));
348        $opt->setInfo($this->lng->txt('tst_pass_last_pass_desc'));
349        $pass_scoring->addOption($opt = new ilRadioOption($this->lng->txt('tst_pass_best_pass'), 1, ''));
350        $opt->setInfo($this->lng->txt('tst_pass_best_pass_desc'));
351        $pass_scoring->setValue($this->testOBJ->getPassScoring());
352        $form->addItem($pass_scoring);
353
354        // deletion of test results
355        $passDeletion = new ilRadioGroupInputGUI($this->lng->txt('tst_pass_deletion'), 'pass_deletion_allowed');
356        $passDeletion->addOption(new ilRadioOption($this->lng->txt('tst_pass_deletion_not_allowed'), 0, ''));
357        $passDeletion->addOption(new ilRadioOption($this->lng->txt('tst_pass_deletion_allowed'), 1, ''));
358        $passDeletion->setValue($this->testOBJ->isPassDeletionAllowed());
359        $form->addItem($passDeletion);
360
361        // disable scoring settings
362        if (!$this->areScoringSettingsWritable()) {
363            $count_system->setDisabled(true);
364            $mc_scoring->setDisabled(true);
365            $score_cutting->setDisabled(true);
366            $pass_scoring->setDisabled(true);
367        }
368    }
369
370    /**
371     * @param ilPropertyFormGUI $form
372     */
373    private function saveScoringSettingsFormSection(ilPropertyFormGUI $form)
374    {
375        if ($this->areScoringSettingsWritable()) {
376            if ($this->formPropertyExists($form, 'count_system')) {
377                $this->testOBJ->setCountSystem($form->getItemByPostVar('count_system')->getValue());
378            }
379
380            if ($this->formPropertyExists($form, 'mc_scoring')) {
381                $this->testOBJ->setMCScoring($form->getItemByPostVar('mc_scoring')->getValue());
382            }
383
384            if ($this->formPropertyExists($form, 'score_cutting')) {
385                $this->testOBJ->setScoreCutting($form->getItemByPostVar('score_cutting')->getValue());
386            }
387
388            if ($this->formPropertyExists($form, 'pass_scoring')) {
389                $this->testOBJ->setPassScoring($form->getItemByPostVar('pass_scoring')->getValue());
390            }
391        }
392
393        if ($this->formPropertyExists($form, 'pass_deletion_allowed')) {
394            $this->testOBJ->setPassDeletionAllowed((bool) $form->getItemByPostVar('pass_deletion_allowed')->getValue());
395        }
396    }
397
398    private function addResultSummarySettingsFormSection(ilPropertyFormGUI $form)
399    {
400        // HEADER: result settings
401        $header_tr = new ilFormSectionHeaderGUI();
402        $header_tr->setTitle($this->lng->txt('test_results'));
403        $form->addItem($header_tr);
404
405        // access to test results
406        $resultsAccessEnabled = new ilCheckboxInputGUI($this->lng->txt('tst_results_access_enabled'), 'results_access_enabled');
407        $resultsAccessEnabled->setInfo($this->lng->txt('tst_results_access_enabled_desc'));
408        $resultsAccessEnabled->setChecked($this->testOBJ->isScoreReportingEnabled());
409        $resultsAccessSetting = new ilRadioGroupInputGUI($this->lng->txt('tst_results_access_setting'), 'results_access_setting');
410        $resultsAccessSetting->setRequired(true);
411        $optAlways = new ilRadioOption($this->lng->txt('tst_results_access_always'));
412        $optAlways->setInfo($this->lng->txt('tst_results_access_always_desc'));
413        $optAlways->setValue(ilObjTest::SCORE_REPORTING_IMMIDIATLY);
414        $resultsAccessSetting->addOption($optAlways);
415        $optFinished = $opt = new ilRadioOption($this->lng->txt('tst_results_access_finished'));
416        $optFinished->setInfo($this->lng->txt('tst_results_access_finished_desc'));
417        $optFinished->setValue(ilObjTest::SCORE_REPORTING_FINISHED);
418        $resultsAccessSetting->addOption($optFinished);
419        $optPassed = $opt = new ilRadioOption($this->lng->txt('tst_results_access_passed'));
420        $optPassed->setInfo($this->lng->txt('tst_results_access_passed_desc'));
421        $optPassed->setValue(ilObjTest::SCORE_REPORTING_AFTER_PASSED);
422        $resultsAccessSetting->addOption($optPassed);
423        $optionDate = new ilRadioOption($this->lng->txt('tst_results_access_date'));
424        $optionDate->setInfo($this->lng->txt('tst_results_access_date_desc'));
425        $optionDate->setValue(ilObjTest::SCORE_REPORTING_DATE);
426        // access date
427        $reportingDate = new ilDateTimeInputGUI($this->lng->txt('tst_reporting_date'), 'reporting_date');
428        $reportingDate->setRequired(true);
429        $reportingDate->setShowTime(true);
430        if (strlen($this->testOBJ->getReportingDate())) {
431            $reportingDate->setDate(new ilDateTime($this->testOBJ->getReportingDate(), IL_CAL_TIMESTAMP));
432        } else {
433            $reportingDate->setDate(new ilDateTime(time(), IL_CAL_UNIX));
434        }
435        $optionDate->addSubItem($reportingDate);
436        $resultsAccessSetting->addOption($optionDate);
437        $resultsAccessSetting->setValue($this->testOBJ->getScoreReporting());
438        $resultsAccessEnabled->addSubItem($resultsAccessSetting);
439        // show pass details
440        $showPassDetails = new ilCheckboxInputGUI($this->lng->txt('tst_show_pass_details'), 'pass_details');
441        $showPassDetails->setInfo($this->lng->txt('tst_show_pass_details_desc'));
442        $showPassDetails->setChecked($this->testOBJ->getShowPassDetails());
443        $resultsAccessEnabled->addSubItem($showPassDetails);
444        $form->addItem($resultsAccessEnabled);
445
446        // grading
447        $chb_only_passed_failed = new ilCheckboxInputGUI($this->lng->txt('tst_results_grading_opt_show_status'), 'grading_status');
448        $chb_only_passed_failed->setInfo($this->lng->txt('tst_results_grading_opt_show_status_desc'));
449        $chb_only_passed_failed->setValue(1);
450        $chb_only_passed_failed->setChecked($this->testOBJ->isShowGradingStatusEnabled());
451        $resultsAccessEnabled->addSubItem($chb_only_passed_failed);
452
453        $chb_resulting_mark_only = new ilCheckboxInputGUI($this->lng->txt('tst_results_grading_opt_show_mark'), 'grading_mark');
454        $chb_resulting_mark_only->setInfo($this->lng->txt('tst_results_grading_opt_show_mark_desc'));
455        $chb_resulting_mark_only->setValue(1);
456        $chb_resulting_mark_only->setChecked($this->testOBJ->isShowGradingMarkEnabled());
457        $resultsAccessEnabled->addSubItem($chb_resulting_mark_only);
458    }
459
460    /**
461     * @param ilPropertyFormGUI $form
462     */
463    private function saveResultSummarySettings(ilPropertyFormGUI $form)
464    {
465        if ($this->formPropertyExists($form, 'results_access_enabled')) {
466            if ($form->getItemByPostVar('results_access_enabled')->getChecked()) {
467                $this->testOBJ->setScoreReporting($form->getItemByPostVar('results_access_setting')->getValue());
468
469                if ($this->testOBJ->getScoreReporting() == ilObjTest::SCORE_REPORTING_DATE) {
470                    $reporting_date = $form->getItemByPostVar('reporting_date')->getDate();
471                    if ($reporting_date instanceof ilDateTime) {
472                        $this->testOBJ->setReportingDate($reporting_date->get(IL_CAL_FKT_DATE, 'YmdHis'));
473                    } else {
474                        $this->testOBJ->setReportingDate('');
475                    }
476                } else {
477                    $this->testOBJ->setReportingDate('');
478                }
479
480                $this->testOBJ->setShowPassDetails($form->getItemByPostVar('pass_details')->getChecked());
481            } else {
482                $this->testOBJ->setScoreReporting(ilObjTest::SCORE_REPORTING_DISABLED);
483                $this->testOBJ->setShowPassDetails(false);
484                $this->testOBJ->setReportingDate('');
485            }
486        }
487
488        if ($this->formPropertyExists($form, 'grading_status')) {
489            $this->testOBJ->setShowGradingStatusEnabled(
490                $form->getItemByPostVar('grading_status')->getChecked()
491            );
492        }
493
494        if ($this->formPropertyExists($form, 'grading_mark')) {
495            $this->testOBJ->setShowGradingMarkEnabled(
496                (int) $form->getItemByPostVar('grading_mark')->getChecked()
497            );
498        }
499    }
500
501    private function addResultDetailsSettingsFormSection(ilPropertyFormGUI $form)
502    {
503        // HEADER: result settings
504        $header_tr = new ilFormSectionHeaderGUI();
505        $header_tr->setTitle($this->lng->txt('tst_results_details_options'));
506        $form->addItem($header_tr);
507
508        // show solution details
509        $showSolutionDetails = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_details'), 'solution_details');
510        $showSolutionDetails->setInfo($this->lng->txt('tst_show_solution_details_desc'));
511        $showSolutionDetails->setChecked($this->testOBJ->getShowSolutionDetails());
512        $form->addItem($showSolutionDetails);
513
514        // best solution in test results
515        $results_print_best_solution = new ilCheckboxInputGUI($this->lng->txt('tst_results_print_best_solution'), 'print_bs_with_res');
516        $results_print_best_solution->setInfo($this->lng->txt('tst_results_print_best_solution_info'));
517        $results_print_best_solution->setChecked((bool) $this->testOBJ->isBestSolutionPrintedWithResult());
518        $showSolutionDetails->addSubItem($results_print_best_solution);
519
520        // show solution feedback ==> solution feedback in test results
521        $showSolutionFeedbackOption = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_feedback'), 'solution_feedback');
522        $showSolutionFeedbackOption->setInfo($this->lng->txt('tst_show_solution_feedback_desc'));
523        $showSolutionFeedbackOption->setChecked($this->testOBJ->getShowSolutionFeedback());
524        $form->addItem($showSolutionFeedbackOption);
525
526        // show suggested solution
527        $showSuggestedSolutionOption = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_suggested'), 'solution_suggested');
528        $showSuggestedSolutionOption->setInfo($this->lng->txt('tst_show_solution_suggested_desc'));
529        $showSuggestedSolutionOption->setChecked($this->testOBJ->getShowSolutionSuggested());
530        $form->addItem($showSuggestedSolutionOption);
531
532        // show solution printview ==> list of answers
533        $showSolutionPrintview = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_printview'), 'solution_printview');
534        $showSolutionPrintview->setInfo($this->lng->txt('tst_show_solution_printview_desc'));
535        $showSolutionPrintview->setChecked($this->testOBJ->getShowSolutionPrintview());
536        $form->addItem($showSolutionPrintview);
537
538        // show best solution in list of answers
539        $solutionCompareInput = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_compare'), 'solution_compare');
540        $solutionCompareInput->setInfo($this->lng->txt('tst_show_solution_compare_desc'));
541        $solutionCompareInput->setChecked($this->testOBJ->getShowSolutionListComparison());
542        $showSolutionPrintview->addSubItem($solutionCompareInput);
543
544        // solution answers only ==> printview of results (answers only)
545        $solutionAnswersOnly = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_answers_only'), 'solution_answers_only');
546        $solutionAnswersOnly->setInfo($this->lng->txt('tst_show_solution_answers_only_desc'));
547        $solutionAnswersOnly->setChecked($this->testOBJ->getShowSolutionAnswersOnly());
548        $showSolutionPrintview->addSubItem($solutionAnswersOnly);
549
550        // high score
551        $highscore = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_enabled"), "highscore_enabled");
552        $highscore->setValue(1);
553        $highscore->setChecked($this->testOBJ->getHighscoreEnabled());
554        $highscore->setInfo($this->lng->txt("tst_highscore_description"));
555        $form->addItem($highscore);
556        $highscore_tables = new ilRadioGroupInputGUI($this->lng->txt('tst_highscore_mode'), 'highscore_mode');
557        $highscore_tables->setRequired(true);
558        $highscore_tables->setValue($this->testOBJ->getHighscoreMode());
559        $highscore_table_own = new ilRadioOption($this->lng->txt('tst_highscore_own_table'), ilObjTest::HIGHSCORE_SHOW_OWN_TABLE);
560        $highscore_table_own->setInfo($this->lng->txt('tst_highscore_own_table_description'));
561        $highscore_tables->addOption($highscore_table_own);
562        $highscore_table_other = new ilRadioOption($this->lng->txt('tst_highscore_top_table'), ilObjTest::HIGHSCORE_SHOW_TOP_TABLE);
563        $highscore_table_other->setInfo($this->lng->txt('tst_highscore_top_table_description'));
564        $highscore_tables->addOption($highscore_table_other);
565        $highscore_table_other = new ilRadioOption($this->lng->txt('tst_highscore_all_tables'), ilObjTest::HIGHSCORE_SHOW_ALL_TABLES);
566        $highscore_table_other->setInfo($this->lng->txt('tst_highscore_all_tables_description'));
567        $highscore_tables->addOption($highscore_table_other);
568        $highscore->addSubItem($highscore_tables);
569        $highscore_top_num = new ilNumberInputGUI($this->lng->txt("tst_highscore_top_num"), "highscore_top_num");
570        $highscore_top_num->setSize(4);
571        $highscore_top_num->setRequired(true);
572        $highscore_top_num->setMinValue(1);
573        $highscore_top_num->setSuffix($this->lng->txt("tst_highscore_top_num_unit"));
574        $highscore_top_num->setValue($this->testOBJ->getHighscoreTopNum(null));
575        $highscore_top_num->setInfo($this->lng->txt("tst_highscore_top_num_description"));
576        $highscore->addSubItem($highscore_top_num);
577        $highscore_anon = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_anon"), "highscore_anon");
578        $highscore_anon->setValue(1);
579        $highscore_anon->setChecked($this->testOBJ->getHighscoreAnon());
580        $highscore_anon->setInfo($this->lng->txt("tst_highscore_anon_description"));
581        $highscore->addSubItem($highscore_anon);
582        $highscore_achieved_ts = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_achieved_ts"), "highscore_achieved_ts");
583        $highscore_achieved_ts->setValue(1);
584        $highscore_achieved_ts->setChecked($this->testOBJ->getHighscoreAchievedTS());
585        $highscore_achieved_ts->setInfo($this->lng->txt("tst_highscore_achieved_ts_description"));
586        $highscore->addSubItem($highscore_achieved_ts);
587        $highscore_score = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_score"), "highscore_score");
588        $highscore_score->setValue(1);
589        $highscore_score->setChecked($this->testOBJ->getHighscoreScore());
590        $highscore_score->setInfo($this->lng->txt("tst_highscore_score_description"));
591        $highscore->addSubItem($highscore_score);
592        $highscore_percentage = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_percentage"), "highscore_percentage");
593        $highscore_percentage->setValue(1);
594        $highscore_percentage->setChecked($this->testOBJ->getHighscorePercentage());
595        $highscore_percentage->setInfo($this->lng->txt("tst_highscore_percentage_description"));
596        $highscore->addSubItem($highscore_percentage);
597        $highscore_hints = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_hints"), "highscore_hints");
598        $highscore_hints->setValue(1);
599        $highscore_hints->setChecked($this->testOBJ->getHighscoreHints());
600        $highscore_hints->setInfo($this->lng->txt("tst_highscore_hints_description"));
601        $highscore->addSubItem($highscore_hints);
602        $highscore_wtime = new ilCheckboxInputGUI($this->lng->txt("tst_highscore_wtime"), "highscore_wtime");
603        $highscore_wtime->setValue(1);
604        $highscore_wtime->setChecked($this->testOBJ->getHighscoreWTime());
605        $highscore_wtime->setInfo($this->lng->txt("tst_highscore_wtime_description"));
606        $highscore->addSubItem($highscore_wtime);
607
608        // show signature placeholder
609        $showSignaturePlaceholder = new ilCheckboxInputGUI($this->lng->txt('tst_show_solution_signature'), 'solution_signature');
610        $showSignaturePlaceholder->setInfo($this->lng->txt('tst_show_solution_signature_desc'));
611        $showSignaturePlaceholder->setChecked($this->testOBJ->getShowSolutionSignature());
612        if ($this->testOBJ->getAnonymity()) {
613            $showSignaturePlaceholder->setDisabled(true);
614        }
615        $form->addItem($showSignaturePlaceholder);
616
617        // show signature placeholder
618        $showExamId = new ilCheckboxInputGUI($this->lng->txt('examid_in_test_res'), 'examid_in_test_res');
619        $showExamId->setInfo($this->lng->txt('examid_in_test_res_desc'));
620        $showExamId->setChecked($this->testOBJ->isShowExamIdInTestResultsEnabled());
621        $form->addItem($showExamId);
622
623        // export settings
624        $export_settings = new ilCheckboxInputGUI($this->lng->txt('tst_exp_sc_short'), 'exp_sc_short');
625        $export_settings->setInfo($this->lng->txt('tst_exp_sc_short_desc'));
626        $export_settings->setChecked($this->testOBJ->getExportSettingsSingleChoiceShort());
627        $form->addItem($export_settings);
628    }
629
630    /**
631     * @param ilPropertyFormGUI $form
632     */
633    private function saveResultDetailsSettings(ilPropertyFormGUI $form)
634    {
635        if ($this->formPropertyExists($form, 'solution_details')) {
636            if ($form->getItemByPostVar('solution_details')->getChecked()) {
637                $this->testOBJ->setShowSolutionDetails(1);
638                $this->testOBJ->setPrintBestSolutionWithResult(
639                    (int) $form->getItemByPostVar('print_bs_with_res')->getChecked()
640                );
641            } else {
642                $this->testOBJ->setShowSolutionDetails(0);
643                $this->testOBJ->setPrintBestSolutionWithResult(0);
644            }
645        }
646
647        if ($this->formPropertyExists($form, 'solution_feedback')) {
648            $this->testOBJ->setShowSolutionFeedback($form->getItemByPostVar('solution_feedback')->getChecked());
649        }
650
651        if ($this->formPropertyExists($form, 'solution_suggested')) {
652            $this->testOBJ->setShowSolutionSuggested($form->getItemByPostVar('solution_suggested')->getChecked());
653        }
654
655        if ($this->formPropertyExists($form, 'solution_printview')) {
656            if ($form->getItemByPostVar('solution_printview')->getChecked()) {
657                $this->testOBJ->setShowSolutionPrintview(1);
658                $this->testOBJ->setShowSolutionListComparison(
659                    (bool) $form->getItemByPostVar('solution_compare')->getChecked()
660                );
661                $this->testOBJ->setShowSolutionAnswersOnly(
662                    (int) $form->getItemByPostVar('solution_answers_only')->getChecked()
663                );
664            } else {
665                $this->testOBJ->setShowSolutionPrintview(0);
666                $this->testOBJ->setShowSolutionListComparison(false);
667                $this->testOBJ->setShowSolutionAnswersOnly(0);
668            }
669        }
670
671        if ($this->formPropertyExists($form, 'highscore_enabled')) {
672            // highscore settings
673            $this->testOBJ->setHighscoreEnabled((bool) $form->getItemByPostVar('highscore_enabled')->getChecked());
674            $this->testOBJ->setHighscoreAnon((bool) $form->getItemByPostVar('highscore_anon')->getChecked());
675            $this->testOBJ->setHighscoreAchievedTS((bool) $form->getItemByPostVar('highscore_achieved_ts')->getChecked());
676            $this->testOBJ->setHighscoreScore((bool) $form->getItemByPostVar('highscore_score')->getChecked());
677            $this->testOBJ->setHighscorePercentage((bool) $form->getItemByPostVar('highscore_percentage')->getChecked());
678            $this->testOBJ->setHighscoreHints((bool) $form->getItemByPostVar('highscore_hints')->getChecked());
679            $this->testOBJ->setHighscoreWTime((bool) $form->getItemByPostVar('highscore_wtime')->getChecked());
680            $this->testOBJ->setHighscoreMode((int) $form->getItemByPostVar('highscore_mode')->getValue());
681            $this->testOBJ->setHighscoreTopNum((int) $form->getItemByPostVar('highscore_top_num')->getValue());
682        }
683
684        if ($this->formPropertyExists($form, 'solution_signature')) {
685            $this->testOBJ->setShowSolutionSignature($form->getItemByPostVar('solution_signature')->getChecked());
686        }
687
688        if ($this->formPropertyExists($form, 'examid_in_test_res')) {
689            $this->testOBJ->setShowExamIdInTestResultsEnabled($form->getItemByPostVar('examid_in_test_res')->getChecked());
690        }
691
692        if ($this->formPropertyExists($form, 'exp_sc_short')) {
693            $this->testOBJ->setExportSettingsSingleChoiceShort((int) $form->getItemByPostVar('exp_sc_short')->getChecked());
694        }
695    }
696
697    private function addMiscSettingsFormSection(ilPropertyFormGUI $form)
698    {
699        if ($this->testQuestionSetConfigFactory->getQuestionSetConfig()->isResultTaxonomyFilterSupported()) {
700            // misc settings
701            $header_misc = new ilFormSectionHeaderGUI();
702            $header_misc->setTitle($this->lng->txt('misc'));
703            $form->addItem($header_misc);
704        }
705
706        // result filter taxonomies
707        if ($this->testQuestionSetConfigFactory->getQuestionSetConfig()->isResultTaxonomyFilterSupported()) {
708            $availableTaxonomyIds = $this->getAvailableTaxonomyIds();
709
710            if (count($availableTaxonomyIds)) {
711                require_once 'Modules/Test/classes/class.ilTestTaxonomyFilterLabelTranslater.php';
712                $labelTranslater = new ilTestTaxonomyFilterLabelTranslater($this->db);
713                $labelTranslater->loadLabelsFromTaxonomyIds($availableTaxonomyIds);
714
715                $results_presentation = new ilCheckboxGroupInputGUI($this->lng->txt('tst_results_tax_filters'), 'results_tax_filters');
716
717                foreach ($availableTaxonomyIds as $taxonomyId) {
718                    $results_presentation->addOption(new ilCheckboxOption(
719                        $labelTranslater->getTaxonomyTreeLabel($taxonomyId),
720                        $taxonomyId,
721                        ''
722                    ));
723                }
724
725                $results_presentation->setValue($this->testOBJ->getResultFilterTaxIds());
726
727                $form->addItem($results_presentation);
728            }
729        }
730    }
731
732    /**
733     * @param ilPropertyFormGUI $form
734     */
735    private function saveResultMiscOptionsSettings(ilPropertyFormGUI $form)
736    {
737        // result filter taxonomies
738        if ($this->testQuestionSetConfigFactory->getQuestionSetConfig()->isResultTaxonomyFilterSupported()) {
739            if (!$this->isHiddenFormItem('results_tax_filters') && count($this->getAvailableTaxonomyIds())) {
740                $taxFilters = array();
741
742                if (is_array($form->getItemByPostVar('results_tax_filters')->getValue())) {
743                    $taxFilters = array_intersect(
744                        $this->getAvailableTaxonomyIds(),
745                        $form->getItemByPostVar('results_tax_filters')->getValue()
746                    );
747                }
748
749                $this->testOBJ->setResultFilterTaxIds($taxFilters);
750            }
751        }
752    }
753
754    private function isScoreReportingAvailable()
755    {
756        if (!$this->testOBJ->getScoreReporting()) {
757            return false;
758        }
759
760        if (
761            $this->testOBJ->getScoreReporting() == ilObjTest::SCORE_REPORTING_DATE
762            && $this->testOBJ->getReportingDate() > time()
763        ) {
764            return false;
765        }
766
767        return true;
768    }
769
770    private function areScoringSettingsWritable()
771    {
772        if (!$this->testOBJ->participantDataExist()) {
773            return true;
774        }
775
776        if (!$this->isScoreReportingAvailable()) {
777            return true;
778        }
779
780        return false;
781    }
782
783    private function isScoreRecalculationRequired(ilPropertyFormGUI $form)
784    {
785        if (!$this->testOBJ->participantDataExist()) {
786            return false;
787        }
788
789        if (!$this->areScoringSettingsWritable()) {
790            return false;
791        }
792
793        if (!$this->hasScoringSettingsChanged($form)) {
794            return false;
795        }
796
797        return true;
798    }
799
800    private function hasScoringSettingsChanged(ilPropertyFormGUI $form)
801    {
802        $countSystem = $form->getItemByPostVar('count_system');
803        if (is_object($countSystem) && $countSystem->getValue() != $this->testOBJ->getCountSystem()) {
804            return true;
805        }
806
807        $mcScoring = $form->getItemByPostVar('mc_scoring');
808        if (is_object($mcScoring) && $mcScoring->getValue() != $this->testOBJ->getMCScoring()) {
809            return true;
810        }
811
812        $scoreCutting = $form->getItemByPostVar('score_cutting');
813        if (is_object($scoreCutting) && $scoreCutting->getValue() != $this->testOBJ->getScoreCutting()) {
814            return true;
815        }
816
817        $passScoring = $form->getItemByPostVar('pass_scoring');
818        if (is_object($passScoring) && $passScoring->getValue() != $this->testOBJ->getPassScoring()) {
819            return true;
820        }
821
822        return false;
823    }
824
825    private $availableTaxonomyIds = null;
826
827    private function getAvailableTaxonomyIds()
828    {
829        if ($this->getAvailableTaxonomyIds === null) {
830            require_once 'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
831            $this->availableTaxonomyIds = (array) ilObjTaxonomy::getUsageOfObject($this->testOBJ->getId());
832        }
833
834        return $this->availableTaxonomyIds;
835    }
836}
837