ILIAS  release_8 Revision v8.24
class.ilMarkSchemaGUI.php
Go to the documentation of this file.
1<?php
2
20use GuzzleHttp\Psr7\Request;
21use ILIAS\Refinery\Factory as Refinery;
22use ILIAS\UI\Factory as UIFactory;
23use ILIAS\UI\Renderer as UIRenderer;
24use ILIAS\UI\Component\Button\Standard as StandardButton;
25use ILIAS\UI\Component\Modal\Interruptive as InterruptiveModal;
26
33{
34 private const RESET_MARK_BUTTON_LABEL = 'tst_mark_reset_to_simple_mark_schema';
36 private Request $request;
37 private Refinery $refinery;
38
42 protected $object;
43 protected ilLanguage $lng;
44 protected ilCtrl $ctrl;
47 protected ilTabsGUI $tabs;
48 protected UIFactory $ui_factory;
49 protected UIRenderer $ui_renderer;
50
54 public function __construct($object)
55 {
57 global $DIC;
58
59 $this->ctrl = $DIC['ilCtrl'];
60 $this->lng = $DIC['lng'];
61 $this->tpl = $DIC['tpl'];
62 $this->toolbar = $DIC['ilToolbar'];
63 $this->object = $object;
64 $this->post_wrapper = $DIC->http()->wrapper()->post();
65 $this->request = $DIC->http()->request();
66 $this->refinery = $DIC->refinery();
67 $this->ui_factory = $DIC['ui.factory'];
68 $this->ui_renderer = $DIC['ui.renderer'];
69 }
70
71 public function executeCommand(): void
72 {
73 global $DIC;
74
75 $DIC->tabs()->activateTab(ilTestTabsManager::TAB_ID_SETTINGS);
76 $cmd = $this->ctrl->getCmd('showMarkSchema');
77 if ($cmd === self::RESET_MARK_BUTTON_LABEL) {
78 $cmd = 'resetToSimpleMarkSchema';
79 }
80 $this->$cmd();
81 }
82
83 protected function ensureMarkSchemaCanBeEdited(): void
84 {
85 if (!$this->object->canEditMarks()) {
86 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
87 $this->ctrl->redirect($this, 'showMarkSchema');
88 }
89 }
90
91 protected function ensureEctsGradesCanBeEdited(): void
92 {
93 if (!$this->object->canEditEctsGrades()) {
94 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
95 $this->ctrl->redirect($this, 'showMarkSchema');
96 }
97 }
98
99 protected function addMarkStep(): void
100 {
102
103 if ($this->saveMarkSchemaFormData()) {
104 $this->object->getMarkSchema()->addMarkStep();
105 } else {
106 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('mark_schema_invalid'), true);
107 }
108 $this->showMarkSchema();
109 }
110
111 protected function saveMarkSchemaFormData(): bool
112 {
113 $no_save_error = true;
114 $this->object->getMarkSchema()->flush();
115 $postdata = $this->request->getParsedBody();
116 foreach ($postdata as $key => $value) {
117 if (preg_match('/mark_short_(\d+)/', $key, $matches)) {
118 $passed = "0";
119 if (isset($postdata["passed_$matches[1]"])) {
120 $passed = "1";
121 }
122
123 $percentage = str_replace(',', '.', ilUtil::stripSlashes($postdata["mark_percentage_$matches[1]"]));
124 if (!is_numeric($percentage)
125 || (float) $percentage < 0.0
126 || (float) $percentage > 100.0) {
127 $percentage = 0;
128 $no_save_error = false;
129 }
130
131 $this->object->getMarkSchema()->addMarkStep(
132 ilUtil::stripSlashes($postdata["mark_short_$matches[1]"]),
133 ilUtil::stripSlashes($postdata["mark_official_$matches[1]"]),
134 (float) $percentage,
135 (int) ilUtil::stripSlashes($passed)
136 );
137 }
138 }
139
140 return $no_save_error;
141 }
142
143 protected function resetToSimpleMarkSchema(): void
144 {
146
147 $this->object->getMarkSchema()->createSimpleSchema(
148 $this->lng->txt('failed_short'),
149 $this->lng->txt('failed_official'),
150 0,
151 0,
152 $this->lng->txt('passed_short'),
153 $this->lng->txt('passed_official'),
154 50,
155 1
156 );
157 $this->object->getMarkSchema()->saveToDb($this->object->getTestId());
158 $this->showMarkSchema();
159 }
160
161 protected function deleteMarkSteps(): void
162 {
163 $marks_trafo = $this->refinery->custom()->transformation(
164 function ($vs): ?array {
165 if ($vs === null || !is_array($vs)) {
166 return null;
167 }
168 return $vs;
169 }
170 );
171 $deleted_mark_steps = null;
172 if ($this->post_wrapper->has('marks')) {
173 $deleted_mark_steps = $this->post_wrapper->retrieve(
174 'marks',
175 $marks_trafo
176 );
177 }
178
180 if (!isset($deleted_mark_steps) || !is_array($deleted_mark_steps)) {
181 $this->showMarkSchema();
182 return;
183 }
184
185 // test delete
186 $schema = clone $this->object->getMarkSchema();
187 $schema->deleteMarkSteps($deleted_mark_steps);
188 $check_result = $schema->checkMarks();
189 if (is_string($check_result)) {
190 $this->tpl->setOnScreenMessage('failure', $this->lng->txt($check_result), true);
191 $this->showMarkSchema();
192 return;
193 }
194
195 // actual delete
196 if (!empty($deleted_mark_steps)) {
197 $this->object->getMarkSchema()->deleteMarkSteps($deleted_mark_steps);
198 } else {
199 $this->tpl->setOnScreenMessage('info', $this->lng->txt('tst_delete_missing_mark'));
200 }
201 $this->object->getMarkSchema()->saveToDb($this->object->getTestId());
202
203 $this->showMarkSchema();
204 }
205
206 protected function saveMarks(): void
207 {
209
210 if ($this->saveMarkSchemaFormData()) {
211 $result = $this->object->checkMarks();
212 } else {
213 $result = 'mark_schema_invalid';
214 }
215
216 if (is_string($result)) {
217 $this->tpl->setOnScreenMessage('failure', $this->lng->txt($result), true);
218 } else {
219 $this->object->getMarkSchema()->saveToDb($this->object->getMarkSchemaForeignId());
220 $this->object->onMarkSchemaSaved();
221 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
222 $this->object->getMarkSchema()->flush();
223 $this->object->getMarkSchema()->loadFromDb($this->object->getTestId());
224 }
225
226 $this->showMarkSchema();
227 }
228
229 private function objectSupportsEctsGrades(): bool
230 {
231 require_once 'Modules/Test/interfaces/interface.ilEctsGradesEnabled.php';
232 return $this->object instanceof ilEctsGradesEnabled;
233 }
234
235 protected function showMarkSchema(?ilPropertyFormGUI $ects_form = null): void
236 {
237 if (!$this->object->canEditMarks()) {
238 $this->tpl->setOnScreenMessage('info', $this->lng->txt('cannot_edit_marks'));
239 }
240
241 $this->toolbar->setFormAction($this->ctrl->getFormAction($this, 'showMarkSchema'));
242
243 require_once 'Modules/Test/classes/tables/class.ilMarkSchemaTableGUI.php';
244 $mark_schema_table = new ilMarkSchemaTableGUI($this, 'showMarkSchema', '', $this->object);
245 $mark_schema_table->setShowRowsSelector(false);
246
247 $rendered_modal = '';
248 if ($this->object->canEditMarks()) {
249 $confirmation_modal = $this->ui_factory->modal()->interruptive(
250 $this->lng->txt(self::RESET_MARK_BUTTON_LABEL),
251 $this->lng->txt('tst_mark_reset_to_simple_mark_schema_confirmation'),
252 $this->ctrl->getFormAction($this, 'resetToSimpleMarkSchema')
253 )->withActionButtonLabel(self::RESET_MARK_BUTTON_LABEL);
254 $this->populateToolbar($confirmation_modal, $mark_schema_table->getId());
255 $rendered_modal = $this->ui_renderer->render($confirmation_modal);
256 }
257
258 $this->tpl->setContent(
259 $mark_schema_table->getHTML() . $rendered_modal
260 );
261 }
262
263 private function populateToolbar(InterruptiveModal $confirmation_modal, string $mark_schema_id): void
264 {
265 $create_simple_schema_button = $this->ui_factory->button()->standard(
266 $this->lng->txt(self::RESET_MARK_BUTTON_LABEL),
267 $confirmation_modal->getShowSignal()
268 );
269 $this->toolbar->addComponent($create_simple_schema_button);
270
271 $create_step_button = $this->buildCreateStepButton($mark_schema_id);
272 $this->toolbar->addComponent($create_step_button);
273 }
274
275 private function buildCreateStepButton(string $mark_schema_id): StandardButton
276 {
277 return $this->ui_factory->button()->standard(
278 $this->lng->txt('tst_mark_create_new_mark_step'),
279 ''
280 )->withAdditionalOnLoadCode(
281 fn (string $id): string =>
282 "{$id}.addEventListener('click', "
283 . ' (e) => {'
284 . ' e.preventDefault();'
285 . ' e.target.name = "cmd[addMarkStep]";'
286 . " let form = document.getElementById('form_{$mark_schema_id}');"
287 . ' let submitter = e.target.cloneNode();'
288 . ' submitter.style.visibility = "hidden";'
289 . ' form.appendChild(submitter);'
290 . ' form.requestSubmit(submitter);'
291 . ' }'
292 . ');'
293 );
294 }
295
296 protected function populateEctsForm(ilPropertyFormGUI $form): void
297 {
298 $data = array();
299
300 $data['ectcs_status'] = $this->object->getECTSOutput();
301 $data['use_ects_fx'] = preg_match('/\d+/', $this->object->getECTSFX());
302 $data['ects_fx_threshold'] = $this->object->getECTSFX();
303
304 $ects_grades = $this->object->getECTSGrades();
305 for ($i = ord('a'); $i <= ord('e'); $i++) {
306 $mark = chr($i);
307 $data['ects_grade_' . $mark] = $ects_grades[chr($i - 32)];
308 }
309
310 $form->setValuesByArray($data);
311 }
312
313 protected function getEctsForm(): ilPropertyFormGUI
314 {
315 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
316
317 $disabled = !$this->object->canEditEctsGrades();
318
319 $form = new ilPropertyFormGUI();
320 $form->setFormAction($this->ctrl->getFormAction($this, 'saveEctsForm'));
321 $form->setTitle($this->lng->txt('ects_output_of_ects_grades'));
322
323 $allow_ects_marks = new ilCheckboxInputGUI($this->lng->txt('ects_allow_ects_grades'), 'ectcs_status');
324 $allow_ects_marks->setDisabled($disabled);
325 for ($i = ord('a'); $i <= ord('e'); $i++) {
326 $mark = chr($i);
327
328 $mark_step = new ilNumberInputGUI(chr($i - 32), 'ects_grade_' . $mark);
329 $mark_step->setInfo(
330 $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_' . $mark . '_desc')
331 );
332 $mark_step->setSize(5);
333 $mark_step->allowDecimals(true);
334 $mark_step->setMinValue(0, true);
335 $mark_step->setMaxValue(100, true);
336 $mark_step->setSuffix($this->lng->txt('percentile'));
337 $mark_step->setRequired(true);
338 $mark_step->setDisabled($disabled);
339 $allow_ects_marks->addSubItem($mark_step);
340 }
341
342 $mark_step = new ilNonEditableValueGUI('F', 'ects_grade_f');
343 $mark_step->setInfo(
344 $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_f_desc')
345 );
346 $allow_ects_marks->addSubItem($mark_step);
347
348 $use_ects_fx = new ilCheckboxInputGUI($this->lng->txt('use_ects_fx'), 'use_ects_fx');
349 $use_ects_fx->setDisabled($disabled);
350 $allow_ects_marks->addSubItem($use_ects_fx);
351
352 $mark_step = new ilNonEditableValueGUI('FX', 'ects_grade_fx');
353 $mark_step->setInfo(
354 $this->lng->txt('ects_grade_desc_prefix') . ' ' . $this->lng->txt('ects_grade_fx_desc')
355 );
356 $use_ects_fx->addSubItem($mark_step);
357
358 $threshold = new ilNumberInputGUI($this->lng->txt('ects_fx_threshold'), 'ects_fx_threshold');
359 $threshold->setInfo($this->lng->txt('ects_fx_threshold_info'));
360 $threshold->setSuffix($this->lng->txt('percentile'));
361 $threshold->allowDecimals(true);
362 $threshold->setSize(5);
363 $threshold->setRequired(true);
364 $threshold->setDisabled($disabled);
365 $use_ects_fx->addSubItem($threshold);
366
367
368 $form->addItem($allow_ects_marks);
369
370 if (!$disabled) {
371 $form->addCommandButton('saveEctsForm', $this->lng->txt('save'));
372 }
373
374 return $form;
375 }
376
377 protected function saveEctsForm(): void
378 {
380
381 $ects_form = $this->getEctsForm();
382 if (!$ects_form->checkInput()) {
383 $ects_form->setValuesByPost();
384 $this->showMarkSchema($ects_form);
385 return;
386 }
387
388 $grades = array();
389 for ($i = ord('a'); $i <= ord('e'); $i++) {
390 $mark = chr($i);
391 $grades[chr($i - 32)] = $ects_form->getInput('ects_grade_' . $mark);
392 }
393
394 $this->object->setECTSGrades($grades);
395 $this->object->setECTSOutput((int) $ects_form->getInput('ectcs_status'));
396 $this->object->setECTSFX(
397 $ects_form->getInput('use_ects_fx') && preg_match('/\d+/', $ects_form->getInput('ects_fx_threshold')) ?
398 $ects_form->getInput('ects_fx_threshold') :
399 null
400 );
401
402 $this->object->saveECTSStatus();
403
404 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'));
405 $ects_form->setValuesByPost();
406 $this->showMarkSchema($ects_form);
407 }
408}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds data types.
Definition: Factory.php:21
This class represents a checkbox property in a property form.
Class ilCtrl provides processing control methods.
language handling
ilGlobalPageTemplate $tpl
populateEctsForm(ilPropertyFormGUI $form)
showMarkSchema(?ilPropertyFormGUI $ects_form=null)
populateToolbar(InterruptiveModal $confirmation_modal, string $mark_schema_id)
buildCreateStepButton(string $mark_schema_id)
RequestWrapper $post_wrapper
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a number property in a property form.
This class represents a property form user interface.
setValuesByArray(array $a_values, bool $a_restrict_to_value_keys=false)
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 stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
global $DIC
Definition: feed.php:28
Interface RequestWrapper.
This describes a standard button.
Definition: Standard.php:27
This is how the factory for UI elements looks.
Definition: Factory.php:38
An entity that renders components to a string output.
Definition: Renderer.php:31
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193