ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
All Data Structures Namespaces Files Functions Variables Modules 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  {
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';
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  if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
599  {
600  require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
603 
604  $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
605  }
606  else
607  {
608  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
609  }
610 
611  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
612  $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
613 
614  $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
615 
616  foreach($solutions as $defId => $terms)
617  {
618  foreach($terms as $termId)
619  {
620  $template->setCurrentBlock("matching_data");
621  $template->setVariable("DEFINITION_ID", $defId);
622  $template->setVariable("TERM_ID", $termId);
623  $template->parseCurrentBlock();
624  }
625  }
626 
627  // shuffle output
628  $terms = $this->object->getTerms();
629  $definitions = $this->object->getDefinitions();
630  switch ($this->object->getShuffle())
631  {
632  case 1:
633  $terms = $this->object->pcArrayShuffle($terms);
634  $definitions = $this->object->pcArrayShuffle($definitions);
635  break;
636  case 2:
637  $terms = $this->object->pcArrayShuffle($terms);
638  break;
639  case 3:
640  $definitions = $this->object->pcArrayShuffle($definitions);
641  break;
642  }
643 
644  // create definitions
645  $counter = 0;
646  foreach ($definitions as $definition)
647  {
648  if (strlen($definition->picture))
649  {
650  $template->setCurrentBlock("definition_picture");
651  $template->setVariable("DEFINITION_ID", $definition->identifier);
652  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
653  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
654  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
655  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
656  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
657  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
658  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
659  $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? $this->object->prepareTextareaOutput($definition->text, TRUE) : '');
660  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
661  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
662  $template->parseCurrentBlock();
663  }
664  else
665  {
666  $template->setCurrentBlock("definition_text");
667  $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, TRUE));
668  $template->parseCurrentBlock();
669  }
670 
671  $template->setCurrentBlock("droparea");
672  $template->setVariable("ID_DROPAREA", $definition->identifier);
673  $template->setVariable("QUESTION_ID", $this->object->getId());
674  $template->parseCurrentBlock();
675 
676  $template->setCurrentBlock("definition_data");
677  $template->setVariable("DEFINITION_ID", $definition->identifier);
678  $template->parseCurrentBlock();
679  }
680 
681  // create terms
682  $counter = 0;
683  foreach ($terms as $term)
684  {
685  if (strlen($term->picture))
686  {
687  $template->setCurrentBlock("term_picture");
688  $template->setVariable("TERM_ID", $term->identifier);
689  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
690  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
691  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
692  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
693  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
694  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
695  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
696  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
697  $template->setVariable("TEXT_TERM", (strlen($term->text)) ? $this->object->prepareTextareaOutput($term->text, TRUE) : '');
698  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
699  $template->parseCurrentBlock();
700  }
701  else
702  {
703  $template->setCurrentBlock("term_text");
704  $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, TRUE));
705  $template->parseCurrentBlock();
706  }
707  $template->setCurrentBlock("draggable");
708  $template->setVariable("ID_DRAGGABLE", $term->identifier);
709  $template->parseCurrentBlock();
710 
711  $template->setCurrentBlock("term_data");
712  $template->setVariable("TERM_ID", $term->identifier);
713  $template->parseCurrentBlock();
714  }
715 
716  $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
717 
718  $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
719 
720  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
721 
722  $questionoutput = $template->get();
723 
724  if (!$show_question_only)
725  {
726  // get page object output
727  $questionoutput = $this->getILIASPage($questionoutput);
728  }
729 
730  return $questionoutput;
731  }
732 
738  protected function sortDefinitionsBySolution(array $solution, array $definitions)
739  {
740  $neworder = array();
741  $handled_defintions = array();
742  foreach($solution as $solution_values)
743  {
744  $id = $solution_values['value2'];
745  if(!isset($handled_defintions[$id]))
746  {
747  $neworder[] = $this->object->getDefinitionWithIdentifier($id);
748  $handled_defintions[$id] = $id;
749  }
750  }
751 
752  foreach($definitions as $definition)
753  {
757  if(!isset($handled_defintions[$definition->identifier]))
758  {
759  $neworder[] = $definition;
760  }
761  }
762 
763  return $neworder;
764  }
765 
766  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $user_post_solution = FALSE)
767  {
768  if($GLOBALS['ilBrowser']->isMobile() || $GLOBALS['ilBrowser']->isIpad())
769  {
770  require_once 'Services/jQuery/classes/class.iljQueryUtil.php';
773 
774  $this->tpl->addJavaScript('./Services/jQuery/js/jquery.ui.touch-punch.min.js');
775  }
776  else
777  {
778  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/jquery-ui-1-10-3-fixed.js');
779  }
780 
781  $this->tpl->addJavaScript('Modules/TestQuestionPool/js/ilMatchingQuestion.js');
782  $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_javascript.css', 'Modules/TestQuestionPool'));
783 
784  $template = new ilTemplate("tpl.il_as_qpl_matching_output.html", true, true, "Modules/TestQuestionPool");
785 
786  if ($active_id)
787  {
788  $solutions = NULL;
789  include_once "./Modules/Test/classes/class.ilObjTest.php";
790  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
791  {
792  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
793  }
794  if (is_array($user_post_solution))
795  {
796  $solutions = array();
797  foreach ($user_post_solution['matching'][$this->object->getId()] as $definition => $term)
798  {
799  array_push($solutions, array("value1" => $term, "value2" => $definition));
800  }
801  }
802  else
803  {
804  $solutions =& $this->object->getSolutionValues($active_id, $pass);
805  }
806 
807  $counter = 0;
808  foreach ($solutions as $idx => $solution_value)
809  {
810  if (($solution_value["value2"] > -1) && ($solution_value["value1"] > -1))
811  {
812  $template->setCurrentBlock("matching_data");
813  $template->setVariable("TERM_ID", $solution_value["value1"]);
814  $template->setVariable("DEFINITION_ID", $solution_value["value2"]);
815  $template->parseCurrentBlock();
816  }
817 
818  $counter++;
819  }
820  }
821 
822  $terms = $this->object->getTerms();
823  $definitions = $this->object->getDefinitions();
824  switch ($this->object->getShuffle())
825  {
826  case 1:
827  $terms = $this->object->pcArrayShuffle($terms);
828  if (count($solutions))
829  {
830  $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
831  }
832  else
833  {
834  $definitions = $this->object->pcArrayShuffle($definitions);
835  }
836  break;
837  case 2:
838  $terms = $this->object->pcArrayShuffle($terms);
839  break;
840  case 3:
841  if (count($solutions))
842  {
843  $definitions = $this->sortDefinitionsBySolution($solutions, $definitions);
844  }
845  else
846  {
847  $definitions = $this->object->pcArrayShuffle($definitions);
848  }
849  break;
850  }
851 
852  // create definitions
853  $counter = 0;
854  foreach ($definitions as $definition)
855  {
856  if (strlen($definition->picture))
857  {
858  $template->setCurrentBlock("definition_picture");
859  $template->setVariable("DEFINITION_ID", $definition->identifier);
860  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $definition->picture);
861  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $definition->picture;
862  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $definition->picture;
863  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
864  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
865  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
866  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
867  $template->setVariable("TEXT_DEFINITION", (strlen($definition->text)) ? ilUtil::prepareFormOutput($definition->text) : '');
868  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
869  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
870  $template->parseCurrentBlock();
871  }
872  else
873  {
874  $template->setCurrentBlock("definition_text");
875  $template->setVariable("DEFINITION", $this->object->prepareTextareaOutput($definition->text, true));
876  $template->parseCurrentBlock();
877  }
878 
879  $template->setCurrentBlock("droparea");
880  $template->setVariable("ID_DROPAREA", $definition->identifier);
881  $template->setVariable("QUESTION_ID", $this->object->getId());
882  $template->parseCurrentBlock();
883 
884  $template->setCurrentBlock("definition_data");
885  $template->setVariable("DEFINITION_ID", $definition->identifier);
886  $template->parseCurrentBlock();
887  }
888 
889  // create terms
890  $counter = 0;
891  foreach ($terms as $term)
892  {
893  if (strlen($term->picture))
894  {
895  $template->setCurrentBlock("term_picture");
896  $template->setVariable("TERM_ID", $term->identifier);
897  $template->setVariable("IMAGE_HREF", $this->object->getImagePathWeb() . $term->picture);
898  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $term->picture;
899  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $term->picture;
900  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
901  $template->setVariable("THUMBNAIL_HREF", $thumbweb);
902  $template->setVariable("THUMB_ALT", $this->lng->txt("image"));
903  $template->setVariable("THUMB_TITLE", $this->lng->txt("image"));
904  $template->setVariable("TEXT_PREVIEW", $this->lng->txt('preview'));
905  $template->setVariable("TEXT_TERM", (strlen($term->text)) ? ilUtil::prepareFormOutput($term->text) : '');
906  $template->setVariable("IMG_PREVIEW", ilUtil::getImagePath('enlarge.svg'));
907  $template->parseCurrentBlock();
908  }
909  else
910  {
911  $template->setCurrentBlock("term_text");
912  $template->setVariable("TERM_TEXT", $this->object->prepareTextareaOutput($term->text, true));
913  $template->parseCurrentBlock();
914  }
915  $template->setCurrentBlock("draggable");
916  $template->setVariable("ID_DRAGGABLE", $term->identifier);
917  $template->parseCurrentBlock();
918 
919  $template->setCurrentBlock('term_data');
920  $template->setVariable('TERM_ID', $term->identifier);
921  $template->parseCurrentBlock();
922  }
923 
924  $template->setVariable('MATCHING_MODE', $this->object->getMatchingMode());
925 
926  $template->setVariable("RESET_BUTTON", $this->lng->txt("reset_terms"));
927 
928  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), TRUE));
929 
930  return $this->outQuestionPage("", $is_postponed, $active_id, $template->get());
931  }
932 
936  function checkInput()
937  {
938  if ((!$_POST["title"]) or (!$_POST["author"]) or (!$_POST["question"]))
939  {
940  return false;
941  }
942  return true;
943  }
944 
952  function setQuestionTabs()
953  {
954  global $rbacsystem, $ilTabs;
955 
956  $ilTabs->clearTargets();
957 
958  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
959  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
960  $q_type = $this->object->getQuestionType();
961 
962  if (strlen($q_type))
963  {
964  $classname = $q_type . "GUI";
965  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
966  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
967  }
968 
969  if ($_GET["q_id"])
970  {
971  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
972  {
973  // edit page
974  $ilTabs->addTarget("edit_page",
975  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
976  array("edit", "insert", "exec_pg"),
977  "", "", $force_active);
978  }
979 
980  $this->addTab_QuestionPreview($ilTabs);
981  }
982 
983  $force_active = false;
984  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
985  {
986  $url = "";
987  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
988  // edit question properties
989  $ilTabs->addTarget("edit_question",
990  $url,
991  array("editQuestion", "save", "saveEdit", "removeimageterms", "uploadterms", "removeimagedefinitions", "uploaddefinitions",
992  "addpairs", "removepairs", "addterms", "removeterms", "adddefinitions", "removedefinitions", "originalSyncForm"),
993  $classname, "", $force_active);
994  }
995 
996  // add tab for question feedback within common class assQuestionGUI
997  $this->addTab_QuestionFeedback($ilTabs);
998 
999  // add tab for question hint within common class assQuestionGUI
1000  $this->addTab_QuestionHints($ilTabs);
1001 
1002  // add tab for question's suggested solution within common class assQuestionGUI
1003  $this->addTab_SuggestedSolution($ilTabs, $classname);
1004 
1005  // Assessment of questions sub menu entry
1006  if ($_GET["q_id"])
1007  {
1008  $ilTabs->addTarget("statistics",
1009  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1010  array("assessment"),
1011  $classname, "");
1012  }
1013 
1014  $this->addBackTab($ilTabs);
1015  }
1016 
1017  function getSpecificFeedbackOutput($active_id, $pass)
1018  {
1019  $matches = array_values($this->object->getMaximumScoringMatchingPairs());
1020 
1021  if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($matches) )
1022  {
1023  return '';
1024  }
1025 
1026  $feedback = '<table class="test_specific_feedback"><tbody>';
1027 
1028  foreach ($matches as $idx => $ans)
1029  {
1030  $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1031  $this->object->getId(), $idx
1032  );
1033  $feedback .= '<tr><td>"' . $ans->definition->text . '"&nbsp;' . $this->lng->txt("matches") . '&nbsp;"';
1034  $feedback .= $ans->term->text . '"</td><td>';
1035  $feedback .= $fb . '</td> </tr>';
1036  }
1037 
1038  $feedback .= '</tbody></table>';
1039  return $this->object->prepareTextareaOutput($feedback, TRUE);
1040  }
1041 
1052  {
1053  return array();
1054  }
1055 
1066  {
1067  return array();
1068  }
1069 
1078  public function getAggregatedAnswersView($relevant_answers)
1079  {
1080  return ''; //print_r($relevant_answers,true);
1081  }
1082 
1083  private function isCorrectMatching($pair, $definition, $term)
1084  {
1085  if( !($pair->points > 0) )
1086  {
1087  return false;
1088  }
1089 
1090  if( !is_object($term) )
1091  {
1092  return false;
1093  }
1094 
1095  if( $pair->definition->identifier != $definition->identifier )
1096  {
1097  return false;
1098  }
1099 
1100  if( $pair->term->identifier != $term->identifier )
1101  {
1102  return false;
1103  }
1104 
1105  return true;
1106  }
1107 }
Class for matching question terms.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
$errors
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
This class represents an option in a radio group.
static initjQueryUI()
Init jQuery UI (see included_components.txt for included components)
Class for matching question pairs.
writePostData()
Evaluates a posted edit form and writes the form data in the question object.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
$_POST['username']
Definition: cron.php:12
getItemByPostVar($a_post_var)
Get Item by POST variable.
setValue($a_value)
Set Value.
This class represents a single choice wizard property in a property form.
This class represents a selection list property in a property form.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
setHideImages($a_hide)
Set hide images.
This class represents a property form user interface.
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
$_GET["client_id"]
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
isValidTermAndDefinitionAmount(ilPropertyFormGUI $form)
for mode 1:1 terms count must not be less than definitions count for mode n:n this limitation is canc...
addItem($a_item)
Add Item (Property, SectionHeader).
getQuestionTemplate()
get question template
Matching question GUI representation.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
Class for matching questions.
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
This class represents a hidden form property in a property form.
This class represents a property in a property form.
setValue($a_value)
Set Value.
__construct($id=-1)
assMatchingQuestionGUI constructor
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
$GLOBALS['ct_recipient']
getILIASPage($html="")
Returns the ILIAS Page around a question.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
This class represents a number property in a property form.
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
special template class to simplify handling of ITX/PEAR
isCorrectMatching($pair, $definition, $term)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
setOptions($a_options)
Set Options.
Basic GUI class for assessment questions.
setErrorMessage($errormessage)
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
$filename
Definition: buildRTE.php:89
setQuestionTabs()
Sets the ILIAS tabs for this question type.
getTestOutput($active_id, $pass=NULL, $is_postponed=FALSE, $user_post_solution=FALSE)
addBackTab(ilTabsGUI $ilTabs)
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.
Class for matching question definitions.
static initjQuery($a_tpl=null)
Init jQuery.
Interface ilGuiAnswerScoringAdjustable.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
Interface ilGuiQuestionScoringAdjustable.
setRequired($a_required)
Set Required.
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
This class represents a key value pair wizard property in a property form.
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.