ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8 
24 {
34  public function __construct($id = -1)
35  {
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';
62  $this->saveTaxonomyAssignments();
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  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
599  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
600  $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
601 
602  $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
603 
604  foreach($solutions as $defId => $terms)
605  {
606  foreach($terms as $termId)
607  {
608  $template->setCurrentBlock("matching_data");
609  $template->setVariable("DEFINITION_ID", $defId);
610  $template->setVariable("TERM_ID", $termId);
611  $template->parseCurrentBlock();
612  }
613  }
614 
615  // shuffle output
616  $terms = $this->object->getTerms();
617  $definitions = $this->object->getDefinitions();
618  switch ($this->object->getShuffle())
619  {
620  case 1:
621  $terms = $this->object->pcArrayShuffle($terms);
622  $definitions = $this->object->pcArrayShuffle($definitions);
623  break;
624  case 2:
625  $terms = $this->object->pcArrayShuffle($terms);
626  break;
627  case 3:
628  $definitions = $this->object->pcArrayShuffle($definitions);
629  break;
630  }
631 
632  // create definitions
633  $counter = 0;
634  foreach ($definitions as $definition)
635  {
636  if (strlen($definition->picture))
637  {
638  $template->setCurrentBlock("definition_picture");
639  $template->setVariable("DEFINITION_ID", $definition->identifier);
640  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
641  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
642  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
643  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
644  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
645  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
646  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
647  $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? $this->object->prepareTextareaOutput($definition->text, TRUE) : '');
648  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
649  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
650  $template->parseCurrentBlock();
651  }
652  else
653  {
654  $template->setCurrentBlock("definition_text");
655  $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
656  $template->parseCurrentBlock();
657  }
658 
659  $template->setCurrentBlock("droparea");
660  $template->setVariable("ID_DROPAREA", $definition->identifier);
661  $template->setVariable("QUESTION_ID", $this->object->getId());
662  $template->parseCurrentBlock();
663 
664  $template->setCurrentBlock("definition_data");
665  $template->setVariable("DEFINITION_ID", $definition->identifier);
666  $template->parseCurrentBlock();
667  }
668 
669  // create terms
670  $counter = 0;
671  foreach ($terms as $term)
672  {
673  if (strlen($term->picture))
674  {
675  $template->setCurrentBlock("term_picture");
676  $template->setVariable("TERM_ID", $term->identifier);
677  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
678  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
679  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
680  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
681  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
682  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
683  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
684  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
685  $template->setVariable("TEXT_TERM", (strlen($term->text)) ? $this->object->prepareTextareaOutput($term->text, TRUE) : '');
686  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
687  $template->parseCurrentBlock();
688  }
689  else
690  {
691  $template->setCurrentBlock("term_text");
692  $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, TRUE));
693  $template->parseCurrentBlock();
694  }
695  $template->setCurrentBlock("draggable");
696  $template->setVariable("ID_DRAGGABLE", $term->identifier);
697  $template->parseCurrentBlock();
698 
699  $template->setCurrentBlock("term_data");
700  $template->setVariable("TERM_ID", $term->identifier);
701  $template->parseCurrentBlock();
702  }
703 
704  $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
705 
706  $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
707 
708  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
709 
710  $questionoutput = $template->get();
711 
712  if (!$show_question_only)
713  {
714  // get page object output
715  $questionoutput = $this->getILIASPage($questionoutput);
716  }
717 
718  return $questionoutput;
719  }
720 
726  protected function sortDefinitionsBySolution(array $solution, array $definitions)
727  {
728  $neworder = array();
729  $handled_defintions = array();
730  foreach($solution as $solution_values)
731  {
732  $id = $solution_values['value2'];
733  if(!isset($handled_defintions[$id]))
734  {
735  $neworder[] = $this->object->getDefinitionWithIdentifier($id);
736  $handled_defintions[$id] = $id;
737  }
738  }
739 
740  foreach($definitions as $definition)
741  {
745  if(!isset($handled_defintions[$definition->identifier]))
746  {
747  $neworder[] = $definition;
748  }
749  }
750 
751  return $neworder;
752  }
753 
754  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $user_post_solution = FALSE)
755  {
756  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
757  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
758  $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
759 
760  $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", true, true, "Modules/TestQuestionPool");
761 
762  if ($active_id)
763  {
764  $solutions = NULL;
765  include_once "./Modules/Test/classes/class.ilObjTest.php";
766  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
767  {
768  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
769  }
770  if (is_array($user_post_solution))
771  {
772  $solutions = array();
773  foreach ($user_post_solution['matching'][$this->object->getId()] as $definition => $term)
774  {
775  array_push($solutions, array("value1" => $term, "value2" => $definition));
776  }
777  }
778  else
779  {
780  $solutions =& $this->object->getSolutionValues($active_id, $pass);
781  }
782 
783  $counter = 0;
784  foreach ($solutions as $idx => $solution_value)
785  {
786  if (($solution_value["value2"] > -1) && ($solution_value["value1"] > -1))
787  {
788  $template->setCurrentBlock("matching_data");
789  $template->setVariable("TERM_ID", $solution_value["value1"]);
790  $template->setVariable("DEFINITION_ID", $solution_value["value2"]);
791  $template->parseCurrentBlock();
792  }
793 
794  $counter++;
795  }
796  }
797 
798  $terms = $this->object->getTerms();
799  $definitions = $this->object->getDefinitions();
800  switch ($this->object->getShuffle())
801  {
802  case 1:
803  $terms = $this->object->pcArrayShuffle($terms);
804  if (count($solutions))
805  {
806  $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
807  }
808  else
809  {
810  $definitions = $this->object->pcArrayShuffle($definitions);
811  }
812  break;
813  case 2:
814  $terms = $this->object->pcArrayShuffle($terms);
815  break;
816  case 3:
817  if (count($solutions))
818  {
819  $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
820  }
821  else
822  {
823  $definitions = $this->object->pcArrayShuffle($definitions);
824  }
825  break;
826  }
827 
828  // create definitions
829  $counter = 0;
830  foreach ($definitions as $definition)
831  {
832  if (strlen($definition->picture))
833  {
834  $template->setCurrentBlock("definition_picture");
835  $template->setVariable("DEFINITION_ID", $definition->identifier);
836  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
837  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
838  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
839  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
840  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
841  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
842  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
843  $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : '');
844  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
845  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
846  $template->parseCurrentBlock();
847  }
848  else
849  {
850  $template->setCurrentBlock("definition_text");
851  $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, true));
852  $template->parseCurrentBlock();
853  }
854 
855  $template->setCurrentBlock("droparea");
856  $template->setVariable("ID_DROPAREA", $definition->identifier);
857  $template->setVariable("QUESTION_ID", $this->object->getId());
858  $template->parseCurrentBlock();
859 
860  $template->setCurrentBlock("definition_data");
861  $template->setVariable("DEFINITION_ID", $definition->identifier);
862  $template->parseCurrentBlock();
863  }
864 
865  // create terms
866  $counter = 0;
867  foreach ($terms as $term)
868  {
869  if (strlen($term->picture))
870  {
871  $template->setCurrentBlock("term_picture");
872  $template->setVariable("TERM_ID", $term->identifier);
873  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
874  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
875  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
876  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
877  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
878  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
879  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
880  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
881  $template->setVariable("TEXT_TERM", (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : '');
882  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
883  $template->parseCurrentBlock();
884  }
885  else
886  {
887  $template->setCurrentBlock("term_text");
888  $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, true));
889  $template->parseCurrentBlock();
890  }
891  $template->setCurrentBlock("draggable");
892  $template->setVariable("ID_DRAGGABLE", $term->identifier);
893  $template->parseCurrentBlock();
894 
895  $template->setCurrentBlock('term_data');
896  $template->setVariable('TERM_ID', $term->identifier);
897  $template->parseCurrentBlock();
898  }
899 
900  $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
901 
902  $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
903 
904  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
905 
906  return $this->outQuestionPage("", $is_postponed, $active_id, $template->get());
907  }
908 
912  function checkInput()
913  {
914  if ((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"]))
915  {
916  return false;
917  }
918  return true;
919  }
920 
928  function setQuestionTabs()
929  {
930  global $rbacsystem, $ilTabs;
931 
932  $ilTabs->clearTargets();
933 
934  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
935  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
936  $q_type = $this->object->getQuestionType();
937 
938  if (strlen($q_type))
939  {
940  $classname = $q_type . "GUI";
941  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
942  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
943  }
944 
945  if ($_GET["q_id"])
946  {
947  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
948  {
949  // edit page
950  $ilTabs->addTarget("edit_page",
951  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
952  array("edit", "insert", "exec_pg"),
953  "", "", $force_active);
954  }
955 
956  $this->addTab_QuestionPreview($ilTabs);
957  }
958 
959  $force_active = false;
960  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
961  {
962  $url = "";
963  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
964  // edit question properties
965  $ilTabs->addTarget("edit_question",
966  $url,
967  array("editQuestion", "save", "saveEdit", "removeimageterms", "uploadterms", "removeimagedefinitions", "uploaddefinitions",
968  "addpairs", "removepairs", "addterms", "removeterms", "adddefinitions", "removedefinitions", "originalSyncForm"),
969  $classname, "", $force_active);
970  }
971 
972  // add tab for question feedback within common class assQuestionGUI
973  $this->addTab_QuestionFeedback($ilTabs);
974 
975  // add tab for question hint within common class assQuestionGUI
976  $this->addTab_QuestionHints($ilTabs);
977 
978  // add tab for question's suggested solution within common class assQuestionGUI
979  $this->addTab_SuggestedSolution($ilTabs, $classname);
980 
981  // Assessment of questions sub menu entry
982  if ($_GET["q_id"])
983  {
984  $ilTabs->addTarget("statistics",
985  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
986  array("assessment"),
987  $classname, "");
988  }
989 
990  $this->addBackTab($ilTabs);
991  }
992 
993  function getSpecificFeedbackOutput($active_id, $pass)
994  {
995  $matches = array_values($this->object->getMaximumScoringMatchingPairs());
996 
997  if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($matches) )
998  {
999  return '';
1000  }
1001 
1002  $feedback = '<table class="test_specific_feedback"><tbody>';
1003 
1004  foreach ($matches as $idx => $ans)
1005  {
1006  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1007  $this->object->getId(), $idx
1008  );
1009  $feedback .= '<tr><td>"' . $ans->definition->text . '"&nbsp;' . $this->lng->txt("matches") . '&nbsp;"';
1010  $feedback .= $ans->term->text . '"</td><td>';
1011  $feedback .= $fb . '</td> </tr>';
1012  }
1013 
1014  $feedback .= '</tbody></table>';
1015  return $this->object->prepareTextareaOutput($feedback, TRUE);
1016  }
1017 
1028  {
1029  return array();
1030  }
1031 
1042  {
1043  return array();
1044  }
1045 
1054  public function getAggregatedAnswersView($relevant_answers)
1055  {
1056  return ''; //print_r($relevant_answers,true);
1057  }
1058 
1059  private function isCorrectMatching($pair, $definition, $term)
1060  {
1061  if( !($pair->points > 0) )
1062  {
1063  return false;
1064  }
1065 
1066  if( !is_object($term) )
1067  {
1068  return false;
1069  }
1070 
1071  if( $pair->definition->identifier != $definition->identifier )
1072  {
1073  return false;
1074  }
1075 
1076  if( $pair->term->identifier != $term->identifier )
1077  {
1078  return false;
1079  }
1080 
1081  return true;
1082  }
1083 }