ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups 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 
23 {
24  const OLD_CLOZE_TEST_UI = false;
25 
29  private $gapIndex;
30 
36  public function __construct($id = -1)
37  {
39  include_once "./Modules/TestQuestionPool/classes/class.assClozeTest.php";
40  $this->object = new assClozeTest();
41  if ($id >= 0)
42  {
43  $this->object->loadFromDb($id);
44  }
45  }
46 
47  function getCommand($cmd)
48  {
49  if (preg_match("/^(removegap|addgap)_(\d+)$/", $cmd, $matches))
50  {
51  $cmd = $matches[1];
52  $this->gapIndex = $matches[2];
53  }
54  return $cmd;
55  }
56 
65  function writePostData($always = false)
66  {
67  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
68  if (!$hasErrors)
69  {
70  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
71 
72  $cloze_text = $this->object->getHtmlQuestionContentPurifier()->purify($_POST['cloze_text']);
73 
74  $cloze_text = $this->removeIndizesFromGapText( $cloze_text );
75  $_POST['cloze_text'] = $cloze_text;
76  $this->object->setQuestion($_POST['question']);
77 
79  $this->object->setClozeText($_POST["cloze_text"]);
81  //$this->object->flushGaps();
83  $this->saveTaxonomyAssignments();
84  return 0;
85  }
86 
87  $cloze_text = $_POST['cloze_text'];
88  $cloze_text = $this->applyIndizesToGapText($cloze_text);
89  $_POST['cloze_text'] = $cloze_text;
90  return 1;
91  }
92 
94  {
95  if (is_array( $_POST['gap'] ))
96  {
97  if ( $this->ctrl->getCmd() != 'createGaps' )
98  {
99  $this->object->clearGapAnswers();
100  }
101 
102  foreach ($_POST['gap'] as $idx => $hidden)
103  {
104  $clozetype = $_POST['clozetype_' . $idx];
105 
106  $this->object->setGapType( $idx, $clozetype );
107 
108  switch($clozetype)
109  {
110  case CLOZE_TEXT:
111 
112  $this->object->setGapShuffle( $idx, 0 );
113 
114  if ($this->ctrl->getCmd() != 'createGaps')
115  {
116  if (is_array( $_POST['gap_' . $idx]['answer'] ))
117  {
118  foreach ($_POST['gap_' . $idx]['answer'] as $order => $value)
119  {
120  $this->object->addGapAnswer( $idx, $order, $value );
121  }
122  }
123  else
124  {
125  $this->object->addGapAnswer( $idx, 0, '' );
126  }
127  }
128 
129  if (is_array( $_POST['gap_' . $idx]['points'] ))
130  {
131  foreach ($_POST['gap_' . $idx]['points'] as $order => $value)
132  {
133  $this->object->setGapAnswerPoints( $idx, $order, $value );
134  }
135  }
136 
137  if (array_key_exists( 'gap_' . $idx . '_gapsize', $_POST ))
138  {
139  $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize'] );
140  }
141 
142  break;
143 
144  case CLOZE_SELECT:
145 
146  $this->object->setGapShuffle( $idx, (int)(isset($_POST["shuffle_$idx"]) && $_POST["shuffle_$idx"]) );
147 
148  if ($this->ctrl->getCmd() != 'createGaps')
149  {
150  if (is_array( $_POST['gap_' . $idx]['answer'] ))
151  {
152  foreach ($_POST['gap_' . $idx]['answer'] as $order => $value)
153  {
154  $this->object->addGapAnswer( $idx, $order, $value );
155  }
156  }
157  else
158  {
159  $this->object->addGapAnswer( $idx, 0, '' );
160  }
161  }
162 
163  if (is_array( $_POST['gap_' . $idx]['points'] ))
164  {
165  foreach ($_POST['gap_' . $idx]['points'] as $order => $value)
166  {
167  $this->object->setGapAnswerPoints( $idx, $order, $value );
168  }
169  }
170  break;
171 
172  case CLOZE_NUMERIC:
173 
174  $this->object->setGapShuffle( $idx, 0 );
175 
176  $gap = $this->object->getGap($idx);
177  if (!$gap) break;
178 
179  $this->object->getGap($idx)->clearItems();
180 
181  if (array_key_exists( 'gap_' . $idx . '_numeric', $_POST ))
182  {
183  if ($this->ctrl->getCmd() != 'createGaps')
184  {
185  $this->object->addGapAnswer(
186  $idx, 0, str_replace(",", ".", $_POST['gap_' . $idx . '_numeric'])
187  );
188  }
189 
190  $this->object->setGapAnswerLowerBound(
191  $idx, 0, str_replace(",", ".", $_POST['gap_' . $idx . '_numeric_lower'])
192  );
193 
194  $this->object->setGapAnswerUpperBound(
195  $idx, 0, str_replace( ",", ".", $_POST['gap_' . $idx . '_numeric_upper'])
196  );
197 
198  $this->object->setGapAnswerPoints( $idx, 0, $_POST['gap_' . $idx . '_numeric_points'] );
199  }
200  else
201  {
202  if ($this->ctrl->getCmd() != 'createGaps')
203  {
204  $this->object->addGapAnswer($idx, 0, '');
205  }
206 
207  $this->object->setGapAnswerLowerBound($idx, 0, '');
208 
209  $this->object->setGapAnswerUpperBound($idx, 0, '');
210  }
211 
212  if (array_key_exists( 'gap_' . $idx . '_gapsize', $_POST ))
213  {
214  $this->object->setGapSize($idx, $order, $_POST['gap_' . $idx . '_gapsize'] );
215  }
216  break;
217  }
218  $assClozeGapCombinationObject = new assClozeGapCombination();
219  $assClozeGapCombinationObject->clearGapCombinationsFromDb($this->object->getId());
220  if(count($_POST['gap_combination']) > 0)
221  {
222  $assClozeGapCombinationObject->saveGapCombinationToDb($this->object->getId(),ilUtil::stripSlashesRecursive($_POST['gap_combination']), ilUtil::stripSlashesRecursive($_POST['gap_combination_values']));
223  }
224  }
225  if ($this->ctrl->getCmd() != 'createGaps')
226  {
227  $this->object->updateClozeTextFromGaps();
228  }
229  }
230  }
231 
233  {
234  $this->object->setClozeText( $_POST['cloze_text'] );
235  $this->object->setTextgapRating( $_POST["textgap_rating"] );
236  $this->object->setIdenticalScoring( $_POST["identical_scoring"] );
237  $this->object->setFixedTextLength( $_POST["fixedTextLength"] );
238  }
239 
245  public function editQuestion($checkonly = FALSE)
246  {
247  $save = $this->isSaveCommand();
248  $this->getQuestionTemplate();
249 
250  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
251  $form = new ilPropertyFormGUI();
252  $form->setFormAction($this->ctrl->getFormAction($this));
253  $form->setTitle($this->outQuestionType());
254  $form->setMultipart(FALSE);
255  $form->setTableWidth("100%");
256  $form->setId("assclozetest");
257 
258  // title, author, description, question, working time (assessment mode)
259  $this->addBasicQuestionFormProperties($form);
260  $this->populateQuestionSpecificFormPart( $form );
261  $this->populateAnswerSpecificFormPart( $form );
262  $this->populateTaxonomyFormSection($form);
263 
264  $this->addQuestionFormCommandButtons($form);
265 
266  $errors = false;
267 
268  if ($save)
269  {
270  $form->setValuesByPost();
271  $errors = !$form->checkInput();
272  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we
273  // need this if we don't want to have duplication of backslashes
274  if ($errors) $checkonly = false;
275  }
276 
277  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
278  return $errors;
279  }
280 
282  {
283  // title
284  $title = new ilTextInputGUI($this->lng->txt("title"), "title");
285  $title->setMaxLength(100);
286  $title->setValue($this->object->getTitle());
287  $title->setRequired(TRUE);
288  $form->addItem($title);
289 
290  if (!$this->object->getSelfAssessmentEditingMode())
291  {
292  // author
293  $author = new ilTextInputGUI($this->lng->txt("author"), "author");
294  $author->setValue($this->object->getAuthor());
295  $author->setRequired(TRUE);
296  $form->addItem($author);
297 
298  // description
299  $description = new ilTextInputGUI($this->lng->txt("description"), "comment");
300  $description->setValue($this->object->getComment());
301  $description->setRequired(FALSE);
302  $form->addItem($description);
303  }
304  else
305  {
306  // author as hidden field
307  $hi = new ilHiddenInputGUI("author");
308  $author = ilUtil::prepareFormOutput($this->object->getAuthor());
309  if (trim($author) == "")
310  {
311  $author = "-";
312  }
313  $hi->setValue($author);
314  $form->addItem($hi);
315 
316  }
317 
318  // questiontext
319  $question = new ilTextAreaInputGUI($this->lng->txt("question"), "question");
320  $question->setValue($this->object->prepareTextareaOutput($this->object->getQuestion()));
321  $question->setRequired(TRUE);
322  $question->setRows(10);
323  $question->setCols(80);
324  if (!$this->object->getSelfAssessmentEditingMode())
325  {
326  if( $this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT )
327  {
328  $question->setUseRte(TRUE);
329  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
330  $question->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
331  $question->addPlugin("latex");
332  $question->addButton("latex");
333  $question->addButton("pastelatex");
334  $question->setRTESupport($this->object->getId(), "qpl", "assessment");
335  }
336  }
337  else
338  {
339  $question->setRteTags(self::getSelfAssessmentTags());
340  $question->setUseTagsForRteOnly(false);
341  }
342  $form->addItem($question);
343 
344 // $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
345 // $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
346 // $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
347 // $tpl->parseCurrentBlock();
348 // $button = new ilCustomInputGUI('&nbsp;','');
349 // $button->setHtml($tpl->get());
350 // $form->addItem($button);
351 
352  if (!$this->object->getSelfAssessmentEditingMode())
353  {
354  // duration
355  $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
356  $duration->setShowHours(TRUE);
357  $duration->setShowMinutes(TRUE);
358  $duration->setShowSeconds(TRUE);
359  $ewt = $this->object->getEstimatedWorkingTime();
360  $duration->setHours($ewt["h"]);
361  $duration->setMinutes($ewt["m"]);
362  $duration->setSeconds($ewt["s"]);
363  $duration->setRequired(FALSE);
364  $form->addItem($duration);
365  }
366  else
367  {
368  // number of tries
369  if (strlen($this->object->getNrOfTries()))
370  {
371  $nr_tries = $this->object->getNrOfTries();
372  }
373  else
374  {
375  $nr_tries = $this->object->getDefaultNrOfTries();
376  }
377  /*if ($nr_tries <= 0)
378  {
379  $nr_tries = 1;
380  }*/
381 
382  if ($nr_tries < 0)
383  {
384  $nr_tries = 0;
385  }
386 
387  $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
388  $ni->setValue($nr_tries);
389  //$ni->setMinValue(1);
390  $ni->setMinValue(0);
391  $ni->setSize(5);
392  $ni->setMaxLength(5);
393  $ni->setRequired(true);
394  $form->addItem($ni);
395  }
396  }
397 
399  {
400  // cloze text
401  $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
402  $cloze_text->setRequired(true);
403  $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
404  $cloze_text->setInfo($this->lng->txt("close_text_hint"));
405  $cloze_text->setRows( 10 );
406  $cloze_text->setCols( 80 );
407  if (!$this->object->getSelfAssessmentEditingMode())
408  {
409  if( $this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT )
410  {
411  $cloze_text->setUseRte(TRUE);
412  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
413  $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
414  $cloze_text->addPlugin("latex");
415  $cloze_text->addButton("latex");
416  $cloze_text->addButton("pastelatex");
417  }
418  }
419  else
420  {
421  $cloze_text->setRteTags(self::getSelfAssessmentTags());
422  $cloze_text->setUseTagsForRteOnly(false);
423  }
424  $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
425  $form->addItem($cloze_text);
426 
427  $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
428  $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
429  $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
430  $tpl->parseCurrentBlock();
431  $button = new ilCustomInputGUI('&nbsp;','');
432  $button->setHtml($tpl->get());
433  $form->addItem($button);
434 
435  // text rating
436  if (!$this->object->getSelfAssessmentEditingMode())
437  {
438  $textrating = new ilSelectInputGUI($this->lng->txt( "text_rating" ), "textgap_rating");
439  $text_options = array(
440  "ci" => $this->lng->txt( "cloze_textgap_case_insensitive" ),
441  "cs" => $this->lng->txt( "cloze_textgap_case_sensitive" ),
442  "l1" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "1" ),
443  "l2" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "2" ),
444  "l3" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "3" ),
445  "l4" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "4" ),
446  "l5" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "5" )
447  );
448  $textrating->setOptions( $text_options );
449  $textrating->setValue( $this->object->getTextgapRating() );
450  $form->addItem( $textrating );
451 
452  // text field length
453  $fixedTextLength = new ilNumberInputGUI($this->lng->txt( "cloze_fixed_textlength" ), "fixedTextLength");
454  $ftl = $this->object->getFixedTextLength();
455 
456  $fixedTextLength->setValue( $ftl > 0 ? $ftl : '' );
457  $fixedTextLength->setMinValue( 0 );
458  $fixedTextLength->setSize( 3 );
459  $fixedTextLength->setMaxLength( 6 );
460  $fixedTextLength->setInfo( $this->lng->txt( 'cloze_fixed_textlength_description' ) );
461  $fixedTextLength->setRequired( false );
462  $form->addItem( $fixedTextLength );
463 
464  // identical scoring
465  $identical_scoring = new ilCheckboxInputGUI($this->lng->txt( "identical_scoring" ), "identical_scoring");
466  $identical_scoring->setValue( 1 );
467  $identical_scoring->setChecked( $this->object->getIdenticalScoring() );
468  $identical_scoring->setInfo( $this->lng->txt( 'identical_scoring_desc' ) );
469  $identical_scoring->setRequired( FALSE );
470  $form->addItem( $identical_scoring );
471  }
472  return $form;
473  }
474 
476  {
477  if(self::OLD_CLOZE_TEST_UI)
478  {
479  for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++)
480  {
481  $this->populateGapFormPart( $form, $gapCounter );
482  }
483  return $form;
484  }
485  else
486  {
487  require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
488  $json=$this->populateJSON();
489  $assClozeGapCombinationObject = new assClozeGapCombination();
490  $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->id);
491  if($combination_exists)
492  {
493  $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->id);
494  }
495  $new_builder = new ilClozeGapInputBuilderGUI();
496  $header = new ilFormSectionHeaderGUI();
497  $form->addItem($header);
498  $new_builder->setValueByArray($json);
499  $new_builder->setValueCombinationFromDb($combinations);
500  $form->addItem($new_builder);
501  return $form;
502  }
503  }
504 
505  protected function populateJSON()
506  {
507  $gap = $this->object->getGaps();
508  $array = array();
509  if ($gap == null)
510  {
511  return $array;
512  }
513  $translate_type=array('text','select','numeric');
514  $i = 0;
515  foreach ($gap as $content)
516  {
517  $shuffle=false;
518  $value=$content->getItemsRaw();
519  $items=array();
520  for($j=0;$j<count($value);$j++)
521  {
522  if($content->getType()==2)
523  {
524  $items[$j] = array(
525  'answer' => $value[$j]->getAnswerText(),
526  'lower' => $value[$j]->getLowerBound(),
527  'upper' => $value[$j]->getUpperBound(),
528  'points' => $value[$j]->getPoints(),
529  'error' => false
530  );
531  }
532  else
533  {
534  $items[$j] = array(
535  'answer' => $value[$j]->getAnswerText(),
536  'points' => $value[$j]->getPoints(),
537  'error' => false
538  );
539 
540  if($content->getType()==1)
541  {
542  $shuffle=$content->getShuffle();
543  }
544  }
545  }
546  $answers[$i]=array(
547  'type' => $translate_type[$content->getType()] ,
548  'values' => $items ,
549  'shuffle' => $shuffle,
550  'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
551  'used_in_gap_combination' => true);
552  $i++;
553  }
554  return $answers;
555  }
567  protected function populateGapFormPart($form, $gapCounter)
568  {
569  $gap = $this->object->getGap( $gapCounter );
570 
571  if ($gap == null)
572  {
573  return $form;
574  }
575 
576  $header = new ilFormSectionHeaderGUI();
577  $header->setTitle( $this->lng->txt( "gap" ) . " " . ($gapCounter + 1) );
578  $form->addItem( $header );
579 
580  $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
581  $gapcounter->setValue( $gapCounter );
582  $form->addItem( $gapcounter );
583 
584  $gaptype = new ilSelectInputGUI($this->lng->txt( 'type' ), "clozetype_$gapCounter");
585  $options = array(
586  0 => $this->lng->txt( "text_gap" ),
587  1 => $this->lng->txt( "select_gap" ),
588  2 => $this->lng->txt( "numeric_gap" )
589  );
590  $gaptype->setOptions( $options );
591  $gaptype->setValue( $gap->getType() );
592  $form->addItem( $gaptype );
593 
594  if ($gap->getType() == CLOZE_TEXT)
595  {
596  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
597 
598  if (count( $gap->getItemsRaw() ) == 0)
599  $gap->addItem( new assAnswerCloze("", 0, 0) );
600  $this->populateTextGapFormPart( $form, $gap, $gapCounter );
601  }
602  else if ($gap->getType() == CLOZE_SELECT)
603  {
604  if (count( $gap->getItemsRaw() ) == 0)
605  $gap->addItem( new assAnswerCloze("", 0, 0) );
606  $this->populateSelectGapFormPart( $form, $gap, $gapCounter );
607  }
608  else if ($gap->getType() == CLOZE_NUMERIC)
609  {
610  $this->populateGapSizeFormPart($form, $gap, $gapCounter);
611 
612  if (count( $gap->getItemsRaw() ) == 0)
613  $gap->addItem( new assAnswerCloze("", 0, 0) );
614  foreach ($gap->getItemsRaw() as $item)
615  {
616  $this->populateNumericGapFormPart( $form, $item, $gapCounter );
617  }
618  }
619  return $form;
620  }
621 
627  protected function populateGapSizeFormPart($form, $gap, $gapCounter)
628  {
629  $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_".$gapCounter.'_gapsize');
630 
631  $gapSizeFormItem->allowDecimals(false);
632  $gapSizeFormItem->setMinValue(0);
633  $gapSizeFormItem->setSize( 3 );
634  $gapSizeFormItem->setMaxLength( 6 );
635  $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
636  $gapSizeFormItem->setValue($gap->getGapSize());
637  $form->addItem($gapSizeFormItem);
638 
639  return $form;
640  }
641 
654  protected function populateSelectGapFormPart($form, $gap, $gapCounter)
655  {
656  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
657  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
658  $values = new ilAnswerWizardInputGUI($this->lng->txt( "values" ), "gap_" . $gapCounter . "");
659  $values->setRequired( true );
660  $values->setQuestionObject( $this->object );
661  $values->setSingleline( true );
662  $values->setAllowMove( false );
663 
664  $values->setValues( $gap->getItemsRaw() );
665  $form->addItem( $values );
666 
667  // shuffle
668  $shuffle = new ilCheckboxInputGUI($this->lng->txt( "shuffle_answers" ), "shuffle_" . $gapCounter . "");
669  $shuffle->setValue( 1 );
670  $shuffle->setChecked( $gap->getShuffle() );
671  $shuffle->setRequired( FALSE );
672  $form->addItem( $shuffle );
673  return $form;
674  }
675 
687  protected function populateTextGapFormPart($form, $gap, $gapCounter)
688  {
689  // Choices
690  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
691  include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
692  $values = new ilAnswerWizardInputGUI($this->lng->txt( "values" ), "gap_" . $gapCounter . "");
693  $values->setRequired( true );
694  $values->setQuestionObject( $this->object );
695  $values->setSingleline( true );
696  $values->setAllowMove( false );
697  $values->setValues( $gap->getItemsRaw() );
698  $form->addItem( $values );
699 
700  if( $this->object->getFixedTextLength() > 0 )
701  {
702  $values->setSize( $this->object->getFixedTextLength() );
703  $values->setMaxLength( $this->object->getFixedTextLength() );
704  }
705 
706  return $form;
707  }
708 
720  protected function populateNumericGapFormPart($form, $gap, $gapCounter)
721  {
722  // #8944: the js-based ouput in self-assessment cannot support formulas
723  if (!$this->object->getSelfAssessmentEditingMode())
724  {
725  $value = new ilFormulaInputGUI($this->lng->txt( 'value' ), "gap_" . $gapCounter . "_numeric");
726  $value->setInlineStyle( 'text-align: right;' );
727 
728  $lowerbound = new ilFormulaInputGUI($this->lng->txt( 'range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
729  $lowerbound->setInlineStyle( 'text-align: right;' );
730 
731  $upperbound = new ilFormulaInputGUI($this->lng->txt( 'range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
732  $upperbound->setInlineStyle( 'text-align: right;' );
733  }
734  else
735  {
736  $value = new ilNumberInputGUI($this->lng->txt( 'value' ), "gap_" . $gapCounter . "_numeric");
737  $value->allowDecimals( true );
738 
739  $lowerbound = new ilNumberInputGUI($this->lng->txt( 'range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
740  $lowerbound->allowDecimals( true );
741 
742  $upperbound = new ilNumberInputGUI($this->lng->txt( 'range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
743  $upperbound->allowDecimals( true );
744  }
745 
746  $value->setSize( 10 );
747  $value->setValue( ilUtil::prepareFormOutput( $gap->getAnswertext() ) );
748  $value->setRequired( true );
749  $form->addItem( $value );
750 
751  $lowerbound->setSize( 10 );
752  $lowerbound->setRequired( true );
753  $lowerbound->setValue( ilUtil::prepareFormOutput( $gap->getLowerBound() ) );
754  $form->addItem( $lowerbound );
755 
756  $upperbound->setSize( 10 );
757  $upperbound->setRequired( true );
758  $upperbound->setValue( ilUtil::prepareFormOutput( $gap->getUpperBound() ) );
759  $form->addItem( $upperbound );
760 
761  if( $this->object->getFixedTextLength() > 0 )
762  {
763  $value->setSize( $this->object->getFixedTextLength() );
764  $value->setMaxLength( $this->object->getFixedTextLength() );
765  $lowerbound->setSize( $this->object->getFixedTextLength() );
766  $lowerbound->setMaxLength( $this->object->getFixedTextLength() );
767  $upperbound->setSize( $this->object->getFixedTextLength() );
768  $upperbound->setMaxLength( $this->object->getFixedTextLength() );
769  }
770 
771  $points = new ilNumberInputGUI($this->lng->txt( 'points' ), "gap_" . $gapCounter . "_numeric_points");
772  $points->allowDecimals(true);
773  $points->setSize( 3 );
774  $points->setRequired( true );
775  $points->setValue( ilUtil::prepareFormOutput( $gap->getPoints() ) );
776  $form->addItem( $points );
777  return $form;
778  }
779 
783  public function createGaps()
784  {
785  $this->writePostData(true);
786  $this->object->saveToDb();
787  $this->editQuestion();
788  }
789 
793  function removegap()
794  {
795  $this->writePostData(true);
796  $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
797  $this->editQuestion();
798  }
799 
803  function addgap()
804  {
805  $this->writePostData(true);
806  $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex])+1, "");
807  $this->editQuestion();
808  }
809 
818  function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
819  {
820  $user_solution = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
821 
822  // generate the question output
823  include_once "./Services/UICore/classes/class.ilTemplate.php";
824  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
825  $output = $this->object->getClozeText();
826  foreach ($this->object->getGaps() as $gap_index => $gap)
827  {
828  switch ($gap->getType())
829  {
830  case CLOZE_TEXT:
831  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", TRUE, TRUE, "Modules/TestQuestionPool");
832 
833  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
834  if($gap_size > 0)
835  {
836  $gaptemplate->setCurrentBlock('size_and_maxlength');
837  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
838  $gaptemplate->parseCurrentBlock();
839  }
840  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
841  foreach ($user_solution as $val1 => $val2)
842  {
843  if (strcmp($val1, $gap_index) == 0)
844  {
845  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
846  }
847  }
848  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
849  break;
850  case CLOZE_SELECT:
851  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", TRUE, TRUE, "Modules/TestQuestionPool");
852  foreach ($gap->getItems() as $item)
853  {
854  $gaptemplate->setCurrentBlock("select_gap_option");
855  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
856  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
857  foreach ($user_solution as $val1 => $val2)
858  {
859  if (strcmp($val1, $gap_index) == 0)
860  {
861  if (strcmp($val2, $item->getOrder()) == 0)
862  {
863  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
864  }
865  }
866  }
867  $gaptemplate->parseCurrentBlock();
868  }
869  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
870  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
871  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
872  break;
873  case CLOZE_NUMERIC:
874  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", TRUE, TRUE, "Modules/TestQuestionPool");
875  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
876  if($gap_size > 0)
877  {
878  $gaptemplate->setCurrentBlock('size_and_maxlength');
879  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
880  $gaptemplate->parseCurrentBlock();
881  }
882  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
883  foreach ($user_solution as $val1 => $val2)
884  {
885  if (strcmp($val1, $gap_index) == 0)
886  {
887  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
888  }
889  }
890  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
891  break;
892  }
893  }
894  $template->setVariable("QUESTIONTEXT",$this->object->prepareTextareaOutput( $this->object->getQuestion(), true));
895  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
896  $questionoutput = $template->get();
897  if (!$show_question_only)
898  {
899  // get page object output
900  $questionoutput = $this->getILIASPage($questionoutput);
901  }
902  return $questionoutput;
903  }
904 
921  $active_id,
922  $pass = NULL,
923  $graphicalOutput = FALSE,
924  $result_output = FALSE,
925  $show_question_only = TRUE,
926  $show_feedback = FALSE,
927  $show_correct_solution = FALSE,
928  $show_manual_scoring = FALSE,
929  $show_question_text = TRUE
930  )
931  {
932  // get the solution of the user for the active pass or from the last pass if allowed
933  $user_solution = array();
934  if (($active_id > 0) && (!$show_correct_solution))
935  {
936  // get the solutions of a user
937  $user_solution =& $this->object->getSolutionValues($active_id, $pass);
938  if(!is_array($user_solution))
939  {
940  $user_solution = array();
941  }
942  }
943 
944  include_once "./Services/UICore/classes/class.ilTemplate.php";
945  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
946  $output = $this->object->getClozeText();
947  foreach ($this->object->getGaps() as $gap_index => $gap)
948  {
949  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", TRUE, TRUE, "Modules/TestQuestionPool");
950  $found = array();
951  foreach ($user_solution as $solutionarray)
952  {
953  if ($solutionarray["value1"] == $gap_index) $found = $solutionarray;
954  }
955 
956  if ($active_id)
957  {
958  if ($graphicalOutput)
959  {
960  // output of ok/not ok icons for user entered solutions
961  $details = $this->object->calculateReachedPoints($active_id, $pass, TRUE);
962  $check = $details[$gap_index];
963 
964  $assClozeGapCombinationObject = new assClozeGapCombination();
965  $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
966  if(count($check_for_gap_combinations) != 0)
967  {
968  $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
969  $custom_user_solution = array();
970  if(array_key_exists($gap_index, $gaps_used_in_combination))
971  {
972  $combination_id = $gaps_used_in_combination[$gap_index];
973  foreach($gaps_used_in_combination as $key => $value)
974  {
975  $a = 0;
976  if($value == $combination_id)
977  {
978 
979  foreach($user_solution as $solution_key => $solution_value)
980  {
981  if($solution_value['value1'] == $key)
982  {
983  $result_row = array();
984  $result_row['gap_id'] = $solution_value['value1'];
985  $result_row['value'] = $solution_value['value2'];
986  array_push($custom_user_solution, $result_row);
987  }
988  }
989  }
990  }
991  $points_array = $this->object->calculateCombinationResult($custom_user_solution);
992  $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
993  if($points_array[0] == $max_combination_points)
994  {
995  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
996  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
997  }
998  else if($points_array[0] > 0)
999  {
1000  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1001  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1002  }
1003  else
1004  {
1005  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1006  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1007  }
1008 
1009  }
1010  else
1011  {
1012  if ($check["best"])
1013  {
1014  $gaptemplate->setCurrentBlock("icon_ok");
1015  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
1016  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
1017  $gaptemplate->parseCurrentBlock();
1018  }
1019  else
1020  {
1021  $gaptemplate->setCurrentBlock("icon_not_ok");
1022  if ($check["positive"])
1023  {
1024  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1025  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1026  }
1027  else
1028  {
1029  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1030  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1031  }
1032  $gaptemplate->parseCurrentBlock();
1033  }
1034  }
1035  }
1036  else
1037  {
1038  if ($check["best"])
1039  {
1040  $gaptemplate->setCurrentBlock("icon_ok");
1041  $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
1042  $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
1043  $gaptemplate->parseCurrentBlock();
1044  }
1045  else
1046  {
1047  $gaptemplate->setCurrentBlock("icon_not_ok");
1048  if ($check["positive"])
1049  {
1050  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1051  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1052  }
1053  else
1054  {
1055  $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1056  $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1057  }
1058  $gaptemplate->parseCurrentBlock();
1059  }
1060  }
1061 
1062  }
1063  }
1064  if ($result_output)
1065  {
1066  $points = $this->object->getMaximumGapPoints($gap_index);
1067  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
1068  $gaptemplate->setCurrentBlock("result_output");
1069  $gaptemplate->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
1070  $gaptemplate->parseCurrentBlock();
1071  }
1072  switch ($gap->getType())
1073  {
1074  case CLOZE_TEXT:
1075  $solutiontext = "";
1076  if (($active_id > 0) && (!$show_correct_solution))
1077  {
1078  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1079  {
1080  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1081  {
1082  $solutiontext .= "&nbsp;";
1083  }
1084  }
1085  else
1086  {
1087  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1088  }
1089  }
1090  else
1091  {
1092  $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput());
1093  }
1094  $gaptemplate->setVariable("SOLUTION", $solutiontext);
1095  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1096  break;
1097  case CLOZE_SELECT:
1098  $solutiontext = "";
1099  if (($active_id > 0) && (!$show_correct_solution))
1100  {
1101  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1102  {
1103  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1104  {
1105  $solutiontext .= "&nbsp;";
1106  }
1107  }
1108  else
1109  {
1110  $item = $gap->getItem($found["value2"]);
1111  if (is_object($item))
1112  {
1113  $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1114  }
1115  else
1116  {
1117  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1118  {
1119  $solutiontext .= "&nbsp;";
1120  }
1121  }
1122  }
1123  }
1124  else
1125  {
1126  $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput());
1127  }
1128  $gaptemplate->setVariable("SOLUTION", $solutiontext);
1129  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1130  break;
1131  case CLOZE_NUMERIC:
1132  $solutiontext = "";
1133  if (($active_id > 0) && (!$show_correct_solution))
1134  {
1135  if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1136  {
1137  for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1138  {
1139  $solutiontext .= "&nbsp;";
1140  }
1141  }
1142  else
1143  {
1144  $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1145  }
1146  }
1147  else
1148  {
1149  $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput());
1150  }
1151  $gaptemplate->setVariable("SOLUTION", $solutiontext);
1152  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1153  break;
1154  }
1155  }
1156 
1157  if ($show_question_text)
1158  {
1159  $template->setVariable(
1160  "QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true)
1161  );
1162  }
1163 
1164  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
1165  // generate the question output
1166  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
1167  $questionoutput = $template->get();
1168 
1169  $feedback = '';
1170  if($show_feedback)
1171  {
1172  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1173  $feedback .= strlen($fb) ? $fb : '';
1174 
1175  $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
1176  $feedback .= strlen($fb) ? $fb : '';
1177  }
1178  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $feedback);
1179 
1180  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1181 
1182  $solutionoutput = $solutiontemplate->get();
1183 
1184  $assClozeGapCombinationObject = new assClozeGapCombination();
1185  $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
1186  if(count($check_for_gap_combinations) != 0)
1187  {
1188  $solutionoutput .= '<i>Best Combination is: ' . $assClozeGapCombinationObject->getBestSolutionCombination($this->object->getId()) . '</i>';
1189  }
1190  if (!$show_question_only)
1191  {
1192  // get page object output
1193  $solutionoutput = $this->getILIASPage($solutionoutput);
1194  }
1195 
1196  return $solutionoutput;
1197  }
1198 
1199  public function getAnswerFeedbackOutput($active_id, $pass)
1200  {
1201  include_once "./Modules/Test/classes/class.ilObjTest.php";
1202  $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1203  if (strlen($manual_feedback))
1204  {
1205  return $manual_feedback;
1206  }
1207  $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1208  $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1209  if (strlen($correct_feedback.$incorrect_feedback))
1210  {
1211  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
1212  $max_points = $this->object->getMaximumPoints();
1213  if ($reached_points == $max_points)
1214  {
1215  $output .= $correct_feedback;
1216  }
1217  else
1218  {
1219  $output .= $incorrect_feedback;
1220  }
1221  }
1222  $test = new ilObjTest($this->object->active_id);
1223  return $this->object->prepareTextareaOutput($output, TRUE);
1224  }
1225 
1226  function getTestOutput(
1227  $active_id,
1228  $pass = NULL,
1229  $is_postponed = FALSE,
1230  $use_post_solutions = FALSE,
1231  $show_feedback = FALSE
1232  )
1233  {
1234  // get the solution of the user for the active pass or from the last pass if allowed
1235  $user_solution = array();
1236  if ($active_id)
1237  {
1238  include_once "./Modules/Test/classes/class.ilObjTest.php";
1239  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1240  {
1241  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1242  }
1243  $user_solution =& $this->object->getSolutionValues($active_id, $pass);
1244  if (!is_array($user_solution))
1245  {
1246  $user_solution = array();
1247  }
1248  }
1249 
1250  // generate the question output
1251  include_once "./Services/UICore/classes/class.ilTemplate.php";
1252  $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
1253  $output = $this->object->getClozeText();
1254  foreach ($this->object->getGaps() as $gap_index => $gap)
1255  {
1256  switch ($gap->getType())
1257  {
1258  case CLOZE_TEXT:
1259  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", TRUE, TRUE, "Modules/TestQuestionPool");
1260  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1261 
1262  if($gap_size > 0)
1263  {
1264  $gaptemplate->setCurrentBlock('size_and_maxlength');
1265  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1266  $gaptemplate->parseCurrentBlock();
1267  }
1268 
1269  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1270  foreach ($user_solution as $solution)
1271  {
1272  if (strcmp($solution["value1"], $gap_index) == 0)
1273  {
1274  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1275  }
1276  }
1277  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1278  break;
1279  case CLOZE_SELECT:
1280  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", TRUE, TRUE, "Modules/TestQuestionPool");
1281  foreach ($gap->getItems() as $item)
1282  {
1283  $gaptemplate->setCurrentBlock("select_gap_option");
1284  $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1285  $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1286  foreach ($user_solution as $solution)
1287  {
1288  if (strcmp($solution["value1"], $gap_index) == 0)
1289  {
1290  if (strcmp($solution["value2"], $item->getOrder()) == 0)
1291  {
1292  $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1293  }
1294  }
1295  }
1296  $gaptemplate->parseCurrentBlock();
1297  }
1298  $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1299  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1300  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1301  break;
1302  case CLOZE_NUMERIC:
1303  $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", TRUE, TRUE, "Modules/TestQuestionPool");
1304  $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1305  if($gap_size > 0)
1306  {
1307  $gaptemplate->setCurrentBlock('size_and_maxlength');
1308  $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1309  $gaptemplate->parseCurrentBlock();
1310  }
1311 
1312  $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1313  foreach ($user_solution as $solution)
1314  {
1315  if (strcmp($solution["value1"], $gap_index) == 0)
1316  {
1317  $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1318  }
1319  }
1320  $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1321  break;
1322  }
1323  }
1324 
1325  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
1326  $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
1327  $questionoutput = $template->get();
1328  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1329  return $pageoutput;
1330  }
1331 
1339  public function setQuestionTabs()
1340  {
1341  global $rbacsystem, $ilTabs;
1342 
1343  $ilTabs->clearTargets();
1344 
1345  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1346  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1347  $q_type = $this->object->getQuestionType();
1348 
1349  if (strlen($q_type))
1350  {
1351  $classname = $q_type . "GUI";
1352  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1353  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1354 # $this->ctrl->setParameterByClass(strtolower($classname), 'prev_qid', $_REQUEST['prev_qid']);
1355  }
1356 
1357  if ($_GET["q_id"])
1358  {
1359  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1360  {
1361  // edit page
1362  $ilTabs->addTarget("edit_page",
1363  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1364  array("edit", "insert", "exec_pg"),
1365  "", "", $force_active);
1366  }
1367 
1368  $this->addTab_QuestionPreview($ilTabs);
1369  }
1370 
1371  $force_active = false;
1372  $commands = $_POST["cmd"];
1373  if (is_array($commands))
1374  {
1375  foreach ($commands as $key => $value)
1376  {
1377  if (preg_match("/^removegap_.*/", $key, $matches) ||
1378  preg_match("/^addgap_.*/", $key, $matches)
1379  )
1380  {
1381  $force_active = true;
1382  }
1383  }
1384  }
1385  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1386  {
1387  $url = "";
1388  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1389  // edit question properties
1390  $ilTabs->addTarget("edit_question",
1391  $url,
1392  array("editQuestion", "originalSyncForm", "save", "createGaps", "saveEdit"),
1393  $classname, "", $force_active);
1394  }
1395 
1396  // add tab for question feedback within common class assQuestionGUI
1397  $this->addTab_QuestionFeedback($ilTabs);
1398 
1399  // add tab for question hint within common class assQuestionGUI
1400  $this->addTab_QuestionHints($ilTabs);
1401 
1402  // add tab for question's suggested solution within common class assQuestionGUI
1403  $this->addTab_SuggestedSolution($ilTabs, $classname);
1404 
1405  // Assessment of questions sub menu entry
1406  if ($_GET["q_id"])
1407  {
1408  $ilTabs->addTarget("statistics",
1409  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1410  array("assessment"),
1411  $classname, "");
1412  }
1413 
1414  $this->addBackTab($ilTabs);
1415  }
1416 
1417  function getSpecificFeedbackOutput($active_id, $pass)
1418  {
1419  if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($this->object->gaps)) )
1420  {
1421  return '';
1422  }
1423 
1424  global $lng;
1425 
1426  $feedback = '<table class="test_specific_feedback"><tbody>';
1427 
1428  foreach ($this->object->gaps as $index => $answer)
1429  {
1430  $caption = $lng->txt('gap').' '.($index+1) .': ';
1431 
1432  $feedback .= '<tr><td>';
1433 
1434  $feedback .= $caption .'</td><td>';
1435  $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1436  $this->object->getId(), $index
1437  ) . '</td> </tr>';
1438  }
1439  $feedback .= '</tbody></table>';
1440 
1441  return $this->object->prepareTextareaOutput($feedback, TRUE);
1442  }
1443 
1454  {
1455  return array();
1456  }
1457 
1468  {
1469  return array();
1470  }
1471 
1480  public function getAggregatedAnswersView($relevant_answers)
1481  {
1482  $overview = array();
1483  $aggregation = array();
1484  foreach ($relevant_answers as $answer)
1485  {
1486  $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1487  }
1488 
1489  foreach($overview as $active)
1490  {
1491  foreach ($active as $answer)
1492  {
1493  foreach ($answer as $option => $value)
1494  {
1495  $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1496  }
1497  }
1498  }
1499 
1500  $html = '<div>';
1501  $i = 0;
1502  foreach ($this->object->getGaps() as $gap)
1503  {
1504  if ($gap->type == CLOZE_SELECT)
1505  {
1506  $html .= '<p>Gap '.$i . ' - SELECT</p>';
1507  $html .= '<ul>';
1508  $j = 0;
1509  foreach($gap->getItems() as $gap_item)
1510  {
1511  $aggregate = $aggregation[$i];
1512  $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1513  $j++;
1514  }
1515  $html .= '</ul>';
1516  }
1517 
1518  if($gap->type == CLOZE_TEXT)
1519  {
1520  $html .= '<p>Gap '.$i . ' - TEXT</p>';
1521  $html .= '<ul>';
1522  $aggregate = (array)$aggregation[$i];
1523  foreach($aggregate as $answer => $count)
1524  {
1525  $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1526  }
1527  $html .= '</ul>';
1528  }
1529 
1530  if($gap->type == CLOZE_NUMERIC)
1531  {
1532  $html .= '<p>Gap '.$i . ' - NUMERIC</p>';
1533  $html .= '<ul>';
1534  $j = 0;
1535  foreach($gap->getItems() as $gap_item)
1536  {
1537  $aggregate = (array)$aggregation[$i];
1538  foreach($aggregate as $answer => $count)
1539  {
1540  $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1541  }
1542  $j++;
1543  }
1544  $html .= '</ul>';
1545  }
1546  $i++;
1547  $html .= '<hr />';
1548  }
1549 
1550  $html .= '</div>';
1551  return $html;
1552  }
1553 
1554  public function applyIndizesToGapText( $question_text )
1555  {
1556  $parts = explode( '[gap', $question_text );
1557  $i = 0;
1558  $question_text = '';
1559  foreach ( $parts as $part )
1560  {
1561  if ( $i == 0 )
1562  {
1563  $question_text .= $part;
1564  }
1565  else
1566  {
1567  $question_text .= '[gap ' . $i . $part;
1568  }
1569  $i++;
1570  }
1571  return $question_text;
1572  }
1573 
1574  public function removeIndizesFromGapText( $question_text )
1575  {
1576  $parts = preg_split( '/\[gap \d*\]/', $question_text );
1577  $question_text = implode( '[gap]', $parts );
1578  return $question_text;
1579  }
1580 }