ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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  {
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  $_POST['cloze_text'] = $this->removeIndizesFromGapText($_POST['cloze_text']);
65  $this->object->setQuestion($_POST['question']);
66 
68  $this->object->setClozeText($_POST["cloze_text"]);
70  //$this->object->flushGaps();
72  $this->saveTaxonomyAssignments();
73  return 0;
74  }
75 
76  $_POST['cloze_text'] = $this->applyIndizesToGapText($_POST['cloze_text']);
77  return 1;
78  }
79 
81  {
82  if (is_array($_POST['gap'])) {
83  if ($this->ctrl->getCmd() != 'createGaps') {
84  $this->object->clearGapAnswers();
85  }
86 
87  foreach ($_POST['gap'] as $idx => $hidden) {
88  $clozetype = $_POST['clozetype_' . $idx];
89 
90  $this->object->setGapType($idx, $clozetype);
91 
92  switch ($clozetype) {
93  case CLOZE_TEXT:
94 
95  $this->object->setGapShuffle($idx, 0);
96 
97  if ($this->ctrl->getCmd() != 'createGaps') {
98  if (is_array($_POST['gap_' . $idx]['answer'])) {
99  foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
100  $this->object->addGapAnswer($idx, $order, $value);
101  }
102  } else {
103  $this->object->addGapAnswer($idx, 0, '');
104  }
105  }
106 
107  if (is_array($_POST['gap_' . $idx]['points'])) {
108  foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
109  $this->object->setGapAnswerPoints($idx, $order, $value);
110  }
111  }
112 
113  if (array_key_exists('gap_' . $idx . '_gapsize', $_POST)) {
114  $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize']);
115  }
116 
117  break;
118 
119  case CLOZE_SELECT:
120 
121  $this->object->setGapShuffle($idx, (int) (isset($_POST["shuffle_$idx"]) && $_POST["shuffle_$idx"]));
122 
123  if ($this->ctrl->getCmd() != 'createGaps') {
124  if (is_array($_POST['gap_' . $idx]['answer'])) {
125  foreach ($_POST['gap_' . $idx]['answer'] as $order => $value) {
126  $this->object->addGapAnswer($idx, $order, $value);
127  }
128  } else {
129  $this->object->addGapAnswer($idx, 0, '');
130  }
131  }
132 
133  if (is_array($_POST['gap_' . $idx]['points'])) {
134  foreach ($_POST['gap_' . $idx]['points'] as $order => $value) {
135  $this->object->setGapAnswerPoints($idx, $order, $value);
136  }
137  }
138  break;
139 
140  case CLOZE_NUMERIC:
141 
142  $this->object->setGapShuffle($idx, 0);
143 
144  $gap = $this->object->getGap($idx);
145  if (!$gap) {
146  break;
147  }
148 
149  $this->object->getGap($idx)->clearItems();
150 
151  if (array_key_exists('gap_' . $idx . '_numeric', $_POST)) {
152  if ($this->ctrl->getCmd() != 'createGaps') {
153  $this->object->addGapAnswer(
154  $idx,
155  0,
156  str_replace(",", ".", $_POST['gap_' . $idx . '_numeric'])
157  );
158  }
159 
160  $this->object->setGapAnswerLowerBound(
161  $idx,
162  0,
163  str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_lower'])
164  );
165 
166  $this->object->setGapAnswerUpperBound(
167  $idx,
168  0,
169  str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_upper'])
170  );
171 
172  $this->object->setGapAnswerPoints($idx, 0, $_POST['gap_' . $idx . '_numeric_points']);
173  } else {
174  if ($this->ctrl->getCmd() != 'createGaps') {
175  $this->object->addGapAnswer($idx, 0, '');
176  }
177 
178  $this->object->setGapAnswerLowerBound($idx, 0, '');
179 
180  $this->object->setGapAnswerUpperBound($idx, 0, '');
181  }
182 
183  if (array_key_exists('gap_' . $idx . '_gapsize', $_POST)) {
184  $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize']);
185  }
186  break;
187  }
188  $assClozeGapCombinationObject = new assClozeGapCombination();
189  $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
190  if (
191  isset($_POST['gap_combination']) &&
192  is_array($_POST['gap_combination']) &&
193  count($_POST['gap_combination']) > 0
194  ) {
195  $assClozeGapCombinationObject->saveGapCombinationToDb(
196  $this->object->getId(),
197  $_POST['gap_combination'],
198  $_POST['gap_combination_values']
199  );
200  }
201  }
202  if ($this->ctrl->getCmd() != 'createGaps') {
203  $this->object->updateClozeTextFromGaps();
204  }
205  }
206  }
207 
209  {
210  $this->object->setClozeText($_POST['cloze_text']);
211  $this->object->setTextgapRating($_POST["textgap_rating"]);
212  $this->object->setIdenticalScoring($_POST["identical_scoring"]);
213  $this->object->setFixedTextLength($_POST["fixedTextLength"]);
214  }
215 
221  public function editQuestion($checkonly = false)
222  {
223  $save = $this->isSaveCommand();
224  $this->getQuestionTemplate();
225 
226  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
227  $form = new ilPropertyFormGUI();
228  $this->editForm = $form;
229 
230  $form->setFormAction($this->ctrl->getFormAction($this));
231  $form->setTitle($this->outQuestionType());
232  $form->setMultipart(false);
233  $form->setTableWidth("100%");
234  $form->setId("assclozetest");
235 
236  // title, author, description, question, working time (assessment mode)
237  $this->addBasicQuestionFormProperties($form);
238  $this->populateQuestionSpecificFormPart($form);
239  $this->populateAnswerSpecificFormPart($form);
240  $this->populateTaxonomyFormSection($form);
241 
242  $this->addQuestionFormCommandButtons($form);
243 
244  $errors = false;
245 
246  if ($save) {
247  $form->setValuesByPost();
248  $errors = !$form->checkInput();
249  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we
250  // need this if we don't want to have duplication of backslashes
251  if ($errors) {
252  $checkonly = false;
253  }
254  }
255 
256  if (!$checkonly) {
257  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
258  }
259  return $errors;
260  }
261 
262  public function addBasicQuestionFormProperties($form)
263  {
264  // title
265  $title = new ilTextInputGUI($this->lng->txt("title"), "title");
266  $title->setMaxLength(100);
267  $title->setValue($this->object->getTitle());
268  $title->setRequired(true);
269  $form->addItem($title);
270 
271  if (!$this->object->getSelfAssessmentEditingMode()) {
272  // author
273  $author = new ilTextInputGUI($this->lng->txt("author"), "author");
274  $author->setValue($this->object->getAuthor());
275  $author->setRequired(true);
276  $form->addItem($author);
277 
278  // description
279  $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
280  $description->setValue($this->object->getComment());
281  $description->setRequired(false);
282  $form->addItem($description);
283  } else {
284  // author as hidden field
285  $hi = new ilHiddenInputGUI("author");
286  $author = ilUtil::prepareFormOutput($this->object->getAuthor());
287  if (trim($author) == "") {
288  $author = "-";
289  }
290  $hi->setValue($author);
291  $form->addItem($hi);
292  }
293 
294  // lifecycle
295  $lifecycle = new ilSelectInputGUI($this->lng->txt('qst_lifecycle'), 'lifecycle');
296  $lifecycle->setOptions($this->object->getLifecycle()->getSelectOptions($this->lng));
297  $lifecycle->setValue($this->object->getLifecycle()->getIdentifier());
298  $form->addItem($lifecycle);
299 
300  // questiontext
301  $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
302  $question->setValue($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_RTE) {
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  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_RTE) {
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();
474  $header = new ilFormSectionHeaderGUI();
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->isNumericGap()) {
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' => $this->escapeTemplatePlaceholders($value[$j]->getAnswerText()),
508  'points' => $value[$j]->getPoints(),
509  'error' => false
510  );
511 
512  if ($content->isSelectGap()) {
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 
546  $header = new ilFormSectionHeaderGUI();
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->getClozeTextForHTMLOutput();
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  // fau: fixGapReplace - use replace function
806  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
807 // fau.
808  break;
809  case CLOZE_SELECT:
810  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
811  foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $item) {
812  $gaptemplate->setCurrentBlock("select_gap_option");
813  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
814  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
815  foreach ($user_solution as $val1 => $val2) {
816  if (strcmp($val1, $gap_index) == 0) {
817  if (strcmp($val2, $item->getOrder()) == 0) {
818  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
819  }
820  }
821  }
822  $gaptemplate->parseCurrentBlock();
823  }
824  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
825  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
826  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
827 // fau.
828  break;
829  case CLOZE_NUMERIC:
830  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
831  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
832  if ($gap_size > 0) {
833  $gaptemplate->setCurrentBlock('size_and_maxlength');
834  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
835  $gaptemplate->parseCurrentBlock();
836  }
837  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
838  foreach ($user_solution as $val1 => $val2) {
839  if (strcmp($val1, $gap_index) == 0) {
840  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
841  }
842  }
843  // fau: fixGapReplace - use replace function
844  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
845 // fau.
846  break;
847  }
848  }
849  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
850  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
851  $questionoutput = $template->get();
852  if (!$show_question_only) {
853  // get page object output
854  $questionoutput = $this->getILIASPage($questionoutput);
855  }
856  return $questionoutput;
857  }
858 
865  {
866  return true;
867  }
868 
884  public function getSolutionOutput(
885  $active_id,
886  $pass = null,
887  $graphicalOutput = false,
888  $result_output = false,
889  $show_question_only = true,
890  $show_feedback = false,
891  $show_correct_solution = false,
892  $show_manual_scoring = false,
893  $show_question_text = true
894  ) {
895  // get the solution of the user for the active pass or from the last pass if allowed
896  $user_solution = array();
897  if (($active_id > 0) && (!$show_correct_solution)) {
898  // get the solutions of a user
899  $user_solution = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
900  if (!is_array($user_solution)) {
901  $user_solution = array();
902  }
903  }
904 
905  include_once "./Services/UICore/classes/class.ilTemplate.php";
906  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", true, true, "Modules/TestQuestionPool");
907  $output = $this->object->getClozeTextForHTMLOutput();
908  $assClozeGapCombinationObject = new assClozeGapCombination();
909  $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
910 
911  foreach ($this->object->getGaps() as $gap_index => $gap) {
912  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", true, true, "Modules/TestQuestionPool");
913  $found = array();
914  foreach ($user_solution as $solutionarray) {
915  if ($solutionarray["value1"] == $gap_index) {
916  $found = $solutionarray;
917  }
918  }
919 
920  if ($active_id) {
921  if ($graphicalOutput) {
922  // output of ok/not ok icons for user entered solutions
923  $details = $this->object->calculateReachedPoints($active_id, $pass, true, true);
924  $check = $details[$gap_index];
925 
926  if (count($check_for_gap_combinations) != 0) {
927  $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
928  $custom_user_solution = array();
929  if (array_key_exists($gap_index, $gaps_used_in_combination)) {
930  $combination_id = $gaps_used_in_combination[$gap_index];
931  foreach ($gaps_used_in_combination as $key => $value) {
932  $a = 0;
933  if ($value == $combination_id) {
934  foreach ($user_solution as $solution_key => $solution_value) {
935  if ($solution_value['value1'] == $key) {
936  $result_row = array();
937  $result_row['gap_id'] = $solution_value['value1'];
938  $result_row['value'] = $solution_value['value2'];
939  array_push($custom_user_solution, $result_row);
940  }
941  }
942  }
943  }
944  $points_array = $this->object->calculateCombinationResult($custom_user_solution);
945  $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
946  if ($points_array[0] == $max_combination_points) {
947  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
948  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
949  } elseif ($points_array[0] > 0) {
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  } else {
957  if ($check["best"]) {
958  $gaptemplate->setCurrentBlock("icon_ok");
959  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
960  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
961  $gaptemplate->parseCurrentBlock();
962  } else {
963  $gaptemplate->setCurrentBlock("icon_not_ok");
964  if ($check["positive"]) {
965  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
966  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
967  } else {
968  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
969  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
970  }
971  $gaptemplate->parseCurrentBlock();
972  }
973  }
974  } else {
975  if ($check["best"]) {
976  $gaptemplate->setCurrentBlock("icon_ok");
977  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
978  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
979  $gaptemplate->parseCurrentBlock();
980  } else {
981  $gaptemplate->setCurrentBlock("icon_not_ok");
982  if ($check["positive"]) {
983  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
984  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
985  } else {
986  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
987  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
988  }
989  $gaptemplate->parseCurrentBlock();
990  }
991  }
992  }
993  }
994  $combination = null;
995  switch ($gap->getType()) {
996  case CLOZE_TEXT:
997  $solutiontext = "";
998  if (($active_id > 0) && (!$show_correct_solution)) {
999  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1000  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1001  $solutiontext .= "&nbsp;";
1002  }
1003  } else {
1004  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1005  }
1006  } else {
1007  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1008  }
1009  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1010  // fau: fixGapReplace - use replace function
1011  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1012 // fau.
1013  break;
1014  case CLOZE_SELECT:
1015  $solutiontext = "";
1016  if (($active_id > 0) && (!$show_correct_solution)) {
1017  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1018  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1019  $solutiontext .= "&nbsp;";
1020  }
1021  } else {
1022  $item = $gap->getItem($found["value2"]);
1023  if (is_object($item)) {
1024  $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1025  } else {
1026  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1027  $solutiontext .= "&nbsp;";
1028  }
1029  }
1030  }
1031  } else {
1032  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1033  }
1034  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1035  // fau: fixGapReplace - use replace function
1036  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1037 // fau.
1038  break;
1039  case CLOZE_NUMERIC:
1040  $solutiontext = "";
1041  if (($active_id > 0) && (!$show_correct_solution)) {
1042  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1043  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1044  $solutiontext .= "&nbsp;";
1045  }
1046  } else {
1047  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1048  }
1049  } else {
1050  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1051  }
1052  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1053  // fau: fixGapReplace - use replace function
1054  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1055 // fau.
1056  break;
1057  }
1058  }
1059 
1060  if ($show_question_text) {
1061  $template->setVariable(
1062  "QUESTIONTEXT",
1063  $this->object->getQuestionForHTMLOutput()
1064  );
1065  }
1066 
1067  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1068  // generate the question output
1069  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
1070  $questionoutput = $template->get();
1071 
1072  $feedback = '';
1073  if ($show_feedback) {
1074  if (!$this->isTestPresentationContext()) {
1075  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1076  $feedback .= strlen($fb) ? $fb : '';
1077  }
1078 
1079  $fb = $this->getSpecificFeedbackOutput(
1080  $this->object->fetchIndexedValuesFromValuePairs($user_solution)
1081  );
1082  $feedback .= strlen($fb) ? $fb : '';
1083  }
1084  if (strlen($feedback)) {
1085  $cssClass = (
1086  $this->hasCorrectSolution($active_id, $pass) ?
1088  );
1089 
1090  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1091  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
1092  }
1093 
1094  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1095 
1096  $solutionoutput = $solutiontemplate->get();
1097 
1098  if (!$show_question_only) {
1099  // get page object output
1100  $solutionoutput = $this->getILIASPage($solutionoutput);
1101  }
1102 
1103  return $solutionoutput;
1104  }
1105 
1112  protected function getBestSolutionText($gap, $gap_index, $gap_combinations)
1113  {
1114  $combination = null;
1115  foreach ((array) $gap_combinations as $combiGapSolRow) {
1116  if ($combiGapSolRow['gap_fi'] == $gap_index && $combiGapSolRow['best_solution']) {
1117  $combination = $combiGapSolRow;
1118  break;
1119  }
1120  }
1121  $best_solution_text = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1122  $this->object->getShuffler(),
1123  $combination
1124  ));
1125  return $best_solution_text;
1126  }
1127 
1128  public function getAnswerFeedbackOutput($active_id, $pass)
1129  {
1130  include_once "./Modules/Test/classes/class.ilObjTest.php";
1131  $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1132  if (strlen($manual_feedback)) {
1133  return $manual_feedback;
1134  }
1135  $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1136  $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1137  if (strlen($correct_feedback . $incorrect_feedback)) {
1138  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1139  $max_points = $this->object->getMaximumPoints();
1140  if ($reached_points == $max_points) {
1141  $output .= $correct_feedback;
1142  } else {
1143  $output .= $incorrect_feedback;
1144  }
1145  }
1146  $test = new ilObjTest($this->object->active_id);
1147  return $this->object->prepareTextareaOutput($output, true);
1148  }
1149 
1150  public function getTestOutput(
1151  $active_id,
1152  // hey: prevPassSolutions - will be always available from now on
1153  $pass,
1154  // hey.
1155  $is_postponed = false,
1156  $use_post_solutions = false,
1157  $show_feedback = false
1158  ) {
1159  // get the solution of the user for the active pass or from the last pass if allowed
1160  $user_solution = array();
1161  if ($use_post_solutions !== false) {
1162  $indexedSolution = $this->object->fetchSolutionSubmit($use_post_solutions);
1163  $user_solution = $this->object->fetchValuePairsFromIndexedValues($indexedSolution);
1164  } elseif ($active_id) {
1165  // hey: prevPassSolutions - obsolete due to central check
1166  #include_once "./Modules/Test/classes/class.ilObjTest.php";
1167  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1168  #{
1169  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1170  #}
1171  $user_solution = $this->object->getTestOutputSolutions($active_id, $pass);
1172  // hey.
1173  if (!is_array($user_solution)) {
1174  $user_solution = array();
1175  }
1176  }
1177 
1178  // generate the question output
1179  include_once "./Services/UICore/classes/class.ilTemplate.php";
1180  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
1181  $output = $this->object->getClozeTextForHTMLOutput();
1182  foreach ($this->object->getGaps() as $gap_index => $gap) {
1183  switch ($gap->getType()) {
1184  case CLOZE_TEXT:
1185  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
1186  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1187 
1188  if ($gap_size > 0) {
1189  $gaptemplate->setCurrentBlock('size_and_maxlength');
1190  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1191  $gaptemplate->parseCurrentBlock();
1192  }
1193 
1194  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1195  foreach ($user_solution as $solution) {
1196  if (strcmp($solution["value1"], $gap_index) == 0) {
1197  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1198  }
1199  }
1200  // fau: fixGapReplace - use replace function
1201  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1202 // fau.
1203  break;
1204  case CLOZE_SELECT:
1205  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
1206  foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $item) {
1207  $gaptemplate->setCurrentBlock("select_gap_option");
1208  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1209  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1210  foreach ($user_solution as $solution) {
1211  if (strcmp($solution["value1"], $gap_index) == 0) {
1212  if (strcmp($solution["value2"], $item->getOrder()) == 0) {
1213  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1214  }
1215  }
1216  }
1217  $gaptemplate->parseCurrentBlock();
1218  }
1219  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1220  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
1221  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1222 // fau.
1223  break;
1224  case CLOZE_NUMERIC:
1225  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
1226  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1227  if ($gap_size > 0) {
1228  $gaptemplate->setCurrentBlock('size_and_maxlength');
1229  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1230  $gaptemplate->parseCurrentBlock();
1231  }
1232 
1233  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1234  foreach ($user_solution as $solution) {
1235  if (strcmp($solution["value1"], $gap_index) == 0) {
1236  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1237  }
1238  }
1239  // fau: fixGapReplace - use replace function
1240  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1241 // fau.
1242  break;
1243  }
1244  }
1245 
1246  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
1247  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1248  $questionoutput = $template->get();
1249  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1250  return $pageoutput;
1251  }
1252 
1253  public function getSpecificFeedbackOutput($userSolution)
1254  {
1255  if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
1256  return '';
1257  }
1258 
1259  global $DIC;
1260  $lng = $DIC['lng'];
1261 
1262  $feedback = '<table class="test_specific_feedback"><tbody>';
1263 
1264  foreach ($this->object->gaps as $gapIndex => $gap) {
1265  $answerValue = $this->object->fetchAnswerValueForGap($userSolution, $gapIndex);
1266  $answerIndex = $this->object->feedbackOBJ->determineAnswerIndexForAnswerValue($gap, $answerValue);
1267  $fb = $this->object->feedbackOBJ->determineTestOutputGapFeedback($gapIndex, $answerIndex);
1268 
1269  $caption = $lng->txt('gap') . ' ' . ($gapIndex + 1) . ': ';
1270  $feedback .= '<tr><td>';
1271  $feedback .= $caption . '</td><td>';
1272  $feedback .= $fb . '</td> </tr>';
1273  }
1274  $feedback .= '</tbody></table>';
1275 
1276  return $this->object->prepareTextareaOutput($feedback, true);
1277  }
1278 
1289  {
1290  return array();
1291  }
1292 
1303  {
1304  return array();
1305  }
1306 
1315  public function getAggregatedAnswersView($relevant_answers)
1316  {
1317  $overview = array();
1318  $aggregation = array();
1319  foreach ($relevant_answers as $answer) {
1320  $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1321  }
1322 
1323  foreach ($overview as $active) {
1324  foreach ($active as $answer) {
1325  foreach ($answer as $option => $value) {
1326  $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1327  }
1328  }
1329  }
1330 
1331  $html = '<div>';
1332  $i = 0;
1333  foreach ($this->object->getGaps() as $gap_index => $gap) {
1334  if ($gap->type == CLOZE_SELECT) {
1335  $html .= '<p>Gap ' . ($i + 1) . ' - SELECT</p>';
1336  $html .= '<ul>';
1337  $j = 0;
1338  foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $gap_item) {
1339  $aggregate = $aggregation[$i];
1340  $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1341  $j++;
1342  }
1343  $html .= '</ul>';
1344  }
1345 
1346  if ($gap->type == CLOZE_TEXT) {
1347  $present_elements = array();
1348  foreach ($gap->getItems(new ilArrayElementShuffler()) as $item) {
1350  $present_elements[] = $item->getAnswertext();
1351  }
1352 
1353  $html .= '<p>Gap ' . ($i + 1) . ' - TEXT</p>';
1354  $html .= '<ul>';
1355  $aggregate = (array) $aggregation[$i];
1356  foreach ($aggregate as $answer => $count) {
1357  $show_mover = '';
1358  if (in_array($answer, $present_elements)) {
1359  $show_mover = ' style="display: none;" ';
1360  }
1361 
1362  $html .= '<li>' . $answer . ' - ' . $count
1363  . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="' . $answer . '" name="add_gap_' . $i . '_0">
1364  <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1365  </li>';
1366  }
1367  $html .= '</ul>';
1368  }
1369 
1370  if ($gap->type == CLOZE_NUMERIC) {
1371  $html .= '<p>Gap ' . ($i + 1) . ' - NUMERIC</p>';
1372  $html .= '<ul>';
1373  $j = 0;
1374  foreach ($gap->getItems($this->object->getShuffler(), $gap_index) as $gap_item) {
1375  $aggregate = (array) $aggregation[$i];
1376  foreach ($aggregate as $answer => $count) {
1377  $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1378  }
1379  $j++;
1380  }
1381  $html .= '</ul>';
1382  }
1383  $i++;
1384  $html .= '<hr />';
1385  }
1386 
1387  $html .= '</div>';
1388  return $html;
1389  }
1390 
1391  public function applyIndizesToGapText($question_text)
1392  {
1393  $parts = explode('[gap', $question_text);
1394  $i = 0;
1395  $question_text = '';
1396  foreach ($parts as $part) {
1397  if ($i == 0) {
1398  $question_text .= $part;
1399  } else {
1400  $question_text .= '[gap ' . $i . $part;
1401  }
1402  $i++;
1403  }
1404  return $question_text;
1405  }
1406 
1407  public function removeIndizesFromGapText($question_text)
1408  {
1409  $parts = preg_split('/\[gap \d*\]/', $question_text);
1410  $question_text = implode('[gap]', $parts);
1411  return $question_text;
1412  }
1413 
1418  private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
1419  {
1420  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
1421  $gaptemplate->setCurrentBlock('gap_span');
1422  $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1423  } elseif ($gap->getType() == CLOZE_SELECT) {
1424  $gaptemplate->setCurrentBlock('gap_select');
1425  $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1426  } else {
1427  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1428 
1429  if ($gap_size > 0) {
1430  $gaptemplate->setCurrentBlock('gap_size');
1431  $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1432  $gaptemplate->parseCurrentBlock();
1433  }
1434 
1435  $gaptemplate->setCurrentBlock('gap_input');
1436  $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1437  }
1438 
1439 
1440  $gaptemplate->parseCurrentBlock();
1441  }
1442 
1443  protected function hasAddAnswerAction($relevantAnswers, $questionIndex)
1444  {
1445  foreach ($this->getAnswersFrequency($relevantAnswers, $questionIndex) as $answer) {
1446  if (isset($answer['actions'])) {
1447  return true;
1448  }
1449  }
1450 
1451  return false;
1452  }
1453 
1454  public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
1455  {
1456  global $DIC; /* @var ILIAS\DI\Container $DIC */
1457 
1458  $table = parent::getAnswerFrequencyTableGUI(
1459  $parentGui,
1460  $parentCmd,
1461  $relevantAnswers,
1462  $questionIndex
1463  );
1464 
1465  $table->setTitle(sprintf(
1466  $DIC->language()->txt('tst_corrections_answers_tbl_subindex'),
1467  $DIC->language()->txt('gap') . ' ' . ($questionIndex + 1)
1468  ));
1469 
1470  if ($this->hasAddAnswerAction($relevantAnswers, $questionIndex)) {
1471  $table->addColumn('', '', '200');
1472  }
1473 
1474  return $table;
1475  }
1476 
1477  public function getSubQuestionsIndex()
1478  {
1479  return array_keys($this->object->getGaps());
1480  }
1481 
1482  protected function getAnswerTextLabel($gapIndex, $answer)
1483  {
1484  $gap = $this->object->getGap($gapIndex);
1485 
1486  switch ($gap->type) {
1487  case CLOZE_NUMERIC:
1488  case CLOZE_TEXT:
1489  return $answer;
1490 
1491  case CLOZE_SELECT:
1492 
1493  $items = $gap->getItems(new ilArrayElementOrderKeeper());
1494  return $items[$answer]->getAnswertext();
1495  }
1496  }
1497 
1498  protected function completeAddAnswerAction($answers, $questionIndex)
1499  {
1500  $gap = $this->object->getGap($questionIndex);
1501 
1502  if ($gap->type != CLOZE_TEXT) {
1503  return $answers;
1504  }
1505 
1506  foreach ($answers as $key => $ans) {
1507  $found = false;
1508 
1509  foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $item) {
1510  if ($ans['answer'] !== $item->getAnswerText()) {
1511  continue;
1512  }
1513 
1514  $found = true;
1515  break;
1516  }
1517 
1518  if (!$found) {
1519  $answers[$key]['addable'] = true;
1520  }
1521  }
1522 
1523  return $answers;
1524  }
1525 
1526  public function getAnswersFrequency($relevant_answers, $questionIndex)
1527  {
1528  $answers = array();
1529 
1530  foreach ($relevant_answers as $row) {
1531  if ($row['value1'] != $questionIndex) {
1532  continue;
1533  }
1534 
1535  if (!isset($answers[$row['value2']])) {
1536  $label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
1537 
1538  $answers[$row['value2']] = array(
1539  'answer' => $label, 'frequency' => 0
1540  );
1541  }
1542 
1543  $answers[$row['value2']]['frequency']++;
1544  }
1545 
1546  $answers = $this->completeAddAnswerAction($answers, $questionIndex);
1547 
1548  return $answers;
1549  }
1550 
1551  protected function isUsedInCombinations($gapIndex)
1552  {
1553  foreach ($this->object->getGapCombinations() as $combination) {
1554  if ($combination['gap_fi'] != $gapIndex) {
1555  continue;
1556  }
1557 
1558  return true;
1559  }
1560 
1561  return false;
1562  }
1563 
1564  protected function getGapCombinations()
1565  {
1566  $combinations = array();
1567 
1568  foreach ($this->object->getGapCombinations() as $c) {
1569  if (!isset($combinations[$c['cid']])) {
1570  $combinations[$c['cid']] = array();
1571  }
1572 
1573  if (!isset($combinations[$c['cid']][$c['row_id']])) {
1574  $combinations[$c['cid']][$c['row_id']] = array(
1575  'gaps' => array(), 'points' => $c['points'],
1576  );
1577  }
1578 
1579  if (!isset($combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']])) {
1580  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = array();
1581  }
1582 
1583  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = $c['answer'];
1584  }
1585 
1586  return $combinations;
1587  }
1588 
1590  {
1591  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1593  $form,
1594  $gap,
1595  $gapIndex,
1596  $this->isUsedInCombinations($gapIndex)
1597  );
1598  }
1599 
1600  if ($this->object->getGapCombinationsExists()) {
1601  foreach ($this->getGapCombinations() as $combiIndex => $gapCombination) {
1602  $this->populateGapCombinationCorrectionFormProperty($form, $gapCombination, $combiIndex);
1603  }
1604  }
1605  }
1606 
1607  protected function populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex)
1608  {
1609  $header = new ilFormSectionHeaderGUI();
1610  $header->setTitle("Gap Combination " . ($combiIndex + 1));
1611  $form->addItem($header);
1612 
1613  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php';
1614  $inp = new ilAssClozeTestCombinationVariantsInputGUI('Answers', 'combination_' . $combiIndex);
1615  $inp->setValues($gapCombi);
1616  $form->addItem($inp);
1617  }
1618 
1624  protected function populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints)
1625  {
1626  $header = new ilFormSectionHeaderGUI();
1627  $header->setTitle($this->lng->txt("gap") . " " . ($gapIndex + 1));
1628  $form->addItem($header);
1629 
1630  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1631  $this->populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints);
1632  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1633  foreach ($gap->getItemsRaw() as $item) {
1634  $this->populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints);
1635  }
1636  }
1637  }
1638 
1639  protected function populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
1640  {
1641  require_once "Modules/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php";
1642  $values = new ilAssAnswerCorrectionsInputGUI($this->lng->txt("values"), "gap_" . $gapIndex);
1643  $values->setHidePointsEnabled($hidePoints);
1644  $values->setRequired(true);
1645  $values->setQuestionObject($this->object);
1646  $values->setValues($gap->getItemsRaw());
1647  $form->addItem($values);
1648  }
1649 
1650  protected function populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints)
1651  {
1652  $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapIndex . "_numeric");
1653  $value->allowDecimals(true);
1654  $value->setSize(10);
1655  $value->setValue(ilUtil::prepareFormOutput($item->getAnswertext()));
1656  $value->setRequired(true);
1657  $form->addItem($value);
1658 
1659  $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapIndex . "_numeric_lower");
1660  $lowerbound->allowDecimals(true);
1661  $lowerbound->setSize(10);
1662  $lowerbound->setRequired(true);
1663  $lowerbound->setValue(ilUtil::prepareFormOutput($item->getLowerBound()));
1664  $form->addItem($lowerbound);
1665 
1666  $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapIndex . "_numeric_upper");
1667  $upperbound->allowDecimals(true);
1668  $upperbound->setSize(10);
1669  $upperbound->setRequired(true);
1670  $upperbound->setValue(ilUtil::prepareFormOutput($item->getUpperBound()));
1671  $form->addItem($upperbound);
1672 
1673  if (!$hidePoints) {
1674  $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapIndex . "_numeric_points");
1675  $points->allowDecimals(true);
1676  $points->setSize(3);
1677  $points->setRequired(true);
1678  $points->setValue(ilUtil::prepareFormOutput($item->getPoints()));
1679  $form->addItem($points);
1680  }
1681  }
1682 
1687  {
1688  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1689  if ($this->isUsedInCombinations($gapIndex)) {
1690  continue;
1691  }
1692 
1693  $this->saveGapCorrectionFormProperty($form, $gap, $gapIndex);
1694  }
1695 
1696  if ($this->object->getGapCombinationsExists()) {
1698  }
1699  }
1700 
1702  {
1703  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1705  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1706  foreach ($gap->getItemsRaw() as $item) {
1707  $this->saveNumericGapCorrectionFormProperty($form, $item, $gapIndex);
1708  }
1709  }
1710  }
1711 
1713  {
1714  $answers = $form->getItemByPostVar('gap_' . $gapIndex)->getValues();
1715 
1716  foreach ($gap->getItemsRaw() as $index => $item) {
1717  $item->setPoints((float) $answers[$index]->getPoints());
1718  }
1719  }
1720 
1722  {
1723  $item->setAnswertext($form->getInput('gap_' . $gapIndex . '_numeric'));
1724  $item->setLowerBound($form->getInput('gap_' . $gapIndex . '_numeric_lower'));
1725  $item->setUpperBound($form->getInput('gap_' . $gapIndex . '_numeric_upper'));
1726  $item->setPoints($form->getInput('gap_' . $gapIndex . '_numeric_points'));
1727  }
1728 
1730  {
1731  // please dont ask (!) -.-
1732 
1733  $combinationPoints = array('points' => array(), 'select' => array());
1734  $combinationValues = array();
1735 
1736  foreach ($this->getGapCombinations() as $combiId => $combi) {
1737  $values = $form->getItemByPostVar('combination_' . $combiId)->getValues();
1738 
1739  if (!isset($combinationPoints['points'][$combiId])) {
1740  $combinationPoints['points'][$combiId] = array();
1741  $combinationPoints['select'][$combiId] = array();
1742  $combinationValues[$combiId] = array();
1743  }
1744 
1745  foreach ($combi as $varId => $variant) {
1746  $combinationPoints['points'][$combiId][$varId] = (float) $values[$varId]['points'];
1747  $combinationPoints['select'][$combiId] = array_keys($values[$varId]['gaps']);
1748  $combinationValues[$combiId][$varId] = array_values($values[$varId]['gaps']);
1749  }
1750  }
1751 
1752  $combinationPoints = $combinationPoints;
1753  $combinationValues = $combinationValues;
1754 
1755  $assClozeGapCombinationObject = new assClozeGapCombination();
1756  $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
1757 
1758  $assClozeGapCombinationObject->saveGapCombinationToDb(
1759  $this->object->getId(),
1760  $combinationPoints,
1761  $combinationValues
1762  );
1763  }
1764 }
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)
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.
$c
Definition: cli.php:37
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
setUpperBound($bound)
Sets the upper bound.
$errors
Definition: imgupload.php:49
This class represents a property form user interface.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
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.
setValue($a_value)
Set Value.
escapeTemplatePlaceholders(string $text)
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.
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.
$index
Definition: metadata.php:128
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)
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.
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 feedback comment for a question in a test if it is finalized.
setValue($a_value)
Set Value.
writePostData($always=false)
{}
populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
global $DIC
Definition: goto.php:24
saveTextOrSelectGapCorrectionFormProperty(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
populateGapSizeFormPart($form, $gap, $gapCounter)
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.
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
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
applyIndizesToGapText($question_text)
__construct(Container $dic, ilPlugin $plugin)
This class represents a text area property in a property form.
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
constant for additional content editing mode "default"
setAnswertext($answertext="")
Sets the answer text.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
getType()
Gets the cloze gap type.
setInlineStyle($a_style)
Set inline style.
Interface ilGuiAnswerScoringAdjustable.
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.
getPreview($show_question_only=false, $showInlineFeedback=false)
Creates a preview output of the question.
$_POST["username"]
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
setRequired($a_required)
Set Required.
removeIndizesFromGapText($question_text)
getAnswerTextLabel($gapIndex, $answer)
$i
Definition: metadata.php:24
$test
Definition: Utf8Test.php:84
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.