1<?php
2/* Copyright (c) 1998-2014 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4/**
5 * Class ilMarkSchemaGUI
6 * @author  Michael Jansen <mjansen@databay.de>
7 * @package ModulesTest
8 */
9class ilMarkSchemaGUI
10{
11    /**
12     * @var ilMarkSchemaAware|ilEctsGradesEnabled
13     */
14    protected $object;
15
16    /**
17     * @var ilLanguage
18     */
19    protected $lng;
20
21    /**
22     * @var ilCtrl
23     */
24    protected $ctrl;
25
26    /**
27     * @var ilTemplate
28     */
29    protected $tpl;
30
31    /**
32     * @var ilToolbarGUI
33     */
34    protected $toolbar;
35
36    /**
37     * @param ilMarkSchemaAware|ilEctsGradesEnabled $object
38     */
39    public function __construct(ilMarkSchemaAware $object)
40    {
41        /**
42         * @var $ilCtrl    ilCtrl
43         * @var $lng       ilLanguage
44         * @var $tpl       ilTemplate
45         * @var $ilToolbar ilToolbarGUI
46         */
47        global $DIC;
48        $ilCtrl = $DIC['ilCtrl'];
49        $lng = $DIC['lng'];
50        $tpl = $DIC['tpl'];
51        $ilToolbar = $DIC['ilToolbar'];
52
53        $this->ctrl = $ilCtrl;
54        $this->lng = $lng;
55        $this->tpl = $tpl;
56        $this->toolbar = $ilToolbar;
57
58        $this->object = $object;
59    }
60
61    /**
62     * Controller method
63     */
64    public function executeCommand()
65    {
66        global $DIC; /* @var ILIAS\DI\Container $DIC */
67
68        $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_SETTINGS);
69
70        $cmd = $this->ctrl->getCmd('showMarkSchema');
71        $this->$cmd();
72    }
73
74    /**
75     *
76     */
77    protected function ensureMarkSchemaCanBeEdited()
78    {
79        if (!$this->object->canEditMarks()) {
80            ilUtil::sendFailure($this->lng->txt('permission_denied'), true);
81            $this->ctrl->redirect($this, 'showMarkSchema');
82        }
83    }
84
85    /**
86     *
87     */
88    protected function ensureEctsGradesCanBeEdited()
89    {
90        if (!$this->object->canEditEctsGrades()) {
91            ilUtil::sendFailure($this->lng->txt('permission_denied'), true);
92            $this->ctrl->redirect($this, 'showMarkSchema');
93        }
94    }
95
96    /**
97     * Add a new mark step to the tests marks
98     */
99    protected function addMarkStep()
100    {
101        $this->ensureMarkSchemaCanBeEdited();
102
103        $this->saveMarkSchemaFormData();
104        $this->object->getMarkSchema()->addMarkStep();
105        $this->showMarkSchema();
106    }
107
108    /**
109     * Save the mark schema POST data when the form was submitted
110     */
111    protected function saveMarkSchemaFormData()
112    {
113        $this->object->getMarkSchema()->flush();
114        foreach ($_POST as $key => $value) {
115            if (preg_match('/mark_short_(\d+)/', $key, $matches)) {
116                $this->object->getMarkSchema()->addMarkStep(
117                    ilUtil::stripSlashes($_POST["mark_short_$matches[1]"]),
118                    ilUtil::stripSlashes($_POST["mark_official_$matches[1]"]),
119                    ilUtil::stripSlashes($_POST["mark_percentage_$matches[1]"]),
120                    ilUtil::stripSlashes($_POST["passed_$matches[1]"])
121                );
122            }
123        }
124    }
125
126    /**
127     * Add a simple mark schema to the tests marks
128     */
129    protected function addSimpleMarkSchema()
130    {
131        $this->ensureMarkSchemaCanBeEdited();
132
133        $this->object->getMarkSchema()->createSimpleSchema(
134            $this->lng->txt('failed_short'),
135            $this->lng->txt('failed_official'),
136            0,
137            0,
138            $this->lng->txt('passed_short'),
139            $this->lng->txt('passed_official'),
140            50,
141            1
142        );
143        $this->showMarkSchema();
144    }
145
146    /**
147     * Delete selected mark steps
148     */
149    protected function deleteMarkSteps()
150    {
151        $this->ensureMarkSchemaCanBeEdited();
152
153        if (!isset($_POST['marks']) || !is_array($_POST['marks'])) {
154            $this->showMarkSchema();
155            return;
156        }
157
158        $this->saveMarkSchemaFormData();
159        $delete_mark_steps = array();
160        foreach ($_POST['marks'] as $mark_step_id) {
161            $delete_mark_steps[] = $mark_step_id;
162        }
163
164        if (count($delete_mark_steps)) {
165            $this->object->getMarkSchema()->deleteMarkSteps($delete_mark_steps);
166        } else {
167            ilUtil::sendInfo($this->lng->txt('tst_delete_missing_mark'));
168        }
169
170        $this->showMarkSchema();
171    }
172
173    /**
174     * Save the mark schema
175     */
176    protected function saveMarks()
177    {
178        $this->ensureMarkSchemaCanBeEdited();
179
180        try {
181            $this->saveMarkSchemaFormData();
182            $result = $this->object->checkMarks();
183        } catch (Exception $e) {
184            $result = $this->lng->txt('mark_schema_invalid');
185        }
186
187        if (is_string($result)) {
188            ilUtil::sendFailure($this->lng->txt($result), true);
189        } else {
190            $this->object->getMarkSchema()->saveToDb($this->object->getMarkSchemaForeignId());
191            $this->object->onMarkSchemaSaved();
192            ilUtil::sendSuccess($this->lng->txt('saved_successfully'), true);
193        }
194
195        $this->ctrl->redirect($this);
196    }
197
198    /**
199     * @return boolean
200     */
201    private function objectSupportsEctsGrades()
202    {
203        require_once 'Modules/Test/interfaces/interface.ilEctsGradesEnabled.php';
204        return $this->object instanceof ilEctsGradesEnabled;
205    }
206
207    /**
208     * Display mark schema
209     * @param ilPropertyFormGUI $ects_form
210     */
211    protected function showMarkSchema(ilPropertyFormGUI $ects_form = null)
212    {
213        if (!$this->object->canEditMarks()) {
214            ilUtil::sendInfo($this->lng->txt('cannot_edit_marks'));
215        }
216
217        $this->toolbar->setFormAction($this->ctrl->getFormAction($this, 'showMarkSchema'));
218
219        require_once 'Modules/Test/classes/tables/class.ilMarkSchemaTableGUI.php';
220        $mark_schema_table = new ilMarkSchemaTableGUI($this, 'showMarkSchema', '', $this->object);
221
222        if ($this->object->canEditMarks()) {
223            require_once 'Services/UIComponent/Button/classes/class.ilSubmitButton.php';
224            $create_simple_mark_schema_button = ilSubmitButton::getInstance();
225            $create_simple_mark_schema_button->setCaption($this->lng->txt('tst_mark_create_simple_mark_schema'), false);
226            $create_simple_mark_schema_button->setCommand('addSimpleMarkSchema');
227            $this->toolbar->addButtonInstance($create_simple_mark_schema_button);
228
229            require_once 'Services/UIComponent/Button/classes/class.ilButton.php';
230            $create_new_mark_step_button = ilButton::getInstance();
231            $create_new_mark_step_button->setCaption($this->lng->txt('tst_mark_create_new_mark_step'), false);
232            $create_new_mark_step_button->setButtonType(ilButton::BUTTON_TYPE_SUBMIT);
233            $create_new_mark_step_button->setForm('form_' . $mark_schema_table->getId());
234            $create_new_mark_step_button->setName('addMarkStep');
235            $this->toolbar->addButtonInstance($create_new_mark_step_button);
236        }
237
238
239        $content_parts = array($mark_schema_table->getHTML());
240
241        if ($this->objectSupportsEctsGrades() && $this->object->canShowEctsGrades()) {
242            if (!($ects_form instanceof ilPropertyFormGUI)) {
243                $ects_form = $this->getEctsForm();
244                $this->populateEctsForm($ects_form);
245            }
246            $content_parts[] = $ects_form->getHTML();
247        }
248
249        $this->tpl->setContent(implode('<br />', $content_parts));
250    }
251
252    /**
253     * @param ilPropertyFormGUI $form
254     */
255    protected function populateEctsForm(ilPropertyFormGUI $form)
256    {
257        $data = array();
258
259        $data['ectcs_status'] = $this->object->getECTSOutput();
260        $data['use_ects_fx'] = preg_match('/\d+/', $this->object->getECTSFX());
261        $data['ects_fx_threshold'] = $this->object->getECTSFX();
262
263        $ects_grades = $this->object->getECTSGrades();
264        for ($i = ord('a'); $i <= ord('e'); $i++) {
265            $mark = chr($i);
266            $data['ects_grade_' . $mark] = $ects_grades[chr($i - 32)];
267        }
268
269        $form->setValuesByArray($data);
270    }
271
272    /**
273     * @return ilPropertyFormGUI
274     */
275    protected function getEctsForm()
276    {
277        require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
278
279        $disabled = !$this->object->canEditEctsGrades();
280
281        $form = new ilPropertyFormGUI();
282        $form->setFormAction($this->ctrl->getFormAction($this, 'saveEctsForm'));
283        $form->setTitle($this->lng->txt('ects_output_of_ects_grades'));
284
285        $allow_ects_marks = new ilCheckboxInputGUI($this->lng->txt('ects_allow_ects_grades'), 'ectcs_status');
286        $allow_ects_marks->setDisabled($disabled);
287        for ($i = ord('a'); $i <= ord('e'); $i++) {
288            $mark = chr($i);
289
290            $mark_step = new ilNumberInputGUI(chr($i - 32), 'ects_grade_' . $mark);
291            $mark_step->setInfo(
292                $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_' . $mark . '_desc')
293            );
294            $mark_step->setSize(5);
295            $mark_step->allowDecimals(true);
296            $mark_step->setMinValue(0, true);
297            $mark_step->setMaxValue(100, true);
298            $mark_step->setSuffix($this->lng->txt('percentile'));
299            $mark_step->setRequired(true);
300            $mark_step->setDisabled($disabled);
301            $allow_ects_marks->addSubItem($mark_step);
302        }
303
304        $mark_step = new ilNonEditableValueGUI('F', 'ects_grade_f');
305        $mark_step->setInfo(
306            $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_f_desc')
307        );
308        $allow_ects_marks->addSubItem($mark_step);
309
310        $use_ects_fx = new ilCheckboxInputGUI($this->lng->txt('use_ects_fx'), 'use_ects_fx');
311        $use_ects_fx->setDisabled($disabled);
312        $allow_ects_marks->addSubItem($use_ects_fx);
313
314        $mark_step = new ilNonEditableValueGUI('FX', 'ects_grade_fx');
315        $mark_step->setInfo(
316            $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_fx_desc')
317        );
318        $use_ects_fx->addSubItem($mark_step);
319
320        $threshold = new ilNumberInputGUI($this->lng->txt('ects_fx_threshold'), 'ects_fx_threshold');
321        $threshold->setInfo($this->lng->txt('ects_fx_threshold_info'));
322        $threshold->setSuffix($this->lng->txt('percentile'));
323        $threshold->allowDecimals(true);
324        $threshold->setSize(5);
325        $threshold->setRequired(true);
326        $threshold->setDisabled($disabled);
327        $use_ects_fx->addSubItem($threshold);
328
329
330        $form->addItem($allow_ects_marks);
331
332        if (!$disabled) {
333            $form->addCommandButton('saveEctsForm', $this->lng->txt('save'));
334        }
335
336        return $form;
337    }
338
339    /**
340     *
341     */
342    protected function saveEctsForm()
343    {
344        $this->ensureEctsGradesCanBeEdited();
345
346        $ects_form = $this->getEctsForm();
347        if (!$ects_form->checkInput()) {
348            $ects_form->setValuesByPost();
349            $this->showMarkSchema($ects_form);
350            return;
351        }
352
353        $grades = array();
354        for ($i = ord('a'); $i <= ord('e'); $i++) {
355            $mark = chr($i);
356            $grades[chr($i - 32)] = $ects_form->getInput('ects_grade_' . $mark);
357        }
358
359        $this->object->setECTSGrades($grades);
360        $this->object->setECTSOutput((int) $ects_form->getInput('ectcs_status'));
361        $this->object->setECTSFX(
362            $ects_form->getInput('use_ects_fx') && preg_match('/\d+/', $ects_form->getInput('ects_fx_threshold')) ?
363            $ects_form->getInput('ects_fx_threshold'):
364            null
365        );
366
367        $this->object->saveECTSStatus();
368
369        ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
370        $ects_form->setValuesByPost();
371        $this->showMarkSchema($ects_form);
372    }
373}
374