ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6 require_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();
76  $this->saveTaxonomyAssignments();
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 (
197  isset($_POST['gap_combination']) &&
198  is_array($_POST['gap_combination']) &&
199  count($_POST['gap_combination']) > 0
200  ) {
201  $assClozeGapCombinationObject->saveGapCombinationToDb(
202  $this->object->getId(),
203  ilUtil::stripSlashesRecursive($_POST['gap_combination']),
204  ilUtil::stripSlashesRecursive($_POST['gap_combination_values'])
205  );
206  }
207  }
208  if ($this->ctrl->getCmd() != 'createGaps') {
209  $this->object->updateClozeTextFromGaps();
210  }
211  }
212  }
213 
215  {
216  $this->object->setClozeText($_POST['cloze_text']);
217  $this->object->setTextgapRating($_POST["textgap_rating"]);
218  $this->object->setIdenticalScoring($_POST["identical_scoring"]);
219  $this->object->setFixedTextLength($_POST["fixedTextLength"]);
220  }
221 
227  public function editQuestion($checkonly = false)
228  {
229  $save = $this->isSaveCommand();
230  $this->getQuestionTemplate();
231 
232  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
233  $form = new ilPropertyFormGUI();
234  $this->editForm = $form;
235 
236  $form->setFormAction($this->ctrl->getFormAction($this));
237  $form->setTitle($this->outQuestionType());
238  $form->setMultipart(false);
239  $form->setTableWidth("100%");
240  $form->setId("assclozetest");
241 
242  // title, author, description, question, working time (assessment mode)
247 
249 
250  $errors = false;
251 
252  if ($save) {
253  $form->setValuesByPost();
254  $errors = !$form->checkInput();
255  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we
256  // need this if we don't want to have duplication of backslashes
257  if ($errors) {
258  $checkonly = false;
259  }
260  }
261 
262  if (!$checkonly) {
263  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
264  }
265  return $errors;
266  }
267 
269  {
270  // title
271  $title = new ilTextInputGUI($this->lng->txt("title"), "title");
272  $title->setMaxLength(100);
273  $title->setValue($this->object->getTitle());
274  $title->setRequired(true);
275  $form->addItem($title);
276 
277  if (!$this->object->getSelfAssessmentEditingMode()) {
278  // author
279  $author = new ilTextInputGUI($this->lng->txt("author"), "author");
280  $author->setValue($this->object->getAuthor());
281  $author->setRequired(true);
282  $form->addItem($author);
283 
284  // description
285  $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
286  $description->setValue($this->object->getComment());
287  $description->setRequired(false);
288  $form->addItem($description);
289  } else {
290  // author as hidden field
291  $hi = new ilHiddenInputGUI("author");
292  $author = ilUtil::prepareFormOutput($this->object->getAuthor());
293  if (trim($author) == "") {
294  $author = "-";
295  }
296  $hi->setValue($author);
297  $form->addItem($hi);
298  }
299 
300  // questiontext
301  $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
302  $question->setValue($this->object->prepareTextareaOutput($this->object->getQuestion()));
303  $question->setRequired(true);
304  $question->setRows(10);
305  $question->setCols(80);
306  if (!$this->object->getSelfAssessmentEditingMode()) {
307  if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
308  $question->setUseRte(true);
309  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
310  $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
311  $question->addPlugin("latex");
312  $question->addButton("latex");
313  $question->addButton("pastelatex");
314  $question->setRTESupport($this->object->getId(), "qpl", "assessment");
315  }
316  } else {
317  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
319  $question->setUseTagsForRteOnly(false);
320  }
321  $form->addItem($question);
322 
323  // $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
324  // $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
325  // $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
326  // $tpl->parseCurrentBlock();
327  // $button = new ilCustomInputGUI('&nbsp;','');
328  // $button->setHtml($tpl->get());
329  // $form->addItem($button);
330 
331  if (!$this->object->getSelfAssessmentEditingMode()) {
332  // duration
333  $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
334  $duration->setShowHours(true);
335  $duration->setShowMinutes(true);
336  $duration->setShowSeconds(true);
337  $ewt = $this->object->getEstimatedWorkingTime();
338  $duration->setHours($ewt["h"]);
339  $duration->setMinutes($ewt["m"]);
340  $duration->setSeconds($ewt["s"]);
341  $duration->setRequired(false);
342  $form->addItem($duration);
343  } else {
344  // number of tries
345  if (strlen($this->object->getNrOfTries())) {
346  $nr_tries = $this->object->getNrOfTries();
347  } else {
348  $nr_tries = $this->object->getDefaultNrOfTries();
349  }
350  /*if ($nr_tries <= 0)
351  {
352  $nr_tries = 1;
353  }*/
354 
355  if ($nr_tries < 0) {
356  $nr_tries = 0;
357  }
358 
359  $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
360  $ni->setValue($nr_tries);
361  //$ni->setMinValue(1);
362  $ni->setMinValue(0);
363  $ni->setSize(5);
364  $ni->setMaxLength(5);
365  $ni->setRequired(true);
366  $form->addItem($ni);
367  }
368  }
369 
371  {
372  // cloze text
373  $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
374  $cloze_text->setRequired(true);
375  $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
376  $cloze_text->setInfo($this->lng->txt("close_text_hint"));
377  $cloze_text->setRows(10);
378  $cloze_text->setCols(80);
379  if (!$this->object->getSelfAssessmentEditingMode()) {
380  if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
381  $cloze_text->setUseRte(true);
382  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
383  $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
384  $cloze_text->addPlugin("latex");
385  $cloze_text->addButton("latex");
386  $cloze_text->addButton("pastelatex");
387  }
388  } else {
389  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
391  $cloze_text->setUseTagsForRteOnly(false);
392  }
393  $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
394  $form->addItem($cloze_text);
395 
396  $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", true, true, "Modules/TestQuestionPool");
397 
398  $button = new ilCustomInputGUI('&nbsp;', '');
399  require_once 'Services/UIComponent/SplitButton/classes/class.ilSplitButtonGUI.php';
400  require_once 'Services/UIComponent/Button/classes/class.ilJsLinkButton.php';
401  $action_button = ilSplitButtonGUI::getInstance();
402 
403  $sb_text_gap = ilJsLinkButton::getInstance();
404  $sb_text_gap->setCaption('text_gap');
405  $sb_text_gap->setName('gapbutton');
406  $sb_text_gap->setId('gaptrigger_text');
407  $action_button->setDefaultButton($sb_text_gap);
408 
409  $sb_sel_gap = ilJsLinkButton::getInstance();
410  $sb_sel_gap->setCaption('select_gap');
411  $sb_sel_gap->setName('gapbutton_select');
412  $sb_sel_gap->setId('gaptrigger_select');
413  $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_sel_gap));
414 
415  $sb_num_gap = ilJsLinkButton::getInstance();
416  $sb_num_gap->setCaption('numeric_gap');
417  $sb_num_gap->setName('gapbutton_numeric');
418  $sb_num_gap->setId('gaptrigger_numeric');
419  $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_num_gap));
420 
421  $tpl->setVariable('BUTTON', $action_button->render());
422  $tpl->parseCurrentBlock();
423 
424  $button->setHtml($tpl->get());
425  $form->addItem($button);
426 
427  // text rating
428  if (!$this->object->getSelfAssessmentEditingMode()) {
429  $textrating = new ilSelectInputGUI($this->lng->txt("text_rating"), "textgap_rating");
430  $text_options = array(
431  "ci" => $this->lng->txt("cloze_textgap_case_insensitive"),
432  "cs" => $this->lng->txt("cloze_textgap_case_sensitive"),
433  "l1" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "1"),
434  "l2" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "2"),
435  "l3" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "3"),
436  "l4" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "4"),
437  "l5" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "5")
438  );
439  $textrating->setOptions($text_options);
440  $textrating->setValue($this->object->getTextgapRating());
441  $form->addItem($textrating);
442 
443  // text field length
444  $fixedTextLength = new ilNumberInputGUI($this->lng->txt("cloze_fixed_textlength"), "fixedTextLength");
445  $ftl = $this->object->getFixedTextLength();
446 
447  $fixedTextLength->setValue($ftl > 0 ? $ftl : '');
448  $fixedTextLength->setMinValue(0);
449  $fixedTextLength->setSize(3);
450  $fixedTextLength->setMaxLength(6);
451  $fixedTextLength->setInfo($this->lng->txt('cloze_fixed_textlength_description'));
452  $fixedTextLength->setRequired(false);
453  $form->addItem($fixedTextLength);
454 
455  // identical scoring
456  $identical_scoring = new ilCheckboxInputGUI($this->lng->txt("identical_scoring"), "identical_scoring");
457  $identical_scoring->setValue(1);
458  $identical_scoring->setChecked($this->object->getIdenticalScoring());
459  $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
460  $identical_scoring->setRequired(false);
461  $form->addItem($identical_scoring);
462  }
463  return $form;
464  }
465 
467  {
468  if (self::OLD_CLOZE_TEST_UI) {
469  for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++) {
470  $this->populateGapFormPart($form, $gapCounter);
471  }
472  return $form;
473  } else {
474  require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
475  $json = $this->populateJSON();
476  $assClozeGapCombinationObject = new assClozeGapCombination();
477  $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->id);
478  if ($combination_exists) {
479  $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->id);
480  }
481  $new_builder = new ilClozeGapInputBuilderGUI();
483  $form->addItem($header);
484  $new_builder->setValueByArray($json);
485  $new_builder->setValueCombinationFromDb($combinations);
486  $form->addItem($new_builder);
487  return $form;
488  }
489  }
490 
491  protected function populateJSON()
492  {
493  $gap = $this->object->getGaps();
494  $array = array();
495  if ($gap == null) {
496  return $array;
497  }
498  $translate_type = array('text','select','numeric');
499  $i = 0;
500  foreach ($gap as $content) {
501  $shuffle = false;
502  $value = $content->getItemsRaw();
503  $items = array();
504  for ($j = 0;$j < count($value);$j++) {
505  if ($content->getType() == 2) {
506  $items[$j] = array(
507  'answer' => $value[$j]->getAnswerText(),
508  'lower' => $value[$j]->getLowerBound(),
509  'upper' => $value[$j]->getUpperBound(),
510  'points' => $value[$j]->getPoints(),
511  'error' => false
512  );
513  } else {
514  $items[$j] = array(
515  'answer' => $value[$j]->getAnswerText(),
516  'points' => $value[$j]->getPoints(),
517  'error' => false
518  );
519 
520  if ($content->getType() == 1) {
521  $shuffle = $content->getShuffle();
522  }
523  }
524  }
525  $answers[$i] = array(
526  'type' => $translate_type[$content->getType()] ,
527  'values' => $items ,
528  'shuffle' => $shuffle,
529  'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
530  'used_in_gap_combination' => true);
531  $i++;
532  }
533  return $answers;
534  }
546  protected function populateGapFormPart($form, $gapCounter)
547  {
548  $gap = $this->object->getGap($gapCounter);
549 
550  if ($gap == null) {
551  return $form;
552  }
553 
555  $header->setTitle($this->lng->txt("gap") . " " . ($gapCounter + 1));
556  $form->addItem($header);
557 
558  $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
559  $gapcounter->setValue($gapCounter);
560  $form->addItem($gapcounter);
561 
562  $gaptype = new ilSelectInputGUI($this->lng->txt('type'), "clozetype_$gapCounter");
563  $options = array(
564  0 => $this->lng->txt("text_gap"),
565  1 => $this->lng->txt("select_gap"),
566  2 => $this->lng->txt("numeric_gap")
567  );
568  $gaptype->setOptions($options);
569  $gaptype->setValue($gap->getType());
570  $form->addItem($gaptype);
571 
572  if ($gap->getType() == CLOZE_TEXT) {
573  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
574 
575  if (count($gap->getItemsRaw()) == 0) {
576  $gap->addItem(new assAnswerCloze("", 0, 0));
577  }
578  $this->populateTextGapFormPart($form, $gap, $gapCounter);
579  } elseif ($gap->getType() == CLOZE_SELECT) {
580  if (count($gap->getItemsRaw()) == 0) {
581  $gap->addItem(new assAnswerCloze("", 0, 0));
582  }
583  $this->populateSelectGapFormPart($form, $gap, $gapCounter);
584  } elseif ($gap->getType() == CLOZE_NUMERIC) {
585  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
586 
587  if (count($gap->getItemsRaw()) == 0) {
588  $gap->addItem(new assAnswerCloze("", 0, 0));
589  }
590  foreach ($gap->getItemsRaw() as $item) {
591  $this->populateNumericGapFormPart($form, $item, $gapCounter);
592  }
593  }
594  return $form;
595  }
596 
602  protected function populateGapSizeFormPart($form, $gap, $gapCounter)
603  {
604  $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_" . $gapCounter . '_gapsize');
605 
606  $gapSizeFormItem->allowDecimals(false);
607  $gapSizeFormItem->setMinValue(0);
608  $gapSizeFormItem->setSize(3);
609  $gapSizeFormItem->setMaxLength(6);
610  $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
611  $gapSizeFormItem->setValue($gap->getGapSize());
612  $form->addItem($gapSizeFormItem);
613 
614  return $form;
615  }
616 
629  protected function populateSelectGapFormPart($form, $gap, $gapCounter)
630  {
631  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
632  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
633  $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
634  $values->setRequired(true);
635  $values->setQuestionObject($this->object);
636  $values->setSingleline(true);
637  $values->setAllowMove(false);
638 
639  $values->setValues($gap->getItemsRaw());
640  $form->addItem($values);
641 
642  // shuffle
643  $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle_" . $gapCounter . "");
644  $shuffle->setValue(1);
645  $shuffle->setChecked($gap->getShuffle());
646  $shuffle->setRequired(false);
647  $form->addItem($shuffle);
648  return $form;
649  }
650 
662  protected function populateTextGapFormPart($form, $gap, $gapCounter)
663  {
664  // Choices
665  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
666  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
667  $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
668  $values->setRequired(true);
669  $values->setQuestionObject($this->object);
670  $values->setSingleline(true);
671  $values->setAllowMove(false);
672  $values->setValues($gap->getItemsRaw());
673  $form->addItem($values);
674 
675  if ($this->object->getFixedTextLength() > 0) {
676  $values->setSize($this->object->getFixedTextLength());
677  $values->setMaxLength($this->object->getFixedTextLength());
678  }
679 
680  return $form;
681  }
682 
694  protected function populateNumericGapFormPart($form, $gap, $gapCounter)
695  {
696  // #8944: the js-based ouput in self-assessment cannot support formulas
697  if (!$this->object->getSelfAssessmentEditingMode()) {
698  $value = new ilFormulaInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
699  $value->setInlineStyle('text-align: right;');
700 
701  $lowerbound = new ilFormulaInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
702  $lowerbound->setInlineStyle('text-align: right;');
703 
704  $upperbound = new ilFormulaInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
705  $upperbound->setInlineStyle('text-align: right;');
706  } else {
707  $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
708  $value->allowDecimals(true);
709 
710  $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
711  $lowerbound->allowDecimals(true);
712 
713  $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
714  $upperbound->allowDecimals(true);
715  }
716 
717  $value->setSize(10);
718  $value->setValue(ilUtil::prepareFormOutput($gap->getAnswertext()));
719  $value->setRequired(true);
720  $form->addItem($value);
721 
722  $lowerbound->setSize(10);
723  $lowerbound->setRequired(true);
724  $lowerbound->setValue(ilUtil::prepareFormOutput($gap->getLowerBound()));
725  $form->addItem($lowerbound);
726 
727  $upperbound->setSize(10);
728  $upperbound->setRequired(true);
729  $upperbound->setValue(ilUtil::prepareFormOutput($gap->getUpperBound()));
730  $form->addItem($upperbound);
731 
732  if ($this->object->getFixedTextLength() > 0) {
733  $value->setSize($this->object->getFixedTextLength());
734  $value->setMaxLength($this->object->getFixedTextLength());
735  $lowerbound->setSize($this->object->getFixedTextLength());
736  $lowerbound->setMaxLength($this->object->getFixedTextLength());
737  $upperbound->setSize($this->object->getFixedTextLength());
738  $upperbound->setMaxLength($this->object->getFixedTextLength());
739  }
740 
741  $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapCounter . "_numeric_points");
742  $points->allowDecimals(true);
743  $points->setSize(3);
744  $points->setRequired(true);
745  $points->setValue(ilUtil::prepareFormOutput($gap->getPoints()));
746  $form->addItem($points);
747  return $form;
748  }
749 
753  public function createGaps()
754  {
755  $this->writePostData(true);
756  $this->object->saveToDb();
757  $this->editQuestion();
758  }
759 
763  public function removegap()
764  {
765  $this->writePostData(true);
766  $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
767  $this->editQuestion();
768  }
769 
773  public function addgap()
774  {
775  $this->writePostData(true);
776  $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex]) + 1, "");
777  $this->editQuestion();
778  }
779 
788  public function getPreview($show_question_only = false, $showInlineFeedback = false)
789  {
790  $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
791 
792  // generate the question output
793  include_once "./Services/UICore/classes/class.ilTemplate.php";
794  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
795  $output = $this->object->getClozeText();
796  foreach ($this->object->getGaps() as $gap_index => $gap) {
797  switch ($gap->getType()) {
798  case CLOZE_TEXT:
799  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
800 
801  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
802  if ($gap_size > 0) {
803  $gaptemplate->setCurrentBlock('size_and_maxlength');
804  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
805  $gaptemplate->parseCurrentBlock();
806  }
807  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
808  foreach ($user_solution as $val1 => $val2) {
809  if (strcmp($val1, $gap_index) == 0) {
810  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
811  }
812  }
813  // fau: fixGapReplace - use replace function
814  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
815 // fau.
816  break;
817  case CLOZE_SELECT:
818  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
819  foreach ($gap->getItems($this->object->getShuffler()) as $item) {
820  $gaptemplate->setCurrentBlock("select_gap_option");
821  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
822  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
823  foreach ($user_solution as $val1 => $val2) {
824  if (strcmp($val1, $gap_index) == 0) {
825  if (strcmp($val2, $item->getOrder()) == 0) {
826  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
827  }
828  }
829  }
830  $gaptemplate->parseCurrentBlock();
831  }
832  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
833  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
834  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
835 // fau.
836  break;
837  case CLOZE_NUMERIC:
838  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
839  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
840  if ($gap_size > 0) {
841  $gaptemplate->setCurrentBlock('size_and_maxlength');
842  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
843  $gaptemplate->parseCurrentBlock();
844  }
845  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
846  foreach ($user_solution as $val1 => $val2) {
847  if (strcmp($val1, $gap_index) == 0) {
848  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
849  }
850  }
851  // fau: fixGapReplace - use replace function
852  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
853 // fau.
854  break;
855  }
856  }
857  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
858  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
859  $questionoutput = $template->get();
860  if (!$show_question_only) {
861  // get page object output
862  $questionoutput = $this->getILIASPage($questionoutput);
863  }
864  return $questionoutput;
865  }
866 
873  {
874  return true;
875  }
876 
892  public function getSolutionOutput(
893  $active_id,
894  $pass = null,
895  $graphicalOutput = false,
896  $result_output = false,
897  $show_question_only = true,
898  $show_feedback = false,
899  $show_correct_solution = false,
900  $show_manual_scoring = false,
901  $show_question_text = true
902  ) {
903  // get the solution of the user for the active pass or from the last pass if allowed
904  $user_solution = array();
905  if (($active_id > 0) && (!$show_correct_solution)) {
906  // get the solutions of a user
907  $user_solution = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
908  if (!is_array($user_solution)) {
909  $user_solution = array();
910  }
911  }
912 
913  include_once "./Services/UICore/classes/class.ilTemplate.php";
914  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", true, true, "Modules/TestQuestionPool");
915  $output = $this->object->getClozeText();
916  $assClozeGapCombinationObject = new assClozeGapCombination();
917  $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
918 
919  foreach ($this->object->getGaps() as $gap_index => $gap) {
920  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", true, true, "Modules/TestQuestionPool");
921  $found = array();
922  foreach ($user_solution as $solutionarray) {
923  if ($solutionarray["value1"] == $gap_index) {
924  $found = $solutionarray;
925  }
926  }
927 
928  if ($active_id) {
929  if ($graphicalOutput) {
930  // output of ok/not ok icons for user entered solutions
931  $details = $this->object->calculateReachedPoints($active_id, $pass, true, true);
932  $check = $details[$gap_index];
933 
934  if (count($check_for_gap_combinations) != 0) {
935  $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
936  $custom_user_solution = array();
937  if (array_key_exists($gap_index, $gaps_used_in_combination)) {
938  $combination_id = $gaps_used_in_combination[$gap_index];
939  foreach ($gaps_used_in_combination as $key => $value) {
940  $a = 0;
941  if ($value == $combination_id) {
942  foreach ($user_solution as $solution_key => $solution_value) {
943  if ($solution_value['value1'] == $key) {
944  $result_row = array();
945  $result_row['gap_id'] = $solution_value['value1'];
946  $result_row['value'] = $solution_value['value2'];
947  array_push($custom_user_solution, $result_row);
948  }
949  }
950  }
951  }
952  $points_array = $this->object->calculateCombinationResult($custom_user_solution);
953  $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
954  if ($points_array[0] == $max_combination_points) {
955  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
956  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
957  } elseif ($points_array[0] > 0) {
958  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
959  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
960  } else {
961  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
962  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
963  }
964  } else {
965  if ($check["best"]) {
966  $gaptemplate->setCurrentBlock("icon_ok");
967  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
968  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
969  $gaptemplate->parseCurrentBlock();
970  } else {
971  $gaptemplate->setCurrentBlock("icon_not_ok");
972  if ($check["positive"]) {
973  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
974  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
975  } else {
976  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
977  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
978  }
979  $gaptemplate->parseCurrentBlock();
980  }
981  }
982  } else {
983  if ($check["best"]) {
984  $gaptemplate->setCurrentBlock("icon_ok");
985  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
986  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
987  $gaptemplate->parseCurrentBlock();
988  } else {
989  $gaptemplate->setCurrentBlock("icon_not_ok");
990  if ($check["positive"]) {
991  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
992  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
993  } else {
994  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
995  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
996  }
997  $gaptemplate->parseCurrentBlock();
998  }
999  }
1000  }
1001  }
1002  if ($result_output) {
1003  $points = $this->object->getMaximumGapPoints($gap_index);
1004  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
1005  $gaptemplate->setCurrentBlock("result_output");
1006  $gaptemplate->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
1007  $gaptemplate->parseCurrentBlock();
1008  }
1009  $combination = null;
1010  switch ($gap->getType()) {
1011  case CLOZE_TEXT:
1012  $solutiontext = "";
1013  if (($active_id > 0) && (!$show_correct_solution)) {
1014  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1015  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1016  $solutiontext .= "&nbsp;";
1017  }
1018  } else {
1019  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1020  }
1021  } else {
1022  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1023  }
1024  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1025  // fau: fixGapReplace - use replace function
1026  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1027 // fau.
1028  break;
1029  case CLOZE_SELECT:
1030  $solutiontext = "";
1031  if (($active_id > 0) && (!$show_correct_solution)) {
1032  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1033  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1034  $solutiontext .= "&nbsp;";
1035  }
1036  } else {
1037  $item = $gap->getItem($found["value2"]);
1038  if (is_object($item)) {
1039  $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1040  } else {
1041  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1042  $solutiontext .= "&nbsp;";
1043  }
1044  }
1045  }
1046  } else {
1047  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1048  }
1049  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1050  // fau: fixGapReplace - use replace function
1051  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1052 // fau.
1053  break;
1054  case CLOZE_NUMERIC:
1055  $solutiontext = "";
1056  if (($active_id > 0) && (!$show_correct_solution)) {
1057  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1058  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1059  $solutiontext .= "&nbsp;";
1060  }
1061  } else {
1062  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1063  }
1064  } else {
1065  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1066  }
1067  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1068  // fau: fixGapReplace - use replace function
1069  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1070 // fau.
1071  break;
1072  }
1073  }
1074 
1075  if ($show_question_text) {
1076  $template->setVariable(
1077  "QUESTIONTEXT",
1078  $this->object->prepareTextareaOutput($this->object->getQuestion(), true)
1079  );
1080  }
1081 
1082  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1083  // generate the question output
1084  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
1085  $questionoutput = $template->get();
1086 
1087  $feedback = '';
1088  if ($show_feedback) {
1089  if (!$this->isTestPresentationContext()) {
1090  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1091  $feedback .= strlen($fb) ? $fb : '';
1092  }
1093 
1094  $fb = $this->getSpecificFeedbackOutput(
1095  $this->object->fetchIndexedValuesFromValuePairs($user_solution)
1096  );
1097  $feedback .= strlen($fb) ? $fb : '';
1098  }
1099  if (strlen($feedback)) {
1100  $cssClass = (
1101  $this->hasCorrectSolution($active_id, $pass) ?
1103  );
1104 
1105  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1106  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
1107  }
1108 
1109  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1110 
1111  $solutionoutput = $solutiontemplate->get();
1112 
1113  if (!$show_question_only) {
1114  // get page object output
1115  $solutionoutput = $this->getILIASPage($solutionoutput);
1116  }
1117 
1118  return $solutionoutput;
1119  }
1120 
1127  protected function getBestSolutionText($gap, $gap_index, $gap_combinations)
1128  {
1129  $combination = null;
1130  foreach ((array) $gap_combinations as $combiGapSolRow) {
1131  if ($combiGapSolRow['gap_fi'] == $gap_index && $combiGapSolRow['best_solution']) {
1132  $combination = $combiGapSolRow;
1133  break;
1134  }
1135  }
1136  $best_solution_text = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1137  $this->object->getShuffler(),
1138  $combination
1139  ));
1140  return $best_solution_text;
1141  }
1142 
1143  public function getAnswerFeedbackOutput($active_id, $pass)
1144  {
1145  include_once "./Modules/Test/classes/class.ilObjTest.php";
1146  $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1147  if (strlen($manual_feedback)) {
1148  return $manual_feedback;
1149  }
1150  $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1151  $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1152  if (strlen($correct_feedback . $incorrect_feedback)) {
1153  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1154  $max_points = $this->object->getMaximumPoints();
1155  if ($reached_points == $max_points) {
1156  $output .= $correct_feedback;
1157  } else {
1158  $output .= $incorrect_feedback;
1159  }
1160  }
1161  $test = new ilObjTest($this->object->active_id);
1162  return $this->object->prepareTextareaOutput($output, true);
1163  }
1164 
1165  public function getTestOutput(
1166  $active_id,
1167  // hey: prevPassSolutions - will be always available from now on
1168  $pass,
1169  // hey.
1170  $is_postponed = false,
1171  $use_post_solutions = false,
1172  $show_feedback = false
1173  ) {
1174  // get the solution of the user for the active pass or from the last pass if allowed
1175  $user_solution = array();
1176  if ($use_post_solutions !== false) {
1177  $indexedSolution = $this->object->fetchSolutionSubmit($use_post_solutions);
1178  $user_solution = $this->object->fetchValuePairsFromIndexedValues($indexedSolution);
1179  } elseif ($active_id) {
1180  // hey: prevPassSolutions - obsolete due to central check
1181  #include_once "./Modules/Test/classes/class.ilObjTest.php";
1182  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1183  #{
1184  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1185  #}
1186  $user_solution = $this->object->getTestOutputSolutions($active_id, $pass);
1187  // hey.
1188  if (!is_array($user_solution)) {
1189  $user_solution = array();
1190  }
1191  }
1192 
1193  // generate the question output
1194  include_once "./Services/UICore/classes/class.ilTemplate.php";
1195  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
1196  $output = $this->object->getClozeText();
1197  foreach ($this->object->getGaps() as $gap_index => $gap) {
1198  switch ($gap->getType()) {
1199  case CLOZE_TEXT:
1200  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
1201  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1202 
1203  if ($gap_size > 0) {
1204  $gaptemplate->setCurrentBlock('size_and_maxlength');
1205  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1206  $gaptemplate->parseCurrentBlock();
1207  }
1208 
1209  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1210  foreach ($user_solution as $solution) {
1211  if (strcmp($solution["value1"], $gap_index) == 0) {
1212  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1213  }
1214  }
1215  // fau: fixGapReplace - use replace function
1216  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1217 // fau.
1218  break;
1219  case CLOZE_SELECT:
1220  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
1221  foreach ($gap->getItems($this->object->getShuffler()) as $item) {
1222  $gaptemplate->setCurrentBlock("select_gap_option");
1223  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1224  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1225  foreach ($user_solution as $solution) {
1226  if (strcmp($solution["value1"], $gap_index) == 0) {
1227  if (strcmp($solution["value2"], $item->getOrder()) == 0) {
1228  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1229  }
1230  }
1231  }
1232  $gaptemplate->parseCurrentBlock();
1233  }
1234  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1235  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
1236  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1237 // fau.
1238  break;
1239  case CLOZE_NUMERIC:
1240  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
1241  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1242  if ($gap_size > 0) {
1243  $gaptemplate->setCurrentBlock('size_and_maxlength');
1244  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1245  $gaptemplate->parseCurrentBlock();
1246  }
1247 
1248  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1249  foreach ($user_solution as $solution) {
1250  if (strcmp($solution["value1"], $gap_index) == 0) {
1251  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1252  }
1253  }
1254  // fau: fixGapReplace - use replace function
1255  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1256 // fau.
1257  break;
1258  }
1259  }
1260 
1261  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
1262  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1263  $questionoutput = $template->get();
1264  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1265  return $pageoutput;
1266  }
1267 
1275  public function setQuestionTabs()
1276  {
1277  global $DIC;
1278  $rbacsystem = $DIC['rbacsystem'];
1279  $ilTabs = $DIC['ilTabs'];
1280 
1281  $ilTabs->clearTargets();
1282 
1283  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1284  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1285  $q_type = $this->object->getQuestionType();
1286 
1287  if (strlen($q_type)) {
1288  $classname = $q_type . "GUI";
1289  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1290  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1291  # $this->ctrl->setParameterByClass(strtolower($classname), 'prev_qid', $_REQUEST['prev_qid']);
1292  }
1293 
1294  if ($_GET["q_id"]) {
1295  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1296  // edit page
1297  $ilTabs->addTarget(
1298  "edit_page",
1299  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1300  array("edit", "insert", "exec_pg"),
1301  "",
1302  "",
1303  $force_active
1304  );
1305  }
1306 
1307  $this->addTab_QuestionPreview($ilTabs);
1308  }
1309 
1310  $force_active = false;
1311  $commands = $_POST["cmd"];
1312  if (is_array($commands)) {
1313  foreach ($commands as $key => $value) {
1314  if (preg_match("/^removegap_.*/", $key, $matches) ||
1315  preg_match("/^addgap_.*/", $key, $matches)
1316  ) {
1317  $force_active = true;
1318  }
1319  }
1320  }
1321  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1322  $url = "";
1323  if ($classname) {
1324  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1325  }
1326  // edit question properties
1327  $ilTabs->addTarget(
1328  "edit_question",
1329  $url,
1330  array("editQuestion", "originalSyncForm", "save", "createGaps", "saveEdit"),
1331  $classname,
1332  "",
1333  $force_active
1334  );
1335  }
1336 
1337  // add tab for question feedback within common class assQuestionGUI
1338  $this->addTab_QuestionFeedback($ilTabs);
1339 
1340  // add tab for question hint within common class assQuestionGUI
1341  $this->addTab_QuestionHints($ilTabs);
1342 
1343  // add tab for question's suggested solution within common class assQuestionGUI
1344  $this->addTab_SuggestedSolution($ilTabs, $classname);
1345 
1346  // Assessment of questions sub menu entry
1347  if ($_GET["q_id"]) {
1348  $ilTabs->addTarget(
1349  "statistics",
1350  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1351  array("assessment"),
1352  $classname,
1353  ""
1354  );
1355  }
1356 
1357  $this->addBackTab($ilTabs);
1358  }
1359 
1360  public function getSpecificFeedbackOutput($userSolution)
1361  {
1362  if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
1363  return '';
1364  }
1365 
1366  global $DIC;
1367  $lng = $DIC['lng'];
1368 
1369  $feedback = '<table class="test_specific_feedback"><tbody>';
1370 
1371  foreach ($this->object->gaps as $gapIndex => $gap) {
1372  $answerValue = $this->object->fetchAnswerValueForGap($userSolution, $gapIndex);
1373  $answerIndex = $this->object->feedbackOBJ->determineAnswerIndexForAnswerValue($gap, $answerValue);
1374  $fb = $this->object->feedbackOBJ->determineTestOutputGapFeedback($gapIndex, $answerIndex);
1375 
1376  $caption = $lng->txt('gap') . ' ' . ($gapIndex + 1) . ': ';
1377  $feedback .= '<tr><td>';
1378  $feedback .= $caption . '</td><td>';
1379  $feedback .= $fb . '</td> </tr>';
1380  }
1381  $feedback .= '</tbody></table>';
1382 
1383  return $this->object->prepareTextareaOutput($feedback, true);
1384  }
1385 
1396  {
1397  return array();
1398  }
1399 
1410  {
1411  return array();
1412  }
1413 
1422  public function getAggregatedAnswersView($relevant_answers)
1423  {
1424  $overview = array();
1425  $aggregation = array();
1426  foreach ($relevant_answers as $answer) {
1427  $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1428  }
1429 
1430  foreach ($overview as $active) {
1431  foreach ($active as $answer) {
1432  foreach ($answer as $option => $value) {
1433  $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1434  }
1435  }
1436  }
1437 
1438  $html = '<div>';
1439  $i = 0;
1440  foreach ($this->object->getGaps() as $gap) {
1441  if ($gap->type == CLOZE_SELECT) {
1442  $html .= '<p>Gap ' . ($i + 1) . ' - SELECT</p>';
1443  $html .= '<ul>';
1444  $j = 0;
1445  foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1446  $aggregate = $aggregation[$i];
1447  $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1448  $j++;
1449  }
1450  $html .= '</ul>';
1451  }
1452 
1453  if ($gap->type == CLOZE_TEXT) {
1454  $present_elements = array();
1455  foreach ($gap->getItems(new ilArrayElementShuffler()) as $item) {
1457  $present_elements[] = $item->getAnswertext();
1458  }
1459 
1460  $html .= '<p>Gap ' . ($i + 1) . ' - TEXT</p>';
1461  $html .= '<ul>';
1462  $aggregate = (array) $aggregation[$i];
1463  foreach ($aggregate as $answer => $count) {
1464  $show_mover = '';
1465  if (in_array($answer, $present_elements)) {
1466  $show_mover = ' style="display: none;" ';
1467  }
1468 
1469  $html .= '<li>' . $answer . ' - ' . $count
1470  . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="' . $answer . '" name="add_gap_' . $i . '_0">
1471  <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1472  </li>';
1473  }
1474  $html .= '</ul>';
1475  }
1476 
1477  if ($gap->type == CLOZE_NUMERIC) {
1478  $html .= '<p>Gap ' . ($i + 1) . ' - NUMERIC</p>';
1479  $html .= '<ul>';
1480  $j = 0;
1481  foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1482  $aggregate = (array) $aggregation[$i];
1483  foreach ($aggregate as $answer => $count) {
1484  $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1485  }
1486  $j++;
1487  }
1488  $html .= '</ul>';
1489  }
1490  $i++;
1491  $html .= '<hr />';
1492  }
1493 
1494  $html .= '</div>';
1495  return $html;
1496  }
1497 
1498  public function applyIndizesToGapText($question_text)
1499  {
1500  $parts = explode('[gap', $question_text);
1501  $i = 0;
1502  $question_text = '';
1503  foreach ($parts as $part) {
1504  if ($i == 0) {
1505  $question_text .= $part;
1506  } else {
1507  $question_text .= '[gap ' . $i . $part;
1508  }
1509  $i++;
1510  }
1511  return $question_text;
1512  }
1513 
1514  public function removeIndizesFromGapText($question_text)
1515  {
1516  $parts = preg_split('/\[gap \d*\]/', $question_text);
1517  $question_text = implode('[gap]', $parts);
1518  return $question_text;
1519  }
1520 
1525  private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
1526  {
1527  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
1528  $gaptemplate->setCurrentBlock('gap_span');
1529  $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1530  } elseif ($gap->getType() == CLOZE_SELECT) {
1531  $gaptemplate->setCurrentBlock('gap_select');
1532  $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1533  } else {
1534  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1535 
1536  if ($gap_size > 0) {
1537  $gaptemplate->setCurrentBlock('gap_size');
1538  $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1539  $gaptemplate->parseCurrentBlock();
1540  }
1541 
1542  $gaptemplate->setCurrentBlock('gap_input');
1543  $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1544  }
1545 
1546 
1547  $gaptemplate->parseCurrentBlock();
1548  }
1549 
1550  protected function hasAddAnswerAction($relevantAnswers, $questionIndex)
1551  {
1552  foreach ($this->getAnswersFrequency($relevantAnswers, $questionIndex) as $answer) {
1553  if (isset($answer['actions'])) {
1554  return true;
1555  }
1556  }
1557 
1558  return false;
1559  }
1560 
1561  public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
1562  {
1563  global $DIC; /* @var ILIAS\DI\Container $DIC */
1564 
1565  $table = parent::getAnswerFrequencyTableGUI(
1566  $parentGui,
1567  $parentCmd,
1568  $relevantAnswers,
1569  $questionIndex
1570  );
1571 
1572  $table->setTitle(sprintf(
1573  $DIC->language()->txt('tst_corrections_answers_tbl_subindex'),
1574  $DIC->language()->txt('gap') . ' ' . ($questionIndex + 1)
1575  ));
1576 
1577  if ($this->hasAddAnswerAction($relevantAnswers, $questionIndex)) {
1578  $table->addColumn('', '', '200');
1579  }
1580 
1581  return $table;
1582  }
1583 
1584  public function getSubQuestionsIndex()
1585  {
1586  return array_keys($this->object->getGaps());
1587  }
1588 
1589  protected function getAnswerTextLabel($gapIndex, $answer)
1590  {
1591  $gap = $this->object->getGap($gapIndex);
1592 
1593  switch ($gap->type) {
1594  case CLOZE_NUMERIC:
1595  case CLOZE_TEXT:
1596  return $answer;
1597 
1598  case CLOZE_SELECT:
1599 
1600  $items = $gap->getItems(new ilArrayElementOrderKeeper());
1601  return $items[$answer]->getAnswertext();
1602  }
1603  }
1604 
1605  protected function completeAddAnswerAction($answers, $questionIndex)
1606  {
1607  $gap = $this->object->getGap($questionIndex);
1608 
1609  if ($gap->type != CLOZE_TEXT) {
1610  return $answers;
1611  }
1612 
1613  foreach ($answers as $key => $ans) {
1614  $found = false;
1615 
1616  foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $item) {
1617  if ($ans['answer'] !== $item->getAnswerText()) {
1618  continue;
1619  }
1620 
1621  $found = true;
1622  break;
1623  }
1624 
1625  if (!$found) {
1626  $answers[$key]['addable'] = true;
1627  }
1628  }
1629 
1630  return $answers;
1631  }
1632 
1633  public function getAnswersFrequency($relevant_answers, $questionIndex)
1634  {
1635  $answers = array();
1636 
1637  foreach ($relevant_answers as $row) {
1638  if ($row['value1'] != $questionIndex) {
1639  continue;
1640  }
1641 
1642  if (!isset($answers[$row['value2']])) {
1643  $label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
1644 
1645  $answers[$row['value2']] = array(
1646  'answer' => $label, 'frequency' => 0
1647  );
1648  }
1649 
1650  $answers[$row['value2']]['frequency']++;
1651  }
1652 
1653  $answers = $this->completeAddAnswerAction($answers, $questionIndex);
1654 
1655  return $answers;
1656  }
1657 
1658  protected function isUsedInCombinations($gapIndex)
1659  {
1660  foreach ($this->object->getGapCombinations() as $combination) {
1661  if ($combination['gap_fi'] != $gapIndex) {
1662  continue;
1663  }
1664 
1665  return true;
1666  }
1667 
1668  return false;
1669  }
1670 
1671  protected function getGapCombinations()
1672  {
1673  $combinations = array();
1674 
1675  foreach ($this->object->getGapCombinations() as $c) {
1676  if (!isset($combinations[$c['cid']])) {
1677  $combinations[$c['cid']] = array();
1678  }
1679 
1680  if (!isset($combinations[$c['cid']][$c['row_id']])) {
1681  $combinations[$c['cid']][$c['row_id']] = array(
1682  'gaps' => array(), 'points' => $c['points'],
1683  );
1684  }
1685 
1686  if (!isset($combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']])) {
1687  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = array();
1688  }
1689 
1690  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = $c['answer'];
1691  }
1692 
1693  return $combinations;
1694  }
1695 
1697  {
1698  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1700  $form,
1701  $gap,
1702  $gapIndex,
1703  $this->isUsedInCombinations($gapIndex)
1704  );
1705  }
1706 
1707  if ($this->object->getGapCombinationsExists()) {
1708  foreach ($this->getGapCombinations() as $combiIndex => $gapCombination) {
1709  $this->populateGapCombinationCorrectionFormProperty($form, $gapCombination, $combiIndex);
1710  }
1711  }
1712  }
1713 
1714  protected function populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex)
1715  {
1717  $header->setTitle("Gap Combination " . ($combiIndex + 1));
1718  $form->addItem($header);
1719 
1720  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php';
1721  $inp = new ilAssClozeTestCombinationVariantsInputGUI('Answers', 'combination_' . $combiIndex);
1722  $inp->setValues($gapCombi);
1723  $form->addItem($inp);
1724  }
1725 
1731  protected function populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints)
1732  {
1734  $header->setTitle($this->lng->txt("gap") . " " . ($gapIndex + 1));
1735  $form->addItem($header);
1736 
1737  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1739  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1740  foreach ($gap->getItemsRaw() as $item) {
1741  $this->populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints);
1742  }
1743  }
1744  }
1745 
1746  protected function populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
1747  {
1748  require_once "Modules/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php";
1749  $values = new ilAssAnswerCorrectionsInputGUI($this->lng->txt("values"), "gap_" . $gapIndex);
1750  $values->setHidePointsEnabled($hidePoints);
1751  $values->setRequired(true);
1752  $values->setQuestionObject($this->object);
1753  $values->setValues($gap->getItemsRaw());
1754  $form->addItem($values);
1755  }
1756 
1757  protected function populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints)
1758  {
1759  $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapIndex . "_numeric");
1760  $value->allowDecimals(true);
1761  $value->setSize(10);
1762  $value->setValue(ilUtil::prepareFormOutput($item->getAnswertext()));
1763  $value->setRequired(true);
1764  $form->addItem($value);
1765 
1766  $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapIndex . "_numeric_lower");
1767  $lowerbound->allowDecimals(true);
1768  $lowerbound->setSize(10);
1769  $lowerbound->setRequired(true);
1770  $lowerbound->setValue(ilUtil::prepareFormOutput($item->getLowerBound()));
1771  $form->addItem($lowerbound);
1772 
1773  $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapIndex . "_numeric_upper");
1774  $upperbound->allowDecimals(true);
1775  $upperbound->setSize(10);
1776  $upperbound->setRequired(true);
1777  $upperbound->setValue(ilUtil::prepareFormOutput($item->getUpperBound()));
1778  $form->addItem($upperbound);
1779 
1780  if (!$hidePoints) {
1781  $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapIndex . "_numeric_points");
1782  $points->allowDecimals(true);
1783  $points->setSize(3);
1784  $points->setRequired(true);
1785  $points->setValue(ilUtil::prepareFormOutput($item->getPoints()));
1786  $form->addItem($points);
1787  }
1788  }
1789 
1794  {
1795  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1796  if ($this->isUsedInCombinations($gapIndex)) {
1797  continue;
1798  }
1799 
1800  $this->saveGapCorrectionFormProperty($form, $gap, $gapIndex);
1801  }
1802 
1803  if ($this->object->getGapCombinationsExists()) {
1805  }
1806  }
1807 
1809  {
1810  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1812  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1813  foreach ($gap->getItemsRaw() as $item) {
1814  $this->saveNumericGapCorrectionFormProperty($form, $item, $gapIndex);
1815  }
1816  }
1817  }
1818 
1820  {
1821  $answers = $form->getItemByPostVar('gap_' . $gapIndex)->getValues();
1822 
1823  foreach ($gap->getItemsRaw() as $index => $item) {
1824  $item->setPoints((float) $answers[$index]->getPoints());
1825  }
1826  }
1827 
1829  {
1830  $item->setAnswertext($form->getInput('gap_' . $gapIndex . '_numeric'));
1831  $item->setLowerBound($form->getInput('gap_' . $gapIndex . '_numeric_lower'));
1832  $item->setUpperBound($form->getInput('gap_' . $gapIndex . '_numeric_upper'));
1833  $item->setPoints($form->getInput('gap_' . $gapIndex . '_numeric_points'));
1834  }
1835 
1837  {
1838  // please dont ask (!) -.-
1839 
1840  $combinationPoints = array('points' => array(), 'select' => array());
1841  $combinationValues = array();
1842 
1843  foreach ($this->getGapCombinations() as $combiId => $combi) {
1844  $values = $form->getItemByPostVar('combination_' . $combiId)->getValues();
1845 
1846  if (!isset($combinationPoints['points'][$combiId])) {
1847  $combinationPoints['points'][$combiId] = array();
1848  $combinationPoints['select'][$combiId] = array();
1849  $combinationValues[$combiId] = array();
1850  }
1851 
1852  foreach ($combi as $varId => $variant) {
1853  $combinationPoints['points'][$combiId][$varId] = (float) $values[$varId]['points'];
1854  $combinationPoints['select'][$combiId] = array_keys($values[$varId]['gaps']);
1855  $combinationValues[$combiId][$varId] = array_values($values[$varId]['gaps']);
1856  }
1857  }
1858 
1859  $combinationPoints = ilUtil::stripSlashesRecursive($combinationPoints);
1860  $combinationValues = ilUtil::stripSlashesRecursive($combinationValues);
1861 
1862  $assClozeGapCombinationObject = new assClozeGapCombination();
1863  $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
1864 
1865  $assClozeGapCombinationObject->saveGapCombinationToDb(
1866  $this->object->getId(),
1867  $combinationPoints,
1868  $combinationValues
1869  );
1870  }
1871 }
getSpecificFeedbackOutput($userSolution)
This class represents a formula text property in a property form.
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
This class represents a duration (typical hh:mm:ss) property in a property form.
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints)
Class for cloze question numeric answers.
getItemByPostVar($a_post_var)
Get Item by POST variable.
Class for cloze tests.
setValue($a_value)
Set Value.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
This class represents a selection list property in a property form.
setUpperBound($bound)
Sets the upper bound.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
$template
This class represents a property form user interface.
global $DIC
Definition: saml.php:7
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
$_GET["client_id"]
getAnswerFeedbackOutput($active_id, $pass)
const CLOZE_TEXT
Cloze question constants.
setShowHours($a_showhours)
Set Show Hours.
This class represents a section header in a property form.
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
saveGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
setPoints($points=0.0)
Sets the points.
getTestOutput( $active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
static _getUsedHTMLTags($a_module="")
Returns an array of all allowed HTML tags for text editing.
if(!array_key_exists('StateId', $_REQUEST)) $id
setValue($a_value)
Set Value.
This class represents a checkbox property in a property form.
setLowerBound($bound)
Sets the lower boind.
getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
saveGapCombinationCorrectionFormProperties(ilPropertyFormGUI $form)
addItem($a_item)
Add Item (Property, SectionHeader).
Class for cloze question gaps.
populateTextGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a text gap.
setQuestionTabs()
Sets the ILIAS tabs for this question type.
$index
Definition: metadata.php:60
populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
getQuestionTemplate()
get question template
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
getBestSolutionText($gap, $gap_index, $gap_combinations)
getAnswersFrequency($relevant_answers, $questionIndex)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
allowDecimals($a_value)
Toggle Decimals.
This class represents a single choice wizard property in a property form.
populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex)
This class represents a hidden form property in a property form.
getItemsRaw()
Gets the items of a cloze gap.
Cloze test question GUI representation.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer 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.
const CLOZE_SELECT
createGaps()
Create gaps from cloze text.
completeAddAnswerAction($answers, $questionIndex)
if(isset($_POST['submit'])) $form
hasAddAnswerAction($relevantAnswers, $questionIndex)
getILIASPage($html="")
Returns the ILIAS Page around a question.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
populateGapFormPart($form, $gapCounter)
Populates a gap form-part.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
This class represents a number property in a property form.
$values
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
Adds the answer specific form parts to a question property form gui.
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the manual feedback for a question in a test.
setValue($a_value)
Set Value.
special template class to simplify handling of ITX/PEAR
writePostData($always=false)
{}
populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
static stripSlashesRecursive($a_data, $a_strip_html=true, $a_allow="")
Strip slashes from array and sub-arrays.
This class represents a text property in a property form.
saveTextOrSelectGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
populateGapSizeFormPart($form, $gap, $gapCounter)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
Basic GUI class for assessment questions.
saveNumericGapCorrectionFormProperty(ilPropertyFormGUI $form, assAnswerCloze $item, $gapIndex)
removegap()
Remove a gap answer.
populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints)
addgap()
Add a gap answer.
$row
const ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT
constant for additional content editing mode "default"
populateNumericGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a numeric gap.
populateSelectGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a select gap.
This class represents a custom property in a property form.
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
$errors
Definition: index.php:6
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
applyIndizesToGapText($question_text)
This class represents a text area property in a property form.
setAnswertext($answertext="")
Sets the answer text.
addBackTab(ilTabsGUI $ilTabs)
$i
Definition: disco.tpl.php:19
getType()
Gets the cloze gap type.
setInlineStyle($a_style)
Set inline style.
Interface ilGuiAnswerScoringAdjustable.
$url
if(empty($password)) $table
Definition: pwgen.php:24
const CLOZE_NUMERIC
$gapIndex
A temporary variable to store gap indexes of ilCtrl commands in the getCommand method.
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
Interface ilGuiQuestionScoringAdjustable.
setValue($a_value)
Set Value.
$key
Definition: croninfo.php:18
getPreview($show_question_only=false, $showInlineFeedback=false)
Creates a preview output of the question.
$_POST["username"]
$html
Definition: example_001.php:87
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
setRequired($a_required)
Set Required.
removeIndizesFromGapText($question_text)
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
getAnswerTextLabel($gapIndex, $answer)
$test
Definition: Utf8Test.php:84
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.