ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.assClozeTestGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7
24{
25 const OLD_CLOZE_TEST_UI = false;
26
30 private $gapIndex;
31
37 public function __construct($id = -1)
38 {
39 parent::__construct();
40 include_once "./Modules/TestQuestionPool/classes/class.assClozeTest.php";
41 $this->object = new assClozeTest();
42 if ($id >= 0) {
43 $this->object->loadFromDb($id);
44 }
45 }
46
47 public function getCommand($cmd)
48 {
49 if (preg_match("/^(removegap|addgap)_(\d+)$/", $cmd, $matches)) {
50 $cmd = $matches[1];
51 $this->gapIndex = $matches[2];
52 }
53 return $cmd;
54 }
55
59 protected function writePostData($always = false)
60 {
61 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
62 if (!$hasErrors) {
63 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
64
65 $cloze_text = $this->object->getHtmlQuestionContentPurifier()->purify($_POST['cloze_text']);
66
67 $cloze_text = $this->removeIndizesFromGapText($cloze_text);
68 $_POST['cloze_text'] = $cloze_text;
69 $this->object->setQuestion($_POST['question']);
70
72 $this->object->setClozeText($_POST["cloze_text"]);
74 //$this->object->flushGaps();
77 return 0;
78 }
79
80 $cloze_text = $_POST['cloze_text'];
81 $cloze_text = $this->applyIndizesToGapText($cloze_text);
82 $_POST['cloze_text'] = $cloze_text;
83 return 1;
84 }
85
87 {
88 if (is_array($_POST['gap'])) {
89 if ($this->ctrl->getCmd() != 'createGaps') {
90 $this->object->clearGapAnswers();
91 }
92
93 foreach ($_POST['gap'] as $idx => $hidden) {
94 $clozetype = $_POST['clozetype_' . $idx];
95
96 $this->object->setGapType($idx, $clozetype);
97
98 switch ($clozetype) {
99 case CLOZE_TEXT:
100
101 $this->object->setGapShuffle($idx, 0);
102
103 if ($this->ctrl->getCmd() != 'createGaps') {
104 if (is_array($_POST['gap_' . $idx]['answer'])) {
105 foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
106 $this->object->addGapAnswer($idx, $order, $value);
107 }
108 } else {
109 $this->object->addGapAnswer($idx, 0, '');
110 }
111 }
112
113 if (is_array($_POST['gap_' . $idx]['points'])) {
114 foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
115 $this->object->setGapAnswerPoints($idx, $order, $value);
116 }
117 }
118
119 if (array_key_exists('gap_' . $idx . '_gapsize', $_POST)) {
120 $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize']);
121 }
122
123 break;
124
125 case CLOZE_SELECT:
126
127 $this->object->setGapShuffle($idx, (int) (isset($_POST["shuffle_$idx"]) && $_POST["shuffle_$idx"]));
128
129 if ($this->ctrl->getCmd() != 'createGaps') {
130 if (is_array($_POST['gap_' . $idx]['answer'])) {
131 foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
132 $this->object->addGapAnswer($idx, $order, $value);
133 }
134 } else {
135 $this->object->addGapAnswer($idx, 0, '');
136 }
137 }
138
139 if (is_array($_POST['gap_' . $idx]['points'])) {
140 foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
141 $this->object->setGapAnswerPoints($idx, $order, $value);
142 }
143 }
144 break;
145
146 case CLOZE_NUMERIC:
147
148 $this->object->setGapShuffle($idx, 0);
149
150 $gap = $this->object->getGap($idx);
151 if (!$gap) {
152 break;
153 }
154
155 $this->object->getGap($idx)->clearItems();
156
157 if (array_key_exists('gap_' . $idx . '_numeric', $_POST)) {
158 if ($this->ctrl->getCmd() != 'createGaps') {
159 $this->object->addGapAnswer(
160 $idx,
161 0,
162 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric'])
163 );
164 }
165
166 $this->object->setGapAnswerLowerBound(
167 $idx,
168 0,
169 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_lower'])
170 );
171
172 $this->object->setGapAnswerUpperBound(
173 $idx,
174 0,
175 str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_upper'])
176 );
177
178 $this->object->setGapAnswerPoints($idx, 0, $_POST['gap_' . $idx . '_numeric_points']);
179 } else {
180 if ($this->ctrl->getCmd() != 'createGaps') {
181 $this->object->addGapAnswer($idx, 0, '');
182 }
183
184 $this->object->setGapAnswerLowerBound($idx, 0, '');
185
186 $this->object->setGapAnswerUpperBound($idx, 0, '');
187 }
188
189 if (array_key_exists('gap_' . $idx . '_gapsize', $_POST)) {
190 $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize']);
191 }
192 break;
193 }
194 $assClozeGapCombinationObject = new assClozeGapCombination();
195 $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
196 if (is_array($_POST['gap_combination']) && count($_POST['gap_combination']) > 0) {
197 $assClozeGapCombinationObject->saveGapCombinationToDb($this->object->getId(), ilUtil::stripSlashesRecursive($_POST['gap_combination']), ilUtil::stripSlashesRecursive($_POST['gap_combination_values']));
198 }
199 }
200 if ($this->ctrl->getCmd() != 'createGaps') {
201 $this->object->updateClozeTextFromGaps();
202 }
203 }
204 }
205
207 {
208 $this->object->setClozeText($_POST['cloze_text']);
209 $this->object->setTextgapRating($_POST["textgap_rating"]);
210 $this->object->setIdenticalScoring($_POST["identical_scoring"]);
211 $this->object->setFixedTextLength($_POST["fixedTextLength"]);
212 }
213
219 public function editQuestion($checkonly = false)
220 {
221 $save = $this->isSaveCommand();
222 $this->getQuestionTemplate();
223
224 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
225 $form = new ilPropertyFormGUI();
226 $this->editForm = $form;
227
228 $form->setFormAction($this->ctrl->getFormAction($this));
229 $form->setTitle($this->outQuestionType());
230 $form->setMultipart(false);
231 $form->setTableWidth("100%");
232 $form->setId("assclozetest");
233
234 // title, author, description, question, working time (assessment mode)
239
241
242 $errors = false;
243
244 if ($save) {
245 $form->setValuesByPost();
246 $errors = !$form->checkInput();
247 $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we
248 // need this if we don't want to have duplication of backslashes
249 if ($errors) {
250 $checkonly = false;
251 }
252 }
253
254 if (!$checkonly) {
255 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
256 }
257 return $errors;
258 }
259
261 {
262 // title
263 $title = new ilTextInputGUI($this->lng->txt("title"), "title");
264 $title->setMaxLength(100);
265 $title->setValue($this->object->getTitle());
266 $title->setRequired(true);
267 $form->addItem($title);
268
269 if (!$this->object->getSelfAssessmentEditingMode()) {
270 // author
271 $author = new ilTextInputGUI($this->lng->txt("author"), "author");
272 $author->setValue($this->object->getAuthor());
273 $author->setRequired(true);
274 $form->addItem($author);
275
276 // description
277 $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
278 $description->setValue($this->object->getComment());
279 $description->setRequired(false);
280 $form->addItem($description);
281 } else {
282 // author as hidden field
283 $hi = new ilHiddenInputGUI("author");
284 $author = ilUtil::prepareFormOutput($this->object->getAuthor());
285 if (trim($author) == "") {
286 $author = "-";
287 }
288 $hi->setValue($author);
289 $form->addItem($hi);
290 }
291
292 // questiontext
293 $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
294 $question->setValue($this->object->prepareTextareaOutput($this->object->getQuestion()));
295 $question->setRequired(true);
296 $question->setRows(10);
297 $question->setCols(80);
298 if (!$this->object->getSelfAssessmentEditingMode()) {
299 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
300 $question->setUseRte(true);
301 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
302 $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
303 $question->addPlugin("latex");
304 $question->addButton("latex");
305 $question->addButton("pastelatex");
306 $question->setRTESupport($this->object->getId(), "qpl", "assessment");
307 }
308 } else {
309 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
311 $question->setUseTagsForRteOnly(false);
312 }
313 $form->addItem($question);
314
315 // $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
316 // $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
317 // $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
318 // $tpl->parseCurrentBlock();
319 // $button = new ilCustomInputGUI('&nbsp;','');
320 // $button->setHtml($tpl->get());
321 // $form->addItem($button);
322
323 if (!$this->object->getSelfAssessmentEditingMode()) {
324 // duration
325 $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
326 $duration->setShowHours(true);
327 $duration->setShowMinutes(true);
328 $duration->setShowSeconds(true);
329 $ewt = $this->object->getEstimatedWorkingTime();
330 $duration->setHours($ewt["h"]);
331 $duration->setMinutes($ewt["m"]);
332 $duration->setSeconds($ewt["s"]);
333 $duration->setRequired(false);
334 $form->addItem($duration);
335 } else {
336 // number of tries
337 if (strlen($this->object->getNrOfTries())) {
338 $nr_tries = $this->object->getNrOfTries();
339 } else {
340 $nr_tries = $this->object->getDefaultNrOfTries();
341 }
342 /*if ($nr_tries <= 0)
343 {
344 $nr_tries = 1;
345 }*/
346
347 if ($nr_tries < 0) {
348 $nr_tries = 0;
349 }
350
351 $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
352 $ni->setValue($nr_tries);
353 //$ni->setMinValue(1);
354 $ni->setMinValue(0);
355 $ni->setSize(5);
356 $ni->setMaxLength(5);
357 $ni->setRequired(true);
358 $form->addItem($ni);
359 }
360 }
361
363 {
364 // cloze text
365 $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
366 $cloze_text->setRequired(true);
367 $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
368 $cloze_text->setInfo($this->lng->txt("close_text_hint"));
369 $cloze_text->setRows(10);
370 $cloze_text->setCols(80);
371 if (!$this->object->getSelfAssessmentEditingMode()) {
372 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
373 $cloze_text->setUseRte(true);
374 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
375 $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
376 $cloze_text->addPlugin("latex");
377 $cloze_text->addButton("latex");
378 $cloze_text->addButton("pastelatex");
379 }
380 } else {
381 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
383 $cloze_text->setUseTagsForRteOnly(false);
384 }
385 $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
386 $form->addItem($cloze_text);
387
388 $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", true, true, "Modules/TestQuestionPool");
389
390 $button = new ilCustomInputGUI('&nbsp;', '');
391 require_once 'Services/UIComponent/SplitButton/classes/class.ilSplitButtonGUI.php';
392 require_once 'Services/UIComponent/Button/classes/class.ilJsLinkButton.php';
393 $action_button = ilSplitButtonGUI::getInstance();
394
395 $sb_text_gap = ilJsLinkButton::getInstance();
396 $sb_text_gap->setCaption('text_gap');
397 $sb_text_gap->setName('gapbutton');
398 $sb_text_gap->setId('gaptrigger_text');
399 $action_button->setDefaultButton($sb_text_gap);
400
401 $sb_sel_gap = ilJsLinkButton::getInstance();
402 $sb_sel_gap->setCaption('select_gap');
403 $sb_sel_gap->setName('gapbutton_select');
404 $sb_sel_gap->setId('gaptrigger_select');
405 $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_sel_gap));
406
407 $sb_num_gap = ilJsLinkButton::getInstance();
408 $sb_num_gap->setCaption('numeric_gap');
409 $sb_num_gap->setName('gapbutton_numeric');
410 $sb_num_gap->setId('gaptrigger_numeric');
411 $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_num_gap));
412
413 $tpl->setVariable('BUTTON', $action_button->render());
414 $tpl->parseCurrentBlock();
415
416 $button->setHtml($tpl->get());
417 $form->addItem($button);
418
419 // text rating
420 if (!$this->object->getSelfAssessmentEditingMode()) {
421 $textrating = new ilSelectInputGUI($this->lng->txt("text_rating"), "textgap_rating");
422 $text_options = array(
423 "ci" => $this->lng->txt("cloze_textgap_case_insensitive"),
424 "cs" => $this->lng->txt("cloze_textgap_case_sensitive"),
425 "l1" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "1"),
426 "l2" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "2"),
427 "l3" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "3"),
428 "l4" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "4"),
429 "l5" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "5")
430 );
431 $textrating->setOptions($text_options);
432 $textrating->setValue($this->object->getTextgapRating());
433 $form->addItem($textrating);
434
435 // text field length
436 $fixedTextLength = new ilNumberInputGUI($this->lng->txt("cloze_fixed_textlength"), "fixedTextLength");
437 $ftl = $this->object->getFixedTextLength();
438
439 $fixedTextLength->setValue($ftl > 0 ? $ftl : '');
440 $fixedTextLength->setMinValue(0);
441 $fixedTextLength->setSize(3);
442 $fixedTextLength->setMaxLength(6);
443 $fixedTextLength->setInfo($this->lng->txt('cloze_fixed_textlength_description'));
444 $fixedTextLength->setRequired(false);
445 $form->addItem($fixedTextLength);
446
447 // identical scoring
448 $identical_scoring = new ilCheckboxInputGUI($this->lng->txt("identical_scoring"), "identical_scoring");
449 $identical_scoring->setValue(1);
450 $identical_scoring->setChecked($this->object->getIdenticalScoring());
451 $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
452 $identical_scoring->setRequired(false);
453 $form->addItem($identical_scoring);
454 }
455 return $form;
456 }
457
459 {
460 if (self::OLD_CLOZE_TEST_UI) {
461 for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++) {
462 $this->populateGapFormPart($form, $gapCounter);
463 }
464 return $form;
465 } else {
466 require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
467 $json=$this->populateJSON();
468 $assClozeGapCombinationObject = new assClozeGapCombination();
469 $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->id);
470 if ($combination_exists) {
471 $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->id);
472 }
473 $new_builder = new ilClozeGapInputBuilderGUI();
475 $form->addItem($header);
476 $new_builder->setValueByArray($json);
477 $new_builder->setValueCombinationFromDb($combinations);
478 $form->addItem($new_builder);
479 return $form;
480 }
481 }
482
483 protected function populateJSON()
484 {
485 $gap = $this->object->getGaps();
486 $array = array();
487 if ($gap == null) {
488 return $array;
489 }
490 $translate_type=array('text','select','numeric');
491 $i = 0;
492 foreach ($gap as $content) {
493 $shuffle=false;
494 $value=$content->getItemsRaw();
495 $items=array();
496 for ($j=0;$j<count($value);$j++) {
497 if ($content->getType()==2) {
498 $items[$j] = array(
499 'answer' => $value[$j]->getAnswerText(),
500 'lower' => $value[$j]->getLowerBound(),
501 'upper' => $value[$j]->getUpperBound(),
502 'points' => $value[$j]->getPoints(),
503 'error' => false
504 );
505 } else {
506 $items[$j] = array(
507 'answer' => $value[$j]->getAnswerText(),
508 'points' => $value[$j]->getPoints(),
509 'error' => false
510 );
511
512 if ($content->getType()==1) {
513 $shuffle=$content->getShuffle();
514 }
515 }
516 }
517 $answers[$i]=array(
518 'type' => $translate_type[$content->getType()] ,
519 'values' => $items ,
520 'shuffle' => $shuffle,
521 'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
522 'used_in_gap_combination' => true);
523 $i++;
524 }
525 return $answers;
526 }
538 protected function populateGapFormPart($form, $gapCounter)
539 {
540 $gap = $this->object->getGap($gapCounter);
541
542 if ($gap == null) {
543 return $form;
544 }
545
547 $header->setTitle($this->lng->txt("gap") . " " . ($gapCounter + 1));
548 $form->addItem($header);
549
550 $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
551 $gapcounter->setValue($gapCounter);
552 $form->addItem($gapcounter);
553
554 $gaptype = new ilSelectInputGUI($this->lng->txt('type'), "clozetype_$gapCounter");
555 $options = array(
556 0 => $this->lng->txt("text_gap"),
557 1 => $this->lng->txt("select_gap"),
558 2 => $this->lng->txt("numeric_gap")
559 );
560 $gaptype->setOptions($options);
561 $gaptype->setValue($gap->getType());
562 $form->addItem($gaptype);
563
564 if ($gap->getType() == CLOZE_TEXT) {
565 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
566
567 if (count($gap->getItemsRaw()) == 0) {
568 $gap->addItem(new assAnswerCloze("", 0, 0));
569 }
570 $this->populateTextGapFormPart($form, $gap, $gapCounter);
571 } elseif ($gap->getType() == CLOZE_SELECT) {
572 if (count($gap->getItemsRaw()) == 0) {
573 $gap->addItem(new assAnswerCloze("", 0, 0));
574 }
575 $this->populateSelectGapFormPart($form, $gap, $gapCounter);
576 } elseif ($gap->getType() == CLOZE_NUMERIC) {
577 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
578
579 if (count($gap->getItemsRaw()) == 0) {
580 $gap->addItem(new assAnswerCloze("", 0, 0));
581 }
582 foreach ($gap->getItemsRaw() as $item) {
583 $this->populateNumericGapFormPart($form, $item, $gapCounter);
584 }
585 }
586 return $form;
587 }
588
594 protected function populateGapSizeFormPart($form, $gap, $gapCounter)
595 {
596 $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_" . $gapCounter . '_gapsize');
597
598 $gapSizeFormItem->allowDecimals(false);
599 $gapSizeFormItem->setMinValue(0);
600 $gapSizeFormItem->setSize(3);
601 $gapSizeFormItem->setMaxLength(6);
602 $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
603 $gapSizeFormItem->setValue($gap->getGapSize());
604 $form->addItem($gapSizeFormItem);
605
606 return $form;
607 }
608
621 protected function populateSelectGapFormPart($form, $gap, $gapCounter)
622 {
623 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
624 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
625 $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
626 $values->setRequired(true);
627 $values->setQuestionObject($this->object);
628 $values->setSingleline(true);
629 $values->setAllowMove(false);
630
631 $values->setValues($gap->getItemsRaw());
632 $form->addItem($values);
633
634 // shuffle
635 $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle_" . $gapCounter . "");
636 $shuffle->setValue(1);
637 $shuffle->setChecked($gap->getShuffle());
638 $shuffle->setRequired(false);
639 $form->addItem($shuffle);
640 return $form;
641 }
642
654 protected function populateTextGapFormPart($form, $gap, $gapCounter)
655 {
656 // Choices
657 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
658 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
659 $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
660 $values->setRequired(true);
661 $values->setQuestionObject($this->object);
662 $values->setSingleline(true);
663 $values->setAllowMove(false);
664 $values->setValues($gap->getItemsRaw());
665 $form->addItem($values);
666
667 if ($this->object->getFixedTextLength() > 0) {
668 $values->setSize($this->object->getFixedTextLength());
669 $values->setMaxLength($this->object->getFixedTextLength());
670 }
671
672 return $form;
673 }
674
686 protected function populateNumericGapFormPart($form, $gap, $gapCounter)
687 {
688 // #8944: the js-based ouput in self-assessment cannot support formulas
689 if (!$this->object->getSelfAssessmentEditingMode()) {
690 $value = new ilFormulaInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
691 $value->setInlineStyle('text-align: right;');
692
693 $lowerbound = new ilFormulaInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
694 $lowerbound->setInlineStyle('text-align: right;');
695
696 $upperbound = new ilFormulaInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
697 $upperbound->setInlineStyle('text-align: right;');
698 } else {
699 $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
700 $value->allowDecimals(true);
701
702 $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
703 $lowerbound->allowDecimals(true);
704
705 $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
706 $upperbound->allowDecimals(true);
707 }
708
709 $value->setSize(10);
710 $value->setValue(ilUtil::prepareFormOutput($gap->getAnswertext()));
711 $value->setRequired(true);
712 $form->addItem($value);
713
714 $lowerbound->setSize(10);
715 $lowerbound->setRequired(true);
716 $lowerbound->setValue(ilUtil::prepareFormOutput($gap->getLowerBound()));
717 $form->addItem($lowerbound);
718
719 $upperbound->setSize(10);
720 $upperbound->setRequired(true);
721 $upperbound->setValue(ilUtil::prepareFormOutput($gap->getUpperBound()));
722 $form->addItem($upperbound);
723
724 if ($this->object->getFixedTextLength() > 0) {
725 $value->setSize($this->object->getFixedTextLength());
726 $value->setMaxLength($this->object->getFixedTextLength());
727 $lowerbound->setSize($this->object->getFixedTextLength());
728 $lowerbound->setMaxLength($this->object->getFixedTextLength());
729 $upperbound->setSize($this->object->getFixedTextLength());
730 $upperbound->setMaxLength($this->object->getFixedTextLength());
731 }
732
733 $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapCounter . "_numeric_points");
734 $points->allowDecimals(true);
735 $points->setSize(3);
736 $points->setRequired(true);
737 $points->setValue(ilUtil::prepareFormOutput($gap->getPoints()));
738 $form->addItem($points);
739 return $form;
740 }
741
745 public function createGaps()
746 {
747 $this->writePostData(true);
748 $this->object->saveToDb();
749 $this->editQuestion();
750 }
751
755 public function removegap()
756 {
757 $this->writePostData(true);
758 $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
759 $this->editQuestion();
760 }
761
765 public function addgap()
766 {
767 $this->writePostData(true);
768 $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex])+1, "");
769 $this->editQuestion();
770 }
771
780 public function getPreview($show_question_only = false, $showInlineFeedback = false)
781 {
782 $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
783
784 // generate the question output
785 include_once "./Services/UICore/classes/class.ilTemplate.php";
786 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
787 $output = $this->object->getClozeText();
788 foreach ($this->object->getGaps() as $gap_index => $gap) {
789 switch ($gap->getType()) {
790 case CLOZE_TEXT:
791 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
792
793 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
794 if ($gap_size > 0) {
795 $gaptemplate->setCurrentBlock('size_and_maxlength');
796 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
797 $gaptemplate->parseCurrentBlock();
798 }
799 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
800 foreach ($user_solution as $val1 => $val2) {
801 if (strcmp($val1, $gap_index) == 0) {
802 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
803 }
804 }
805 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
806 break;
807 case CLOZE_SELECT:
808 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
809 foreach ($gap->getItems($this->object->getShuffler()) as $item) {
810 $gaptemplate->setCurrentBlock("select_gap_option");
811 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
812 $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
813 foreach ($user_solution as $val1 => $val2) {
814 if (strcmp($val1, $gap_index) == 0) {
815 if (strcmp($val2, $item->getOrder()) == 0) {
816 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
817 }
818 }
819 }
820 $gaptemplate->parseCurrentBlock();
821 }
822 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
823 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
824 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
825 break;
826 case CLOZE_NUMERIC:
827 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
828 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
829 if ($gap_size > 0) {
830 $gaptemplate->setCurrentBlock('size_and_maxlength');
831 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
832 $gaptemplate->parseCurrentBlock();
833 }
834 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
835 foreach ($user_solution as $val1 => $val2) {
836 if (strcmp($val1, $gap_index) == 0) {
837 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
838 }
839 }
840 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
841 break;
842 }
843 }
844 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
845 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
846 $questionoutput = $template->get();
847 if (!$show_question_only) {
848 // get page object output
849 $questionoutput = $this->getILIASPage($questionoutput);
850 }
851 return $questionoutput;
852 }
853
869 public function getSolutionOutput(
870 $active_id,
871 $pass = null,
872 $graphicalOutput = false,
873 $result_output = false,
874 $show_question_only = true,
875 $show_feedback = false,
876 $show_correct_solution = false,
877 $show_manual_scoring = false,
878 $show_question_text = true
879 ) {
880 // get the solution of the user for the active pass or from the last pass if allowed
881 $user_solution = array();
882 if (($active_id > 0) && (!$show_correct_solution)) {
883 // get the solutions of a user
884 $user_solution =&$this->object->getSolutionValues($active_id, $pass);
885 if (!is_array($user_solution)) {
886 $user_solution = array();
887 }
888 }
889
890 include_once "./Services/UICore/classes/class.ilTemplate.php";
891 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", true, true, "Modules/TestQuestionPool");
892 $output = $this->object->getClozeText();
893 $assClozeGapCombinationObject = new assClozeGapCombination();
894 $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
895
896 foreach ($this->object->getGaps() as $gap_index => $gap) {
897 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", true, true, "Modules/TestQuestionPool");
898 $found = array();
899 foreach ($user_solution as $solutionarray) {
900 if ($solutionarray["value1"] == $gap_index) {
901 $found = $solutionarray;
902 }
903 }
904
905 if ($active_id) {
906 if ($graphicalOutput) {
907 // output of ok/not ok icons for user entered solutions
908 $details = $this->object->calculateReachedPoints($active_id, $pass, true, true);
909 $check = $details[$gap_index];
910
911 if (count($check_for_gap_combinations) != 0) {
912 $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
913 $custom_user_solution = array();
914 if (array_key_exists($gap_index, $gaps_used_in_combination)) {
915 $combination_id = $gaps_used_in_combination[$gap_index];
916 foreach ($gaps_used_in_combination as $key => $value) {
917 $a = 0;
918 if ($value == $combination_id) {
919 foreach ($user_solution as $solution_key => $solution_value) {
920 if ($solution_value['value1'] == $key) {
921 $result_row = array();
922 $result_row['gap_id'] = $solution_value['value1'];
923 $result_row['value'] = $solution_value['value2'];
924 array_push($custom_user_solution, $result_row);
925 }
926 }
927 }
928 }
929 $points_array = $this->object->calculateCombinationResult($custom_user_solution);
930 $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
931 if ($points_array[0] == $max_combination_points) {
932 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
933 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
934 } elseif ($points_array[0] > 0) {
935 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
936 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
937 } else {
938 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
939 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
940 }
941 } else {
942 if ($check["best"]) {
943 $gaptemplate->setCurrentBlock("icon_ok");
944 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
945 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
946 $gaptemplate->parseCurrentBlock();
947 } else {
948 $gaptemplate->setCurrentBlock("icon_not_ok");
949 if ($check["positive"]) {
950 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
951 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
952 } else {
953 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
954 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
955 }
956 $gaptemplate->parseCurrentBlock();
957 }
958 }
959 } else {
960 if ($check["best"]) {
961 $gaptemplate->setCurrentBlock("icon_ok");
962 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
963 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
964 $gaptemplate->parseCurrentBlock();
965 } else {
966 $gaptemplate->setCurrentBlock("icon_not_ok");
967 if ($check["positive"]) {
968 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
969 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
970 } else {
971 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
972 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
973 }
974 $gaptemplate->parseCurrentBlock();
975 }
976 }
977 }
978 }
979 if ($result_output) {
980 $points = $this->object->getMaximumGapPoints($gap_index);
981 $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
982 $gaptemplate->setCurrentBlock("result_output");
983 $gaptemplate->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
984 $gaptemplate->parseCurrentBlock();
985 }
986 $combination = null;
987 switch ($gap->getType()) {
988 case CLOZE_TEXT:
989 $solutiontext = "";
990 if (($active_id > 0) && (!$show_correct_solution)) {
991 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
992 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
993 $solutiontext .= "&nbsp;";
994 }
995 } else {
996 $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
997 }
998 } else {
999 $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1000 }
1001 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1002 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1003 break;
1004 case CLOZE_SELECT:
1005 $solutiontext = "";
1006 if (($active_id > 0) && (!$show_correct_solution)) {
1007 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1008 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1009 $solutiontext .= "&nbsp;";
1010 }
1011 } else {
1012 $item = $gap->getItem($found["value2"]);
1013 if (is_object($item)) {
1014 $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1015 } else {
1016 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1017 $solutiontext .= "&nbsp;";
1018 }
1019 }
1020 }
1021 } else {
1022 $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1023 }
1024 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1025 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1026 break;
1027 case CLOZE_NUMERIC:
1028 $solutiontext = "";
1029 if (($active_id > 0) && (!$show_correct_solution)) {
1030 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1031 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1032 $solutiontext .= "&nbsp;";
1033 }
1034 } else {
1035 $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1036 }
1037 } else {
1038 $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1039 }
1040 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1041 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1042 break;
1043 }
1044 }
1045
1046 if ($show_question_text) {
1047 $template->setVariable(
1048 "QUESTIONTEXT",
1049 $this->object->prepareTextareaOutput($this->object->getQuestion(), true)
1050 );
1051 }
1052
1053 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1054 // generate the question output
1055 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
1056 $questionoutput = $template->get();
1057
1058 $feedback = '';
1059 if ($show_feedback) {
1060 if (!$this->isTestPresentationContext()) {
1061 $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1062 $feedback .= strlen($fb) ? $fb : '';
1063 }
1064
1065 $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
1066 $feedback .= strlen($fb) ? $fb : '';
1067 }
1068 if (strlen($feedback)) {
1069 $cssClass = (
1070 $this->hasCorrectSolution($active_id, $pass) ?
1072 );
1073
1074 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1075 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
1076 }
1077
1078 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1079
1080 $solutionoutput = $solutiontemplate->get();
1081
1082 if (!$show_question_only) {
1083 // get page object output
1084 $solutionoutput = $this->getILIASPage($solutionoutput);
1085 }
1086
1087 return $solutionoutput;
1088 }
1089
1096 protected function getBestSolutionText($gap, $gap_index, $gap_combinations)
1097 {
1098 $combination = null;
1099 foreach ((array) $gap_combinations as $combiGapSolRow) {
1100 if ($combiGapSolRow['gap_fi'] == $gap_index) {
1101 $combination = $combiGapSolRow;
1102 break;
1103 }
1104 }
1105 $best_solution_text = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1106 $this->object->getShuffler(),
1107 $combination
1108 ));
1109 return $best_solution_text;
1110 }
1111
1112 public function getAnswerFeedbackOutput($active_id, $pass)
1113 {
1114 include_once "./Modules/Test/classes/class.ilObjTest.php";
1115 $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1116 if (strlen($manual_feedback)) {
1117 return $manual_feedback;
1118 }
1119 $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1120 $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1121 if (strlen($correct_feedback . $incorrect_feedback)) {
1122 $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1123 $max_points = $this->object->getMaximumPoints();
1124 if ($reached_points == $max_points) {
1125 $output .= $correct_feedback;
1126 } else {
1127 $output .= $incorrect_feedback;
1128 }
1129 }
1130 $test = new ilObjTest($this->object->active_id);
1131 return $this->object->prepareTextareaOutput($output, true);
1132 }
1133
1134 public function getTestOutput(
1135 $active_id,
1136 // hey: prevPassSolutions - will be always available from now on
1137 $pass,
1138 // hey.
1139 $is_postponed = false,
1140 $use_post_solutions = false,
1141 $show_feedback = false
1142 ) {
1143 // get the solution of the user for the active pass or from the last pass if allowed
1144 $user_solution = array();
1145 if ($use_post_solutions !== false) {
1146 $indexedSolution = $this->object->fetchSolutionSubmit($use_post_solutions);
1147 $user_solution = $this->object->fetchValuePairsFromIndexedValues($indexedSolution);
1148 } elseif ($active_id) {
1149 // hey: prevPassSolutions - obsolete due to central check
1150 #include_once "./Modules/Test/classes/class.ilObjTest.php";
1151 #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1152 #{
1153 # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1154 #}
1155 $user_solution = $this->object->getTestOutputSolutions($active_id, $pass);
1156 // hey.
1157 if (!is_array($user_solution)) {
1158 $user_solution = array();
1159 }
1160 }
1161
1162 // generate the question output
1163 include_once "./Services/UICore/classes/class.ilTemplate.php";
1164 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
1165 $output = $this->object->getClozeText();
1166 foreach ($this->object->getGaps() as $gap_index => $gap) {
1167 switch ($gap->getType()) {
1168 case CLOZE_TEXT:
1169 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
1170 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1171
1172 if ($gap_size > 0) {
1173 $gaptemplate->setCurrentBlock('size_and_maxlength');
1174 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1175 $gaptemplate->parseCurrentBlock();
1176 }
1177
1178 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1179 foreach ($user_solution as $solution) {
1180 if (strcmp($solution["value1"], $gap_index) == 0) {
1181 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1182 }
1183 }
1184 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1185 break;
1186 case CLOZE_SELECT:
1187 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
1188 foreach ($gap->getItems($this->object->getShuffler()) as $item) {
1189 $gaptemplate->setCurrentBlock("select_gap_option");
1190 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1191 $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1192 foreach ($user_solution as $solution) {
1193 if (strcmp($solution["value1"], $gap_index) == 0) {
1194 if (strcmp($solution["value2"], $item->getOrder()) == 0) {
1195 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1196 }
1197 }
1198 }
1199 $gaptemplate->parseCurrentBlock();
1200 }
1201 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1202 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1203 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1204 break;
1205 case CLOZE_NUMERIC:
1206 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
1207 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1208 if ($gap_size > 0) {
1209 $gaptemplate->setCurrentBlock('size_and_maxlength');
1210 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1211 $gaptemplate->parseCurrentBlock();
1212 }
1213
1214 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1215 foreach ($user_solution as $solution) {
1216 if (strcmp($solution["value1"], $gap_index) == 0) {
1217 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1218 }
1219 }
1220 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1221 break;
1222 }
1223 }
1224
1225 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
1226 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1227 $questionoutput = $template->get();
1228 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1229 return $pageoutput;
1230 }
1231
1239 public function setQuestionTabs()
1240 {
1241 global $rbacsystem, $ilTabs;
1242
1243 $ilTabs->clearTargets();
1244
1245 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1246 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1247 $q_type = $this->object->getQuestionType();
1248
1249 if (strlen($q_type)) {
1250 $classname = $q_type . "GUI";
1251 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1252 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1253 # $this->ctrl->setParameterByClass(strtolower($classname), 'prev_qid', $_REQUEST['prev_qid']);
1254 }
1255
1256 if ($_GET["q_id"]) {
1257 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1258 // edit page
1259 $ilTabs->addTarget(
1260 "edit_page",
1261 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1262 array("edit", "insert", "exec_pg"),
1263 "",
1264 "",
1265 $force_active
1266 );
1267 }
1268
1269 $this->addTab_QuestionPreview($ilTabs);
1270 }
1271
1272 $force_active = false;
1273 $commands = $_POST["cmd"];
1274 if (is_array($commands)) {
1275 foreach ($commands as $key => $value) {
1276 if (preg_match("/^removegap_.*/", $key, $matches) ||
1277 preg_match("/^addgap_.*/", $key, $matches)
1278 ) {
1279 $force_active = true;
1280 }
1281 }
1282 }
1283 if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1284 $url = "";
1285 if ($classname) {
1286 $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1287 }
1288 // edit question properties
1289 $ilTabs->addTarget(
1290 "edit_question",
1291 $url,
1292 array("editQuestion", "originalSyncForm", "save", "createGaps", "saveEdit"),
1293 $classname,
1294 "",
1295 $force_active
1296 );
1297 }
1298
1299 // add tab for question feedback within common class assQuestionGUI
1300 $this->addTab_QuestionFeedback($ilTabs);
1301
1302 // add tab for question hint within common class assQuestionGUI
1303 $this->addTab_QuestionHints($ilTabs);
1304
1305 // add tab for question's suggested solution within common class assQuestionGUI
1306 $this->addTab_SuggestedSolution($ilTabs, $classname);
1307
1308 // Assessment of questions sub menu entry
1309 if ($_GET["q_id"]) {
1310 $ilTabs->addTarget(
1311 "statistics",
1312 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1313 array("assessment"),
1314 $classname,
1315 ""
1316 );
1317 }
1318
1319 $this->addBackTab($ilTabs);
1320 }
1321
1322 public function getSpecificFeedbackOutput($active_id, $pass)
1323 {
1324 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($this->object->gaps))) {
1325 return '';
1326 }
1327
1328 global $lng;
1329
1330 $feedback = '<table class="test_specific_feedback"><tbody>';
1331
1332 foreach ($this->object->gaps as $index => $answer) {
1333 $caption = $lng->txt('gap') . ' ' . ($index+1) . ': ';
1334
1335 $feedback .= '<tr><td>';
1336
1337 $feedback .= $caption . '</td><td>';
1338 $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1339 $this->object->getId(),
1340 $index
1341 ) . '</td> </tr>';
1342 }
1343 $feedback .= '</tbody></table>';
1344
1345 return $this->object->prepareTextareaOutput($feedback, true);
1346 }
1347
1358 {
1359 return array();
1360 }
1361
1372 {
1373 return array();
1374 }
1375
1384 public function getAggregatedAnswersView($relevant_answers)
1385 {
1386 $overview = array();
1387 $aggregation = array();
1388 foreach ($relevant_answers as $answer) {
1389 $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1390 }
1391
1392 foreach ($overview as $active) {
1393 foreach ($active as $answer) {
1394 foreach ($answer as $option => $value) {
1395 $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1396 }
1397 }
1398 }
1399
1400 $html = '<div>';
1401 $i = 0;
1402 foreach ($this->object->getGaps() as $gap) {
1403 if ($gap->type == CLOZE_SELECT) {
1404 $html .= '<p>Gap ' . ($i+1) . ' - SELECT</p>';
1405 $html .= '<ul>';
1406 $j = 0;
1407 foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1408 $aggregate = $aggregation[$i];
1409 $html .= '<li>' . ilUtil::prepareFormOutput($gap_item->getAnswerText()) . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1410 $j++;
1411 }
1412 $html .= '</ul>';
1413 }
1414
1415 if ($gap->type == CLOZE_TEXT) {
1416 $present_elements = array();
1417 foreach ($gap->getItems(new ilArrayElementShuffler()) as $item) {
1419 $present_elements[] = $item->getAnswertext();
1420 }
1421
1422 $html .= '<p>Gap ' . ($i+1) . ' - TEXT</p>';
1423 $html .= '<ul>';
1424 $aggregate = (array) $aggregation[$i];
1425 foreach ($aggregate as $answer => $count) {
1426 $show_mover = '';
1427 if (in_array($answer, $present_elements)) {
1428 $show_mover = ' style="display: none;" ';
1429 }
1430
1431 $html .= '<li>' . ilUtil::prepareFormOutput($answer) . ' - ' . $count
1432 . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="' . ilUtil::prepareFormOutput($answer) . '" name="add_gap_' . $i . '_0">
1433 <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1434 </li>';
1435 }
1436 $html .= '</ul>';
1437 }
1438
1439 if ($gap->type == CLOZE_NUMERIC) {
1440 $html .= '<p>Gap ' . ($i+1) . ' - NUMERIC</p>';
1441 $html .= '<ul>';
1442 $j = 0;
1443 foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1444 $aggregate = (array) $aggregation[$i];
1445 foreach ($aggregate as $answer => $count) {
1446 $html .= '<li>' . ilUtil::prepareFormOutput($answer) . ' - ' . $count . '</li>';
1447 }
1448 $j++;
1449 }
1450 $html .= '</ul>';
1451 }
1452 $i++;
1453 $html .= '<hr />';
1454 }
1455
1456 $html .= '</div>';
1457 return $html;
1458 }
1459
1460 public function applyIndizesToGapText($question_text)
1461 {
1462 $parts = explode('[gap', $question_text);
1463 $i = 0;
1464 $question_text = '';
1465 foreach ($parts as $part) {
1466 if ($i == 0) {
1467 $question_text .= $part;
1468 } else {
1469 $question_text .= '[gap ' . $i . $part;
1470 }
1471 $i++;
1472 }
1473 return $question_text;
1474 }
1475
1476 public function removeIndizesFromGapText($question_text)
1477 {
1478 $parts = preg_split('/\[gap \d*\]/', $question_text);
1479 $question_text = implode('[gap]', $parts);
1480 return $question_text;
1481 }
1482
1487 private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
1488 {
1489 if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
1490 $gaptemplate->setCurrentBlock('gap_span');
1491 $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1492 } elseif ($gap->getType() == CLOZE_SELECT) {
1493 $gaptemplate->setCurrentBlock('gap_select');
1494 $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1495 } else {
1496 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1497
1498 if ($gap_size > 0) {
1499 $gaptemplate->setCurrentBlock('gap_size');
1500 $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1501 $gaptemplate->parseCurrentBlock();
1502 }
1503
1504 $gaptemplate->setCurrentBlock('gap_input');
1505 $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1506 }
1507
1508
1509 $gaptemplate->parseCurrentBlock();
1510 }
1511}
sprintf('%.4f', $callTime)
$test
Definition: Utf8Test.php:84
if(!isset( $_REQUEST[ 'ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
Definition: as_login.php:20
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Class for cloze question numeric answers.
Cloze test question GUI representation.
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
applyIndizesToGapText($question_text)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
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.
__construct($id=-1)
assClozeTestGUI constructor
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)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
Adds the question specific forms parts to a question property form gui.
getSpecificFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
populateGapSizeFormPart($form, $gap, $gapCounter)
setQuestionTabs()
Sets the ILIAS tabs for this question type.
getBestSolutionText($gap, $gap_index, $gap_combinations)
populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
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.
populateGapFormPart($form, $gapCounter)
Populates a gap form-part.
addgap()
Add a gap answer.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
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)
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
Adds the answer specific form parts to a question property form gui.
writePostData($always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
removegap()
Remove a gap answer.
Class for cloze tests.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
addBackTab(ilTabsGUI $ilTabs)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
const ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT
constant for additional content editing mode "default"
This class represents a single choice wizard property in a property form.
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
This class represents a checkbox property in a property form.
This class represents a custom property in a property form.
This class represents a duration (typical hh:mm:ss) property in a property form.
This class represents a section header in a property form.
This class represents a formula text property in a property form.
This class represents a hidden form property in a property form.
This class represents a number property in a property form.
static _getUsedHTMLTags($a_module="")
Returns an array of all allowed HTML tags for text editing.
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the manual feedback for a question in a test.
This class represents a property form user interface.
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.
static stripSlashesRecursive($a_data, $a_strip_html=true, $a_allow="")
Strip slashes from array and sub-arrays.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
$template
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
$html
Definition: example_001.php:87
if(!array_key_exists('StateId', $_REQUEST)) $id
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\s+" &#(? foreach( $entity_files as $file) $output
const CLOZE_NUMERIC
const CLOZE_SELECT
const CLOZE_TEXT
Cloze question constants.
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
$index
Definition: metadata.php:60
$errors
Definition: index.php:6
$url
if(isset($_POST['submit'])) $form