ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.assClozeTestGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7
23{
24 const OLD_CLOZE_TEST_UI = false;
25
29 private $gapIndex;
30
36 public function __construct($id = -1)
37 {
38 parent::__construct();
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();
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 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
341 $question->setUseTagsForRteOnly(false);
342 }
343 $form->addItem($question);
344
345// $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
346// $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
347// $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
348// $tpl->parseCurrentBlock();
349// $button = new ilCustomInputGUI('&nbsp;','');
350// $button->setHtml($tpl->get());
351// $form->addItem($button);
352
353 if (!$this->object->getSelfAssessmentEditingMode())
354 {
355 // duration
356 $duration = new ilDurationInputGUI($this->lng->txt("working_time"), "Estimated");
357 $duration->setShowHours(TRUE);
358 $duration->setShowMinutes(TRUE);
359 $duration->setShowSeconds(TRUE);
360 $ewt = $this->object->getEstimatedWorkingTime();
361 $duration->setHours($ewt["h"]);
362 $duration->setMinutes($ewt["m"]);
363 $duration->setSeconds($ewt["s"]);
364 $duration->setRequired(FALSE);
365 $form->addItem($duration);
366 }
367 else
368 {
369 // number of tries
370 if (strlen($this->object->getNrOfTries()))
371 {
372 $nr_tries = $this->object->getNrOfTries();
373 }
374 else
375 {
376 $nr_tries = $this->object->getDefaultNrOfTries();
377 }
378 /*if ($nr_tries <= 0)
379 {
380 $nr_tries = 1;
381 }*/
382
383 if ($nr_tries < 0)
384 {
385 $nr_tries = 0;
386 }
387
388 $ni = new ilNumberInputGUI($this->lng->txt("qst_nr_of_tries"), "nr_of_tries");
389 $ni->setValue($nr_tries);
390 //$ni->setMinValue(1);
391 $ni->setMinValue(0);
392 $ni->setSize(5);
393 $ni->setMaxLength(5);
394 $ni->setRequired(true);
395 $form->addItem($ni);
396 }
397 }
398
400 {
401 // cloze text
402 $cloze_text = new ilTextAreaInputGUI($this->lng->txt("cloze_text"), 'cloze_text');
403 $cloze_text->setRequired(true);
404 $cloze_text->setValue($this->applyIndizesToGapText($this->object->getClozeText()));
405 $cloze_text->setInfo($this->lng->txt("close_text_hint"));
406 $cloze_text->setRows( 10 );
407 $cloze_text->setCols( 80 );
408 if (!$this->object->getSelfAssessmentEditingMode())
409 {
410 if( $this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT )
411 {
412 $cloze_text->setUseRte(TRUE);
413 include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
414 $cloze_text->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
415 $cloze_text->addPlugin("latex");
416 $cloze_text->addButton("latex");
417 $cloze_text->addButton("pastelatex");
418 }
419 }
420 else
421 {
422 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
424 $cloze_text->setUseTagsForRteOnly(false);
425 }
426 $cloze_text->setRTESupport($this->object->getId(), "qpl", "assessment");
427 $form->addItem($cloze_text);
428
429 $tpl = new ilTemplate("tpl.il_as_qpl_cloze_gap_button_code.html", TRUE, TRUE, "Modules/TestQuestionPool");
430 $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
431 $tpl->setVariable('CREATE_GAPS', $this->lng->txt('create_gaps'));
432 $tpl->parseCurrentBlock();
433 $button = new ilCustomInputGUI('&nbsp;','');
434 $button->setHtml($tpl->get());
435 $form->addItem($button);
436
437 // text rating
438 if (!$this->object->getSelfAssessmentEditingMode())
439 {
440 $textrating = new ilSelectInputGUI($this->lng->txt( "text_rating" ), "textgap_rating");
441 $text_options = array(
442 "ci" => $this->lng->txt( "cloze_textgap_case_insensitive" ),
443 "cs" => $this->lng->txt( "cloze_textgap_case_sensitive" ),
444 "l1" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "1" ),
445 "l2" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "2" ),
446 "l3" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "3" ),
447 "l4" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "4" ),
448 "l5" => sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "5" )
449 );
450 $textrating->setOptions( $text_options );
451 $textrating->setValue( $this->object->getTextgapRating() );
452 $form->addItem( $textrating );
453
454 // text field length
455 $fixedTextLength = new ilNumberInputGUI($this->lng->txt( "cloze_fixed_textlength" ), "fixedTextLength");
456 $ftl = $this->object->getFixedTextLength();
457
458 $fixedTextLength->setValue( $ftl > 0 ? $ftl : '' );
459 $fixedTextLength->setMinValue( 0 );
460 $fixedTextLength->setSize( 3 );
461 $fixedTextLength->setMaxLength( 6 );
462 $fixedTextLength->setInfo( $this->lng->txt( 'cloze_fixed_textlength_description' ) );
463 $fixedTextLength->setRequired( false );
464 $form->addItem( $fixedTextLength );
465
466 // identical scoring
467 $identical_scoring = new ilCheckboxInputGUI($this->lng->txt( "identical_scoring" ), "identical_scoring");
468 $identical_scoring->setValue( 1 );
469 $identical_scoring->setChecked( $this->object->getIdenticalScoring() );
470 $identical_scoring->setInfo( $this->lng->txt( 'identical_scoring_desc' ) );
471 $identical_scoring->setRequired( FALSE );
472 $form->addItem( $identical_scoring );
473 }
474 return $form;
475 }
476
478 {
479 if(self::OLD_CLOZE_TEST_UI)
480 {
481 for ($gapCounter = 0; $gapCounter < $this->object->getGapCount(); $gapCounter++)
482 {
483 $this->populateGapFormPart( $form, $gapCounter );
484 }
485 return $form;
486 }
487 else
488 {
489 require_once 'Modules/TestQuestionPool/classes/Form/class.ilClozeGapInputBuilderGUI.php';
490 $json=$this->populateJSON();
491 $assClozeGapCombinationObject = new assClozeGapCombination();
492 $combination_exists = $assClozeGapCombinationObject->combinationExistsForQid($this->object->id);
493 if($combination_exists)
494 {
495 $combinations = $assClozeGapCombinationObject->loadFromDb($this->object->id);
496 }
497 $new_builder = new ilClozeGapInputBuilderGUI();
499 $form->addItem($header);
500 $new_builder->setValueByArray($json);
501 $new_builder->setValueCombinationFromDb($combinations);
502 $form->addItem($new_builder);
503 return $form;
504 }
505 }
506
507 protected function populateJSON()
508 {
509 $gap = $this->object->getGaps();
510 $array = array();
511 if ($gap == null)
512 {
513 return $array;
514 }
515 $translate_type=array('text','select','numeric');
516 $i = 0;
517 foreach ($gap as $content)
518 {
519 $shuffle=false;
520 $value=$content->getItemsRaw();
521 $items=array();
522 for($j=0;$j<count($value);$j++)
523 {
524 if($content->getType()==2)
525 {
526 $items[$j] = array(
527 'answer' => $value[$j]->getAnswerText(),
528 'lower' => $value[$j]->getLowerBound(),
529 'upper' => $value[$j]->getUpperBound(),
530 'points' => $value[$j]->getPoints(),
531 'error' => false
532 );
533 }
534 else
535 {
536 $items[$j] = array(
537 'answer' => $value[$j]->getAnswerText(),
538 'points' => $value[$j]->getPoints(),
539 'error' => false
540 );
541
542 if($content->getType()==1)
543 {
544 $shuffle=$content->getShuffle();
545 }
546 }
547 }
548 $answers[$i]=array(
549 'type' => $translate_type[$content->getType()] ,
550 'values' => $items ,
551 'shuffle' => $shuffle,
552 'text_field_length' => $content->getGapSize() > 0 ? $content->getGapSize() : '',
553 'used_in_gap_combination' => true);
554 $i++;
555 }
556 return $answers;
557 }
569 protected function populateGapFormPart($form, $gapCounter)
570 {
571 $gap = $this->object->getGap( $gapCounter );
572
573 if ($gap == null)
574 {
575 return $form;
576 }
577
579 $header->setTitle( $this->lng->txt( "gap" ) . " " . ($gapCounter + 1) );
580 $form->addItem( $header );
581
582 $gapcounter = new ilHiddenInputGUI("gap[$gapCounter]");
583 $gapcounter->setValue( $gapCounter );
584 $form->addItem( $gapcounter );
585
586 $gaptype = new ilSelectInputGUI($this->lng->txt( 'type' ), "clozetype_$gapCounter");
587 $options = array(
588 0 => $this->lng->txt( "text_gap" ),
589 1 => $this->lng->txt( "select_gap" ),
590 2 => $this->lng->txt( "numeric_gap" )
591 );
592 $gaptype->setOptions( $options );
593 $gaptype->setValue( $gap->getType() );
594 $form->addItem( $gaptype );
595
596 if ($gap->getType() == CLOZE_TEXT)
597 {
598 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
599
600 if (count( $gap->getItemsRaw() ) == 0)
601 $gap->addItem( new assAnswerCloze("", 0, 0) );
602 $this->populateTextGapFormPart( $form, $gap, $gapCounter );
603 }
604 else if ($gap->getType() == CLOZE_SELECT)
605 {
606 if (count( $gap->getItemsRaw() ) == 0)
607 $gap->addItem( new assAnswerCloze("", 0, 0) );
608 $this->populateSelectGapFormPart( $form, $gap, $gapCounter );
609 }
610 else if ($gap->getType() == CLOZE_NUMERIC)
611 {
612 $this->populateGapSizeFormPart($form, $gap, $gapCounter);
613
614 if (count( $gap->getItemsRaw() ) == 0)
615 $gap->addItem( new assAnswerCloze("", 0, 0) );
616 foreach ($gap->getItemsRaw() as $item)
617 {
618 $this->populateNumericGapFormPart( $form, $item, $gapCounter );
619 }
620 }
621 return $form;
622 }
623
629 protected function populateGapSizeFormPart($form, $gap, $gapCounter)
630 {
631 $gapSizeFormItem = new ilNumberInputGUI($this->lng->txt('cloze_fixed_textlength'), "gap_".$gapCounter.'_gapsize');
632
633 $gapSizeFormItem->allowDecimals(false);
634 $gapSizeFormItem->setMinValue(0);
635 $gapSizeFormItem->setSize( 3 );
636 $gapSizeFormItem->setMaxLength( 6 );
637 $gapSizeFormItem->setInfo($this->lng->txt('cloze_gap_size_info'));
638 $gapSizeFormItem->setValue($gap->getGapSize());
639 $form->addItem($gapSizeFormItem);
640
641 return $form;
642 }
643
656 protected function populateSelectGapFormPart($form, $gap, $gapCounter)
657 {
658 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
659 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
660 $values = new ilAnswerWizardInputGUI($this->lng->txt( "values" ), "gap_" . $gapCounter . "");
661 $values->setRequired( true );
662 $values->setQuestionObject( $this->object );
663 $values->setSingleline( true );
664 $values->setAllowMove( false );
665
666 $values->setValues( $gap->getItemsRaw() );
667 $form->addItem( $values );
668
669 // shuffle
670 $shuffle = new ilCheckboxInputGUI($this->lng->txt( "shuffle_answers" ), "shuffle_" . $gapCounter . "");
671 $shuffle->setValue( 1 );
672 $shuffle->setChecked( $gap->getShuffle() );
673 $shuffle->setRequired( FALSE );
674 $form->addItem( $shuffle );
675 return $form;
676 }
677
689 protected function populateTextGapFormPart($form, $gap, $gapCounter)
690 {
691 // Choices
692 include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
693 include_once "./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
694 $values = new ilAnswerWizardInputGUI($this->lng->txt( "values" ), "gap_" . $gapCounter . "");
695 $values->setRequired( true );
696 $values->setQuestionObject( $this->object );
697 $values->setSingleline( true );
698 $values->setAllowMove( false );
699 $values->setValues( $gap->getItemsRaw() );
700 $form->addItem( $values );
701
702 if( $this->object->getFixedTextLength() > 0 )
703 {
704 $values->setSize( $this->object->getFixedTextLength() );
705 $values->setMaxLength( $this->object->getFixedTextLength() );
706 }
707
708 return $form;
709 }
710
722 protected function populateNumericGapFormPart($form, $gap, $gapCounter)
723 {
724 // #8944: the js-based ouput in self-assessment cannot support formulas
725 if (!$this->object->getSelfAssessmentEditingMode())
726 {
727 $value = new ilFormulaInputGUI($this->lng->txt( 'value' ), "gap_" . $gapCounter . "_numeric");
728 $value->setInlineStyle( 'text-align: right;' );
729
730 $lowerbound = new ilFormulaInputGUI($this->lng->txt( 'range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
731 $lowerbound->setInlineStyle( 'text-align: right;' );
732
733 $upperbound = new ilFormulaInputGUI($this->lng->txt( 'range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
734 $upperbound->setInlineStyle( 'text-align: right;' );
735 }
736 else
737 {
738 $value = new ilNumberInputGUI($this->lng->txt( 'value' ), "gap_" . $gapCounter . "_numeric");
739 $value->allowDecimals( true );
740
741 $lowerbound = new ilNumberInputGUI($this->lng->txt( 'range_lower_limit'), "gap_" . $gapCounter . "_numeric_lower");
742 $lowerbound->allowDecimals( true );
743
744 $upperbound = new ilNumberInputGUI($this->lng->txt( 'range_upper_limit'), "gap_" . $gapCounter . "_numeric_upper");
745 $upperbound->allowDecimals( true );
746 }
747
748 $value->setSize( 10 );
749 $value->setValue( ilUtil::prepareFormOutput( $gap->getAnswertext() ) );
750 $value->setRequired( true );
751 $form->addItem( $value );
752
753 $lowerbound->setSize( 10 );
754 $lowerbound->setRequired( true );
755 $lowerbound->setValue( ilUtil::prepareFormOutput( $gap->getLowerBound() ) );
756 $form->addItem( $lowerbound );
757
758 $upperbound->setSize( 10 );
759 $upperbound->setRequired( true );
760 $upperbound->setValue( ilUtil::prepareFormOutput( $gap->getUpperBound() ) );
761 $form->addItem( $upperbound );
762
763 if( $this->object->getFixedTextLength() > 0 )
764 {
765 $value->setSize( $this->object->getFixedTextLength() );
766 $value->setMaxLength( $this->object->getFixedTextLength() );
767 $lowerbound->setSize( $this->object->getFixedTextLength() );
768 $lowerbound->setMaxLength( $this->object->getFixedTextLength() );
769 $upperbound->setSize( $this->object->getFixedTextLength() );
770 $upperbound->setMaxLength( $this->object->getFixedTextLength() );
771 }
772
773 $points = new ilNumberInputGUI($this->lng->txt( 'points' ), "gap_" . $gapCounter . "_numeric_points");
774 $points->allowDecimals(true);
775 $points->setSize( 3 );
776 $points->setRequired( true );
777 $points->setValue( ilUtil::prepareFormOutput( $gap->getPoints() ) );
778 $form->addItem( $points );
779 return $form;
780 }
781
785 public function createGaps()
786 {
787 $this->writePostData(true);
788 $this->object->saveToDb();
789 $this->editQuestion();
790 }
791
795 function removegap()
796 {
797 $this->writePostData(true);
798 $this->object->deleteAnswerText($this->gapIndex, key($_POST['cmd']['removegap_' . $this->gapIndex]));
799 $this->editQuestion();
800 }
801
805 function addgap()
806 {
807 $this->writePostData(true);
808 $this->object->addGapAnswer($this->gapIndex, key($_POST['cmd']['addgap_' . $this->gapIndex])+1, "");
809 $this->editQuestion();
810 }
811
820 function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
821 {
822 $user_solution = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
823
824 // generate the question output
825 include_once "./Services/UICore/classes/class.ilTemplate.php";
826 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
827 $output = $this->object->getClozeText();
828 foreach ($this->object->getGaps() as $gap_index => $gap)
829 {
830 switch ($gap->getType())
831 {
832 case CLOZE_TEXT:
833 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", TRUE, TRUE, "Modules/TestQuestionPool");
834
835 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
836 if($gap_size > 0)
837 {
838 $gaptemplate->setCurrentBlock('size_and_maxlength');
839 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
840 $gaptemplate->parseCurrentBlock();
841 }
842 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
843 foreach ($user_solution as $val1 => $val2)
844 {
845 if (strcmp($val1, $gap_index) == 0)
846 {
847 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
848 }
849 }
850 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
851 break;
852 case CLOZE_SELECT:
853 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", TRUE, TRUE, "Modules/TestQuestionPool");
854 foreach ($gap->getItems($this->object->getShuffler()) as $item)
855 {
856 $gaptemplate->setCurrentBlock("select_gap_option");
857 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
858 $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
859 foreach ($user_solution as $val1 => $val2)
860 {
861 if (strcmp($val1, $gap_index) == 0)
862 {
863 if (strcmp($val2, $item->getOrder()) == 0)
864 {
865 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
866 }
867 }
868 }
869 $gaptemplate->parseCurrentBlock();
870 }
871 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
872 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
873 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
874 break;
875 case CLOZE_NUMERIC:
876 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", TRUE, TRUE, "Modules/TestQuestionPool");
877 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
878 if($gap_size > 0)
879 {
880 $gaptemplate->setCurrentBlock('size_and_maxlength');
881 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
882 $gaptemplate->parseCurrentBlock();
883 }
884 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
885 foreach ($user_solution as $val1 => $val2)
886 {
887 if (strcmp($val1, $gap_index) == 0)
888 {
889 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($val2) . "\"");
890 }
891 }
892 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
893 break;
894 }
895 }
896 $template->setVariable("QUESTIONTEXT",$this->object->prepareTextareaOutput( $this->object->getQuestion(), true));
897 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
898 $questionoutput = $template->get();
899 if (!$show_question_only)
900 {
901 // get page object output
902 $questionoutput = $this->getILIASPage($questionoutput);
903 }
904 return $questionoutput;
905 }
906
923 $active_id,
924 $pass = NULL,
925 $graphicalOutput = FALSE,
926 $result_output = FALSE,
927 $show_question_only = TRUE,
928 $show_feedback = FALSE,
929 $show_correct_solution = FALSE,
930 $show_manual_scoring = FALSE,
931 $show_question_text = TRUE
932 )
933 {
934 // get the solution of the user for the active pass or from the last pass if allowed
935 $user_solution = array();
936 if (($active_id > 0) && (!$show_correct_solution))
937 {
938 // get the solutions of a user
939 $user_solution =& $this->object->getSolutionValues($active_id, $pass);
940 if(!is_array($user_solution))
941 {
942 $user_solution = array();
943 }
944 }
945
946 include_once "./Services/UICore/classes/class.ilTemplate.php";
947 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
948 $output = $this->object->getClozeText();
949 foreach ($this->object->getGaps() as $gap_index => $gap)
950 {
951 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_output_solution_gap.html", TRUE, TRUE, "Modules/TestQuestionPool");
952 $found = array();
953 foreach ($user_solution as $solutionarray)
954 {
955 if ($solutionarray["value1"] == $gap_index) $found = $solutionarray;
956 }
957
958 if ($active_id)
959 {
960 if ($graphicalOutput)
961 {
962 // output of ok/not ok icons for user entered solutions
963 $details = $this->object->calculateReachedPoints($active_id, $pass, true, TRUE);
964 $check = $details[$gap_index];
965
966 $assClozeGapCombinationObject = new assClozeGapCombination();
967 $check_for_gap_combinations = $assClozeGapCombinationObject->loadFromDb($this->object->getId());
968 if(count($check_for_gap_combinations) != 0)
969 {
970 $gaps_used_in_combination = $assClozeGapCombinationObject->getGapsWhichAreUsedInCombination($this->object->getId());
971 $custom_user_solution = array();
972 if(array_key_exists($gap_index, $gaps_used_in_combination))
973 {
974 $combination_id = $gaps_used_in_combination[$gap_index];
975 foreach($gaps_used_in_combination as $key => $value)
976 {
977 $a = 0;
978 if($value == $combination_id)
979 {
980
981 foreach($user_solution as $solution_key => $solution_value)
982 {
983 if($solution_value['value1'] == $key)
984 {
985 $result_row = array();
986 $result_row['gap_id'] = $solution_value['value1'];
987 $result_row['value'] = $solution_value['value2'];
988 array_push($custom_user_solution, $result_row);
989 }
990 }
991 }
992 }
993 $points_array = $this->object->calculateCombinationResult($custom_user_solution);
994 $max_combination_points = $assClozeGapCombinationObject->getMaxPointsForCombination($this->object->getId(), $combination_id);
995 if($points_array[0] == $max_combination_points)
996 {
997 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
998 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
999 }
1000 else if($points_array[0] > 0)
1001 {
1002 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1003 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1004 }
1005 else
1006 {
1007 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1008 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1009 }
1010
1011 }
1012 else
1013 {
1014 if ($check["best"])
1015 {
1016 $gaptemplate->setCurrentBlock("icon_ok");
1017 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
1018 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
1019 $gaptemplate->parseCurrentBlock();
1020 }
1021 else
1022 {
1023 $gaptemplate->setCurrentBlock("icon_not_ok");
1024 if ($check["positive"])
1025 {
1026 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1027 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1028 }
1029 else
1030 {
1031 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1032 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1033 }
1034 $gaptemplate->parseCurrentBlock();
1035 }
1036 }
1037 }
1038 else
1039 {
1040 if ($check["best"])
1041 {
1042 $gaptemplate->setCurrentBlock("icon_ok");
1043 $gaptemplate->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
1044 $gaptemplate->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
1045 $gaptemplate->parseCurrentBlock();
1046 }
1047 else
1048 {
1049 $gaptemplate->setCurrentBlock("icon_not_ok");
1050 if ($check["positive"])
1051 {
1052 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
1053 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
1054 }
1055 else
1056 {
1057 $gaptemplate->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
1058 $gaptemplate->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
1059 }
1060 $gaptemplate->parseCurrentBlock();
1061 }
1062 }
1063
1064 }
1065 }
1066 if ($result_output)
1067 {
1068 $points = $this->object->getMaximumGapPoints($gap_index);
1069 $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
1070 $gaptemplate->setCurrentBlock("result_output");
1071 $gaptemplate->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
1072 $gaptemplate->parseCurrentBlock();
1073 }
1074 switch ($gap->getType())
1075 {
1076 case CLOZE_TEXT:
1077 $solutiontext = "";
1078 if (($active_id > 0) && (!$show_correct_solution))
1079 {
1080 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1081 {
1082 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1083 {
1084 $solutiontext .= "&nbsp;";
1085 }
1086 }
1087 else
1088 {
1089 $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1090 }
1091 }
1092 else
1093 {
1094 $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1095 $this->object->getShuffler()
1096 ));
1097 }
1098 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1099 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1100 break;
1101 case CLOZE_SELECT:
1102 $solutiontext = "";
1103 if (($active_id > 0) && (!$show_correct_solution))
1104 {
1105 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1106 {
1107 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1108 {
1109 $solutiontext .= "&nbsp;";
1110 }
1111 }
1112 else
1113 {
1114 $item = $gap->getItem($found["value2"]);
1115 if (is_object($item))
1116 {
1117 $solutiontext = ilUtil::prepareFormOutput($item->getAnswertext());
1118 }
1119 else
1120 {
1121 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1122 {
1123 $solutiontext .= "&nbsp;";
1124 }
1125 }
1126 }
1127 }
1128 else
1129 {
1130 $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1131 $this->object->getShuffler()
1132 ));
1133 }
1134 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1135 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1136 break;
1137 case CLOZE_NUMERIC:
1138 $solutiontext = "";
1139 if (($active_id > 0) && (!$show_correct_solution))
1140 {
1141 if ((count($found) == 0) || (strlen(trim($found["value2"])) == 0))
1142 {
1143 for ($chars = 0; $chars < $gap->getMaxWidth(); $chars++)
1144 {
1145 $solutiontext .= "&nbsp;";
1146 }
1147 }
1148 else
1149 {
1150 $solutiontext = ilUtil::prepareFormOutput($found["value2"]);
1151 }
1152 }
1153 else
1154 {
1155 $solutiontext = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
1156 $this->object->getShuffler()
1157 ));
1158 }
1159 $this->populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext);
1160 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1161 break;
1162 }
1163 }
1164
1165 if ($show_question_text)
1166 {
1167 $template->setVariable(
1168 "QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true)
1169 );
1170 }
1171
1172 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
1173 // generate the question output
1174 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
1175 $questionoutput = $template->get();
1176
1177 $feedback = '';
1178 if($show_feedback)
1179 {
1180 if( !$this->isTestPresentationContext() )
1181 {
1182 $fb = $this->getGenericFeedbackOutput($active_id, $pass);
1183 $feedback .= strlen($fb) ? $fb : '';
1184 }
1185
1186 $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
1187 $feedback .= strlen($fb) ? $fb : '';
1188 }
1189 if (strlen($feedback))
1190 {
1191 $cssClass = ( $this->hasCorrectSolution($active_id, $pass) ?
1193 );
1194
1195 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
1196 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
1197 }
1198
1199 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
1200
1201 $solutionoutput = $solutiontemplate->get();
1202
1203 if (!$show_question_only)
1204 {
1205 // get page object output
1206 $solutionoutput = $this->getILIASPage($solutionoutput);
1207 }
1208
1209 return $solutionoutput;
1210 }
1211
1212 public function getAnswerFeedbackOutput($active_id, $pass)
1213 {
1214 include_once "./Modules/Test/classes/class.ilObjTest.php";
1215 $manual_feedback = ilObjTest::getManualFeedback($active_id, $this->object->getId(), $pass);
1216 if (strlen($manual_feedback))
1217 {
1218 return $manual_feedback;
1219 }
1220 $useAuthorizedSolution = $this->isLastSolutionSubmitAuthorized($active_id, $pass);
1221 $correct_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), true);
1222 $incorrect_feedback = $this->object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(), false);
1223 if (strlen($correct_feedback.$incorrect_feedback))
1224 {
1225 $reached_points = $this->object->calculateReachedPoints($active_id, $pass, (bool)$useAuthorizedSolution);
1226 $max_points = $this->object->getMaximumPoints();
1227 if ($reached_points == $max_points)
1228 {
1229 $output .= $correct_feedback;
1230 }
1231 else
1232 {
1233 $output .= $incorrect_feedback;
1234 }
1235 }
1236 $test = new ilObjTest($this->object->active_id);
1237 return $this->object->prepareTextareaOutput($output, TRUE);
1238 }
1239
1241 $active_id,
1242 // hey: prevPassSolutions - will be always available from now on
1243 $pass,
1244 // hey.
1245 $is_postponed = FALSE,
1246 $use_post_solutions = FALSE,
1247 $show_feedback = FALSE
1248 )
1249 {
1250 // get the solution of the user for the active pass or from the last pass if allowed
1251 $user_solution = array();
1252 if ($active_id)
1253 {
1254 // hey: prevPassSolutions - obsolete due to central check
1255 #include_once "./Modules/Test/classes/class.ilObjTest.php";
1256 #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1257 #{
1258 # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1259 #}
1260 $user_solution = $this->getTestOutputSolutions($active_id, $pass);
1261 // hey.
1262 if (!is_array($user_solution))
1263 {
1264 $user_solution = array();
1265 }
1266 }
1267
1268 // generate the question output
1269 include_once "./Services/UICore/classes/class.ilTemplate.php";
1270 $template = new ilTemplate("tpl.il_as_qpl_cloze_question_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
1271 $output = $this->object->getClozeText();
1272 foreach ($this->object->getGaps() as $gap_index => $gap)
1273 {
1274 switch ($gap->getType())
1275 {
1276 case CLOZE_TEXT:
1277 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_text.html", TRUE, TRUE, "Modules/TestQuestionPool");
1278 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1279
1280 if($gap_size > 0)
1281 {
1282 $gaptemplate->setCurrentBlock('size_and_maxlength');
1283 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1284 $gaptemplate->parseCurrentBlock();
1285 }
1286
1287 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1288 foreach ($user_solution as $solution)
1289 {
1290 if (strcmp($solution["value1"], $gap_index) == 0)
1291 {
1292 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1293 }
1294 }
1295 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1296 break;
1297 case CLOZE_SELECT:
1298 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_select.html", TRUE, TRUE, "Modules/TestQuestionPool");
1299 foreach ($gap->getItems($this->object->getShuffler()) as $item)
1300 {
1301 $gaptemplate->setCurrentBlock("select_gap_option");
1302 $gaptemplate->setVariable("SELECT_GAP_VALUE", $item->getOrder());
1303 $gaptemplate->setVariable("SELECT_GAP_TEXT", ilUtil::prepareFormOutput($item->getAnswerText()));
1304 foreach ($user_solution as $solution)
1305 {
1306 if (strcmp($solution["value1"], $gap_index) == 0)
1307 {
1308 if (strcmp($solution["value2"], $item->getOrder()) == 0)
1309 {
1310 $gaptemplate->setVariable("SELECT_GAP_SELECTED", " selected=\"selected\"");
1311 }
1312 }
1313 }
1314 $gaptemplate->parseCurrentBlock();
1315 }
1316 $gaptemplate->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
1317 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1318 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1319 break;
1320 case CLOZE_NUMERIC:
1321 $gaptemplate = new ilTemplate("tpl.il_as_qpl_cloze_question_gap_numeric.html", TRUE, TRUE, "Modules/TestQuestionPool");
1322 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1323 if($gap_size > 0)
1324 {
1325 $gaptemplate->setCurrentBlock('size_and_maxlength');
1326 $gaptemplate->setVariable("TEXT_GAP_SIZE", $gap_size);
1327 $gaptemplate->parseCurrentBlock();
1328 }
1329
1330 $gaptemplate->setVariable("GAP_COUNTER", $gap_index);
1331 foreach ($user_solution as $solution)
1332 {
1333 if (strcmp($solution["value1"], $gap_index) == 0)
1334 {
1335 $gaptemplate->setVariable("VALUE_GAP", " value=\"" . ilUtil::prepareFormOutput($solution["value2"]) . "\"");
1336 }
1337 }
1338 $output = preg_replace("/\[gap\].*?\[\/gap\]/", $gaptemplate->get(), $output, 1);
1339 break;
1340 }
1341 }
1342
1343 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
1344 $template->setVariable("CLOZETEXT", $this->object->prepareTextareaOutput($output, TRUE));
1345 $questionoutput = $template->get();
1346 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1347 return $pageoutput;
1348 }
1349
1357 public function setQuestionTabs()
1358 {
1359 global $rbacsystem, $ilTabs;
1360
1361 $ilTabs->clearTargets();
1362
1363 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1364 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1365 $q_type = $this->object->getQuestionType();
1366
1367 if (strlen($q_type))
1368 {
1369 $classname = $q_type . "GUI";
1370 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1371 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1372# $this->ctrl->setParameterByClass(strtolower($classname), 'prev_qid', $_REQUEST['prev_qid']);
1373 }
1374
1375 if ($_GET["q_id"])
1376 {
1377 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1378 {
1379 // edit page
1380 $ilTabs->addTarget("edit_page",
1381 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1382 array("edit", "insert", "exec_pg"),
1383 "", "", $force_active);
1384 }
1385
1386 $this->addTab_QuestionPreview($ilTabs);
1387 }
1388
1389 $force_active = false;
1390 $commands = $_POST["cmd"];
1391 if (is_array($commands))
1392 {
1393 foreach ($commands as $key => $value)
1394 {
1395 if (preg_match("/^removegap_.*/", $key, $matches) ||
1396 preg_match("/^addgap_.*/", $key, $matches)
1397 )
1398 {
1399 $force_active = true;
1400 }
1401 }
1402 }
1403 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1404 {
1405 $url = "";
1406 if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1407 // edit question properties
1408 $ilTabs->addTarget("edit_question",
1409 $url,
1410 array("editQuestion", "originalSyncForm", "save", "createGaps", "saveEdit"),
1411 $classname, "", $force_active);
1412 }
1413
1414 // add tab for question feedback within common class assQuestionGUI
1415 $this->addTab_QuestionFeedback($ilTabs);
1416
1417 // add tab for question hint within common class assQuestionGUI
1418 $this->addTab_QuestionHints($ilTabs);
1419
1420 // add tab for question's suggested solution within common class assQuestionGUI
1421 $this->addTab_SuggestedSolution($ilTabs, $classname);
1422
1423 // Assessment of questions sub menu entry
1424 if ($_GET["q_id"])
1425 {
1426 $ilTabs->addTarget("statistics",
1427 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1428 array("assessment"),
1429 $classname, "");
1430 }
1431
1432 $this->addBackTab($ilTabs);
1433 }
1434
1435 function getSpecificFeedbackOutput($active_id, $pass)
1436 {
1437 if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($this->object->gaps)) )
1438 {
1439 return '';
1440 }
1441
1442 global $lng;
1443
1444 $feedback = '<table class="test_specific_feedback"><tbody>';
1445
1446 foreach ($this->object->gaps as $index => $answer)
1447 {
1448 $caption = $lng->txt('gap').' '.($index+1) .': ';
1449
1450 $feedback .= '<tr><td>';
1451
1452 $feedback .= $caption .'</td><td>';
1453 $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1454 $this->object->getId(), $index
1455 ) . '</td> </tr>';
1456 }
1457 $feedback .= '</tbody></table>';
1458
1459 return $this->object->prepareTextareaOutput($feedback, TRUE);
1460 }
1461
1472 {
1473 return array();
1474 }
1475
1486 {
1487 return array();
1488 }
1489
1498 public function getAggregatedAnswersView($relevant_answers)
1499 {
1500 $overview = array();
1501 $aggregation = array();
1502 foreach ($relevant_answers as $answer)
1503 {
1504 $overview[$answer['active_fi']][$answer['pass']][$answer['value1']] = $answer['value2'];
1505 }
1506
1507 foreach($overview as $active)
1508 {
1509 foreach ($active as $answer)
1510 {
1511 foreach ($answer as $option => $value)
1512 {
1513 $aggregation[$option][$value] = $aggregation[$option][$value] + 1;
1514 }
1515 }
1516 }
1517
1518 $html = '<div>';
1519 $i = 0;
1520 foreach ($this->object->getGaps() as $gap)
1521 {
1522 if ($gap->type == CLOZE_SELECT)
1523 {
1524 $html .= '<p>Gap '. ($i+1) . ' - SELECT</p>';
1525 $html .= '<ul>';
1526 $j = 0;
1527 foreach($gap->getItems($this->object->getShuffler()) as $gap_item)
1528 {
1529 $aggregate = $aggregation[$i];
1530 $html .= '<li>' . $gap_item->getAnswerText() . ' - ' . ($aggregate[$j] ? $aggregate[$j] : 0) . '</li>';
1531 $j++;
1532 }
1533 $html .= '</ul>';
1534 }
1535
1536 if($gap->type == CLOZE_TEXT)
1537 {
1538 $present_elements = array();
1539 foreach($gap->getItems(new ilArrayElementShuffler()) as $item)
1540 {
1542 $present_elements[] = $item->getAnswertext();
1543 }
1544
1545 $html .= '<p>Gap ' . ($i+1) . ' - TEXT</p>';
1546 $html .= '<ul>';
1547 $aggregate = (array)$aggregation[$i];
1548 foreach($aggregate as $answer => $count)
1549 {
1550 $show_mover = '';
1551 if(in_array($answer, $present_elements))
1552 {
1553 $show_mover = ' style="display: none;" ';
1554 }
1555
1556 $html .= '<li>' . $answer . ' - ' . $count
1557 . '&nbsp;<button class="clone_fields_add btn btn-link" ' . $show_mover . ' data-answer="'.$answer.'" name="add_gap_'.$i.'_0">
1558 <span class="sr-only"></span><span class="glyphicon glyphicon-plus"></span></button>
1559 </li>';
1560 }
1561 $html .= '</ul>';
1562 }
1563
1564 if($gap->type == CLOZE_NUMERIC)
1565 {
1566 $html .= '<p>Gap ' . ($i+1) . ' - NUMERIC</p>';
1567 $html .= '<ul>';
1568 $j = 0;
1569 foreach($gap->getItems($this->object->getShuffler()) as $gap_item)
1570 {
1571 $aggregate = (array)$aggregation[$i];
1572 foreach($aggregate as $answer => $count)
1573 {
1574 $html .= '<li>' . $answer . ' - ' . $count . '</li>';
1575 }
1576 $j++;
1577 }
1578 $html .= '</ul>';
1579 }
1580 $i++;
1581 $html .= '<hr />';
1582 }
1583
1584 $html .= '</div>';
1585 return $html;
1586 }
1587
1588 public function applyIndizesToGapText( $question_text )
1589 {
1590 $parts = explode( '[gap', $question_text );
1591 $i = 0;
1592 $question_text = '';
1593 foreach ( $parts as $part )
1594 {
1595 if ( $i == 0 )
1596 {
1597 $question_text .= $part;
1598 }
1599 else
1600 {
1601 $question_text .= '[gap ' . $i . $part;
1602 }
1603 $i++;
1604 }
1605 return $question_text;
1606 }
1607
1608 public function removeIndizesFromGapText( $question_text )
1609 {
1610 $parts = preg_split( '/\[gap \d*\]/', $question_text );
1611 $question_text = implode( '[gap]', $parts );
1612 return $question_text;
1613 }
1614
1619 private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
1620 {
1621 if( $this->isPdfOutputMode() || $this->isContentEditingOutputMode() )
1622 {
1623 $gaptemplate->setCurrentBlock('gap_span');
1624 $gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
1625 }
1626 elseif($gap->getType() == CLOZE_SELECT)
1627 {
1628 $gaptemplate->setCurrentBlock('gap_select');
1629 $gaptemplate->setVariable('SELECT_SOLUTION', $solutiontext);
1630 }
1631 else
1632 {
1633 $gap_size = $gap->getGapSize() > 0 ? $gap->getGapSize() : $this->object->getFixedTextLength();
1634
1635 if($gap_size > 0)
1636 {
1637 $gaptemplate->setCurrentBlock('gap_size');
1638 $gaptemplate->setVariable("GAP_SIZE", $gap_size);
1639 $gaptemplate->parseCurrentBlock();
1640 }
1641
1642 $gaptemplate->setCurrentBlock('gap_input');
1643 $gaptemplate->setVariable('INPUT_SOLUTION', $solutiontext);
1644 }
1645
1646
1647 $gaptemplate->parseCurrentBlock();
1648 }
1649}
$test
Definition: Utf8Test.php:85
$_GET["client_id"]
Class for cloze question numeric answers.
Cloze test question GUI representation.
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
__construct($id=-1)
assClozeTestGUI constructor
editQuestion($checkonly=FALSE)
Creates an output of the edit form for the question.
getTestOutput( $active_id, $pass, $is_postponed=FALSE, $use_post_solutions=FALSE, $show_feedback=FALSE)
populateSelectGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a select gap.
populateNumericGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a numeric gap.
createGaps()
Create gaps from cloze text.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
Creates a preview output of the question.
$gapIndex
A temporary variable to store gap indexes of ilCtrl commands in the getCommand method.
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
Adds the question specific forms parts to a question property form gui.
getSpecificFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
populateGapSizeFormPart($form, $gap, $gapCounter)
setQuestionTabs()
Sets the ILIAS tabs for this question type.
populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
populateTextGapFormPart($form, $gap, $gapCounter)
Populates the form-part for a text gap.
populateGapFormPart($form, $gapCounter)
Populates a gap form-part.
addgap()
Add a gap answer.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
removeIndizesFromGapText( $question_text)
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.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
Adds the answer specific form parts to a question property form gui.
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
removegap()
Remove a gap answer.
applyIndizesToGapText( $question_text)
Class for cloze tests.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
isLastSolutionSubmitAuthorized($active_id, $pass)
fetches solutions from database and prefers intermediate solutions, but falls back to authorized solu...
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
writePostData()
Evaluates a posted edit form and writes the form data in the question object.
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
getTestOutputSolutions($activeId, $pass)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
addBackTab(ilTabsGUI $ilTabs)
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
const ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT
constant for additional content editing mode "default"
This class represents a single choice wizard property in a property form.
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
This class represents a checkbox property in a property form.
This class represents a custom property in a property form.
This class represents a duration (typical hh:mm:ss) property in a property form.
This class represents a section header in a property form.
This class represents a formula text property in a property form.
This class represents a hidden form property in a property form.
This class represents a number property in a property form.
& _getUsedHTMLTags($a_module="")
Returns an array of all allowed HTML tags for text editing.
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the manual feedback for a question in a test.
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
This class represents a selection list property in a property form.
special template class to simplify handling of ITX/PEAR
This class represents a text area property in a property form.
This class represents a text property in a property form.
static stripSlashesRecursive($a_data, $a_strip_html=true, $a_allow="")
Strip slashes from array and sub-arrays.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
$_POST['username']
Definition: cron.php:12
$html
Definition: example_001.php:87
$header
const CLOZE_NUMERIC
const CLOZE_SELECT
const CLOZE_TEXT
Cloze question constants.
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
$cmd
Definition: sahs_server.php:35
$url
Definition: shib_logout.php:72
$errors
if(!is_array($argv)) $options