ILIAS  release_8 Revision v8.24
class.assClozeTestGUI.php
Go to the documentation of this file.
1<?php
2
19use ILIAS\Refinery\Random\Group as RandomGroup;
25
42{
43 public const OLD_CLOZE_TEST_UI = false;
44
45 public const JS_INSERT_GAP_CODE_AT_CARET = <<<JS
46 jQuery.fn.extend({
47 insertGapCodeAtCaret: function() {
48 return this.each(function(i) {
49 var code_start = "[gap]"
50 var code_end = "[/gap]"
51 if (typeof tinyMCE != "undefined" && typeof tinyMCE.get('cloze_text') != "undefined") {
52 var ed = tinyMCE.get('cloze_text');
53 il.ClozeHelper.internetExplorerTinyMCECursorFix(ed);
54 ed.selection.setContent(code_start + ed.selection.getContent() + code_end);
55 ed.focus();
56 return;
57 }
58 if (document.selection) {
59 //For browsers like Internet Explorer
60 this.focus();
61 sel = document.selection.createRange();
62 sel.text = code_start + sel.text + code_end;
63 this.focus();
64 }
65 else if (this.selectionStart || this.selectionStart == '0') {
66 //For browsers like Firefox and Webkit based
67 var startPos = this.selectionStart;
68 var endPos = this.selectionEnd;
69 var scrollTop = this.scrollTop;
70 this.value = this.value.substring(0, startPos)
71 + code_start
72 + this.value.substring(startPos, endPos)
73 + code_end
74 + this.value.substring(endPos, this.value.length);
75 this.focus();
76 this.scrollTop = scrollTop;
77 } else {
78 this.value += code_start + code_end;
79 this.focus();
80 }
81 });
82 }
83 });
84JS;
85
89 private $gapIndex;
90
91 private RandomGroup $randomGroup;
92 private Container $dic;
95
101 public function __construct(int $id = -1)
102 {
104 global $DIC;
105 $this->dic = $DIC;
106 $this->refinery = $this->dic->refinery();
107 $this->post = $this->dic->http()->wrapper()->post();
108
109 $this->object = new assClozeTest();
110 if ($id >= 0) {
111 $this->object->loadFromDb($id);
112 }
113
114 $this->randomGroup = $this->refinery->random();
115 }
116
117 public function getCommand($cmd)
118 {
119 if (preg_match("/^(removegap|addgap)_(\d+)$/", $cmd, $matches)) {
120 $cmd = $matches[1];
121 $this->gapIndex = $matches[2];
122 }
123 return $cmd;
124 }
125
129 protected function writePostData(bool $always = false): int
130 {
131 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
132 if (!$hasErrors) {
133 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
134
135 $cloze_text = $this->removeIndizesFromGapText(
136 $this->request->raw('cloze_text')
137 );
138
139 $this->object->setQuestion(
140 $this->request->raw('question')
141 );
142
144 $this->object->setClozeText($cloze_text);
145 $this->object->setTextgapRating($this->request->raw('textgap_rating'));
146 $this->object->setIdenticalScoring((bool) ($this->request->raw('identical_scoring') ?? false));
147 $this->object->setFixedTextLength(($this->request->int('fixedTextLength') ?? 0));
150 return 0;
151 }
152
153 return 1;
154 }
155
157 {
158 if (!$this->post->has('gap')) {
159 return;
160 }
161
162 $gaps = $this->post->retrieve(
163 "gap",
164 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string())
165 );
166
167 if ($this->ctrl->getCmd() !== 'createGaps') {
168 $this->object->clearGapAnswers();
169 }
170
171 foreach ($gaps as $idx => $hidden) {
172 $clozetype = $this->post->retrieve(
173 "clozetype_" . $idx,
174 $this->refinery->kindlyTo()->string()
175 );
176
177 $this->object->setGapType($idx, $clozetype);
178
179 switch ($clozetype) {
180 case CLOZE_TEXT:
181
182 $this->object->setGapShuffle($idx, 0);
183
184 if ($this->ctrl->getCmd() != 'createGaps') {
185 if (is_array($_POST['gap_' . $idx]['answer'])) {
186 foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
187 $this->object->addGapAnswer($idx, $order, $value);
188 }
189 } else {
190 $this->object->addGapAnswer($idx, 0, '');
191 }
192 }
193
194 if (is_array($_POST['gap_' . $idx]['points'])) {
195 foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
196 $this->object->setGapAnswerPoints($idx, $order, $value);
197 }
198 }
199
200 $k_gapsize = 'gap_' . $idx . '_gapsize';
201 if ($this->request->isset($k_gapsize)) {
202 $this->object->setGapSize($idx, $_POST[$k_gapsize]);
203 }
204 break;
205
206 case CLOZE_SELECT:
207
208 $this->object->setGapShuffle($idx, (int) (isset($_POST["shuffle_$idx"]) && $_POST["shuffle_$idx"]));
209
210 if ($this->ctrl->getCmd() != 'createGaps') {
211 if (is_array($_POST['gap_' . $idx]['answer'])) {
212 foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
213 $this->object->addGapAnswer($idx, $order, $value);
214 }
215 } else {
216 $this->object->addGapAnswer($idx, 0, '');
217 }
218 }
219
220 if (is_array($_POST['gap_' . $idx]['points'])) {
221 foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
222 $this->object->setGapAnswerPoints($idx, $order, $value);
223 }
224 }
225 break;
226
227 case CLOZE_NUMERIC:
228
229 $this->object->setGapShuffle($idx, 0);
230
231 $gap = $this->object->getGap($idx);
232 if (!$gap) {
233 break;
234 }
235
236 $this->object->getGap($idx)->clearItems();
237
238 if ($this->post->has('gap_' . $idx . '_numeric')) {
239 if ($this->ctrl->getCmd() !== 'createGaps') {
240 $this->object->addGapAnswer(
241 $idx,
242 0,
243 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric'])
244 );
245 }
246
247 $this->object->setGapAnswerLowerBound(
248 $idx,
249 0,
250 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_lower'])
251 );
252
253 $this->object->setGapAnswerUpperBound(
254 $idx,
255 0,
256 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_upper'])
257 );
258
259 $this->object->setGapAnswerPoints($idx, 0, $_POST['gap_' . $idx . '_numeric_points']);
260 } else {
261 if ($this->ctrl->getCmd() != 'createGaps') {
262 $this->object->addGapAnswer($idx, 0, '');
263 }
264
265 $this->object->setGapAnswerLowerBound($idx, 0, '');
266
267 $this->object->setGapAnswerUpperBound($idx, 0, '');
268 }
269
270 if ($this->post->has('gap_' . $idx . '_gapsize')) {
271 $this->object->setGapSize($idx, $_POST['gap_' . $idx . '_gapsize']);
272 }
273 break;
274 }
275 $assClozeGapCombinationObject = new assClozeGapCombination();
276 $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
277 if (
278 isset($_POST['gap_combination']) &&
279 is_array($_POST['gap_combination']) &&
280 count($_POST['gap_combination']) > 0
281 ) {
282 $assClozeGapCombinationObject->saveGapCombinationToDb(
283 $this->object->getId(),
284 $_POST['gap_combination'],
285 $_POST['gap_combination_values']
286 );
287 }
288 }
289 if ($this->ctrl->getCmd() != 'createGaps') {
290 $this->object->updateClozeTextFromGaps();
291 }
292 }
293
295 {
296 $this->object->setClozeText($_POST['cloze_text']);
297 $this->object->setTextgapRating($_POST["textgap_rating"]);
298 $this->object->setIdenticalScoring($_POST["identical_scoring"]);
299 $this->object->setFixedTextLength($_POST["fixedTextLength"]);
300 }
301
307 public function editQuestion($checkonly = false): bool
308 {
309 $save = $this->isSaveCommand();
310 $this->getQuestionTemplate();
311
312 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
313 $form = new ilPropertyFormGUI();
314 $this->editForm = $form;
315
316 $form->setFormAction($this->ctrl->getFormAction($this));
317 $form->setTitle($this->outQuestionType());
318 $form->setMultipart(false);
319 $form->setTableWidth("100%");
320 $form->setId("assclozetest");
321
322 $this->addBasicQuestionFormProperties($form);
324 $this->populateAnswerSpecificFormPart($form);
325 $this->populateTaxonomyFormSection($form);
326
327 $this->addQuestionFormCommandButtons($form);
328
329 $errors = false;
330
331 if ($save) {
332 $form->setValuesByPost();
333 $errors = !$form->checkInput();
334 $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we
335 // need this if we don't want to have duplication of backslashes
336 if ($errors) {
337 $checkonly = false;
338 }
339 }
340
341 if (!$checkonly) {
342 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
343 }
344 return $errors;
345 }
346
348 {
349 // title
350 $title = new ilTextInputGUI($this->lng->txt("title"), "title");
351 $title->setMaxLength(100);
352 $title->setValue($this->object->getTitle());
353 $title->setRequired(true);
354 $form->addItem($title);
355
356 if (!$this->object->getSelfAssessmentEditingMode()) {
357 // author
358 $author = new ilTextInputGUI($this->lng->txt("author"), "author");
359 $author->setValue($this->object->getAuthor());
360 $author->setRequired(true);
361 $form->addItem($author);
362
363 // description
364 $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
365 $description->setValue($this->object->getComment());
366 $description->setRequired(false);
367 $form->addItem($description);
368 } else {
369 // author as hidden field
370 $hi = new ilHiddenInputGUI("author");
371 $author = ilLegacyFormElementsUtil::prepareFormOutput($this->object->getAuthor());
372 if (trim($author) == "") {
373 $author = "-";
374 }
375 $hi->setValue($author);
376 $form->addItem($hi);
377 }
378
379 // lifecycle
380 $lifecycle = new ilSelectInputGUI($this->lng->txt('qst_lifecycle'), 'lifecycle');
381 $lifecycle->setOptions($this->object->getLifecycle()->getSelectOptions($this->lng));
382 $lifecycle->setValue($this->object->getLifecycle()->getIdentifier());
383 $form->addItem($lifecycle);
384
385 // questiontext
386 $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
387 $question->setValue($this->object->getQuestion());
388 $question->setRequired(true);
389 $question->setRows(10);
390 $question->setCols(80);
391 if (!$this->object->getSelfAssessmentEditingMode()) {
392 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_RTE) {
393 $question->setUseRte(true);
394 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
395 $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
396 $question->addPlugin("latex");
397 $question->addButton("latex");
398 $question->addButton("pastelatex");
399 $question->setRTESupport($this->object->getId(), "qpl", "assessment");
400 }
401 } else {
402 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
404 $question->setUseTagsForRteOnly(false);
405 }
406 $form->addItem($question);
408 }
409
411 {
412 // cloze text
413 $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
414 $cloze_text->setRequired(true);
415 $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
416 $cloze_text->setInfo($this->lng->txt("close_text_hint"));
417 $cloze_text->setRows(10);
418 $cloze_text->setCols(80);
419 if (!$this->object->getSelfAssessmentEditingMode()) {
420 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_RTE) {
421 $cloze_text->setUseRte(true);
422 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
423 $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
424 $cloze_text->addPlugin("latex");
425 $cloze_text->addButton("latex");
426 $cloze_text->addButton("pastelatex");
427 }
428 } else {
429 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
431 $cloze_text->setUseTagsForRteOnly(false);
432 }
433 $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
434 $form->addItem($cloze_text);
435
436 $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", true, true, "Modules/TestQuestionPool");
437
438 $button = new ilCustomInputGUI('&nbsp;', '');
439 $action_button = ilSplitButtonGUI::getInstance();
440
441 $sb_text_gap = ilJsLinkButton::getInstance();
442 $sb_text_gap->setCaption('text_gap');
443 $sb_text_gap->setName('gapbutton');
444 $sb_text_gap->setId('gaptrigger_text');
445 $sb_text_gap->setTarget('');
446 $action_button->setDefaultButton($sb_text_gap);
447
448 $sb_sel_gap = ilJsLinkButton::getInstance();
449 $sb_sel_gap->setCaption('select_gap');
450 $sb_sel_gap->setName('gapbutton_select');
451 $sb_sel_gap->setId('gaptrigger_select');
452 $sb_sel_gap->setTarget('');
453 $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_sel_gap));
454
455 $sb_num_gap = ilJsLinkButton::getInstance();
456 $sb_num_gap->setCaption('numeric_gap');
457 $sb_num_gap->setName('gapbutton_numeric');
458 $sb_num_gap->setId('gaptrigger_numeric');
459 $sb_num_gap->setTarget('');
460 $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_num_gap));
461
462 $tpl->setVariable('BUTTON', $action_button->render());
464
465 $button->setHtml($tpl->get());
466 $this->tpl->addOnloadCode(self::JS_INSERT_GAP_CODE_AT_CARET);
467 $form->addItem($button);
468
469 // text rating
470 if (!$this->object->getSelfAssessmentEditingMode()) {
471 $textrating = new ilSelectInputGUI($this->lng->txt("text_rating"), "textgap_rating");
472 $text_options = array(
473 "ci" => $this->lng->txt("cloze_textgap_case_insensitive"),
474 "cs" => $this->lng->txt("cloze_textgap_case_sensitive"),
475 "l1" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "1"),
476 "l2" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "2"),
477 "l3" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "3"),
478 "l4" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "4"),
479 "l5" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "5")
480 );
481 $textrating->setOptions($text_options);
482 $textrating->setValue($this->object->getTextgapRating());
483 $form->addItem($textrating);
484
485 // text field length
486 $fixedTextLength = new ilNumberInputGUI($this->lng->txt("cloze_fixed_textlength"), "fixedTextLength");
487 $ftl = $this->object->getFixedTextLength();
488
489 $fixedTextLength->setValue($ftl > 0 ? $ftl : '');
490 $fixedTextLength->setMinValue(0);
491 $fixedTextLength->setSize(3);
492 $fixedTextLength->setMaxLength(6);
493 $fixedTextLength->setInfo($this->lng->txt('cloze_fixed_textlength_description'));
494 $fixedTextLength->setRequired(false);
495 $form->addItem($fixedTextLength);
496
497 // identical scoring
498 $identical_scoring = new ilCheckboxInputGUI($this->lng->txt("identical_scoring"), "identical_scoring");
499 $identical_scoring->setValue(1);
500 $identical_scoring->setChecked($this->object->getIdenticalScoring());
501 $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
502 $identical_scoring->setRequired(false);
503 $form->addItem($identical_scoring);
504 }
505 return $form;
506 }
507
509 {
510 if (self::OLD_CLOZE_TEST_UI) {
511 for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++) {
512 $this->populateGapFormPart($form, $gapCounter);
513 }
514 return $form;
515 } else {
516 require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
517 $json = $this->populateJSON();
518 $assClozeGapCombinationObject = new assClozeGapCombination();
519 $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->getId());
520 $combinations = array();
521 if ($combination_exists) {
522 $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
523 }
524 $new_builder = new ilClozeGapInputBuilderGUI();
525 $header = new ilFormSectionHeaderGUI();
526 $form->addItem($header);
527 $new_builder->setValueByArray($json);
528 $new_builder->setValueCombinationFromDb($combinations);
529 $form->addItem($new_builder);
530 return $form;
531 }
532 }
533
534 protected function populateJSON(): array
535 {
536 $gap = $this->object->getGaps();
537 $array = array();
538 if ($gap == null) {
539 return $array;
540 }
541 $translate_type = array('text','select','numeric');
542 $i = 0;
543 foreach ($gap as $content) {
544 $shuffle = false;
545 $value = $content->getItemsRaw();
546 $items = array();
547 for ($j = 0, $jMax = count($value); $j < $jMax; $j++) {
548 if ($content->isNumericGap()) {
549 $items[$j] = array(
550 'answer' => $value[$j]->getAnswerText(),
551 'lower' => $value[$j]->getLowerBound(),
552 'upper' => $value[$j]->getUpperBound(),
553 'points' => $value[$j]->getPoints(),
554 'error' => false
555 );
556 } else {
557 $items[$j] = array(
558 'answer' => $this->escapeTemplatePlaceholders($value[$j]->getAnswerText()),
559 'points' => $value[$j]->getPoints(),
560 'error' => false
561 );
562
563 if ($content->isSelectGap()) {
564 $shuffle = $content->getShuffle();
565 }
566 }
567 }
568 $answers[$i] = array(
569 'type' => $translate_type[$content->getType()] ,
570 'values' => $items ,
571 'shuffle' => $shuffle,
572 'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
573 'used_in_gap_combination' => true);
574 $i++;
575 }
576 return $answers;
577 }
589 protected function populateGapFormPart($form, $gapCounter): ilPropertyFormGUI
590 {
591 $gap = $this->object->getGap($gapCounter);
592
593 if ($gap == null) {
594 return $form;
595 }
596
597 $header = new ilFormSectionHeaderGUI();
598 $header->setTitle($this->lng->txt("gap") . " " . ($gapCounter + 1));
599 $form->addItem($header);
600
601 $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
602 $gapcounter->setValue($gapCounter);
603 $form->addItem($gapcounter);
604
605 $gaptype = new ilSelectInputGUI($this->lng->txt('type'), "clozetype_$gapCounter");
606 $options = array(
607 0 => $this->lng->txt("text_gap"),
608 1 => $this->lng->txt("select_gap"),
609 2 => $this->lng->txt("numeric_gap")
610 );
611 $gaptype->setOptions($options);
612 $gaptype->setValue($gap->getType());
613 $form->addItem($gaptype);
614
615 if ($gap->getType() == CLOZE_TEXT) {
616 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
617
618 if (count($gap->getItemsRaw()) == 0) {
619 $gap->addItem(new assAnswerCloze("", 0, 0));
620 }
621 $this->populateTextGapFormPart($form, $gap, $gapCounter);
622 } elseif ($gap->getType() == CLOZE_SELECT) {
623 if (count($gap->getItemsRaw()) == 0) {
624 $gap->addItem(new assAnswerCloze("", 0, 0));
625 }
626 $this->populateSelectGapFormPart($form, $gap, $gapCounter);
627 } elseif ($gap->getType() == CLOZE_NUMERIC) {
628 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
629
630 if (count($gap->getItemsRaw()) == 0) {
631 $gap->addItem(new assAnswerCloze("", 0, 0));
632 }
633 foreach ($gap->getItemsRaw() as $item) {
634 $this->populateNumericGapFormPart($form, $item, $gapCounter);
635 }
636 }
637 return $form;
638 }
639
645 protected function populateGapSizeFormPart($form, $gap, $gapCounter): ilPropertyFormGUI
646 {
647 $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_" . $gapCounter . '_gapsize');
648
649 $gapSizeFormItem->allowDecimals(false);
650 $gapSizeFormItem->setMinValue(0);
651 $gapSizeFormItem->setSize(3);
652 $gapSizeFormItem->setMaxLength(6);
653 $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
654 $gapSizeFormItem->setValue($gap->getGapSize());
655 $form->addItem($gapSizeFormItem);
656
657 return $form;
658 }
659
672 protected function populateSelectGapFormPart($form, $gap, $gapCounter): ilPropertyFormGUI
673 {
674 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
675 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
676 $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
677 $values->setRequired(true);
678 $values->setQuestionObject($this->object);
679 $values->setSingleline(true);
680 $values->setAllowMove(false);
681
682 $values->setValues($gap->getItemsRaw());
683 $form->addItem($values);
684
685 // shuffle
686 $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle_" . $gapCounter . "");
687 $shuffle->setValue(1);
688 $shuffle->setChecked($gap->getShuffle());
689 $shuffle->setRequired(false);
690 $form->addItem($shuffle);
691 return $form;
692 }
693
705 protected function populateTextGapFormPart($form, $gap, $gapCounter): ilPropertyFormGUI
706 {
707 // Choices
708 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
709 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
710 $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
711 $values->setRequired(true);
712 $values->setQuestionObject($this->object);
713 $values->setSingleline(true);
714 $values->setAllowMove(false);
715 $values->setValues($gap->getItemsRaw());
716 $form->addItem($values);
717
718 if ($this->object->getFixedTextLength() > 0) {
719 $values->setSize($this->object->getFixedTextLength());
720 $values->setMaxLength($this->object->getFixedTextLength());
721 }
722
723 return $form;
724 }
725
737 protected function populateNumericGapFormPart($form, $gap, $gapCounter): ilPropertyFormGUI
738 {
739 // #8944: the js-based ouput in self-assessment cannot support formulas
740 if (!$this->object->getSelfAssessmentEditingMode()) {
741 $value = new ilFormulaInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
742 $value->setInlineStyle('text-align: right;');
743
744 $lowerbound = new ilFormulaInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
745 $lowerbound->setInlineStyle('text-align: right;');
746
747 $upperbound = new ilFormulaInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
748 $upperbound->setInlineStyle('text-align: right;');
749 } else {
750 $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
751 $value->allowDecimals(true);
752
753 $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
754 $lowerbound->allowDecimals(true);
755
756 $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
757 $upperbound->allowDecimals(true);
758 }
759
760 $value->setSize(10);
761 $value->setValue(ilLegacyFormElementsUtil::prepareFormOutput($gap->getAnswertext()));
762 $value->setRequired(true);
763 $form->addItem($value);
764
765 $lowerbound->setSize(10);
766 $lowerbound->setRequired(true);
767 $lowerbound->setValue(ilLegacyFormElementsUtil::prepareFormOutput($gap->getLowerBound()));
768 $form->addItem($lowerbound);
769
770 $upperbound->setSize(10);
771 $upperbound->setRequired(true);
772 $upperbound->setValue(ilLegacyFormElementsUtil::prepareFormOutput($gap->getUpperBound()));
773 $form->addItem($upperbound);
774
775 if ($this->object->getFixedTextLength() > 0) {
776 $value->setSize($this->object->getFixedTextLength());
777 $value->setMaxLength($this->object->getFixedTextLength());
778 $lowerbound->setSize($this->object->getFixedTextLength());
779 $lowerbound->setMaxLength($this->object->getFixedTextLength());
780 $upperbound->setSize($this->object->getFixedTextLength());
781 $upperbound->setMaxLength($this->object->getFixedTextLength());
782 }
783
784 $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapCounter . "_numeric_points");
785 $points->allowDecimals(true);
786 $points->setSize(3);
787 $points->setRequired(true);
788 $points->setValue(ilLegacyFormElementsUtil::prepareFormOutput($gap->getPoints()));
789 $form->addItem($points);
790 return $form;
791 }
792
796 public function createGaps(): void
797 {
798 $this->writePostData(true);
799 $this->object->saveToDb();
800 $this->editQuestion();
801 }
802
806 public function removegap(): void
807 {
808 $this->writePostData(true);
809 $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
810 $this->editQuestion();
811 }
812
816 public function addgap(): void
817 {
818 $this->writePostData(true);
819 $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex]) + 1, "");
820 $this->editQuestion();
821 }
822
831 public function getPreview($show_question_only = false, $showInlineFeedback = false): string
832 {
833 $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
834
835 // generate the question output
836 include_once "./Services/UICore/classes/class.ilTemplate.php";
837 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
838 $output = $this->object->getClozeTextForHTMLOutput();
839 foreach ($this->object->getGaps() as $gap_index => $gap) {
840 switch ($gap->getType()) {
841 case CLOZE_TEXT:
842 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
843
844 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
845 if ($gap_size > 0) {
846 $gaptemplate->setCurrentBlock('size_and_maxlength');
847 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
848 $gaptemplate->parseCurrentBlock();
849 }
850 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
851 foreach ($user_solution as $val1 => $val2) {
852 if (strcmp($val1, $gap_index) == 0) {
853 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilLegacyFormElementsUtil::prepareFormOutput(
854 $val2
855 ) . "\"");
856 }
857 }
858 // fau: fixGapReplace - use replace function
859 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
860 // fau.
861 break;
862 case CLOZE_SELECT:
863 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
864 foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $item) {
865 $gaptemplate->setCurrentBlock("select_gap_option");
866 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
867 $gaptemplate->setVariable(
868 "SELECT_GAP_TEXT",
869 ilLegacyFormElementsUtil::prepareFormOutput($item->getAnswerText())
870 );
871 foreach ($user_solution as $val1 => $val2) {
872 if (strcmp($val1, $gap_index) == 0) {
873 if (strcmp($val2, $item->getOrder()) == 0) {
874 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
875 }
876 }
877 }
878 $gaptemplate->parseCurrentBlock();
879 }
880 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
881 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
882 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
883 // fau.
884 break;
885 case CLOZE_NUMERIC:
886 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
887 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
888 if ($gap_size > 0) {
889 $gaptemplate->setCurrentBlock('size_and_maxlength');
890 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
891 $gaptemplate->parseCurrentBlock();
892 }
893 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
894 foreach ($user_solution as $val1 => $val2) {
895 if (strcmp($val1, $gap_index) == 0) {
896 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilLegacyFormElementsUtil::prepareFormOutput(
897 $val2
898 ) . "\"");
899 }
900 }
901 // fau: fixGapReplace - use replace function
902 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
903 // fau.
904 break;
905 }
906 }
907 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
908 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
909 $questionoutput = $template->get();
910 if (!$show_question_only) {
911 // get page object output
912 $questionoutput = $this->getILIASPage($questionoutput);
913 }
914 return $questionoutput;
915 }
916
930 public function getSolutionOutput(
931 $active_id,
932 $pass = null,
933 $graphicalOutput = false,
934 $result_output = false,
935 $show_question_only = true,
936 $show_feedback = false,
937 $show_correct_solution = false,
938 $show_manual_scoring = false,
939 $show_question_text = true
940 ): string {
941 // get the solution of the user for the active pass or from the last pass if allowed
942 $user_solution = array();
943 if (($active_id > 0) && (!$show_correct_solution)) {
944 // get the solutions of a user
945 $user_solution = $this->object->getSolutionValues($active_id, $pass);
946 if (!is_array($user_solution)) {
947 $user_solution = array();
948 }
949 }
950
951 include_once "./Services/UICore/classes/class.ilTemplate.php";
952 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", true, true, "Modules/TestQuestionPool");
953 $output = $this->object->getClozeTextForHTMLOutput();
954 $assClozeGapCombinationObject = new assClozeGapCombination();
955 $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
956
957 foreach ($this->object->getGaps() as $gap_index => $gap) {
958 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", true, true, "Modules/TestQuestionPool");
959 $found = array();
960 foreach ($user_solution as $solutionarray) {
961 if ($solutionarray["value1"] == $gap_index) {
962 $found = $solutionarray;
963 }
964 }
965
966 if ($active_id) {
967 if ($graphicalOutput) {
968 // output of ok/not ok icons for user entered solutions
969 $details = $this->object->calculateReachedPoints($active_id, $pass, true, true);
970 $check = $details[$gap_index] ?? [];
971
972 if (count($check_for_gap_combinations) != 0) {
973 $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
974 $custom_user_solution = array();
975 if (array_key_exists($gap_index, $gaps_used_in_combination)) {
976 $combination_id = $gaps_used_in_combination[$gap_index];
977 foreach ($gaps_used_in_combination as $key => $value) {
978 $a = 0;
979 if ($value == $combination_id) {
980 foreach ($user_solution as $solution_key => $solution_value) {
981 if ($solution_value['value1'] == $key) {
982 $result_row = array();
983 $result_row['gap_id'] = $solution_value['value1'];
984 $result_row['value'] = $solution_value['value2'];
985 array_push($custom_user_solution, $result_row);
986 }
987 }
988 }
989 }
990 $points_array = $this->object->calculateCombinationResult($custom_user_solution);
991 $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
992 if ($points_array[0] == $max_combination_points) {
993 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK));
994 } elseif ($points_array[0] > 0) {
995 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_MOSTLY_OK));
996 } else {
997 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK));
998 }
999 } else {
1000 if (array_key_exists('best', $check) && $check["best"]) {
1001 $gaptemplate->setCurrentBlock("icon_ok");
1002 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK));
1003 $gaptemplate->parseCurrentBlock();
1004 } else {
1005 $gaptemplate->setCurrentBlock("icon_ok");
1006 if (array_key_exists('positive', $check) && $check["positive"]) {
1007 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_MOSTLY_OK));
1008 } else {
1009 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK));
1010 }
1011 $gaptemplate->parseCurrentBlock();
1012 }
1013 }
1014 } else {
1015 if (array_key_exists('best', $check) && $check["best"]) {
1016 $gaptemplate->setCurrentBlock("icon_ok");
1017 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK));
1018 $gaptemplate->parseCurrentBlock();
1019 } else {
1020 $gaptemplate->setCurrentBlock("icon_ok");
1021 if (array_key_exists('positive', $check) && $check["positive"]) {
1022 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_MOSTLY_OK));
1023 } else {
1024 $gaptemplate->setVariable("ICON_OK", $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK));
1025 }
1026 $gaptemplate->parseCurrentBlock();
1027 }
1028 }
1029 }
1030 }
1031 $combination = null;
1032 switch ($gap->getType()) {
1033 case CLOZE_NUMERIC:
1034 case CLOZE_TEXT:
1035 $solutiontext = "";
1036 if (($active_id > 0) && (!$show_correct_solution)) {
1037 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1038 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1039 $solutiontext .= "&nbsp;";
1040 }
1041 } else {
1042 $solutiontext = ilLegacyFormElementsUtil::prepareFormOutput($found["value2"]);
1043 }
1044 } else {
1045 $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1046 }
1047 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1048 // fau: fixGapReplace - use replace function
1049 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1050 // fau.
1051 break;
1052 case CLOZE_SELECT:
1053 $solutiontext = "";
1054 if (($active_id > 0) && (!$show_correct_solution)) {
1055 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1056 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1057 $solutiontext .= "&nbsp;";
1058 }
1059 } else {
1060 $item = $gap->getItem($found["value2"]);
1061 if (is_object($item)) {
1062 $solutiontext = ilLegacyFormElementsUtil::prepareFormOutput($item->getAnswertext());
1063 } else {
1064 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1065 $solutiontext .= "&nbsp;";
1066 }
1067 }
1068 }
1069 } else {
1070 $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1071 }
1072 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1073 // fau: fixGapReplace - use replace function
1074 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1075 // fau.
1076 break;
1077 }
1078 }
1079
1080 if ($show_question_text) {
1081 $template->setVariable(
1082 "QUESTIONTEXT",
1083 $this->object->getQuestionForHTMLOutput()
1084 );
1085 }
1086
1087 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1088 // generate the question output
1089 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
1090 $questionoutput = $template->get();
1091
1092 $feedback = '';
1093 if ($show_feedback) {
1094 if (!$this->isTestPresentationContext()) {
1095 $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
1096 $feedback .= strlen($fb) ? $fb : '';
1097 }
1098
1099 $fb = $this->getSpecificFeedbackOutput(
1100 $this->object->fetchIndexedValuesFromValuePairs($user_solution)
1101 );
1102 $feedback .= strlen($fb) ? $fb : '';
1103 }
1104 if (strlen($feedback)) {
1105 $cssClass = (
1106 $this->hasCorrectSolution($active_id, $pass) ?
1108 );
1109
1110 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1111 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
1112 }
1113
1114 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1115
1116 $solutionoutput = $solutiontemplate->get();
1117
1118 if (!$show_question_only) {
1119 // get page object output
1120 $solutionoutput = $this->getILIASPage($solutionoutput);
1121 }
1122
1123 return $solutionoutput;
1124 }
1125
1132 protected function getBestSolutionText($gap, $gap_index, $gap_combinations): string
1133 {
1134 $combination = null;
1135 foreach ((array) $gap_combinations as $combiGapSolRow) {
1136 if ($combiGapSolRow['gap_fi'] == $gap_index && $combiGapSolRow['best_solution']) {
1137 $combination = $combiGapSolRow;
1138 break;
1139 }
1140 }
1141 $best_solution_text = ilLegacyFormElementsUtil::prepareFormOutput(
1142 $gap->getBestSolutionOutput(
1143 $this->object->getShuffler(),
1144 $combination
1145 )
1146 );
1147 return $best_solution_text;
1148 }
1149
1150 public function getGenericFeedbackOutput(int $active_id, $pass): string
1151 {
1152 include_once "./Modules/Test/classes/class.ilObjTest.php";
1153 $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1154 if (strlen($manual_feedback)) {
1155 return $manual_feedback;
1156 }
1157 $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1158 $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1159
1160 $output = '';
1161 if ($correct_feedback . $incorrect_feedback !== '') {
1162 $output = $this->genericFeedbackOutputBuilder($correct_feedback, $incorrect_feedback, $active_id, $pass);
1163 }
1164 //$test = new ilObjTest($this->object->active_id);
1165 return $this->object->prepareTextareaOutput($output, true);
1166 }
1167
1168 public function getTestOutput(
1169 $active_id,
1170 // hey: prevPassSolutions - will be always available from now on
1171 $pass,
1172 // hey.
1173 $is_postponed = false,
1174 $use_post_solutions = false,
1175 $show_feedback = false
1176 ): string {
1177 // get the solution of the user for the active pass or from the last pass if allowed
1178 $user_solution = array();
1179 if ($use_post_solutions !== false) {
1180 $indexedSolution = $this->object->fetchSolutionSubmit($use_post_solutions);
1181 $user_solution = $this->object->fetchValuePairsFromIndexedValues($indexedSolution);
1182 } elseif ($active_id) {
1183 $user_solution = $this->object->getTestOutputSolutions($active_id, $pass);
1184 // hey.
1185 if (!is_array($user_solution)) {
1186 $user_solution = array();
1187 }
1188 }
1189
1190 // generate the question output
1191 include_once "./Services/UICore/classes/class.ilTemplate.php";
1192 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
1193 $output = $this->object->getClozeTextForHTMLOutput();
1194 foreach ($this->object->getGaps() as $gap_index => $gap) {
1195 switch ($gap->getType()) {
1196 case CLOZE_TEXT:
1197 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
1198 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1199
1200 if ($gap_size > 0) {
1201 $gaptemplate->setCurrentBlock('size_and_maxlength');
1202 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1203 $gaptemplate->parseCurrentBlock();
1204 }
1205
1206 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1207 foreach ($user_solution as $solution) {
1208 if (strcmp($solution["value1"], $gap_index) == 0) {
1209 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilLegacyFormElementsUtil::prepareFormOutput(
1210 $solution["value2"]
1211 ) . "\"");
1212 }
1213 }
1214 // fau: fixGapReplace - use replace function
1215 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1216 // fau.
1217 break;
1218 case CLOZE_SELECT:
1219 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
1220 foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $item) {
1221 $gaptemplate->setCurrentBlock("select_gap_option");
1222 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1223 $gaptemplate->setVariable(
1224 "SELECT_GAP_TEXT",
1225 ilLegacyFormElementsUtil::prepareFormOutput($item->getAnswerText())
1226 );
1227 foreach ($user_solution as $solution) {
1228 if (strcmp($solution["value1"], $gap_index) == 0) {
1229 if (strcmp($solution["value2"], $item->getOrder()) == 0) {
1230 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1231 }
1232 }
1233 }
1234 $gaptemplate->parseCurrentBlock();
1235 }
1236 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1237 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
1238 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1239 // fau.
1240 break;
1241 case CLOZE_NUMERIC:
1242 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
1243 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1244 if ($gap_size > 0) {
1245 $gaptemplate->setCurrentBlock('size_and_maxlength');
1246 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1247 $gaptemplate->parseCurrentBlock();
1248 }
1249
1250 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1251 foreach ($user_solution as $solution) {
1252 if (strcmp($solution["value1"], $gap_index) == 0) {
1253 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilLegacyFormElementsUtil::prepareFormOutput(
1254 $solution["value2"]
1255 ) . "\"");
1256 }
1257 }
1258 // fau: fixGapReplace - use replace function
1259 $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1260 // fau.
1261 break;
1262 }
1263 }
1264
1265 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
1266 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1267 $questionoutput = $template->get();
1268 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1269 return $pageoutput;
1270 }
1271
1272 public function getSpecificFeedbackOutput(array $userSolution): string
1273 {
1274 if (!$this->object->feedbackOBJ->isSpecificAnswerFeedbackAvailable($this->object->getId())) {
1275 return '';
1276 }
1277
1278 $feedback = '<table class="test_specific_feedback"><tbody>';
1279
1280 foreach ($this->object->gaps as $gapIndex => $gap) {
1281 $answerValue = $this->object->fetchAnswerValueForGap($userSolution, $gapIndex);
1282 if ($gap->getType() !== assClozeGap::TYPE_TEXT
1283 && $answerValue === '') {
1284 continue;
1285 }
1286 $answerIndex = $this->object->feedbackOBJ->determineAnswerIndexForAnswerValue($gap, $answerValue);
1287 $fb = $this->object->feedbackOBJ->determineTestOutputGapFeedback($gapIndex, $answerIndex);
1288
1289 $caption = $this->lng->txt('gap') . ' ' . ($gapIndex + 1) . ': ';
1290 $feedback .= '<tr><td>';
1291 $feedback .= $caption . '</td><td>';
1292 $feedback .= $fb . '</td> </tr>';
1293 }
1294 $feedback .= '</tbody></table>';
1295
1296 return $this->object->prepareTextareaOutput($feedback, true);
1297 }
1298
1309 {
1310 return array();
1311 }
1312
1323 {
1324 return array();
1325 }
1326
1333 public function getAggregatedAnswersView(array $relevant_answers): string
1334 {
1335 $overview = array();
1336 $aggregation = array();
1337 foreach ($relevant_answers as $answer) {
1338 $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1339 }
1340
1341 foreach ($overview as $active) {
1342 foreach ($active as $answer) {
1343 foreach ($answer as $option => $value) {
1344 $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1345 }
1346 }
1347 }
1348
1349 $html = '<div>';
1350 $i = 0;
1351 foreach ($this->object->getGaps() as $gap_index => $gap) {
1352 if ($gap->type == CLOZE_SELECT) {
1353 $html .= '<p>Gap ' . ($i + 1) . ' - SELECT</p>';
1354 $html .= '<ul>';
1355 $j = 0;
1356 foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $gap_item) {
1357 $aggregate = $aggregation[$i];
1358 $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1359 $j++;
1360 }
1361 $html .= '</ul>';
1362 }
1363
1364 if ($gap->type == CLOZE_TEXT) {
1365 $present_elements = array();
1366 foreach ($gap->getItems($this->randomGroup->shuffleArray(new Seed\RandomSeed())) as $item) {
1368 $present_elements[] = $item->getAnswertext();
1369 }
1370
1371 $html .= '<p>Gap ' . ($i + 1) . ' - TEXT</p>';
1372 $html .= '<ul>';
1373 $aggregate = (array) $aggregation[$i];
1374 foreach ($aggregate as $answer => $count) {
1375 $show_mover = '';
1376 if (in_array($answer, $present_elements)) {
1377 $show_mover = ' style="display: none;" ';
1378 }
1379
1380 $html .= '<li>' . $answer . ' - ' . $count
1381 . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="' . $answer . '" name="add_gap_' . $i . '_0">
1382 <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1383 </li>';
1384 }
1385 $html .= '</ul>';
1386 }
1387
1388 if ($gap->type == CLOZE_NUMERIC) {
1389 $html .= '<p>Gap ' . ($i + 1) . ' - NUMERIC</p>';
1390 $html .= '<ul>';
1391 $j = 0;
1392 foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $gap_item) {
1393 $aggregate = (array) $aggregation[$i];
1394 foreach ($aggregate as $answer => $count) {
1395 $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1396 }
1397 $j++;
1398 }
1399 $html .= '</ul>';
1400 }
1401 $i++;
1402 $html .= '<hr />';
1403 }
1404
1405 $html .= '</div>';
1406 return $html;
1407 }
1408
1409 public function applyIndizesToGapText($question_text): string
1410 {
1411 $parts = explode('[gap', $question_text);
1412 $i = 0;
1413 $question_text = '';
1414 foreach ($parts as $part) {
1415 if ($i == 0) {
1416 $question_text .= $part;
1417 } else {
1418 $question_text .= '[gap ' . $i . $part;
1419 }
1420 $i++;
1421 }
1422 return $question_text;
1423 }
1424
1425 public function removeIndizesFromGapText($question_text): string
1426 {
1427 $parts = preg_split('/\[gap \d*\]/', $question_text);
1428 $question_text = implode('[gap]', $parts);
1429 return $question_text;
1430 }
1431
1436 private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext): void
1437 {
1438 if ($this->isRenderPurposePrintPdf()) {
1439 $gaptemplate->setCurrentBlock('gap_span');
1440 $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1441 } elseif ($gap->getType() == CLOZE_SELECT) {
1442 $gaptemplate->setCurrentBlock('gap_select');
1443 $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1444 } else {
1445 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1446
1447 if ($gap_size > 0) {
1448 $gaptemplate->setCurrentBlock('gap_size');
1449 $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1450 $gaptemplate->parseCurrentBlock();
1451 }
1452
1453 $gaptemplate->setCurrentBlock('gap_input');
1454 $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1455 }
1456
1457
1458 $gaptemplate->parseCurrentBlock();
1459 }
1460
1461 protected function hasAddAnswerAction($relevantAnswers, $questionIndex): bool
1462 {
1463 foreach ($this->getAnswersFrequency($relevantAnswers, $questionIndex) as $answer) {
1464 if (isset($answer['actions'])) {
1465 return true;
1466 }
1467 }
1468
1469 return false;
1470 }
1471
1472 public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex): ilAnswerFrequencyStatisticTableGUI
1473 {
1474 $table = parent::getAnswerFrequencyTableGUI(
1475 $parentGui,
1476 $parentCmd,
1477 $relevantAnswers,
1478 $questionIndex
1479 );
1480
1481 $table->setTitle(
1482 sprintf(
1483 $this->lng->txt('tst_corrections_answers_tbl_subindex'),
1484 $this->lng->txt('gap') . ' ' . ($questionIndex + 1)
1485 )
1486 );
1487
1488 if ($this->hasAddAnswerAction($relevantAnswers, $questionIndex)) {
1489 $table->addColumn('', '', '200');
1490 }
1491
1492 return $table;
1493 }
1494
1495 public function getSubQuestionsIndex(): array
1496 {
1497 return array_keys($this->object->getGaps());
1498 }
1499
1500 protected function getAnswerTextLabel($gapIndex, $answer)
1501 {
1502 $gap = $this->object->getGap($gapIndex);
1503
1504 switch ($gap->type) {
1505 case CLOZE_NUMERIC:
1506 case CLOZE_TEXT:
1507 return $answer;
1508
1509 case CLOZE_SELECT:
1510 default:
1511 $items = $gap->getItems($this->randomGroup->dontShuffle());
1512 return $items[$answer]->getAnswertext();
1513 }
1514 }
1515
1516 protected function completeAddAnswerAction($answers, $gap_index): array
1517 {
1518 $gap = $this->object->getGap($gap_index);
1519
1520 if ($gap->type != CLOZE_TEXT ||
1521 $this->isUsedInCombinations($gap_index)) {
1522 return $answers;
1523 }
1524
1525 foreach ($answers as $key => $ans) {
1526 $found = false;
1527
1528 foreach ($gap->getItems($this->randomGroup->dontShuffle()) as $item) {
1529 if ($ans['answer'] !== $item->getAnswerText()) {
1530 continue;
1531 }
1532
1533 $found = true;
1534 break;
1535 }
1536
1537 if (!$found) {
1538 $answers[$key]['addable'] = true;
1539 }
1540 }
1541
1542 return $answers;
1543 }
1544
1545 public function getAnswersFrequency($relevantAnswers, $questionIndex): array
1546 {
1547 $answers = array();
1548
1549 foreach ($relevantAnswers as $row) {
1550 if ($row['value1'] != $questionIndex) {
1551 continue;
1552 }
1553
1554 if (!isset($answers[$row['value2']])) {
1555 $label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
1556
1557 $answers[$row['value2']] = array(
1558 'answer' => $label, 'frequency' => 0
1559 );
1560 }
1561
1562 $answers[$row['value2']]['frequency']++;
1563 }
1564
1565 $answers = $this->completeAddAnswerAction($answers, $questionIndex);
1566
1567 return $answers;
1568 }
1569
1570 protected function isUsedInCombinations($gapIndex): bool
1571 {
1572 foreach ($this->object->getGapCombinations() as $combination) {
1573 if ($combination['gap_fi'] != $gapIndex) {
1574 continue;
1575 }
1576
1577 return true;
1578 }
1579
1580 return false;
1581 }
1582
1583 protected function getGapCombinations(): array
1584 {
1585 $combinations = array();
1586
1587 foreach ($this->object->getGapCombinations() as $c) {
1588 if (!isset($combinations[$c['cid']])) {
1589 $combinations[$c['cid']] = array();
1590 }
1591
1592 if (!isset($combinations[$c['cid']][$c['row_id']])) {
1593 $combinations[$c['cid']][$c['row_id']] = array(
1594 'gaps' => array(), 'points' => $c['points'],
1595 );
1596 }
1597
1598 if (!isset($combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']])) {
1599 $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = array();
1600 }
1601
1602 $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = $c['answer'];
1603 }
1604
1605 return $combinations;
1606 }
1607
1609 {
1610 foreach ($this->object->getGaps() as $gapIndex => $gap) {
1611 $this->populateGapCorrectionFormProperties(
1612 $form,
1613 $gap,
1614 $gapIndex,
1615 $this->isUsedInCombinations($gapIndex)
1616 );
1617 }
1618
1619 if ($this->object->getGapCombinationsExists()) {
1620 foreach ($this->getGapCombinations() as $combiIndex => $gapCombination) {
1621 $this->populateGapCombinationCorrectionFormProperty($form, $gapCombination, $combiIndex);
1622 }
1623 }
1624 }
1625
1626 protected function populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex): void
1627 {
1628 $header = new ilFormSectionHeaderGUI();
1629 $header->setTitle("Gap Combination " . ($combiIndex + 1));
1630 $form->addItem($header);
1631
1632 require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php';
1633 $inp = new ilAssClozeTestCombinationVariantsInputGUI('Answers', 'combination_' . $combiIndex);
1634 $inp->setValues($gapCombi);
1635 $form->addItem($inp);
1636 }
1637
1643 protected function populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints): void
1644 {
1645 $header = new ilFormSectionHeaderGUI();
1646 $header->setTitle($this->lng->txt("gap") . " " . ($gapIndex + 1));
1647 $form->addItem($header);
1648
1649 if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1650 $this->populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints);
1651 } elseif ($gap->getType() == CLOZE_NUMERIC) {
1652 foreach ($gap->getItemsRaw() as $item) {
1653 $this->populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints);
1654 }
1655 }
1656 }
1657
1658 protected function populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints): void
1659 {
1660 require_once "Modules/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php";
1661 $values = new ilAssAnswerCorrectionsInputGUI($this->lng->txt("values"), "gap_" . $gapIndex);
1662 $values->setHidePointsEnabled($hidePoints);
1663 $values->setRequired(true);
1664 $values->setQuestionObject($this->object);
1665 $values->setValues($gap->getItemsRaw());
1666 $form->addItem($values);
1667 }
1668
1669 protected function populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints): void
1670 {
1671 $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapIndex . "_numeric");
1672 $value->allowDecimals(true);
1673 $value->setSize(10);
1674 $value->setValue(ilLegacyFormElementsUtil::prepareFormOutput($item->getAnswertext()));
1675 $value->setRequired(true);
1676 $form->addItem($value);
1677
1678 $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapIndex . "_numeric_lower");
1679 $lowerbound->allowDecimals(true);
1680 $lowerbound->setSize(10);
1681 $lowerbound->setRequired(true);
1682 $lowerbound->setValue(ilLegacyFormElementsUtil::prepareFormOutput($item->getLowerBound()));
1683 $form->addItem($lowerbound);
1684
1685 $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapIndex . "_numeric_upper");
1686 $upperbound->allowDecimals(true);
1687 $upperbound->setSize(10);
1688 $upperbound->setRequired(true);
1689 $upperbound->setValue(ilLegacyFormElementsUtil::prepareFormOutput($item->getUpperBound()));
1690 $form->addItem($upperbound);
1691
1692 if (!$hidePoints) {
1693 $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapIndex . "_numeric_points");
1694 $points->allowDecimals(true);
1695 $points->setSize(3);
1696 $points->setRequired(true);
1697 $points->setValue(ilLegacyFormElementsUtil::prepareFormOutput($item->getPoints()));
1698 $form->addItem($points);
1699 }
1700 }
1701
1706 {
1707 foreach ($this->object->getGaps() as $gapIndex => $gap) {
1708 if ($this->isUsedInCombinations($gapIndex)) {
1709 continue;
1710 }
1711
1712 $this->saveGapCorrectionFormProperty($form, $gap, $gapIndex);
1713 }
1714
1715 if ($this->object->getGapCombinationsExists()) {
1716 $this->saveGapCombinationCorrectionFormProperties($form);
1717 }
1718 }
1719
1720 protected function saveGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex): void
1721 {
1722 if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1723 $this->saveTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex);
1724 } elseif ($gap->getType() == CLOZE_NUMERIC) {
1725 foreach ($gap->getItemsRaw() as $item) {
1726 $this->saveNumericGapCorrectionFormProperty($form, $item, $gapIndex);
1727 }
1728 }
1729 }
1730
1731 protected function saveTextOrSelectGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex): void
1732 {
1733 $answers = $form->getItemByPostVar('gap_' . $gapIndex)->getValues();
1734
1735 foreach ($gap->getItemsRaw() as $index => $item) {
1736 $item->setPoints((float) str_replace(',', '.', $answers[$index]->getPoints()));
1737 }
1738 }
1739
1740 protected function saveNumericGapCorrectionFormProperty(ilPropertyFormGUI $form, assAnswerCloze $item, $gapIndex): void
1741 {
1742 $item->setAnswertext($form->getInput('gap_' . $gapIndex . '_numeric'));
1743 $item->setLowerBound($form->getInput('gap_' . $gapIndex . '_numeric_lower'));
1744 $item->setUpperBound($form->getInput('gap_' . $gapIndex . '_numeric_upper'));
1745 $item->setPoints((float) str_replace(',', '.', $form->getInput('gap_' . $gapIndex . '_numeric_points')));
1746 }
1747
1749 {
1750 // please dont ask (!) -.-
1751
1752 $combinationPoints = array('points' => array(), 'select' => array());
1753 $combinationValues = array();
1754
1755 foreach ($this->getGapCombinations() as $combiId => $combi) {
1756 $values = $form->getItemByPostVar('combination_' . $combiId)->getValues();
1757
1758 if (!isset($combinationPoints['points'][$combiId])) {
1759 $combinationPoints['points'][$combiId] = array();
1760 $combinationPoints['select'][$combiId] = array();
1761 $combinationValues[$combiId] = array();
1762 }
1763
1764 foreach ($combi as $varId => $variant) {
1765 $combinationPoints['points'][$combiId][$varId] = (float) str_replace(',', '.', $values[$varId]['points']);
1766 $combinationPoints['select'][$combiId] = array_keys($values[$varId]['gaps']);
1767 $combinationValues[$combiId][$varId] = array_values($values[$varId]['gaps']);
1768 }
1769 }
1770
1771 $combinationPoints = $combinationPoints;
1772 $combinationValues = $combinationValues;
1773
1774 $assClozeGapCombinationObject = new assClozeGapCombination();
1775 $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
1776
1777 $assClozeGapCombinationObject->saveGapCombinationToDb(
1778 $this->object->getId(),
1779 $combinationPoints,
1780 $combinationValues
1781 );
1782 }
1783}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$check
Definition: buildRTE.php:81
setAnswertext($answertext="")
Sets the answer text.
setPoints($points=0.0)
Sets the points.
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:32
Builds data types.
Definition: Factory.php:21
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setUpperBound(string $bound)
Sets the upper bound.
setLowerBound(string $bound)
Sets the lower boind.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class for cloze question gaps.
getItemsRaw()
Gets the items of a cloze gap.
Cloze test question GUI representation.
hasAddAnswerAction($relevantAnswers, $questionIndex)
applyIndizesToGapText($question_text)
populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex)
populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
getSpecificFeedbackOutput(array $userSolution)
Returns the answer specific feedback for the question.
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints)
getAnswerTextLabel($gapIndex, $answer)
getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
writePostData(bool $always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
getSolutionOutput( $active_id, $pass=null, $graphicalOutput=false, $result_output=false, $show_question_only=true, $show_feedback=false, $show_correct_solution=false, $show_manual_scoring=false, $show_question_text=true)
Get the question solution output.
populateSelectGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a select gap.
populateNumericGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a numeric gap.
createGaps()
Create gaps from cloze text.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
$gapIndex
A temporary variable to store gap indexes of ilCtrl commands in the getCommand method.
removeIndizesFromGapText($question_text)
populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
__construct(int $id=-1)
assClozeTestGUI constructor
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
Adds the question specific forms parts to a question property form gui.
populateGapSizeFormPart($form, $gap, $gapCounter)
getBestSolutionText($gap, $gap_index, $gap_combinations)
populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
populateTextGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a text gap.
getPreview($show_question_only=false, $showInlineFeedback=false)
Creates a preview output of the question.
ArrayBasedRequestWrapper $post
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
populateGapFormPart($form, $gapCounter)
Populates a gap form-part.
getAnswersFrequency($relevantAnswers, $questionIndex)
addgap()
Add a gap answer.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
saveGapCombinationCorrectionFormProperties(ilPropertyFormGUI $form)
completeAddAnswerAction($answers, $gap_index)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
saveNumericGapCorrectionFormProperty(ilPropertyFormGUI $form, assAnswerCloze $item, $gapIndex)
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
Adds the answer specific form parts to a question property form gui.
removegap()
Remove a gap answer.
saveGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
getGenericFeedbackOutput(int $active_id, $pass)
saveTextOrSelectGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
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...
populateTaxonomyFormSection(ilPropertyFormGUI $form)
escapeTemplatePlaceholders(string $text)
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
ilGlobalPageTemplate $tpl
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
hasCorrectSolution($activeId, $passIndex)
generateCorrectnessIconsForCorrectness(int $correctness)
addNumberOfTriesToFormIfNecessary(ilPropertyFormGUI $form)
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
setVariable(string $variable, $value='')
Sets the given variable to the given value.
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static prepareFormOutput($a_str, bool $a_strip=false)
This class represents a number property in a property form.
static _getUsedHTMLTags(string $a_module="")
Returns an array of all allowed HTML tags for text editing.
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the feedback comment for a question in a test if it is finalized.
This class represents a property form user interface.
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
getItemByPostVar(string $a_post_var)
This class represents a selection list property in a property form.
special template class to simplify handling of ITX/PEAR
This class represents a text area property in a property form.
This class represents a text property in a property form.
$c
Definition: cli.php:38
if(!file_exists(getcwd() . '/ilias.ini.php'))
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: confirmReg.php:20
global $DIC
Definition: feed.php:28
$errors
Definition: imgupload.php:65
const CLOZE_NUMERIC
const CLOZE_SELECT
const CLOZE_TEXT
Cloze question constants.
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...
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
$index
Definition: metadata.php:145
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
array $details
Details for error message relating to last request processed.
Definition: System.php:109
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: GivenSeed.php:21
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples