ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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
272 private function isDefImgUploadCommand()
273 {
274 return $this->ctrl->getCmd() == 'uploaddefinitions';
275 }
276
277 private function isTermImgUploadCommand()
278 {
279 return $this->ctrl->getCmd() == 'uploadterms';
280 }
281
290 {
291 $matchingMode = $form->getItemByPostVar('matching_mode')->getValue();
292
293 if( $matchingMode == assMatchingQuestion::MATCHING_MODE_N_ON_N )
294 {
295 return true;
296 }
297
298 $numTerms = count($form->getItemByPostVar('terms')->getValues());
299 $numDefinitions = count($form->getItemByPostVar('definitions')->getValues());
300
301 if($numTerms >= $numDefinitions)
302 {
303 return true;
304 }
305
306 return false;
307 }
308
310 {
311 // Definitions
312 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingWizardInputGUI.php";
313 $definitions = new ilMatchingWizardInputGUI($this->lng->txt( "definitions" ), "definitions");
314 if ($this->object->getSelfAssessmentEditingMode())
315 {
316 $definitions->setHideImages( true );
317 }
318
319 $definitions->setRequired( true );
320 $definitions->setQuestionObject( $this->object );
321 $definitions->setTextName( $this->lng->txt( 'definition_text' ) );
322 $definitions->setImageName( $this->lng->txt( 'definition_image' ) );
323 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
324 if (!count( $this->object->getDefinitions() ))
325 {
326 $this->object->addDefinition( new assAnswerMatchingDefinition() );
327 }
328 $definitionvalues = $this->object->getDefinitions();
329 $definitions->setValues( $definitionvalues );
330 if( $this->isDefImgUploadCommand() )
331 {
332 $definitions->checkInput();
333 }
334 $form->addItem( $definitions );
335
336 // Terms
337 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingWizardInputGUI.php";
338 $terms = new ilMatchingWizardInputGUI($this->lng->txt( "terms" ), "terms");
339 if ($this->object->getSelfAssessmentEditingMode())
340 $terms->setHideImages( true );
341 $terms->setRequired( true );
342 $terms->setQuestionObject( $this->object );
343 $terms->setTextName( $this->lng->txt( 'term_text' ) );
344 $terms->setImageName( $this->lng->txt( 'term_image' ) );
345 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
346 if (!count( $this->object->getTerms() ))
347 $this->object->addTerm( new assAnswerMatchingTerm() );
348 $termvalues = $this->object->getTerms();
349 $terms->setValues( $termvalues );
350 if( $this->isTermImgUploadCommand() )
351 {
352 $terms->checkInput();
353 }
354 $form->addItem( $terms );
355
356 // Matching Pairs
357 include_once "./Modules/TestQuestionPool/classes/class.ilMatchingPairWizardInputGUI.php";
358 $pairs = new ilMatchingPairWizardInputGUI($this->lng->txt( 'matching_pairs' ), 'pairs');
359 $pairs->setRequired( true );
360 $pairs->setTerms( $this->object->getTerms() );
361 $pairs->setDefinitions( $this->object->getDefinitions() );
362 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
363 if (count( $this->object->getMatchingPairs() ) == 0)
364 {
365 $this->object->addMatchingPair( new assAnswerMatchingPair($termvalues[0], $definitionvalues[0], 0) );
366 }
367 $pairs->setPairs( $this->object->getMatchingPairs() );
368 $form->addItem( $pairs );
369
370 return $form;
371 }
372
374 {
375 // Edit mode
376 $hidden = new ilHiddenInputGUI("matching_type");
377 $hidden->setValue($matchingtype);
378 $form->addItem($hidden);
379
380 if (!$this->object->getSelfAssessmentEditingMode())
381 {
382 // shuffle
383 $shuffle = new ilSelectInputGUI($this->lng->txt( "shuffle_answers" ), "shuffle");
384 $shuffle_options = array(
385 0 => $this->lng->txt( "no" ),
386 1 => $this->lng->txt( "matching_shuffle_terms_definitions" ),
387 2 => $this->lng->txt( "matching_shuffle_terms" ),
388 3 => $this->lng->txt( "matching_shuffle_definitions" )
389 );
390 $shuffle->setOptions( $shuffle_options );
391 $shuffle->setValue($this->object->getShuffle() != null ? $this->object->getShuffle() : 1);
392 $shuffle->setRequired( FALSE );
393 $form->addItem( $shuffle );
394
395 $geometry = new ilNumberInputGUI($this->lng->txt( "thumb_geometry" ), "thumb_geometry");
396 $geometry->setValue( $this->object->getThumbGeometry() );
397 $geometry->setRequired( true );
398 $geometry->setMaxLength( 6 );
399 $geometry->setMinValue( 20 );
400 $geometry->setSize( 6 );
401 $geometry->setInfo( $this->lng->txt( "thumb_geometry_info" ) );
402 $form->addItem( $geometry );
403 }
404
405 // Matching Mode
406 $mode = new ilRadioGroupInputGUI($this->lng->txt('qpl_qst_inp_matching_mode'), 'matching_mode');
407 $mode->setRequired(true);
408
409 $modeONEonONE = new ilRadioOption(
410 $this->lng->txt('qpl_qst_inp_matching_mode_one_on_one'), assMatchingQuestion::MATCHING_MODE_1_ON_1
411 );
412 $mode->addOption($modeONEonONE);
413
414 $modeALLonALL = new ilRadioOption(
415 $this->lng->txt('qpl_qst_inp_matching_mode_all_on_all'), assMatchingQuestion::MATCHING_MODE_N_ON_N
416 );
417 $mode->addOption($modeALLonALL);
418
419 $mode->setValue($this->object->getMatchingMode());
420
421 $form->addItem($mode);
422 }
423
438 $active_id,
439 $pass = NULL,
440 $graphicalOutput = FALSE,
441 $result_output = FALSE,
442 $show_question_only = TRUE,
443 $show_feedback = FALSE,
444 $show_correct_solution = FALSE,
445 $show_manual_scoring = FALSE,
446 $show_question_text = TRUE
447 )
448 {
449 // generate the question output
450 include_once "./Services/UICore/classes/class.ilTemplate.php";
451 $template = new ilTemplate("tpl.il_as_qpl_matching_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
452 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
453
454 $solutions = array();
455 if (($active_id > 0) && (!$show_correct_solution))
456 {
457 include_once "./Modules/Test/classes/class.ilObjTest.php";
458 $solutions =& $this->object->getSolutionValues($active_id, $pass);
459 $solution_script .= "";
460 }
461 else
462 {
463 foreach ($this->object->getMaximumScoringMatchingPairs() as $pair)
464 {
465 $solutions[] = array(
466 "value1" => $pair->term->identifier,
467 "value2" => $pair->definition->identifier,
468 'points' => $pair->points
469 );
470 }
471 }
472
473 $i = 0;
474
475 foreach ($solutions as $solution)
476 {
477 $definition = $this->object->getDefinitionWithIdentifier($solution['value2']);
478 $term = $this->object->getTermWithIdentifier($solution['value1']);
479 $points = $solution['points'];
480
481 if (is_object($definition))
482 {
483 if (strlen($definition->picture))
484 {
485 if( strlen($definition->text) )
486 {
487 $template->setCurrentBlock('definition_image_text');
488 $template->setVariable("TEXT_DEFINITION", ilUtil::prepareFormOutput($definition->text));
489 $template->parseCurrentBlock();
490 }
491
492 $template->setCurrentBlock('definition_image');
493 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture);
494 $template->setVariable('ANSWER_IMAGE_ALT', (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : ilUtil::prepareFormOutput($definition->picture));
495 $template->setVariable('ANSWER_IMAGE_TITLE', (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : ilUtil::prepareFormOutput($definition->picture));
496 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $definition->picture);
497 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
498 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
499 $template->parseCurrentBlock();
500 }
501 else
502 {
503 $template->setCurrentBlock('definition_text');
504 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
505 $template->parseCurrentBlock();
506 }
507 }
508 if (is_object($term))
509 {
510 if (strlen($term->picture))
511 {
512 if( strlen($term->text) )
513 {
514 $template->setCurrentBlock('term_image_text');
515 $template->setVariable("TEXT_TERM", ilUtil::prepareFormOutput($term->text));
516 $template->parseCurrentBlock();
517 }
518
519 $template->setCurrentBlock('term_image');
520 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture);
521 $template->setVariable('ANSWER_IMAGE_ALT', (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : ilUtil::prepareFormOutput($term->picture));
522 $template->setVariable('ANSWER_IMAGE_TITLE', (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : ilUtil::prepareFormOutput($term->picture));
523 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $term->picture);
524 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
525 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
526 $template->parseCurrentBlock();
527 }
528 else
529 {
530 $template->setCurrentBlock('term_text');
531 $template->setVariable("TERM", $this->object->prepareTextareaOutput($term->text, TRUE));
532 $template->parseCurrentBlock();
533 }
534 $i++;
535 }
536 if (($active_id > 0) && (!$show_correct_solution))
537 {
538 if ($graphicalOutput)
539 {
540 // output of ok/not ok icons for user entered solutions
541 $ok = false;
542 foreach ($this->object->getMatchingPairs() as $pair)
543 {
544 if( $this->isCorrectMatching($pair, $definition, $term) )
545 {
546 $ok = true;
547 }
548 }
549
550 if ($ok)
551 {
552 $template->setCurrentBlock("icon_ok");
553 $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
554 $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
555 $template->parseCurrentBlock();
556 }
557 else
558 {
559 $template->setCurrentBlock("icon_ok");
560 $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
561 $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
562 $template->parseCurrentBlock();
563 }
564 }
565 }
566
567 if ($result_output)
568 {
569 $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
570 $template->setCurrentBlock("result_output");
571 $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
572 $template->parseCurrentBlock();
573 }
574
575 $template->setCurrentBlock("row");
576 $template->setVariable("TEXT_MATCHES", $this->lng->txt("matches"));
577 $template->parseCurrentBlock();
578 }
579
580 $questiontext = $this->object->getQuestion();
581 if ($show_question_text==true)
582 {
583 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
584 }
585
586 $questionoutput = $template->get();
587
588 $feedback = '';
589 if($show_feedback)
590 {
591 if( !$this->isTestPresentationContext() )
592 {
593 $fb = $this->getGenericFeedbackOutput($active_id, $pass);
594 $feedback .= strlen($fb) ? $fb : '';
595 }
596
597 $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
598 $feedback .= strlen($fb) ? $fb : '';
599 }
600 if (strlen($feedback))
601 {
602 $cssClass = ( $this->hasCorrectSolution($active_id, $pass) ?
604 );
605
606 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
607 $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
608 }
609
610 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
611
612 $solutionoutput = $solutiontemplate->get();
613 if (!$show_question_only)
614 {
615 // get page object output
616 $solutionoutput = $this->getILIASPage($solutionoutput);
617 }
618 return $solutionoutput;
619 }
620
621 public function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
622 {
623 $solutions = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
624
625 if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
626 {
627 require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
630
631 $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
632 }
633 else
634 {
635 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
636 }
637
638 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
639 $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
640
641 $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
642
643 foreach($solutions as $defId => $terms)
644 {
645 foreach($terms as $termId)
646 {
647 $template->setCurrentBlock("matching_data");
648 $template->setVariable("DEFINITION_ID", $defId);
649 $template->setVariable("TERM_ID", $termId);
650 $template->parseCurrentBlock();
651 }
652 }
653
654 // shuffle output
655 $terms = $this->object->getTerms();
656 $definitions = $this->object->getDefinitions();
657 switch ($this->object->getShuffle())
658 {
659 case 1:
660 $seed = $this->object->getShuffler()->getSeed();
661 $this->object->getShuffler()->setSeed($seed.'1');
662 $terms = $this->object->getShuffler()->shuffle($terms);
663 $this->object->getShuffler()->setSeed($seed.'2');
664 $definitions = $this->object->getShuffler()->shuffle($definitions);
665 $this->object->getShuffler()->setSeed($seed);
666 break;
667 case 2:
668 $terms = $this->object->getShuffler()->shuffle($terms);
669 break;
670 case 3:
671 $definitions = $this->object->getShuffler()->shuffle($definitions);
672 break;
673 }
674
675 // create definitions
676 $counter = 0;
677 foreach ($definitions as $definition)
678 {
679 if (strlen($definition->picture))
680 {
681 $template->setCurrentBlock("definition_picture");
682 $template->setVariable("DEFINITION_ID", $definition->identifier);
683 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
684 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
685 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
686 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
687 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
688 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
689 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
690 $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? $this->object->prepareTextareaOutput($definition->text, TRUE) : '');
691 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
692 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
693 $template->parseCurrentBlock();
694 }
695 else
696 {
697 $template->setCurrentBlock("definition_text");
698 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
699 $template->parseCurrentBlock();
700 }
701
702 $template->setCurrentBlock("droparea");
703 $template->setVariable("ID_DROPAREA", $definition->identifier);
704 $template->setVariable("QUESTION_ID", $this->object->getId());
705 $template->parseCurrentBlock();
706
707 $template->setCurrentBlock("definition_data");
708 $template->setVariable("DEFINITION_ID", $definition->identifier);
709 $template->parseCurrentBlock();
710 }
711
712 // create terms
713 $counter = 0;
714 foreach ($terms as $term)
715 {
716 if (strlen($term->picture))
717 {
718 $template->setCurrentBlock("term_picture");
719 $template->setVariable("TERM_ID", $term->identifier);
720 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
721 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
722 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
723 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
724 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
725 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
726 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
727 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
728 $template->setVariable("TEXT_TERM", (strlen($term->text)) ? $this->object->prepareTextareaOutput($term->text, TRUE) : '');
729 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
730 $template->parseCurrentBlock();
731 }
732 else
733 {
734 $template->setCurrentBlock("term_text");
735 $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, TRUE));
736 $template->parseCurrentBlock();
737 }
738 $template->setCurrentBlock("draggable");
739 $template->setVariable("ID_DRAGGABLE", $term->identifier);
740 $template->parseCurrentBlock();
741
742 $template->setCurrentBlock("term_data");
743 $template->setVariable("TERM_ID", $term->identifier);
744 $template->parseCurrentBlock();
745 }
746
747 $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
748
749 $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
750
751 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
752
753 $questionoutput = $template->get();
754
755 if (!$show_question_only)
756 {
757 // get page object output
758 $questionoutput = $this->getILIASPage($questionoutput);
759 }
760
761 return $questionoutput;
762 }
763
769 protected function sortDefinitionsBySolution(array $solution, array $definitions)
770 {
771 $neworder = array();
772 $handled_defintions = array();
773 foreach($solution as $solution_values)
774 {
775 $id = $solution_values['value2'];
776 if(!isset($handled_defintions[$id]))
777 {
778 $neworder[] = $this->object->getDefinitionWithIdentifier($id);
779 $handled_defintions[$id] = $id;
780 }
781 }
782
783 foreach($definitions as $definition)
784 {
788 if(!isset($handled_defintions[$definition->identifier]))
789 {
790 $neworder[] = $definition;
791 }
792 }
793
794 return $neworder;
795 }
796
797 // hey: prevPassSolutions - pass will be always available from now on
798 function getTestOutput($active_id, $pass, $is_postponed = FALSE, $user_post_solution = FALSE, $inlineFeedback = false)
799 // hey.
800 {
801 if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
802 {
803 require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
806
807 $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
808 }
809 else
810 {
811 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
812 }
813
814 $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
815 $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
816
817 $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", true, true, "Modules/TestQuestionPool");
818
819 if ($active_id)
820 {
821 // hey: prevPassSolutions - obsolete due to central check
822 #$solutions = NULL;
823 #include_once "./Modules/Test/classes/class.ilObjTest.php";
824 #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
825 #{
826 # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
827 #}
828 // hey.
829 if (is_array($user_post_solution))
830 {
831 $solutions = array();
832 foreach ($user_post_solution['matching'][$this->object->getId()] as $definition => $term)
833 {
834 array_push($solutions, array("value1" => $term, "value2" => $definition));
835 }
836 }
837 else
838 {
839 // hey: prevPassSolutions - obsolete due to central check
840 $solutions = $this->getTestOutputSolutions($active_id, $pass);
841 // hey.
842 }
843
844 $counter = 0;
845 foreach ($solutions as $idx => $solution_value)
846 {
847 if (($solution_value["value2"] > -1) && ($solution_value["value1"] > -1))
848 {
849 $template->setCurrentBlock("matching_data");
850 $template->setVariable("TERM_ID", $solution_value["value1"]);
851 $template->setVariable("DEFINITION_ID", $solution_value["value2"]);
852 $template->parseCurrentBlock();
853 }
854
855 $counter++;
856 }
857 }
858
859 $terms = $this->object->getTerms();
860 $definitions = $this->object->getDefinitions();
861 switch ($this->object->getShuffle())
862 {
863 case 1:
864 $seed = $this->object->getShuffler()->getSeed();
865 $this->object->getShuffler()->setSeed($seed.'1');
866 $terms = $this->object->getShuffler()->shuffle($terms);
867 if (count($solutions))
868 {
869 $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
870 }
871 else
872 {
873 $this->object->getShuffler()->setSeed($seed.'2');
874 $definitions = $this->object->getShuffler()->shuffle($definitions);
875 }
876 $this->object->getShuffler()->setSeed($seed);
877 break;
878 case 2:
879 $terms = $this->object->getShuffler()->shuffle($terms);
880 break;
881 case 3:
882 if (count($solutions))
883 {
884 $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
885 }
886 else
887 {
888 $definitions = $this->object->getShuffler()->shuffle($definitions);
889 }
890 break;
891 }
892
893 // create definitions
894 $counter = 0;
895 foreach ($definitions as $definition)
896 {
897 if (strlen($definition->picture))
898 {
899 $template->setCurrentBlock("definition_picture");
900 $template->setVariable("DEFINITION_ID", $definition->identifier);
901 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
902 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
903 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
904 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
905 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
906 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
907 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
908 $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : '');
909 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
910 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
911 $template->parseCurrentBlock();
912 }
913 else
914 {
915 $template->setCurrentBlock("definition_text");
916 $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, true));
917 $template->parseCurrentBlock();
918 }
919
920 $template->setCurrentBlock("droparea");
921 $template->setVariable("ID_DROPAREA", $definition->identifier);
922 $template->setVariable("QUESTION_ID", $this->object->getId());
923 $template->parseCurrentBlock();
924
925 $template->setCurrentBlock("definition_data");
926 $template->setVariable("DEFINITION_ID", $definition->identifier);
927 $template->parseCurrentBlock();
928 }
929
930 // create terms
931 $counter = 0;
932 foreach ($terms as $term)
933 {
934 if (strlen($term->picture))
935 {
936 $template->setCurrentBlock("term_picture");
937 $template->setVariable("TERM_ID", $term->identifier);
938 $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
939 $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
940 $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
941 if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
942 $template->setVariable("THUMBNAIL_HREF", $thumbweb);
943 $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
944 $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
945 $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
946 $template->setVariable("TEXT_TERM", (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : '');
947 $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
948 $template->parseCurrentBlock();
949 }
950 else
951 {
952 $template->setCurrentBlock("term_text");
953 $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, true));
954 $template->parseCurrentBlock();
955 }
956 $template->setCurrentBlock("draggable");
957 $template->setVariable("ID_DRAGGABLE", $term->identifier);
958 $template->parseCurrentBlock();
959
960 $template->setCurrentBlock('term_data');
961 $template->setVariable('TERM_ID', $term->identifier);
962 $template->parseCurrentBlock();
963 }
964
965 $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
966
967 $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
968
969 $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
970
971 return $this->outQuestionPage("", $is_postponed, $active_id, $template->get());
972 }
973
977 function checkInput()
978 {
979 if ((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"]))
980 {
981 return false;
982 }
983 return true;
984 }
985
994 {
995 global $rbacsystem, $ilTabs;
996
997 $ilTabs->clearTargets();
998
999 $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1000 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1001 $q_type = $this->object->getQuestionType();
1002
1003 if (strlen($q_type))
1004 {
1005 $classname = $q_type . "GUI";
1006 $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1007 $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1008 }
1009
1010 if ($_GET["q_id"])
1011 {
1012 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1013 {
1014 // edit page
1015 $ilTabs->addTarget("edit_page",
1016 $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1017 array("edit", "insert", "exec_pg"),
1018 "", "", $force_active);
1019 }
1020
1021 $this->addTab_QuestionPreview($ilTabs);
1022 }
1023
1024 $force_active = false;
1025 if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1026 {
1027 $url = "";
1028 if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1029 // edit question properties
1030 $ilTabs->addTarget("edit_question",
1031 $url,
1032 array("editQuestion", "save", "saveEdit", "removeimageterms", "uploadterms", "removeimagedefinitions", "uploaddefinitions",
1033 "addpairs", "removepairs", "addterms", "removeterms", "adddefinitions", "removedefinitions", "originalSyncForm"),
1034 $classname, "", $force_active);
1035 }
1036
1037 // add tab for question feedback within common class assQuestionGUI
1038 $this->addTab_QuestionFeedback($ilTabs);
1039
1040 // add tab for question hint within common class assQuestionGUI
1041 $this->addTab_QuestionHints($ilTabs);
1042
1043 // add tab for question's suggested solution within common class assQuestionGUI
1044 $this->addTab_SuggestedSolution($ilTabs, $classname);
1045
1046 // Assessment of questions sub menu entry
1047 if ($_GET["q_id"])
1048 {
1049 $ilTabs->addTarget("statistics",
1050 $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1051 array("assessment"),
1052 $classname, "");
1053 }
1054
1055 $this->addBackTab($ilTabs);
1056 }
1057
1058 function getSpecificFeedbackOutput($active_id, $pass)
1059 {
1060 $matches = array_values($this->object->getMaximumScoringMatchingPairs());
1061
1062 if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($matches) )
1063 {
1064 return '';
1065 }
1066
1067 $feedback = '<table class="test_specific_feedback"><tbody>';
1068
1069 foreach ($matches as $idx => $ans)
1070 {
1071 $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1072 $this->object->getId(), $idx
1073 );
1074 $feedback .= '<tr><td>"' . $ans->definition->text . '"&nbsp;' . $this->lng->txt("matches") . '&nbsp;"';
1075 $feedback .= $ans->term->text . '"</td><td>';
1076 $feedback .= $fb . '</td> </tr>';
1077 }
1078
1079 $feedback .= '</tbody></table>';
1080 return $this->object->prepareTextareaOutput($feedback, TRUE);
1081 }
1082
1093 {
1094 return array();
1095 }
1096
1107 {
1108 return array();
1109 }
1110
1119 public function getAggregatedAnswersView($relevant_answers)
1120 {
1121 return ''; //print_r($relevant_answers,true);
1122 }
1123
1124 private function isCorrectMatching($pair, $definition, $term)
1125 {
1126 if( !($pair->points > 0) )
1127 {
1128 return false;
1129 }
1130
1131 if( !is_object($term) )
1132 {
1133 return false;
1134 }
1135
1136 if( $pair->definition->identifier != $definition->identifier )
1137 {
1138 return false;
1139 }
1140
1141 if( $pair->term->identifier != $term->identifier )
1142 {
1143 return false;
1144 }
1145
1146 return true;
1147 }
1148}
$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.
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
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
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 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['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
$url
Definition: shib_logout.php:72
$errors