ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
class.assMatchingQuestionGUI.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';
7require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8
24{
34 public function __construct($id = -1)
35 {
36 parent::__construct();
37 include_once "./Modules/TestQuestionPool/classes/class.assMatchingQuestion.php";
38 $this->object = new assMatchingQuestion();
39 $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
40 if ($id >= 0)
41 {
42 $this->object->loadFromDb($id);
43 }
44 }
45
53 public function writePostData($always = false)
54 {
55 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
56 if (!$hasErrors)
57 {
58 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
63 return 0;
64 }
65 return 1;
66 }
67
69 {
70 // Delete all existing answers and create new answers from the form data
71 $this->object->flushMatchingPairs();
72 $this->object->flushTerms();
73 $this->object->flushDefinitions();
74
75 // add terms
76 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php';
77 foreach ($_POST['terms']['answer'] as $index => $answer)
78 {
79 $filename = $_POST['terms']['imagename'][$index];
80 if (strlen( $_FILES['terms']['name']['image'][$index] ))
81 {
82 // upload the new file
83 $name = $_FILES['terms']['name']['image'][$index];
84 if ($this->object->setImageFile( $_FILES['terms']['tmp_name']['image'][$index],
85 $this->object->getEncryptedFilename( $name )
86 )
87 )
88 {
89 $filename = $this->object->getEncryptedFilename( $name );
90 }
91 else
92 {
93 $filename = "";
94 }
95 }
96 $this->object->addTerm( new assAnswerMatchingTerm($answer, $filename, $_POST['terms']['identifier'][$index])
97 );
98 }
99 // add definitions
100 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php';
101 foreach ($_POST['definitions']['answer'] as $index => $answer)
102 {
103 $filename = $_POST['definitions']['imagename'][$index];
104 if (strlen( $_FILES['definitions']['name']['image'][$index] ))
105 {
106 // upload the new file
107 $name = $_FILES['definitions']['name']['image'][$index];
108 if ($this->object->setImageFile( $_FILES['definitions']['tmp_name']['image'][$index],
109 $this->object->getEncryptedFilename( $name )
110 )
111 )
112 {
113 $filename = $this->object->getEncryptedFilename( $name );
114 }
115 else
116 {
117 $filename = "";
118 }
119 }
120 $this->object->addDefinition(
121 new assAnswerMatchingDefinition($answer, $filename, $_POST['definitions']['identifier'][$index])
122 );
123 }
124
125 // add matching pairs
126 if (is_array( $_POST['pairs']['points'] ))
127 {
128 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php';
129 foreach ($_POST['pairs']['points'] as $index => $points)
130 {
131 $term_id = $_POST['pairs']['term'][$index];
132 $definition_id = $_POST['pairs']['definition'][$index];
133 $this->object->addMatchingPair( $this->object->getTermWithIdentifier( $term_id ),
134 $this->object->getDefinitionWithIdentifier( $definition_id ),
135 $points
136 );
137 }
138 }
139 }
140
142 {
143 if (!$this->object->getSelfAssessmentEditingMode())
144 {
145 $this->object->setShuffle( $_POST["shuffle"] );
146 }
147 else
148 {
149 $this->object->setShuffle( 1 );
150 }
151 $this->object->setThumbGeometry( $_POST["thumb_geometry"] );
152 $this->object->setMatchingMode($_POST['matching_mode']);
153 }
154
155 public function uploadterms()
156 {
157 $this->writePostData(true);
158 $this->editQuestion();
159 }
160
161 public function removeimageterms()
162 {
163 $this->writePostData(true);
164 $position = key($_POST['cmd']['removeimageterms']);
165 $this->object->removeTermImage($position);
166 $this->editQuestion();
167 }
168
169 public function uploaddefinitions()
170 {
171 $this->writePostData(true);
172 $this->editQuestion();
173 }
174
175 public function removeimagedefinitions()
176 {
177 $this->writePostData(true);
178 $position = key($_POST['cmd']['removeimagedefinitions']);
179 $this->object->removeDefinitionImage($position);
180 $this->editQuestion();
181 }
182
183 public function addterms()
184 {
185 $this->writePostData();
186 $position = key($_POST["cmd"]["addterms"]);
187 $this->object->insertTerm($position+1);
188 $this->editQuestion();
189 }
190
191 public function removeterms()
192 {
193 $this->writePostData();
194 $position = key($_POST["cmd"]["removeterms"]);
195 $this->object->deleteTerm($position);
196 $this->editQuestion();
197 }
198
199 public function adddefinitions()
200 {
201 $this->writePostData();
202 $position = key($_POST["cmd"]["adddefinitions"]);
203 $this->object->insertDefinition($position+1);
204 $this->editQuestion();
205 }
206
207 public function removedefinitions()
208 {
209 $this->writePostData();
210 $position = key($_POST["cmd"]["removedefinitions"]);
211 $this->object->deleteDefinition($position);
212 $this->editQuestion();
213 }
214
215 public function addpairs()
216 {
217 $this->writePostData();
218 $position = key($_POST["cmd"]["addpairs"]);
219 $this->object->insertMatchingPair($position+1);
220 $this->editQuestion();
221 }
222
223 public function removepairs()
224 {
225 $this->writePostData();
226 $position = key($_POST["cmd"]["removepairs"]);
227 $this->object->deleteMatchingPair($position);
228 $this->editQuestion();
229 }
230
231 public function editQuestion($checkonly = FALSE)
232 {
233 $save = $this->isSaveCommand();
234 $this->getQuestionTemplate();
235
236 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
237 $form = new ilPropertyFormGUI();
238 $form->setFormAction($this->ctrl->getFormAction($this));
239 $form->setTitle($this->outQuestionType());
240 $form->setMultipart(true);
241 $form->setTableWidth("100%");
242 $form->setId("matching");
243
244
245 // title, author, description, question, working time (assessment mode)
246 $this->addBasicQuestionFormProperties($form);
247 $this->populateQuestionSpecificFormPart( $form );
248 $this->populateAnswerSpecificFormPart( $form );
249 $this->populateTaxonomyFormSection($form);
250 $this->addQuestionFormCommandButtons($form);
251
252 $errors = false;
253 if ($save)
254 {
255 $form->setValuesByPost();
256 $errors = !$form->checkInput();
257 $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we need this if we don't want to have duplication of backslashes
258 if( !$errors && !$this->isValidTermAndDefinitionAmount($form) && !$this->object->getSelfAssessmentEditingMode() )
259 {
260 $errors = true;
261 $terms = $form->getItemByPostVar('terms');
262 $terms->setAlert($this->lng->txt("msg_number_of_terms_too_low"));
263 ilUtil::sendFailure($this->lng->txt('form_input_not_valid'));
264 }
265 if ($errors) $checkonly = false;
266 }
267
268 if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
269 return $errors;
270 }
271
280 {
281 $matchingMode = $form->getItemByPostVar('matching_mode')->getValue();
282
283 if( $matchingMode == assMatchingQuestion::MATCHING_MODE_N_ON_N )
284 {
285 return true;
286 }
287
288 $numTerms = count($form->getItemByPostVar('terms')->getValues());
289 $numDefinitions = count($form->getItemByPostVar('definitions')->getValues());
290
291 if($numTerms >= $numDefinitions)
292 {
293 return true;
294 }
295
296 return false;
297 }
298
300 {
301 // Definitions
302 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingWizardInputGUI.php";
303 $definitions = new ilMatchingWizardInputGUI($this->lng->txt( "definitions" ), "definitions");
304 if ($this->object->getSelfAssessmentEditingMode())
305 {
306 $definitions->setHideImages( true );
307 }
308
309 $definitions->setRequired( true );
310 $definitions->setQuestionObject( $this->object );
311 $definitions->setTextName( $this->lng->txt( 'definition_text' ) );
312 $definitions->setImageName( $this->lng->txt( 'definition_image' ) );
313 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
314 if (!count( $this->object->getDefinitions() ))
315 {
316 $this->object->addDefinition( new assAnswerMatchingDefinition() );
317 }
318 $definitionvalues = $this->object->getDefinitions();
319 $definitions->setValues( $definitionvalues );
320 $definitions->checkInput();
321 $form->addItem( $definitions );
322
323 // Terms
324 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingWizardInputGUI.php";
325 $terms = new ilMatchingWizardInputGUI($this->lng->txt( "terms" ), "terms");
326 if ($this->object->getSelfAssessmentEditingMode())
327 $terms->setHideImages( true );
328 $terms->setRequired( true );
329 $terms->setQuestionObject( $this->object );
330 $terms->setTextName( $this->lng->txt( 'term_text' ) );
331 $terms->setImageName( $this->lng->txt( 'term_image' ) );
332 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
333 if (!count( $this->object->getTerms() ))
334 $this->object->addTerm( new assAnswerMatchingTerm() );
335 $termvalues = $this->object->getTerms();
336 $terms->setValues( $termvalues );
337 $terms->checkInput();
338 $form->addItem( $terms );
339
340 // Matching Pairs
341 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingPairWizardInputGUI.php";
342 $pairs = new ilMatchingPairWizardInputGUI($this->lng->txt( 'matching_pairs' ), 'pairs');
343 $pairs->setRequired( true );
344 $pairs->setTerms( $this->object->getTerms() );
345 $pairs->setDefinitions( $this->object->getDefinitions() );
346 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
347 if (count( $this->object->getMatchingPairs() ) == 0)
348 {
349 $this->object->addMatchingPair( new assAnswerMatchingPair($termvalues[0], $definitionvalues[0], 0) );
350 }
351 $pairs->setPairs( $this->object->getMatchingPairs() );
352 $form->addItem( $pairs );
353
354 return $form;
355 }
356
358 {
359 // Edit mode
360 $hidden = new ilHiddenInputGUI("matching_type");
361 $hidden->setValue($matchingtype);
362 $form->addItem($hidden);
363
364 if (!$this->object->getSelfAssessmentEditingMode())
365 {
366 // shuffle
367 $shuffle = new ilSelectInputGUI($this->lng->txt( "shuffle_answers" ), "shuffle");
368 $shuffle_options = array(
369 0 => $this->lng->txt( "no" ),
370 1 => $this->lng->txt( "matching_shuffle_terms_definitions" ),
371 2 => $this->lng->txt( "matching_shuffle_terms" ),
372 3 => $this->lng->txt( "matching_shuffle_definitions" )
373 );
374 $shuffle->setOptions( $shuffle_options );
375 $shuffle->setValue($this->object->getShuffle() != null ? $this->object->getShuffle() : 1);
376 $shuffle->setRequired( FALSE );
377 $form->addItem( $shuffle );
378
379 $geometry = new ilNumberInputGUI($this->lng->txt( "thumb_geometry" ), "thumb_geometry");
380 $geometry->setValue( $this->object->getThumbGeometry() );
381 $geometry->setRequired( true );
382 $geometry->setMaxLength( 6 );
383 $geometry->setMinValue( 20 );
384 $geometry->setSize( 6 );
385 $geometry->setInfo( $this->lng->txt( "thumb_geometry_info" ) );
386 $form->addItem( $geometry );
387 }
388
389 // Matching Mode
390 $mode = new ilRadioGroupInputGUI($this->lng->txt('qpl_qst_inp_matching_mode'), 'matching_mode');
391 $mode->setRequired(true);
392
393 $modeONEonONE = new ilRadioOption(
394 $this->lng->txt('qpl_qst_inp_matching_mode_one_on_one'), assMatchingQuestion::MATCHING_MODE_1_ON_1
395 );
396 $mode->addOption($modeONEonONE);
397
398 $modeALLonALL = new ilRadioOption(
399 $this->lng->txt('qpl_qst_inp_matching_mode_all_on_all'), assMatchingQuestion::MATCHING_MODE_N_ON_N
400 );
401 $mode->addOption($modeALLonALL);
402
403 $mode->setValue($this->object->getMatchingMode());
404
405 $form->addItem($mode);
406 }
407
422 $active_id,
423 $pass = NULL,
424 $graphicalOutput = FALSE,
425 $result_output = FALSE,
426 $show_question_only = TRUE,
427 $show_feedback = FALSE,
428 $show_correct_solution = FALSE,
429 $show_manual_scoring = FALSE,
430 $show_question_text = TRUE
431 )
432 {
433 // generate the question output
434 include_once "./Services/UICore/classes/class.ilTemplate.php";
435 $template = new ilTemplate("tpl.il_as_qpl_matching_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
436 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
437
438 $solutions = array();
439 if (($active_id > 0) && (!$show_correct_solution))
440 {
441 include_once "./Modules/Test/classes/class.ilObjTest.php";
442 $solutions =& $this->object->getSolutionValues($active_id, $pass);
443 $solution_script .= "";
444 }
445 else
446 {
447 foreach ($this->object->getMaximumScoringMatchingPairs() as $pair)
448 {
449 $solutions[] = array(
450 "value1" => $pair->term->identifier,
451 "value2" => $pair->definition->identifier,
452 'points' => $pair->points
453 );
454 }
455 }
456
457 $i = 0;
458
459 foreach ($solutions as $solution)
460 {
461 $definition = $this->object->getDefinitionWithIdentifier($solution['value2']);
462 $term = $this->object->getTermWithIdentifier($solution['value1']);
463 $points = $solution['points'];
464
465 if (is_object($definition))
466 {
467 if (strlen($definition->picture))
468 {
469 if( strlen($definition->text) )
470 {
471 $template->setCurrentBlock('definition_image_text');
472 $template->setVariable("TEXT_DEFINITION", ilUtil::prepareFormOutput($definition->text));
473 $template->parseCurrentBlock();
474 }
475
476 $template->setCurrentBlock('definition_image');
477 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture);
478 $template->setVariable('ANSWER_IMAGE_ALT', (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : ilUtil::prepareFormOutput($definition->picture));
479 $template->setVariable('ANSWER_IMAGE_TITLE', (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : ilUtil::prepareFormOutput($definition->picture));
480 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $definition->picture);
481 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
482 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
483 $template->parseCurrentBlock();
484 }
485 else
486 {
487 $template->setCurrentBlock('definition_text');
488 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
489 $template->parseCurrentBlock();
490 }
491 }
492 if (is_object($term))
493 {
494 if (strlen($term->picture))
495 {
496 if( strlen($term->text) )
497 {
498 $template->setCurrentBlock('term_image_text');
499 $template->setVariable("TEXT_TERM", ilUtil::prepareFormOutput($term->text));
500 $template->parseCurrentBlock();
501 }
502
503 $template->setCurrentBlock('term_image');
504 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture);
505 $template->setVariable('ANSWER_IMAGE_ALT', (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : ilUtil::prepareFormOutput($term->picture));
506 $template->setVariable('ANSWER_IMAGE_TITLE', (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : ilUtil::prepareFormOutput($term->picture));
507 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $term->picture);
508 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
509 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
510 $template->parseCurrentBlock();
511 }
512 else
513 {
514 $template->setCurrentBlock('term_text');
515 $template->setVariable("TERM", $this->object->prepareTextareaOutput($term->text, TRUE));
516 $template->parseCurrentBlock();
517 }
518 $i++;
519 }
520 if (($active_id > 0) && (!$show_correct_solution))
521 {
522 if ($graphicalOutput)
523 {
524 // output of ok/not ok icons for user entered solutions
525 $ok = false;
526 foreach ($this->object->getMatchingPairs() as $pair)
527 {
528 if( $this->isCorrectMatching($pair, $definition, $term) )
529 {
530 $ok = true;
531 }
532 }
533
534 if ($ok)
535 {
536 $template->setCurrentBlock("icon_ok");
537 $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
538 $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
539 $template->parseCurrentBlock();
540 }
541 else
542 {
543 $template->setCurrentBlock("icon_ok");
544 $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
545 $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
546 $template->parseCurrentBlock();
547 }
548 }
549 }
550
551 if ($result_output)
552 {
553 $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
554 $template->setCurrentBlock("result_output");
555 $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
556 $template->parseCurrentBlock();
557 }
558
559 $template->setCurrentBlock("row");
560 $template->setVariable("TEXT_MATCHES", $this->lng->txt("matches"));
561 $template->parseCurrentBlock();
562 }
563
564 $questiontext = $this->object->getQuestion();
565 if ($show_question_text==true)
566 {
567 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
568 }
569
570 $questionoutput = $template->get();
571
572 $feedback = '';
573 if($show_feedback)
574 {
575 $fb = $this->getGenericFeedbackOutput($active_id, $pass);
576 $feedback .= strlen($fb) ? $fb : '';
577
578 $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
579 $feedback .= strlen($fb) ? $fb : '';
580 }
581 if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
582
583 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
584
585 $solutionoutput = $solutiontemplate->get();
586 if (!$show_question_only)
587 {
588 // get page object output
589 $solutionoutput = $this->getILIASPage($solutionoutput);
590 }
591 return $solutionoutput;
592 }
593
594 public function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
595 {
596 $solutions = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
597
598 if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
599 {
600 require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
603
604 $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
605 }
606 else
607 {
608 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
609 }
610
611 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
612 $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
613
614 $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
615
616 foreach($solutions as $defId => $terms)
617 {
618 foreach($terms as $termId)
619 {
620 $template->setCurrentBlock("matching_data");
621 $template->setVariable("DEFINITION_ID", $defId);
622 $template->setVariable("TERM_ID", $termId);
623 $template->parseCurrentBlock();
624 }
625 }
626
627 // shuffle output
628 $terms = $this->object->getTerms();
629 $definitions = $this->object->getDefinitions();
630 switch ($this->object->getShuffle())
631 {
632 case 1:
633 $terms = $this->object->pcArrayShuffle($terms);
634 $definitions = $this->object->pcArrayShuffle($definitions);
635 break;
636 case 2:
637 $terms = $this->object->pcArrayShuffle($terms);
638 break;
639 case 3:
640 $definitions = $this->object->pcArrayShuffle($definitions);
641 break;
642 }
643
644 // create definitions
645 $counter = 0;
646 foreach ($definitions as $definition)
647 {
648 if (strlen($definition->picture))
649 {
650 $template->setCurrentBlock("definition_picture");
651 $template->setVariable("DEFINITION_ID", $definition->identifier);
652 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
653 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
654 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
655 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
656 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
657 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
658 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
659 $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? $this->object->prepareTextareaOutput($definition->text, TRUE) : '');
660 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
661 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
662 $template->parseCurrentBlock();
663 }
664 else
665 {
666 $template->setCurrentBlock("definition_text");
667 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
668 $template->parseCurrentBlock();
669 }
670
671 $template->setCurrentBlock("droparea");
672 $template->setVariable("ID_DROPAREA", $definition->identifier);
673 $template->setVariable("QUESTION_ID", $this->object->getId());
674 $template->parseCurrentBlock();
675
676 $template->setCurrentBlock("definition_data");
677 $template->setVariable("DEFINITION_ID", $definition->identifier);
678 $template->parseCurrentBlock();
679 }
680
681 // create terms
682 $counter = 0;
683 foreach ($terms as $term)
684 {
685 if (strlen($term->picture))
686 {
687 $template->setCurrentBlock("term_picture");
688 $template->setVariable("TERM_ID", $term->identifier);
689 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
690 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
691 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
692 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
693 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
694 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
695 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
696 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
697 $template->setVariable("TEXT_TERM", (strlen($term->text)) ? $this->object->prepareTextareaOutput($term->text, TRUE) : '');
698 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
699 $template->parseCurrentBlock();
700 }
701 else
702 {
703 $template->setCurrentBlock("term_text");
704 $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, TRUE));
705 $template->parseCurrentBlock();
706 }
707 $template->setCurrentBlock("draggable");
708 $template->setVariable("ID_DRAGGABLE", $term->identifier);
709 $template->parseCurrentBlock();
710
711 $template->setCurrentBlock("term_data");
712 $template->setVariable("TERM_ID", $term->identifier);
713 $template->parseCurrentBlock();
714 }
715
716 $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
717
718 $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
719
720 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
721
722 $questionoutput = $template->get();
723
724 if (!$show_question_only)
725 {
726 // get page object output
727 $questionoutput = $this->getILIASPage($questionoutput);
728 }
729
730 return $questionoutput;
731 }
732
738 protected function sortDefinitionsBySolution(array $solution, array $definitions)
739 {
740 $neworder = array();
741 $handled_defintions = array();
742 foreach($solution as $solution_values)
743 {
744 $id = $solution_values['value2'];
745 if(!isset($handled_defintions[$id]))
746 {
747 $neworder[] = $this->object->getDefinitionWithIdentifier($id);
748 $handled_defintions[$id] = $id;
749 }
750 }
751
752 foreach($definitions as $definition)
753 {
757 if(!isset($handled_defintions[$definition->identifier]))
758 {
759 $neworder[] = $definition;
760 }
761 }
762
763 return $neworder;
764 }
765
766 function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $user_post_solution = FALSE)
767 {
768 if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
769 {
770 require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
773
774 $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
775 }
776 else
777 {
778 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
779 }
780
781 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
782 $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
783
784 $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", true, true, "Modules/TestQuestionPool");
785
786 if ($active_id)
787 {
788 $solutions = NULL;
789 include_once "./Modules/Test/classes/class.ilObjTest.php";
790 if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
791 {
792 if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
793 }
794 if (is_array($user_post_solution))
795 {
796 $solutions = array();
797 foreach ($user_post_solution['matching'][$this->object->getId()] as $definition => $term)
798 {
799 array_push($solutions, array("value1" => $term, "value2" => $definition));
800 }
801 }
802 else
803 {
804 $solutions =& $this->object->getSolutionValues($active_id, $pass);
805 }
806
807 $counter = 0;
808 foreach ($solutions as $idx => $solution_value)
809 {
810 if (($solution_value["value2"] > -1) && ($solution_value["value1"] > -1))
811 {
812 $template->setCurrentBlock("matching_data");
813 $template->setVariable("TERM_ID", $solution_value["value1"]);
814 $template->setVariable("DEFINITION_ID", $solution_value["value2"]);
815 $template->parseCurrentBlock();
816 }
817
818 $counter++;
819 }
820 }
821
822 $terms = $this->object->getTerms();
823 $definitions = $this->object->getDefinitions();
824 switch ($this->object->getShuffle())
825 {
826 case 1:
827 $terms = $this->object->pcArrayShuffle($terms);
828 if (count($solutions))
829 {
830 $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
831 }
832 else
833 {
834 $definitions = $this->object->pcArrayShuffle($definitions);
835 }
836 break;
837 case 2:
838 $terms = $this->object->pcArrayShuffle($terms);
839 break;
840 case 3:
841 if (count($solutions))
842 {
843 $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
844 }
845 else
846 {
847 $definitions = $this->object->pcArrayShuffle($definitions);
848 }
849 break;
850 }
851
852 // create definitions
853 $counter = 0;
854 foreach ($definitions as $definition)
855 {
856 if (strlen($definition->picture))
857 {
858 $template->setCurrentBlock("definition_picture");
859 $template->setVariable("DEFINITION_ID", $definition->identifier);
860 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
861 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
862 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
863 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
864 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
865 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
866 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
867 $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : '');
868 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
869 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
870 $template->parseCurrentBlock();
871 }
872 else
873 {
874 $template->setCurrentBlock("definition_text");
875 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, true));
876 $template->parseCurrentBlock();
877 }
878
879 $template->setCurrentBlock("droparea");
880 $template->setVariable("ID_DROPAREA", $definition->identifier);
881 $template->setVariable("QUESTION_ID", $this->object->getId());
882 $template->parseCurrentBlock();
883
884 $template->setCurrentBlock("definition_data");
885 $template->setVariable("DEFINITION_ID", $definition->identifier);
886 $template->parseCurrentBlock();
887 }
888
889 // create terms
890 $counter = 0;
891 foreach ($terms as $term)
892 {
893 if (strlen($term->picture))
894 {
895 $template->setCurrentBlock("term_picture");
896 $template->setVariable("TERM_ID", $term->identifier);
897 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
898 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
899 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
900 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
901 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
902 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
903 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
904 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
905 $template->setVariable("TEXT_TERM", (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : '');
906 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
907 $template->parseCurrentBlock();
908 }
909 else
910 {
911 $template->setCurrentBlock("term_text");
912 $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, true));
913 $template->parseCurrentBlock();
914 }
915 $template->setCurrentBlock("draggable");
916 $template->setVariable("ID_DRAGGABLE", $term->identifier);
917 $template->parseCurrentBlock();
918
919 $template->setCurrentBlock('term_data');
920 $template->setVariable('TERM_ID', $term->identifier);
921 $template->parseCurrentBlock();
922 }
923
924 $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
925
926 $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
927
928 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
929
930 return $this->outQuestionPage("", $is_postponed, $active_id, $template->get());
931 }
932
936 function checkInput()
937 {
938 if ((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"]))
939 {
940 return false;
941 }
942 return true;
943 }
944
953 {
954 global $rbacsystem, $ilTabs;
955
956 $ilTabs->clearTargets();
957
958 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
959 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
960 $q_type = $this->object->getQuestionType();
961
962 if (strlen($q_type))
963 {
964 $classname = $q_type . "GUI";
965 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
966 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
967 }
968
969 if ($_GET["q_id"])
970 {
971 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
972 {
973 // edit page
974 $ilTabs->addTarget("edit_page",
975 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
976 array("edit", "insert", "exec_pg"),
977 "", "", $force_active);
978 }
979
980 $this->addTab_QuestionPreview($ilTabs);
981 }
982
983 $force_active = false;
984 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
985 {
986 $url = "";
987 if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
988 // edit question properties
989 $ilTabs->addTarget("edit_question",
990 $url,
991 array("editQuestion", "save", "saveEdit", "removeimageterms", "uploadterms", "removeimagedefinitions", "uploaddefinitions",
992 "addpairs", "removepairs", "addterms", "removeterms", "adddefinitions", "removedefinitions", "originalSyncForm"),
993 $classname, "", $force_active);
994 }
995
996 // add tab for question feedback within common class assQuestionGUI
997 $this->addTab_QuestionFeedback($ilTabs);
998
999 // add tab for question hint within common class assQuestionGUI
1000 $this->addTab_QuestionHints($ilTabs);
1001
1002 // add tab for question's suggested solution within common class assQuestionGUI
1003 $this->addTab_SuggestedSolution($ilTabs, $classname);
1004
1005 // Assessment of questions sub menu entry
1006 if ($_GET["q_id"])
1007 {
1008 $ilTabs->addTarget("statistics",
1009 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1010 array("assessment"),
1011 $classname, "");
1012 }
1013
1014 $this->addBackTab($ilTabs);
1015 }
1016
1017 function getSpecificFeedbackOutput($active_id, $pass)
1018 {
1019 $matches = array_values($this->object->getMaximumScoringMatchingPairs());
1020
1021 if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($matches) )
1022 {
1023 return '';
1024 }
1025
1026 $feedback = '<table class="test_specific_feedback"><tbody>';
1027
1028 foreach ($matches as $idx => $ans)
1029 {
1030 $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1031 $this->object->getId(), $idx
1032 );
1033 $feedback .= '<tr><td>"' . $ans->definition->text . '"&nbsp;' . $this->lng->txt("matches") . '&nbsp;"';
1034 $feedback .= $ans->term->text . '"</td><td>';
1035 $feedback .= $fb . '</td> </tr>';
1036 }
1037
1038 $feedback .= '</tbody></table>';
1039 return $this->object->prepareTextareaOutput($feedback, TRUE);
1040 }
1041
1052 {
1053 return array();
1054 }
1055
1066 {
1067 return array();
1068 }
1069
1078 public function getAggregatedAnswersView($relevant_answers)
1079 {
1080 return ''; //print_r($relevant_answers,true);
1081 }
1082
1083 private function isCorrectMatching($pair, $definition, $term)
1084 {
1085 if( !($pair->points > 0) )
1086 {
1087 return false;
1088 }
1089
1090 if( !is_object($term) )
1091 {
1092 return false;
1093 }
1094
1095 if( $pair->definition->identifier != $definition->identifier )
1096 {
1097 return false;
1098 }
1099
1100 if( $pair->term->identifier != $term->identifier )
1101 {
1102 return false;
1103 }
1104
1105 return true;
1106 }
1107}
$filename
Definition: buildRTE.php:89
$_GET["client_id"]
Class for matching question definitions.
Class for matching question pairs.
Class for matching question terms.
Matching question GUI representation.
isValidTermAndDefinitionAmount(ilPropertyFormGUI $form)
for mode 1:1 terms count must not be less than definitions count for mode n:n this limitation is canc...
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
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.
getTestOutput($active_id, $pass=NULL, $is_postponed=FALSE, $user_post_solution=FALSE)
getSpecificFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
isCorrectMatching($pair, $definition, $term)
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
setQuestionTabs()
Sets the ILIAS tabs for this question type.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
__construct($id=-1)
assMatchingQuestionGUI constructor
Class for matching questions.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
setErrorMessage($errormessage)
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)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
addBackTab(ilTabsGUI $ilTabs)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
This class represents a hidden form property in a property form.
This class represents a key value pair wizard property in a property form.
This class represents a single choice wizard property in a property form.
This class represents a number property in a property form.
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
getItemByPostVar($a_post_var)
Get Item by POST variable.
This class represents a property in a property form.
This class represents an option in a radio group.
This class represents a selection list property in a property form.
special template class to simplify handling of ITX/PEAR
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
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
static initjQueryUI()
Init jQuery UI (see included_components.txt for included components)
static initjQuery($a_tpl=null)
Init jQuery.
$_POST['username']
Definition: cron.php:12
$GLOBALS['ct_recipient']
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
$errors