ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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 
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)
243  $this->addBasicQuestionFormProperties($form);
244  $this->populateQuestionSpecificFormPart($form);
245  $this->populateAnswerSpecificFormPart($form);
246  $this->populateTaxonomyFormSection($form);
247 
248  $this->addQuestionFormCommandButtons($form);
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 
268  public function addBasicQuestionFormProperties($form)
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  // lifecycle
301  $lifecycle = new ilSelectInputGUI($this->lng->txt('qst_lifecycle'), 'lifecycle');
302  $lifecycle->setOptions($this->object->getLifecycle()->getSelectOptions($this->lng));
303  $lifecycle->setValue($this->object->getLifecycle()->getIdentifier());
304  $form->addItem($lifecycle);
305 
306  // questiontext
307  $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
308  $question->setValue($this->object->prepareTextareaOutput($this->object->getQuestion()));
309  $question->setRequired(true);
310  $question->setRows(10);
311  $question->setCols(80);
312  if (!$this->object->getSelfAssessmentEditingMode()) {
313  if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
314  $question->setUseRte(true);
315  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
316  $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
317  $question->addPlugin("latex");
318  $question->addButton("latex");
319  $question->addButton("pastelatex");
320  $question->setRTESupport($this->object->getId(), "qpl", "assessment");
321  }
322  } else {
323  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
325  $question->setUseTagsForRteOnly(false);
326  }
327  $form->addItem($question);
328 
329  // $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
330  // $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
331  // $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
332  // $tpl->parseCurrentBlock();
333  // $button = new ilCustomInputGUI('&nbsp;','');
334  // $button->setHtml($tpl->get());
335  // $form->addItem($button);
336 
337  if (!$this->object->getSelfAssessmentEditingMode()) {
338  // duration
339  $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
340  $duration->setShowHours(true);
341  $duration->setShowMinutes(true);
342  $duration->setShowSeconds(true);
343  $ewt = $this->object->getEstimatedWorkingTime();
344  $duration->setHours($ewt["h"]);
345  $duration->setMinutes($ewt["m"]);
346  $duration->setSeconds($ewt["s"]);
347  $duration->setRequired(false);
348  $form->addItem($duration);
349  } else {
350  // number of tries
351  if (strlen($this->object->getNrOfTries())) {
352  $nr_tries = $this->object->getNrOfTries();
353  } else {
354  $nr_tries = $this->object->getDefaultNrOfTries();
355  }
356  /*if ($nr_tries <= 0)
357  {
358  $nr_tries = 1;
359  }*/
360 
361  if ($nr_tries < 0) {
362  $nr_tries = 0;
363  }
364 
365  $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
366  $ni->setValue($nr_tries);
367  //$ni->setMinValue(1);
368  $ni->setMinValue(0);
369  $ni->setSize(5);
370  $ni->setMaxLength(5);
371  $ni->setRequired(true);
372  $form->addItem($ni);
373  }
374  }
375 
377  {
378  // cloze text
379  $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
380  $cloze_text->setRequired(true);
381  $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
382  $cloze_text->setInfo($this->lng->txt("close_text_hint"));
383  $cloze_text->setRows(10);
384  $cloze_text->setCols(80);
385  if (!$this->object->getSelfAssessmentEditingMode()) {
386  if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT) {
387  $cloze_text->setUseRte(true);
388  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
389  $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
390  $cloze_text->addPlugin("latex");
391  $cloze_text->addButton("latex");
392  $cloze_text->addButton("pastelatex");
393  }
394  } else {
395  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
397  $cloze_text->setUseTagsForRteOnly(false);
398  }
399  $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
400  $form->addItem($cloze_text);
401 
402  $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", true, true, "Modules/TestQuestionPool");
403 
404  $button = new ilCustomInputGUI('&nbsp;', '');
405  require_once 'Services/UIComponent/SplitButton/classes/class.ilSplitButtonGUI.php';
406  require_once 'Services/UIComponent/Button/classes/class.ilJsLinkButton.php';
407  $action_button = ilSplitButtonGUI::getInstance();
408 
409  $sb_text_gap = ilJsLinkButton::getInstance();
410  $sb_text_gap->setCaption('text_gap');
411  $sb_text_gap->setName('gapbutton');
412  $sb_text_gap->setId('gaptrigger_text');
413  $action_button->setDefaultButton($sb_text_gap);
414 
415  $sb_sel_gap = ilJsLinkButton::getInstance();
416  $sb_sel_gap->setCaption('select_gap');
417  $sb_sel_gap->setName('gapbutton_select');
418  $sb_sel_gap->setId('gaptrigger_select');
419  $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_sel_gap));
420 
421  $sb_num_gap = ilJsLinkButton::getInstance();
422  $sb_num_gap->setCaption('numeric_gap');
423  $sb_num_gap->setName('gapbutton_numeric');
424  $sb_num_gap->setId('gaptrigger_numeric');
425  $action_button->addMenuItem(new ilButtonToSplitButtonMenuItemAdapter($sb_num_gap));
426 
427  $tpl->setVariable('BUTTON', $action_button->render());
428  $tpl->parseCurrentBlock();
429 
430  $button->setHtml($tpl->get());
431  $form->addItem($button);
432 
433  // text rating
434  if (!$this->object->getSelfAssessmentEditingMode()) {
435  $textrating = new ilSelectInputGUI($this->lng->txt("text_rating"), "textgap_rating");
436  $text_options = array(
437  "ci" => $this->lng->txt("cloze_textgap_case_insensitive"),
438  "cs" => $this->lng->txt("cloze_textgap_case_sensitive"),
439  "l1" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "1"),
440  "l2" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "2"),
441  "l3" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "3"),
442  "l4" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "4"),
443  "l5" => sprintf($this->lng->txt("cloze_textgap_levenshtein_of"), "5")
444  );
445  $textrating->setOptions($text_options);
446  $textrating->setValue($this->object->getTextgapRating());
447  $form->addItem($textrating);
448 
449  // text field length
450  $fixedTextLength = new ilNumberInputGUI($this->lng->txt("cloze_fixed_textlength"), "fixedTextLength");
451  $ftl = $this->object->getFixedTextLength();
452 
453  $fixedTextLength->setValue($ftl > 0 ? $ftl : '');
454  $fixedTextLength->setMinValue(0);
455  $fixedTextLength->setSize(3);
456  $fixedTextLength->setMaxLength(6);
457  $fixedTextLength->setInfo($this->lng->txt('cloze_fixed_textlength_description'));
458  $fixedTextLength->setRequired(false);
459  $form->addItem($fixedTextLength);
460 
461  // identical scoring
462  $identical_scoring = new ilCheckboxInputGUI($this->lng->txt("identical_scoring"), "identical_scoring");
463  $identical_scoring->setValue(1);
464  $identical_scoring->setChecked($this->object->getIdenticalScoring());
465  $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
466  $identical_scoring->setRequired(false);
467  $form->addItem($identical_scoring);
468  }
469  return $form;
470  }
471 
473  {
474  if (self::OLD_CLOZE_TEST_UI) {
475  for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++) {
476  $this->populateGapFormPart($form, $gapCounter);
477  }
478  return $form;
479  } else {
480  require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
481  $json = $this->populateJSON();
482  $assClozeGapCombinationObject = new assClozeGapCombination();
483  $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->id);
484  if ($combination_exists) {
485  $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->id);
486  }
487  $new_builder = new ilClozeGapInputBuilderGUI();
488  $header = new ilFormSectionHeaderGUI();
489  $form->addItem($header);
490  $new_builder->setValueByArray($json);
491  $new_builder->setValueCombinationFromDb($combinations);
492  $form->addItem($new_builder);
493  return $form;
494  }
495  }
496 
497  protected function populateJSON()
498  {
499  $gap = $this->object->getGaps();
500  $array = array();
501  if ($gap == null) {
502  return $array;
503  }
504  $translate_type = array('text','select','numeric');
505  $i = 0;
506  foreach ($gap as $content) {
507  $shuffle = false;
508  $value = $content->getItemsRaw();
509  $items = array();
510  for ($j = 0;$j < count($value);$j++) {
511  if ($content->getType() == 2) {
512  $items[$j] = array(
513  'answer' => $value[$j]->getAnswerText(),
514  'lower' => $value[$j]->getLowerBound(),
515  'upper' => $value[$j]->getUpperBound(),
516  'points' => $value[$j]->getPoints(),
517  'error' => false
518  );
519  } else {
520  $items[$j] = array(
521  'answer' => $value[$j]->getAnswerText(),
522  'points' => $value[$j]->getPoints(),
523  'error' => false
524  );
525 
526  if ($content->getType() == 1) {
527  $shuffle = $content->getShuffle();
528  }
529  }
530  }
531  $answers[$i] = array(
532  'type' => $translate_type[$content->getType()] ,
533  'values' => $items ,
534  'shuffle' => $shuffle,
535  'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
536  'used_in_gap_combination' => true);
537  $i++;
538  }
539  return $answers;
540  }
552  protected function populateGapFormPart($form, $gapCounter)
553  {
554  $gap = $this->object->getGap($gapCounter);
555 
556  if ($gap == null) {
557  return $form;
558  }
559 
560  $header = new ilFormSectionHeaderGUI();
561  $header->setTitle($this->lng->txt("gap") . " " . ($gapCounter + 1));
562  $form->addItem($header);
563 
564  $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
565  $gapcounter->setValue($gapCounter);
566  $form->addItem($gapcounter);
567 
568  $gaptype = new ilSelectInputGUI($this->lng->txt('type'), "clozetype_$gapCounter");
569  $options = array(
570  0 => $this->lng->txt("text_gap"),
571  1 => $this->lng->txt("select_gap"),
572  2 => $this->lng->txt("numeric_gap")
573  );
574  $gaptype->setOptions($options);
575  $gaptype->setValue($gap->getType());
576  $form->addItem($gaptype);
577 
578  if ($gap->getType() == CLOZE_TEXT) {
579  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
580 
581  if (count($gap->getItemsRaw()) == 0) {
582  $gap->addItem(new assAnswerCloze("", 0, 0));
583  }
584  $this->populateTextGapFormPart($form, $gap, $gapCounter);
585  } elseif ($gap->getType() == CLOZE_SELECT) {
586  if (count($gap->getItemsRaw()) == 0) {
587  $gap->addItem(new assAnswerCloze("", 0, 0));
588  }
589  $this->populateSelectGapFormPart($form, $gap, $gapCounter);
590  } elseif ($gap->getType() == CLOZE_NUMERIC) {
591  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
592 
593  if (count($gap->getItemsRaw()) == 0) {
594  $gap->addItem(new assAnswerCloze("", 0, 0));
595  }
596  foreach ($gap->getItemsRaw() as $item) {
597  $this->populateNumericGapFormPart($form, $item, $gapCounter);
598  }
599  }
600  return $form;
601  }
602 
608  protected function populateGapSizeFormPart($form, $gap, $gapCounter)
609  {
610  $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_" . $gapCounter . '_gapsize');
611 
612  $gapSizeFormItem->allowDecimals(false);
613  $gapSizeFormItem->setMinValue(0);
614  $gapSizeFormItem->setSize(3);
615  $gapSizeFormItem->setMaxLength(6);
616  $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
617  $gapSizeFormItem->setValue($gap->getGapSize());
618  $form->addItem($gapSizeFormItem);
619 
620  return $form;
621  }
622 
635  protected function populateSelectGapFormPart($form, $gap, $gapCounter)
636  {
637  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
638  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
639  $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
640  $values->setRequired(true);
641  $values->setQuestionObject($this->object);
642  $values->setSingleline(true);
643  $values->setAllowMove(false);
644 
645  $values->setValues($gap->getItemsRaw());
646  $form->addItem($values);
647 
648  // shuffle
649  $shuffle = new ilCheckboxInputGUI($this->lng->txt("shuffle_answers"), "shuffle_" . $gapCounter . "");
650  $shuffle->setValue(1);
651  $shuffle->setChecked($gap->getShuffle());
652  $shuffle->setRequired(false);
653  $form->addItem($shuffle);
654  return $form;
655  }
656 
668  protected function populateTextGapFormPart($form, $gap, $gapCounter)
669  {
670  // Choices
671  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
672  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
673  $values = new ilAnswerWizardInputGUI($this->lng->txt("values"), "gap_" . $gapCounter . "");
674  $values->setRequired(true);
675  $values->setQuestionObject($this->object);
676  $values->setSingleline(true);
677  $values->setAllowMove(false);
678  $values->setValues($gap->getItemsRaw());
679  $form->addItem($values);
680 
681  if ($this->object->getFixedTextLength() > 0) {
682  $values->setSize($this->object->getFixedTextLength());
683  $values->setMaxLength($this->object->getFixedTextLength());
684  }
685 
686  return $form;
687  }
688 
700  protected function populateNumericGapFormPart($form, $gap, $gapCounter)
701  {
702  // #8944: the js-based ouput in self-assessment cannot support formulas
703  if (!$this->object->getSelfAssessmentEditingMode()) {
704  $value = new ilFormulaInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
705  $value->setInlineStyle('text-align: right;');
706 
707  $lowerbound = new ilFormulaInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
708  $lowerbound->setInlineStyle('text-align: right;');
709 
710  $upperbound = new ilFormulaInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
711  $upperbound->setInlineStyle('text-align: right;');
712  } else {
713  $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapCounter . "_numeric");
714  $value->allowDecimals(true);
715 
716  $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
717  $lowerbound->allowDecimals(true);
718 
719  $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
720  $upperbound->allowDecimals(true);
721  }
722 
723  $value->setSize(10);
724  $value->setValue(ilUtil::prepareFormOutput($gap->getAnswertext()));
725  $value->setRequired(true);
726  $form->addItem($value);
727 
728  $lowerbound->setSize(10);
729  $lowerbound->setRequired(true);
730  $lowerbound->setValue(ilUtil::prepareFormOutput($gap->getLowerBound()));
731  $form->addItem($lowerbound);
732 
733  $upperbound->setSize(10);
734  $upperbound->setRequired(true);
735  $upperbound->setValue(ilUtil::prepareFormOutput($gap->getUpperBound()));
736  $form->addItem($upperbound);
737 
738  if ($this->object->getFixedTextLength() > 0) {
739  $value->setSize($this->object->getFixedTextLength());
740  $value->setMaxLength($this->object->getFixedTextLength());
741  $lowerbound->setSize($this->object->getFixedTextLength());
742  $lowerbound->setMaxLength($this->object->getFixedTextLength());
743  $upperbound->setSize($this->object->getFixedTextLength());
744  $upperbound->setMaxLength($this->object->getFixedTextLength());
745  }
746 
747  $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapCounter . "_numeric_points");
748  $points->allowDecimals(true);
749  $points->setSize(3);
750  $points->setRequired(true);
751  $points->setValue(ilUtil::prepareFormOutput($gap->getPoints()));
752  $form->addItem($points);
753  return $form;
754  }
755 
759  public function createGaps()
760  {
761  $this->writePostData(true);
762  $this->object->saveToDb();
763  $this->editQuestion();
764  }
765 
769  public function removegap()
770  {
771  $this->writePostData(true);
772  $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
773  $this->editQuestion();
774  }
775 
779  public function addgap()
780  {
781  $this->writePostData(true);
782  $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex]) + 1, "");
783  $this->editQuestion();
784  }
785 
794  public function getPreview($show_question_only = false, $showInlineFeedback = false)
795  {
796  $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
797 
798  // generate the question output
799  include_once "./Services/UICore/classes/class.ilTemplate.php";
800  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
801  $output = $this->object->getClozeText();
802  foreach ($this->object->getGaps() as $gap_index => $gap) {
803  switch ($gap->getType()) {
804  case CLOZE_TEXT:
805  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
806 
807  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
808  if ($gap_size > 0) {
809  $gaptemplate->setCurrentBlock('size_and_maxlength');
810  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
811  $gaptemplate->parseCurrentBlock();
812  }
813  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
814  foreach ($user_solution as $val1 => $val2) {
815  if (strcmp($val1, $gap_index) == 0) {
816  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
817  }
818  }
819  // fau: fixGapReplace - use replace function
820  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
821 // fau.
822  break;
823  case CLOZE_SELECT:
824  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
825  foreach ($gap->getItems($this->object->getShuffler()) as $item) {
826  $gaptemplate->setCurrentBlock("select_gap_option");
827  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
828  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
829  foreach ($user_solution as $val1 => $val2) {
830  if (strcmp($val1, $gap_index) == 0) {
831  if (strcmp($val2, $item->getOrder()) == 0) {
832  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
833  }
834  }
835  }
836  $gaptemplate->parseCurrentBlock();
837  }
838  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
839  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
840  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
841 // fau.
842  break;
843  case CLOZE_NUMERIC:
844  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
845  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
846  if ($gap_size > 0) {
847  $gaptemplate->setCurrentBlock('size_and_maxlength');
848  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
849  $gaptemplate->parseCurrentBlock();
850  }
851  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
852  foreach ($user_solution as $val1 => $val2) {
853  if (strcmp($val1, $gap_index) == 0) {
854  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
855  }
856  }
857  // fau: fixGapReplace - use replace function
858  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
859 // fau.
860  break;
861  }
862  }
863  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
864  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
865  $questionoutput = $template->get();
866  if (!$show_question_only) {
867  // get page object output
868  $questionoutput = $this->getILIASPage($questionoutput);
869  }
870  return $questionoutput;
871  }
872 
879  {
880  return true;
881  }
882 
898  public function getSolutionOutput(
899  $active_id,
900  $pass = null,
901  $graphicalOutput = false,
902  $result_output = false,
903  $show_question_only = true,
904  $show_feedback = false,
905  $show_correct_solution = false,
906  $show_manual_scoring = false,
907  $show_question_text = true
908  ) {
909  // get the solution of the user for the active pass or from the last pass if allowed
910  $user_solution = array();
911  if (($active_id > 0) && (!$show_correct_solution)) {
912  // get the solutions of a user
913  $user_solution = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
914  if (!is_array($user_solution)) {
915  $user_solution = array();
916  }
917  }
918 
919  include_once "./Services/UICore/classes/class.ilTemplate.php";
920  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", true, true, "Modules/TestQuestionPool");
921  $output = $this->object->getClozeText();
922  $assClozeGapCombinationObject = new assClozeGapCombination();
923  $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
924 
925  foreach ($this->object->getGaps() as $gap_index => $gap) {
926  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", true, true, "Modules/TestQuestionPool");
927  $found = array();
928  foreach ($user_solution as $solutionarray) {
929  if ($solutionarray["value1"] == $gap_index) {
930  $found = $solutionarray;
931  }
932  }
933 
934  if ($active_id) {
935  if ($graphicalOutput) {
936  // output of ok/not ok icons for user entered solutions
937  $details = $this->object->calculateReachedPoints($active_id, $pass, true, true);
938  $check = $details[$gap_index];
939 
940  if (count($check_for_gap_combinations) != 0) {
941  $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
942  $custom_user_solution = array();
943  if (array_key_exists($gap_index, $gaps_used_in_combination)) {
944  $combination_id = $gaps_used_in_combination[$gap_index];
945  foreach ($gaps_used_in_combination as $key => $value) {
946  $a = 0;
947  if ($value == $combination_id) {
948  foreach ($user_solution as $solution_key => $solution_value) {
949  if ($solution_value['value1'] == $key) {
950  $result_row = array();
951  $result_row['gap_id'] = $solution_value['value1'];
952  $result_row['value'] = $solution_value['value2'];
953  array_push($custom_user_solution, $result_row);
954  }
955  }
956  }
957  }
958  $points_array = $this->object->calculateCombinationResult($custom_user_solution);
959  $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
960  if ($points_array[0] == $max_combination_points) {
961  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
962  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
963  } elseif ($points_array[0] > 0) {
964  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
965  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
966  } else {
967  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
968  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
969  }
970  } else {
971  if ($check["best"]) {
972  $gaptemplate->setCurrentBlock("icon_ok");
973  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
974  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
975  $gaptemplate->parseCurrentBlock();
976  } else {
977  $gaptemplate->setCurrentBlock("icon_not_ok");
978  if ($check["positive"]) {
979  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
980  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
981  } else {
982  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
983  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
984  }
985  $gaptemplate->parseCurrentBlock();
986  }
987  }
988  } else {
989  if ($check["best"]) {
990  $gaptemplate->setCurrentBlock("icon_ok");
991  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
992  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
993  $gaptemplate->parseCurrentBlock();
994  } else {
995  $gaptemplate->setCurrentBlock("icon_not_ok");
996  if ($check["positive"]) {
997  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
998  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
999  } else {
1000  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1001  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1002  }
1003  $gaptemplate->parseCurrentBlock();
1004  }
1005  }
1006  }
1007  }
1008  if ($result_output) {
1009  $points = $this->object->getMaximumGapPoints($gap_index);
1010  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
1011  $gaptemplate->setCurrentBlock("result_output");
1012  $gaptemplate->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
1013  $gaptemplate->parseCurrentBlock();
1014  }
1015  $combination = null;
1016  switch ($gap->getType()) {
1017  case CLOZE_TEXT:
1018  $solutiontext = "";
1019  if (($active_id > 0) && (!$show_correct_solution)) {
1020  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1021  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1022  $solutiontext .= "&nbsp;";
1023  }
1024  } else {
1025  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1026  }
1027  } else {
1028  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1029  }
1030  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1031  // fau: fixGapReplace - use replace function
1032  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1033 // fau.
1034  break;
1035  case CLOZE_SELECT:
1036  $solutiontext = "";
1037  if (($active_id > 0) && (!$show_correct_solution)) {
1038  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1039  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1040  $solutiontext .= "&nbsp;";
1041  }
1042  } else {
1043  $item = $gap->getItem($found["value2"]);
1044  if (is_object($item)) {
1045  $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1046  } else {
1047  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1048  $solutiontext .= "&nbsp;";
1049  }
1050  }
1051  }
1052  } else {
1053  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1054  }
1055  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1056  // fau: fixGapReplace - use replace function
1057  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1058 // fau.
1059  break;
1060  case CLOZE_NUMERIC:
1061  $solutiontext = "";
1062  if (($active_id > 0) && (!$show_correct_solution)) {
1063  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0)) {
1064  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++) {
1065  $solutiontext .= "&nbsp;";
1066  }
1067  } else {
1068  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1069  }
1070  } else {
1071  $solutiontext = $this-> getBestSolutionText($gap, $gap_index, $check_for_gap_combinations);
1072  }
1073  $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1074  // fau: fixGapReplace - use replace function
1075  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1076 // fau.
1077  break;
1078  }
1079  }
1080 
1081  if ($show_question_text) {
1082  $template->setVariable(
1083  "QUESTIONTEXT",
1084  $this->object->prepareTextareaOutput($this->object->getQuestion(), true)
1085  );
1086  }
1087 
1088  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1089  // generate the question output
1090  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
1091  $questionoutput = $template->get();
1092 
1093  $feedback = '';
1094  if ($show_feedback) {
1095  if (!$this->isTestPresentationContext()) {
1096  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1097  $feedback .= strlen($fb) ? $fb : '';
1098  }
1099 
1100  $fb = $this->getSpecificFeedbackOutput(
1101  $this->object->fetchIndexedValuesFromValuePairs($user_solution)
1102  );
1103  $feedback .= strlen($fb) ? $fb : '';
1104  }
1105  if (strlen($feedback)) {
1106  $cssClass = (
1107  $this->hasCorrectSolution($active_id, $pass) ?
1109  );
1110 
1111  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1112  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
1113  }
1114 
1115  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1116 
1117  $solutionoutput = $solutiontemplate->get();
1118 
1119  if (!$show_question_only) {
1120  // get page object output
1121  $solutionoutput = $this->getILIASPage($solutionoutput);
1122  }
1123 
1124  return $solutionoutput;
1125  }
1126 
1133  protected function getBestSolutionText($gap, $gap_index, $gap_combinations)
1134  {
1135  $combination = null;
1136  foreach ((array) $gap_combinations as $combiGapSolRow) {
1137  if ($combiGapSolRow['gap_fi'] == $gap_index && $combiGapSolRow['best_solution']) {
1138  $combination = $combiGapSolRow;
1139  break;
1140  }
1141  }
1142  $best_solution_text = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1143  $this->object->getShuffler(),
1144  $combination
1145  ));
1146  return $best_solution_text;
1147  }
1148 
1149  public function getAnswerFeedbackOutput($active_id, $pass)
1150  {
1151  include_once "./Modules/Test/classes/class.ilObjTest.php";
1152  $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1153  if (strlen($manual_feedback)) {
1154  return $manual_feedback;
1155  }
1156  $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1157  $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1158  if (strlen($correct_feedback . $incorrect_feedback)) {
1159  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1160  $max_points = $this->object->getMaximumPoints();
1161  if ($reached_points == $max_points) {
1162  $output .= $correct_feedback;
1163  } else {
1164  $output .= $incorrect_feedback;
1165  }
1166  }
1167  $test = new ilObjTest($this->object->active_id);
1168  return $this->object->prepareTextareaOutput($output, true);
1169  }
1170 
1171  public function getTestOutput(
1172  $active_id,
1173  // hey: prevPassSolutions - will be always available from now on
1174  $pass,
1175  // hey.
1176  $is_postponed = false,
1177  $use_post_solutions = false,
1178  $show_feedback = false
1179  ) {
1180  // get the solution of the user for the active pass or from the last pass if allowed
1181  $user_solution = array();
1182  if ($use_post_solutions !== false) {
1183  $indexedSolution = $this->object->fetchSolutionSubmit($use_post_solutions);
1184  $user_solution = $this->object->fetchValuePairsFromIndexedValues($indexedSolution);
1185  } elseif ($active_id) {
1186  // hey: prevPassSolutions - obsolete due to central check
1187  #include_once "./Modules/Test/classes/class.ilObjTest.php";
1188  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1189  #{
1190  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1191  #}
1192  $user_solution = $this->object->getTestOutputSolutions($active_id, $pass);
1193  // hey.
1194  if (!is_array($user_solution)) {
1195  $user_solution = array();
1196  }
1197  }
1198 
1199  // generate the question output
1200  include_once "./Services/UICore/classes/class.ilTemplate.php";
1201  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", true, true, "Modules/TestQuestionPool");
1202  $output = $this->object->getClozeText();
1203  foreach ($this->object->getGaps() as $gap_index => $gap) {
1204  switch ($gap->getType()) {
1205  case CLOZE_TEXT:
1206  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", true, true, "Modules/TestQuestionPool");
1207  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1208 
1209  if ($gap_size > 0) {
1210  $gaptemplate->setCurrentBlock('size_and_maxlength');
1211  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1212  $gaptemplate->parseCurrentBlock();
1213  }
1214 
1215  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1216  foreach ($user_solution as $solution) {
1217  if (strcmp($solution["value1"], $gap_index) == 0) {
1218  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1219  }
1220  }
1221  // fau: fixGapReplace - use replace function
1222  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1223 // fau.
1224  break;
1225  case CLOZE_SELECT:
1226  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", true, true, "Modules/TestQuestionPool");
1227  foreach ($gap->getItems($this->object->getShuffler()) as $item) {
1228  $gaptemplate->setCurrentBlock("select_gap_option");
1229  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1230  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1231  foreach ($user_solution as $solution) {
1232  if (strcmp($solution["value1"], $gap_index) == 0) {
1233  if (strcmp($solution["value2"], $item->getOrder()) == 0) {
1234  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1235  }
1236  }
1237  }
1238  $gaptemplate->parseCurrentBlock();
1239  }
1240  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1241  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);// fau: fixGapReplace - use replace function
1242  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1243 // fau.
1244  break;
1245  case CLOZE_NUMERIC:
1246  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", true, true, "Modules/TestQuestionPool");
1247  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1248  if ($gap_size > 0) {
1249  $gaptemplate->setCurrentBlock('size_and_maxlength');
1250  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1251  $gaptemplate->parseCurrentBlock();
1252  }
1253 
1254  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1255  foreach ($user_solution as $solution) {
1256  if (strcmp($solution["value1"], $gap_index) == 0) {
1257  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1258  }
1259  }
1260  // fau: fixGapReplace - use replace function
1261  $output = $this->object->replaceFirstGap($output, $gaptemplate->get());
1262 // fau.
1263  break;
1264  }
1265  }
1266 
1267  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
1268  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, true));
1269  $questionoutput = $template->get();
1270  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1271  return $pageoutput;
1272  }
1273 
1281  public function setQuestionTabs()
1282  {
1283  global $DIC;
1284  $rbacsystem = $DIC['rbacsystem'];
1285  $ilTabs = $DIC['ilTabs'];
1286 
1287  $ilTabs->clearTargets();
1288 
1289  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1290  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1291  $q_type = $this->object->getQuestionType();
1292 
1293  if (strlen($q_type)) {
1294  $classname = $q_type . "GUI";
1295  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1296  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1297  # $this->ctrl->setParameterByClass(strtolower($classname), 'prev_qid', $_REQUEST['prev_qid']);
1298  }
1299 
1300  if ($_GET["q_id"]) {
1301  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1302  // edit page
1303  $ilTabs->addTarget(
1304  "edit_page",
1305  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1306  array("edit", "insert", "exec_pg"),
1307  "",
1308  "",
1309  $force_active
1310  );
1311  }
1312 
1313  $this->addTab_QuestionPreview($ilTabs);
1314  }
1315 
1316  $force_active = false;
1317  $commands = $_POST["cmd"];
1318  if (is_array($commands)) {
1319  foreach ($commands as $key => $value) {
1320  if (preg_match("/^removegap_.*/", $key, $matches) ||
1321  preg_match("/^addgap_.*/", $key, $matches)
1322  ) {
1323  $force_active = true;
1324  }
1325  }
1326  }
1327  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
1328  $url = "";
1329  if ($classname) {
1330  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1331  }
1332  // edit question properties
1333  $ilTabs->addTarget(
1334  "edit_question",
1335  $url,
1336  array("editQuestion", "originalSyncForm", "save", "createGaps", "saveEdit"),
1337  $classname,
1338  "",
1339  $force_active
1340  );
1341  }
1342 
1343  // add tab for question feedback within common class assQuestionGUI
1344  $this->addTab_QuestionFeedback($ilTabs);
1345 
1346  // add tab for question hint within common class assQuestionGUI
1347  $this->addTab_QuestionHints($ilTabs);
1348 
1349  // add tab for question's suggested solution within common class assQuestionGUI
1350  $this->addTab_SuggestedSolution($ilTabs, $classname);
1351 
1352  // Assessment of questions sub menu entry
1353  if ($_GET["q_id"]) {
1354  $ilTabs->addTarget(
1355  "statistics",
1356  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1357  array("assessment"),
1358  $classname,
1359  ""
1360  );
1361  }
1362 
1363  $this->addBackTab($ilTabs);
1364  }
1365 
1366  public function getSpecificFeedbackOutput($userSolution)
1367  {
1368  if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
1369  return '';
1370  }
1371 
1372  global $DIC;
1373  $lng = $DIC['lng'];
1374 
1375  $feedback = '<table class="test_specific_feedback"><tbody>';
1376 
1377  foreach ($this->object->gaps as $gapIndex => $gap) {
1378  $answerValue = $this->object->fetchAnswerValueForGap($userSolution, $gapIndex);
1379  $answerIndex = $this->object->feedbackOBJ->determineAnswerIndexForAnswerValue($gap, $answerValue);
1380  $fb = $this->object->feedbackOBJ->determineTestOutputGapFeedback($gapIndex, $answerIndex);
1381 
1382  $caption = $lng->txt('gap') . ' ' . ($gapIndex + 1) . ': ';
1383  $feedback .= '<tr><td>';
1384  $feedback .= $caption . '</td><td>';
1385  $feedback .= $fb . '</td> </tr>';
1386  }
1387  $feedback .= '</tbody></table>';
1388 
1389  return $this->object->prepareTextareaOutput($feedback, true);
1390  }
1391 
1402  {
1403  return array();
1404  }
1405 
1416  {
1417  return array();
1418  }
1419 
1428  public function getAggregatedAnswersView($relevant_answers)
1429  {
1430  $overview = array();
1431  $aggregation = array();
1432  foreach ($relevant_answers as $answer) {
1433  $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1434  }
1435 
1436  foreach ($overview as $active) {
1437  foreach ($active as $answer) {
1438  foreach ($answer as $option => $value) {
1439  $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1440  }
1441  }
1442  }
1443 
1444  $html = '<div>';
1445  $i = 0;
1446  foreach ($this->object->getGaps() as $gap) {
1447  if ($gap->type == CLOZE_SELECT) {
1448  $html .= '<p>Gap ' . ($i + 1) . ' - SELECT</p>';
1449  $html .= '<ul>';
1450  $j = 0;
1451  foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1452  $aggregate = $aggregation[$i];
1453  $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1454  $j++;
1455  }
1456  $html .= '</ul>';
1457  }
1458 
1459  if ($gap->type == CLOZE_TEXT) {
1460  $present_elements = array();
1461  foreach ($gap->getItems(new ilArrayElementShuffler()) as $item) {
1463  $present_elements[] = $item->getAnswertext();
1464  }
1465 
1466  $html .= '<p>Gap ' . ($i + 1) . ' - TEXT</p>';
1467  $html .= '<ul>';
1468  $aggregate = (array) $aggregation[$i];
1469  foreach ($aggregate as $answer => $count) {
1470  $show_mover = '';
1471  if (in_array($answer, $present_elements)) {
1472  $show_mover = ' style="display: none;" ';
1473  }
1474 
1475  $html .= '<li>' . $answer . ' - ' . $count
1476  . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="' . $answer . '" name="add_gap_' . $i . '_0">
1477  <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1478  </li>';
1479  }
1480  $html .= '</ul>';
1481  }
1482 
1483  if ($gap->type == CLOZE_NUMERIC) {
1484  $html .= '<p>Gap ' . ($i + 1) . ' - NUMERIC</p>';
1485  $html .= '<ul>';
1486  $j = 0;
1487  foreach ($gap->getItems($this->object->getShuffler()) as $gap_item) {
1488  $aggregate = (array) $aggregation[$i];
1489  foreach ($aggregate as $answer => $count) {
1490  $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1491  }
1492  $j++;
1493  }
1494  $html .= '</ul>';
1495  }
1496  $i++;
1497  $html .= '<hr />';
1498  }
1499 
1500  $html .= '</div>';
1501  return $html;
1502  }
1503 
1504  public function applyIndizesToGapText($question_text)
1505  {
1506  $parts = explode('[gap', $question_text);
1507  $i = 0;
1508  $question_text = '';
1509  foreach ($parts as $part) {
1510  if ($i == 0) {
1511  $question_text .= $part;
1512  } else {
1513  $question_text .= '[gap ' . $i . $part;
1514  }
1515  $i++;
1516  }
1517  return $question_text;
1518  }
1519 
1520  public function removeIndizesFromGapText($question_text)
1521  {
1522  $parts = preg_split('/\[gap \d*\]/', $question_text);
1523  $question_text = implode('[gap]', $parts);
1524  return $question_text;
1525  }
1526 
1531  private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
1532  {
1533  if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
1534  $gaptemplate->setCurrentBlock('gap_span');
1535  $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1536  } elseif ($gap->getType() == CLOZE_SELECT) {
1537  $gaptemplate->setCurrentBlock('gap_select');
1538  $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1539  } else {
1540  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1541 
1542  if ($gap_size > 0) {
1543  $gaptemplate->setCurrentBlock('gap_size');
1544  $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1545  $gaptemplate->parseCurrentBlock();
1546  }
1547 
1548  $gaptemplate->setCurrentBlock('gap_input');
1549  $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1550  }
1551 
1552 
1553  $gaptemplate->parseCurrentBlock();
1554  }
1555 
1556  protected function hasAddAnswerAction($relevantAnswers, $questionIndex)
1557  {
1558  foreach ($this->getAnswersFrequency($relevantAnswers, $questionIndex) as $answer) {
1559  if (isset($answer['actions'])) {
1560  return true;
1561  }
1562  }
1563 
1564  return false;
1565  }
1566 
1567  public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
1568  {
1569  global $DIC; /* @var ILIAS\DI\Container $DIC */
1570 
1571  $table = parent::getAnswerFrequencyTableGUI(
1572  $parentGui,
1573  $parentCmd,
1574  $relevantAnswers,
1575  $questionIndex
1576  );
1577 
1578  $table->setTitle(sprintf(
1579  $DIC->language()->txt('tst_corrections_answers_tbl_subindex'),
1580  $DIC->language()->txt('gap') . ' ' . ($questionIndex + 1)
1581  ));
1582 
1583  if ($this->hasAddAnswerAction($relevantAnswers, $questionIndex)) {
1584  $table->addColumn('', '', '200');
1585  }
1586 
1587  return $table;
1588  }
1589 
1590  public function getSubQuestionsIndex()
1591  {
1592  return array_keys($this->object->getGaps());
1593  }
1594 
1595  protected function getAnswerTextLabel($gapIndex, $answer)
1596  {
1597  $gap = $this->object->getGap($gapIndex);
1598 
1599  switch ($gap->type) {
1600  case CLOZE_NUMERIC:
1601  case CLOZE_TEXT:
1602  return $answer;
1603 
1604  case CLOZE_SELECT:
1605 
1606  $items = $gap->getItems(new ilArrayElementOrderKeeper());
1607  return $items[$answer]->getAnswertext();
1608  }
1609  }
1610 
1611  protected function completeAddAnswerAction($answers, $questionIndex)
1612  {
1613  $gap = $this->object->getGap($questionIndex);
1614 
1615  if ($gap->type != CLOZE_TEXT) {
1616  return $answers;
1617  }
1618 
1619  foreach ($answers as $key => $ans) {
1620  $found = false;
1621 
1622  foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $item) {
1623  if ($ans['answer'] !== $item->getAnswerText()) {
1624  continue;
1625  }
1626 
1627  $found = true;
1628  break;
1629  }
1630 
1631  if (!$found) {
1632  $answers[$key]['addable'] = true;
1633  }
1634  }
1635 
1636  return $answers;
1637  }
1638 
1639  public function getAnswersFrequency($relevant_answers, $questionIndex)
1640  {
1641  $answers = array();
1642 
1643  foreach ($relevant_answers as $row) {
1644  if ($row['value1'] != $questionIndex) {
1645  continue;
1646  }
1647 
1648  if (!isset($answers[$row['value2']])) {
1649  $label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
1650 
1651  $answers[$row['value2']] = array(
1652  'answer' => $label, 'frequency' => 0
1653  );
1654  }
1655 
1656  $answers[$row['value2']]['frequency']++;
1657  }
1658 
1659  $answers = $this->completeAddAnswerAction($answers, $questionIndex);
1660 
1661  return $answers;
1662  }
1663 
1664  protected function isUsedInCombinations($gapIndex)
1665  {
1666  foreach ($this->object->getGapCombinations() as $combination) {
1667  if ($combination['gap_fi'] != $gapIndex) {
1668  continue;
1669  }
1670 
1671  return true;
1672  }
1673 
1674  return false;
1675  }
1676 
1677  protected function getGapCombinations()
1678  {
1679  $combinations = array();
1680 
1681  foreach ($this->object->getGapCombinations() as $c) {
1682  if (!isset($combinations[$c['cid']])) {
1683  $combinations[$c['cid']] = array();
1684  }
1685 
1686  if (!isset($combinations[$c['cid']][$c['row_id']])) {
1687  $combinations[$c['cid']][$c['row_id']] = array(
1688  'gaps' => array(), 'points' => $c['points'],
1689  );
1690  }
1691 
1692  if (!isset($combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']])) {
1693  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = array();
1694  }
1695 
1696  $combinations[$c['cid']][$c['row_id']]['gaps'][$c['gap_fi']] = $c['answer'];
1697  }
1698 
1699  return $combinations;
1700  }
1701 
1703  {
1704  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1706  $form,
1707  $gap,
1708  $gapIndex,
1709  $this->isUsedInCombinations($gapIndex)
1710  );
1711  }
1712 
1713  if ($this->object->getGapCombinationsExists()) {
1714  foreach ($this->getGapCombinations() as $combiIndex => $gapCombination) {
1715  $this->populateGapCombinationCorrectionFormProperty($form, $gapCombination, $combiIndex);
1716  }
1717  }
1718  }
1719 
1720  protected function populateGapCombinationCorrectionFormProperty(ilPropertyFormGUI $form, $gapCombi, $combiIndex)
1721  {
1722  $header = new ilFormSectionHeaderGUI();
1723  $header->setTitle("Gap Combination " . ($combiIndex + 1));
1724  $form->addItem($header);
1725 
1726  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssClozeTestCombinationVariantsInputGUI.php';
1727  $inp = new ilAssClozeTestCombinationVariantsInputGUI('Answers', 'combination_' . $combiIndex);
1728  $inp->setValues($gapCombi);
1729  $form->addItem($inp);
1730  }
1731 
1737  protected function populateGapCorrectionFormProperties($form, $gap, $gapIndex, $hidePoints)
1738  {
1739  $header = new ilFormSectionHeaderGUI();
1740  $header->setTitle($this->lng->txt("gap") . " " . ($gapIndex + 1));
1741  $form->addItem($header);
1742 
1743  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1744  $this->populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints);
1745  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1746  foreach ($gap->getItemsRaw() as $item) {
1747  $this->populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints);
1748  }
1749  }
1750  }
1751 
1752  protected function populateTextOrSelectGapCorrectionFormProperty($form, $gap, $gapIndex, $hidePoints)
1753  {
1754  require_once "Modules/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php";
1755  $values = new ilAssAnswerCorrectionsInputGUI($this->lng->txt("values"), "gap_" . $gapIndex);
1756  $values->setHidePointsEnabled($hidePoints);
1757  $values->setRequired(true);
1758  $values->setQuestionObject($this->object);
1759  $values->setValues($gap->getItemsRaw());
1760  $form->addItem($values);
1761  }
1762 
1763  protected function populateNumericGapCorrectionFormProperty($form, $item, $gapIndex, $hidePoints)
1764  {
1765  $value = new ilNumberInputGUI($this->lng->txt('value'), "gap_" . $gapIndex . "_numeric");
1766  $value->allowDecimals(true);
1767  $value->setSize(10);
1768  $value->setValue(ilUtil::prepareFormOutput($item->getAnswertext()));
1769  $value->setRequired(true);
1770  $form->addItem($value);
1771 
1772  $lowerbound = new ilNumberInputGUI($this->lng->txt('range_lower_limit'), "gap_" . $gapIndex . "_numeric_lower");
1773  $lowerbound->allowDecimals(true);
1774  $lowerbound->setSize(10);
1775  $lowerbound->setRequired(true);
1776  $lowerbound->setValue(ilUtil::prepareFormOutput($item->getLowerBound()));
1777  $form->addItem($lowerbound);
1778 
1779  $upperbound = new ilNumberInputGUI($this->lng->txt('range_upper_limit'), "gap_" . $gapIndex . "_numeric_upper");
1780  $upperbound->allowDecimals(true);
1781  $upperbound->setSize(10);
1782  $upperbound->setRequired(true);
1783  $upperbound->setValue(ilUtil::prepareFormOutput($item->getUpperBound()));
1784  $form->addItem($upperbound);
1785 
1786  if (!$hidePoints) {
1787  $points = new ilNumberInputGUI($this->lng->txt('points'), "gap_" . $gapIndex . "_numeric_points");
1788  $points->allowDecimals(true);
1789  $points->setSize(3);
1790  $points->setRequired(true);
1791  $points->setValue(ilUtil::prepareFormOutput($item->getPoints()));
1792  $form->addItem($points);
1793  }
1794  }
1795 
1800  {
1801  foreach ($this->object->getGaps() as $gapIndex => $gap) {
1802  if ($this->isUsedInCombinations($gapIndex)) {
1803  continue;
1804  }
1805 
1806  $this->saveGapCorrectionFormProperty($form, $gap, $gapIndex);
1807  }
1808 
1809  if ($this->object->getGapCombinationsExists()) {
1811  }
1812  }
1813 
1815  {
1816  if ($gap->getType() == CLOZE_TEXT || $gap->getType() == CLOZE_SELECT) {
1818  } elseif ($gap->getType() == CLOZE_NUMERIC) {
1819  foreach ($gap->getItemsRaw() as $item) {
1820  $this->saveNumericGapCorrectionFormProperty($form, $item, $gapIndex);
1821  }
1822  }
1823  }
1824 
1826  {
1827  $answers = $form->getItemByPostVar('gap_' . $gapIndex)->getValues();
1828 
1829  foreach ($gap->getItemsRaw() as $index => $item) {
1830  $item->setPoints((float) $answers[$index]->getPoints());
1831  }
1832  }
1833 
1835  {
1836  $item->setAnswertext($form->getInput('gap_' . $gapIndex . '_numeric'));
1837  $item->setLowerBound($form->getInput('gap_' . $gapIndex . '_numeric_lower'));
1838  $item->setUpperBound($form->getInput('gap_' . $gapIndex . '_numeric_upper'));
1839  $item->setPoints($form->getInput('gap_' . $gapIndex . '_numeric_points'));
1840  }
1841 
1843  {
1844  // please dont ask (!) -.-
1845 
1846  $combinationPoints = array('points' => array(), 'select' => array());
1847  $combinationValues = array();
1848 
1849  foreach ($this->getGapCombinations() as $combiId => $combi) {
1850  $values = $form->getItemByPostVar('combination_' . $combiId)->getValues();
1851 
1852  if (!isset($combinationPoints['points'][$combiId])) {
1853  $combinationPoints['points'][$combiId] = array();
1854  $combinationPoints['select'][$combiId] = array();
1855  $combinationValues[$combiId] = array();
1856  }
1857 
1858  foreach ($combi as $varId => $variant) {
1859  $combinationPoints['points'][$combiId][$varId] = (float) $values[$varId]['points'];
1860  $combinationPoints['select'][$combiId] = array_keys($values[$varId]['gaps']);
1861  $combinationValues[$combiId][$varId] = array_values($values[$varId]['gaps']);
1862  }
1863  }
1864 
1865  $combinationPoints = ilUtil::stripSlashesRecursive($combinationPoints);
1866  $combinationValues = ilUtil::stripSlashesRecursive($combinationValues);
1867 
1868  $assClozeGapCombinationObject = new assClozeGapCombination();
1869  $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
1870 
1871  $assClozeGapCombinationObject->saveGapCombinationToDb(
1872  $this->object->getId(),
1873  $combinationPoints,
1874  $combinationValues
1875  );
1876  }
1877 }
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)
$errors
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...
setUpperBound($bound)
Sets the upper bound.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
This class represents a property form user interface.
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.
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.
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)
static stripSlashesRecursive($a_data, $a_strip_html=true, $a_allow="")
Strip slashes from array and sub-arrays.
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.
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
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.
setAnswertext($answertext="")
Sets the answer text.
addBackTab(ilTabsGUI $ilTabs)
$DIC
Definition: xapitoken.php:46
$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.
$url
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)
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
getAnswerTextLabel($gapIndex, $answer)
$i
Definition: metadata.php:24
$test
Definition: Utf8Test.php:84
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.