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