ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assOrderingQuestionGUI.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 
23 {
24  private $uploadAlert = null;
25 
26  public $old_ordering_depth = array();
27  public $leveled_ordering = array();
28 
33 
43  public function __construct($id = -1)
44  {
46  include_once "./Modules/TestQuestionPool/classes/class.assOrderingQuestion.php";
47  $this->object = new assOrderingQuestion();
48  if ($id >= 0)
49  {
50  $this->object->loadFromDb($id);
51  }
52  $this->object->setOutputType(OUTPUT_JAVASCRIPT);
53 
54  $this->clearAnswersOnWritingPostDataEnabled = false;
55  }
56 
61  {
62  $this->clearAnswersOnWritingPostDataEnabled = $clearAnswersOnWritingPostDataEnabled;
63  }
64 
69  {
71  }
72 
73  public function changeToPictures()
74  {
75  if($this->object->getOrderingType() != OQ_NESTED_PICTURES && $this->object->getOrderingType() != OQ_PICTURES)
76  {
78  }
79 
80  $this->object->setOrderingType(OQ_PICTURES);
81  $this->writePostData(true);
82  $this->object->saveToDb();
83 
84  $this->editQuestion();
85  }
86 
87  public function changeToText()
88  {
89  if($this->object->getOrderingType() != OQ_NESTED_TERMS && $this->object->getOrderingType() != OQ_TERMS)
90  {
92  }
93 
94  $this->object->setOrderingType(OQ_TERMS);
95  $this->writePostData(true);
96  $this->object->saveToDb();
97 
98  $this->editQuestion();
99  }
100 
101  public function orderNestedTerms()
102  {
103  if($this->object->getOrderingType() != OQ_NESTED_TERMS && $this->object->getOrderingType() != OQ_TERMS)
104  {
106  }
107 
108  $this->object->setOrderingType(OQ_NESTED_TERMS);
109  $this->writePostData(true);
110  $this->object->saveToDb();
111 
112  $this->editQuestion();
113  }
114 
115  public function orderNestedPictures()
116  {
117  $this->object->setOrderingType(OQ_NESTED_PICTURES);
118  $this->writePostData(true);
119  $this->object->saveToDb();
120 
121  $this->editQuestion();
122  }
123 
124  public function addanswers()
125  {
126  $this->writePostData(true);
127  $position = key($_POST["cmd"]["addanswers"]);
128  $this->object->addAnswer("", $position+1);
129  $this->editQuestion();
130  }
131 
132  public function removeimageanswers()
133  {
134  $this->writePostData(true);
135  $position = key($_POST['cmd']['removeimageanswers']);
136  $filename = $_POST['answers']['imagename'][$position];
137  $this->object->removeAnswerImage($position);
138  $this->editQuestion();
139  }
140 
141  public function removeanswers()
142  {
143  $this->writePostData(true);
144  $position = key($_POST["cmd"]["removeanswers"]);
145  $this->object->deleteAnswer($position);
146  $this->editQuestion();
147  }
148 
149  public function upanswers()
150  {
151  $this->writePostData(true);
152  $position = key($_POST["cmd"]["upanswers"]);
153  $this->object->moveAnswerUp($position);
154  $this->editQuestion();
155  }
156 
157  public function downanswers()
158  {
159  $this->writePostData(true);
160  $position = key($_POST["cmd"]["downanswers"]);
161  $this->object->moveAnswerDown($position);
162  $this->editQuestion();
163  }
164 
169  {
170  include_once "./Modules/TestQuestionPool/classes/class.ilImageWizardInputGUI.php";
171  $answers = new ilImageWizardInputGUI($this->lng->txt("answers"), "answers");
172  $answers->setRequired(TRUE);
173  $answers->setQuestionObject($this->object);
174  $answers->setInfo($this->lng->txt('ordering_answer_sequence_info'));
175  $answers->setAllowMove(TRUE);
176  $answervalues = array();
177  foreach ($this->object->getAnswers() as $index => $answervalue)
178  {
179  $answervalues[$index] = $answervalue->getAnswertext();
180  }
181  $answers->setValues($answervalues);
182  return $answers;
183  }
184 
185  public function uploadanswers()
186  {
187  $this->lng->loadLanguageModule('form');
188 
190 
191  if( !$inp->checkInput() )
192  {
193  $this->uploadAlert = $inp->getAlert();
194  ilUtil::sendFailure($inp->getAlert());
195  }
196 
197  $this->writePostData(true);
198  $this->editQuestion();
199  }
200 
202  {
203  $this->object->setThumbGeometry( $_POST["thumb_geometry"] );
204  $this->object->setElementHeight( $_POST["element_height"] );
205  //$this->object->setOrderingType( $_POST["ordering_type"] );
206  $this->object->setPoints($_POST["points"]);
207  }
208 
210  {
211  $ordering_type = $this->object->getOrderingType();
212  // Delete all existing answers and create new answers from the form data
213  $this->object->flushAnswers();
214  $saved = false;
215 
216  // add answers
217  if ($ordering_type == OQ_TERMS
218  || $ordering_type == OQ_NESTED_TERMS
219  || $ordering_type == OQ_NESTED_PICTURES
220  )
221  {
222  $answers = $_POST["answers"];
223  if (is_array( $answers ))
224  {
226  $answers_ordering = $_POST['answers_ordering__default']; // __default is added by js
227  $new_hierarchy = json_decode( $answers_ordering );
228 
229  $this->getOldLeveledOrdering();
230 
231  if (!is_array( $new_hierarchy ))
232  {
233  $this->leveled_ordering = $this->old_ordering_depth;
234  }
235  else
236  {
237  $this->setLeveledOrdering( $new_hierarchy );
238  }
239 
240  $counter = 0;
241 
242  if(is_array($answers['imagename']))
243  {
244  foreach($answers['imagename'] as $index => $answer)
245  {
247  {
248  $answer = "";
249  }
250  $this->object->addAnswer($answer, -1, $this->leveled_ordering[$counter]);
251  $counter++;
252  }
253  }
254  else
255  {
256  foreach($answers as $index => $answer)
257  {
259  {
260  $answer = "";
261  }
262  $this->object->addAnswer($answer, -1, $this->leveled_ordering[$counter]);
263  $counter++;
264  }
265  }
266  }
267  }
268  else
269  {
270  if (is_array( $_POST['answers']['count'] ))
271  {
272  foreach (array_keys( $_POST['answers']['count'] ) as $index)
273  {
275  {
276  $this->object->addAnswer( "" );
277  continue;
278  }
279 
280  $picturefile = $_POST['answers']['imagename'][$index];
281  $file_org_name = $_FILES['answers']['name']['image'][$index];
282  $file_temp_name = $_FILES['answers']['tmp_name']['image'][$index];
283 
284  // new file
285  if (strlen( $file_temp_name ))
286  {
287  // check suffix
288  $suffix = strtolower( array_pop( explode( ".", $file_org_name ) ) );
289  if (in_array( $suffix, array( "jpg", "jpeg", "png", "gif" ) ))
290  {
291  // upload image
292  $filename = $this->object->createNewImageFileName( $file_org_name );
293  $filename = $this->object->getEncryptedFilename( $filename );
294  if ($this->object->setImageFile( $file_temp_name, $filename, $picturefile ))
295  {
296  $picturefile = $filename;
297  }
298  }
299  }
300 
301  $this->object->addAnswer( $picturefile );
302  }
303  }
304  else if(is_array($_POST['answers']))
305  {
306  foreach($_POST['answers'] as $random_id => $text_value)
307  {
308  $this->object->addAnswer( $text_value );
309  }
310  }
311  }
312  }
313 
315  {
316  $orderingtype = $this->object->getOrderingType();
317 
318  if (count($this->object->getAnswers()) == 0)
319  {
320  $this->object->addAnswer();
321  }
322 
323  $header = new ilFormSectionHeaderGUI();
324  $header->setTitle($this->lng->txt('oq_header_ordering_elements'));
325  $form->addItem($header);
326 
327  if ($orderingtype == OQ_PICTURES)
328  {
329  $answerImageUpload = $this->getAnswerImageFileUploadWizardFormProperty();
330  if ($this->uploadAlert !== null)
331  {
332  $answerImageUpload->setAlert( $this->uploadAlert );
333  }
334  $form->addItem( $answerImageUpload );
335  }
336  else if ($orderingtype == OQ_NESTED_TERMS || $orderingtype == OQ_NESTED_PICTURES)
337  {
338  require_once 'Modules/TestQuestionPool/classes/class.ilNestedOrderingGUI.php';
339  $answers = new ilNestedOrderingGUI($this->lng->txt( "answers" ), "answers");
340  $answers->setOrderingType( $orderingtype );
341  $answers->setObjAnswersArray( $this->object->getAnswers() );
342 
343  if ($orderingtype == OQ_NESTED_PICTURES)
344  {
345  $answers->setImagePath( $this->object->getImagePath() );
346  $answers->setImagePathWeb( $this->object->getImagePathWeb() );
347  $answers->setThumbPrefix( $this->object->getThumbPrefix() );
348  }
349  $answers->setInfo( $this->lng->txt( 'ordering_answer_sequence_info' ) );
350  $form->addItem( $answers );
351  }
352  else
353  {
354  $answers = new ilTextWizardInputGUI($this->lng->txt( "answers" ), "answers");
355  $answervalues = array();
356  foreach ($this->object->getAnswers() as $index => $answervalue)
357  {
358  $answervalues[$index] = $answervalue->getAnswertext();
359  }
360  ksort( $answervalues );
361  $answers->setValues( $answervalues );
362  $answers->setAllowMove( TRUE );
363  $answers->setRequired( TRUE );
364 
365  $answers->setInfo( $this->lng->txt( 'ordering_answer_sequence_info' ) );
366  $form->addItem( $answers );
367  }
368 
369  return $form;
370  }
371 
373  {
374  $orderingtype = $this->object->getOrderingType();
375 
376  // Edit mode
377 
378  //$hidden = new ilHiddenInputGUI("ordering_type");
379  //$hidden->setValue( $orderingtype );
380  //$form->addItem( $hidden );
381 
382  if (!$this->object->getSelfAssessmentEditingMode())
383  {
384  $element_height = new ilNumberInputGUI($this->lng->txt( "element_height" ), "element_height");
385  $element_height->setValue( $this->object->getElementHeight() );
386  $element_height->setRequired( false );
387  $element_height->setMaxLength( 6 );
388  $element_height->setMinValue( 20 );
389  $element_height->setSize( 6 );
390  $element_height->setInfo( $this->lng->txt( "element_height_info" ) );
391  $form->addItem( $element_height );
392  }
393 
394  if ($orderingtype == OQ_PICTURES)
395  {
396  $geometry = new ilNumberInputGUI($this->lng->txt( "thumb_geometry" ), "thumb_geometry");
397  $geometry->setValue( $this->object->getThumbGeometry() );
398  $geometry->setRequired( true );
399  $geometry->setMaxLength( 6 );
400  $geometry->setMinValue( 20 );
401  $geometry->setSize( 6 );
402  $geometry->setInfo( $this->lng->txt( "thumb_geometry_info" ) );
403  $form->addItem( $geometry );
404  }
405 
406  // points
407  $points = new ilNumberInputGUI($this->lng->txt( "points" ), "points");
408  $points->allowDecimals( true );
409  $points->setValue( $this->object->getPoints() );
410  $points->setRequired( TRUE );
411  $points->setSize( 3 );
412  $points->setMinValue( 0 );
413  $points->setMinvalueShouldBeGreater( true );
414  $form->addItem( $points );
415 
416  return $form;
417  }
418 
419  private function isUploadAnswersCommand()
420  {
421  return $this->ctrl->getCmd() == 'uploadanswers';
422  }
423 
432  public function writePostData($always = false)
433  {
434  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
435  if (!$hasErrors)
436  {
437  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
441  $this->saveTaxonomyAssignments();
442  return 0;
443  }
444 
445  return 1;
446  }
447 
451  public function editQuestion($checkonly = FALSE)
452  {
453  $save = $this->isSaveCommand();
454  $this->getQuestionTemplate();
455 
456  $orderingtype = $this->object->getOrderingType();
457 
458  require_once "./Services/Form/classes/class.ilPropertyFormGUI.php";
459  $form = new ilPropertyFormGUI();
460  $form->setFormAction($this->ctrl->getFormAction($this));
461  $form->setTitle($this->outQuestionType());
462  $form->setMultipart(($orderingtype == OQ_PICTURES) ? TRUE : FALSE);
463  $form->setTableWidth("100%");
464  $form->setId("ordering");
465  // title, author, description, question, working time (assessment mode)
466  $this->addBasicQuestionFormProperties( $form );
467  $this->populateQuestionSpecificFormPart($form );
468  $this->populateAnswerSpecificFormPart( $form );
469 
470  if (true || !$this->object->getSelfAssessmentEditingMode())
471  {
472  $this->populateCommandButtons($form);
473  }
474 
475  $this->populateTaxonomyFormSection($form);
476  $this->addQuestionFormCommandButtons($form);
477  $errors = false;
478  if ($save)
479  {
480  $form->setValuesByPost();
481  $errors = !$form->checkInput();
482  $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
483  if ($errors) $checkonly = false;
484  }
485 
486  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
487  return $errors;
488  }
489 
491  {
492  switch( $this->object->getOrderingType() )
493  {
494  case OQ_TERMS:
495 
496  $form->addCommandButton("changeToPictures", $this->lng->txt("oq_btn_use_order_pictures"));
497  $form->addCommandButton("orderNestedTerms", $this->lng->txt("oq_btn_nest_terms"));
498  break;
499 
500  case OQ_PICTURES:
501 
502  $form->addCommandButton("changeToText", $this->lng->txt("oq_btn_use_order_terms"));
503  $form->addCommandButton("orderNestedPictures", $this->lng->txt("oq_btn_nest_pictures"));
504  break;
505 
506  case OQ_NESTED_TERMS:
507 
508  $form->addCommandButton("changeToPictures", $this->lng->txt("oq_btn_use_order_pictures"));
509  $form->addCommandButton("changeToText", $this->lng->txt("oq_btn_define_terms"));
510  break;
511 
512  case OQ_NESTED_PICTURES:
513 
514  $form->addCommandButton("changeToText", $this->lng->txt("oq_btn_use_order_terms"));
515  $form->addCommandButton("changeToPictures", $this->lng->txt("oq_btn_define_pictures"));
516  break;
517  }
518  }
519 
536  $active_id,
537  $pass = NULL,
538  $graphicalOutput = FALSE,
539  $result_output = FALSE,
540  $show_question_only = TRUE,
541  $show_feedback = FALSE,
542  $show_correct_solution = FALSE,
543  $show_manual_scoring = FALSE,
544  $show_question_text = TRUE
545  )
546  {
547  if($this->object->getOrderingType() == OQ_NESTED_TERMS
548  || $this->object->getOrderingType() == OQ_NESTED_PICTURES)
549  {
550  $keys = array_keys($this->object->answers);
551 
552  // generate the question output
553  include_once "./Services/UICore/classes/class.ilTemplate.php";
554  $template = new ilTemplate("tpl.il_as_qpl_nested_ordering_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
555 
556  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
557 
558  // get the solution of the user for the active pass or from the last pass if allowed
559  $solutions = array();
560 
561  if (($active_id > 0) && (!$show_correct_solution))
562  {
563  $solutions = $this->object->getSolutionValues($active_id, $pass);
564  $user_order = array();
565  foreach ($solutions as $solution)
566  {
567  if(strchr( $solution['value2'],':') == true)
568  {
569  $current_solution = explode(':', $solution['value2']);
570 
571  $user_order[$solution["value1"]]['index'] = $solution["value1"];
572  $user_order[$solution["value1"]]['random_id'] = $current_solution[0];
573  $user_order[$solution["value1"]]['depth'] = $current_solution[1];
574  // needed for graphical output
575  $answer_text = $this->object->lookupAnswerTextByRandomId($current_solution[0]);
576  $user_order[$solution["value1"]]['answertext'] = $answer_text;
577  }
578  }
579  foreach ($this->object->answers as $k => $a)
580  {
581  $ok = FALSE;
582  if ($k == $user_order[$k]['index']
583  && $a->getOrderingDepth() == $user_order[$k]['depth']
584  && $a->getAnswerText() == $user_order[$k]['answertext'])
585  {
586  $ok = TRUE;
587 
588  }
589  $user_order[$k]['ok'] = $ok;
590  }
591 
592  $solution_output = $user_order;
593  }
594  else
595  {
596  foreach ($this->object->answers as $index => $answer)
597  {
598 
599  $expected_solution[$index]['index'] = $index;
600  $expected_solution[$index]['random_id'] = $answer->getRandomId();
601  $expected_solution[$index]['depth'] = $answer->getOrderingDepth();
602  if($this->object->getOrderingType() == OQ_NESTED_PICTURES)
603  {
604  $expected_solution[$index]['answertext'] = $answer->getAnswertext();
605  }
606  else
607  {
608  $expected_solution[$index]['answertext'] = $answer->getAnswertext();
609  }
610  }
611  $solution_output = $expected_solution;
612  }
613 
614  include_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
615  include_once 'Modules/TestQuestionPool/classes/class.ilNestedOrderingGUI.php';
616 
617  $answers_gui = new ilNestedOrderingGUI($this->lng->txt("answers"), "answers", $graphicalOutput);
618 
619  $no_js_for_cmds = array('outParticipantsPassDetails', 'outCorrectSolution', 'showManScoringParticipantScreen');
620 
621  //PERFORM_JAVASCRIPT
622  if(in_array($this->ctrl->getCmd(), $no_js_for_cmds))
623  {
624  $answers_gui->setPerformJavascript(false);
625  }
626  else
627  {
628  $answers_gui->setPerformJavascript(true);
629  }
630 
631  $answers_gui->setOrderingType($this->object->getOrderingType());
632 
633  if($this->object->getOrderingType() == OQ_NESTED_PICTURES)
634  {
635  $answers_gui->setImagePath($this->object->getImagePath());
636  $answers_gui->setImagePathWeb($this->object->getImagePathWeb());
637  $answers_gui->setThumbPrefix($this->object->getThumbPrefix());
638  }
639 
640  $solution_html = $answers_gui->getSolutionHTML($solution_output);
641 
642  $template->setVariable('SOLUTION_OUTPUT', $solution_html);
643 
644  $questiontext = $this->object->getQuestion();
645  if ($show_question_text==true)
646  {
647  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
648  }
649  $questionoutput = $template->get();
650 
651  $feedback = '';
652  if($show_feedback)
653  {
654  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
655  $feedback .= strlen($fb) ? $fb : '';
656 
657  $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
658  $feedback .= strlen($fb) ? $fb : '';
659  }
660  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
661 
662  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
663 
664  $solutionoutput = $solutiontemplate->get();
665  if (!$show_question_only)
666  {
667  // get page object output
668  $solutionoutput = $this->getILIASPage($solutionoutput);
669  }
670  }
671  else
672  {
673  $keys = array_keys($this->object->answers);
674 
675  // generate the question output
676  include_once "./Services/UICore/classes/class.ilTemplate.php";
677  $template = new ilTemplate("tpl.il_as_qpl_ordering_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
678  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html",TRUE, TRUE, "Modules/TestQuestionPool");
679 
680  // get the solution of the user for the active pass or from the last pass if allowed
681  $solutions = array();
682  if (($active_id > 0) && (!$show_correct_solution))
683  {
684  $solutions = $this->object->getSolutionValues($active_id, $pass);
685  }
686  else
687  {
688  foreach ($this->object->answers as $index => $answer)
689  {
690  array_push($solutions, array("value1" => $index, "value2" => $index+1));
691  }
692  }
693  foreach ($keys as $idx)
694  {
695  if (!$show_correct_solution)
696  {
697  foreach($solutions as $index => $item)
698  {
699  if($item['value2'] == $idx+1)
700  {
701  $answer = $this->object->answers[$item['value1']];
702  }
703  }
704  }
705  else
706  {
707  $answer = $this->object->answers[$idx];
708  }
709  if (!$answer)
710  {
711  continue;
712  }
713  if (($active_id > 0) && (!$show_correct_solution))
714  {
715  if ($graphicalOutput)
716  {
717  $sol = array();
718  foreach ($solutions as $solution)
719  {
720  $sol[$solution["value1"]] = $solution["value2"];
721  }
722  asort($sol);
723  $sol = array_keys($sol);
724  $ans = array();
725  foreach ($this->object->answers as $k => $a)
726  {
727  $ans[$k] = $k;
728  }
729  asort($ans);
730  $ans = array_keys($ans);
731  $ok = FALSE;
732  foreach ($ans as $arr_idx => $ans_idx)
733  {
734  if ($ans_idx == $idx)
735  {
736  if ($ans_idx == $sol[$arr_idx])
737  {
738  $ok = TRUE;
739  }
740  }
741  }
742  // output of ok/not ok icons for user entered solutions
743  if ($ok)
744  {
745  $template->setCurrentBlock("icon_ok");
746  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
747  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
748  $template->parseCurrentBlock();
749  }
750  else
751  {
752  $template->setCurrentBlock("icon_ok");
753  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
754  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
755  $template->parseCurrentBlock();
756  }
757  }
758  }
759  if ($this->object->getOrderingType() == OQ_PICTURES)
760  {
761  $template->setCurrentBlock("ordering_row_standard_pictures");
762  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getAnswertext();
763  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $answer->getAnswertext();
764  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
765  $template->setVariable("THUMB_HREF", $thumbweb);
766  list($width, $height, $type, $attr) = getimagesize($thumb);
767  $template->setVariable("ATTR", $attr);
768  $template->setVariable("THUMB_ALT", $this->lng->txt("thumbnail"));
769  $template->setVariable("THUMB_TITLE", $this->lng->txt("enlarge"));
770  $template->parseCurrentBlock();
771  }
772  else
773  {
774  $template->setCurrentBlock("ordering_row_standard_text");
775  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
776  $template->parseCurrentBlock();
777  }
778  $template->setCurrentBlock("ordering_row_standard");
779  if ($result_output)
780  {
781  $answer = $this->object->answers[$idx];
782  $points = $answer->getPoints();
783  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
784  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
785  }
786  foreach ($solutions as $solution)
787  {
788  if (strcmp($solution["value1"], $idx) == 0)
789  {
790  $template->setVariable("ANSWER_ORDER", $solution["value2"]);
791  }
792  }
793  $template->parseCurrentBlock();
794  }
795  $questiontext = $this->object->getQuestion();
796  if ($show_question_text==true)
797  {
798  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
799  }
800  $questionoutput = $template->get();
801  $feedback = ($show_feedback) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
802  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
803  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
804 
805  $solutionoutput = $solutiontemplate->get();
806  if (!$show_question_only)
807  {
808  // get page object output
809  $solutionoutput = $this->getILIASPage($solutionoutput);
810  }
811  }
812 
813  return $solutionoutput;
814  }
815 
816  function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
817  {
818  global $tpl;
819 
820  $this->object->setOutputType(OUTPUT_JAVASCRIPT);
821  $tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_javascript.css", "Modules/TestQuestionPool"));
822 
823  include_once "./Services/UICore/classes/class.ilTemplate.php";
824  $template = new ilTemplate("tpl.il_as_qpl_ordering_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
825 
826  if( is_object($this->getPreviewSession()) && count((array)$this->getPreviewSession()->getParticipantsSolution()) )
827  {
828  if ($this->object->getOrderingType() == OQ_NESTED_TERMS || $this->object->getOrderingType() == OQ_NESTED_PICTURES)
829  {
830  $answerMap = $this->getRandomIdToAnswerMap();
831 
832  $answerArray = array();
833  $shuffleAnswers = false;
834 
835  foreach((array)$this->getPreviewSession()->getParticipantsSolution() as $val1 => $val2)
836  {
837  list($randomId, $depth) = explode(':', $val2);
838 
839  $answ = new ASS_AnswerOrdering(
840  $answerMap[$randomId]->getAnswertext(), $randomId, $depth
841  );
842 
843  $answerArray[] = $answ;
844 
845  $jssolutions[$val2] = $val1;
846  }
847  }
848  else
849  {
850  foreach((array)$this->getPreviewSession()->getParticipantsSolution() as $val1 => $val2)
851  {
852  $jssolutions[$val2] = $val1;
853  }
854  }
855  }
856  else
857  {
858  $answerArray = $this->object->answers;
859  $shuffleAnswers = true;
860  }
861 
862 
863  global $ilUser;
864 
865  // shuffle output
866  $keys = array_keys($this->object->answers);
867  if($shuffleAnswers)
868  {
869  shuffle($keys);
870  }
871 
872  if ($this->object->getOrderingType() == OQ_NESTED_TERMS || $this->object->getOrderingType() == OQ_NESTED_PICTURES)
873  {
874  include_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
875  include_once 'Modules/TestQuestionPool/classes/class.ilNestedOrderingGUI.php';
876  $answers = new ilNestedOrderingGUI($this->lng->txt("answers"), "answers");
877  $answers->setOrderingType($this->object->getOrderingType());
878  $answers->setObjAnswersArray($answerArray, $shuffleAnswers);
879 
880  if($this->object->getOrderingType() == OQ_NESTED_PICTURES)
881  {
882  $answers->setImagePath($this->object->getImagePath());
883  $answers->setImagePathWeb($this->object->getImagePathWeb());
884  $answers->setThumbPrefix($this->object->getThumbPrefix());
885  }
886 
887  $template->setCurrentBlock('nested_ordering_output');
888  $template->setVariable('NESTED_ORDERING',$answers->getHtml());
889  $template->parseCurrentBlock();
890  $questiontext = $this->object->getQuestion();
891  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
892  $questionoutput = $template->get();
893  if (!$show_question_only)
894  {
895  // get page object output
896  $questionoutput = $this->getILIASPage($questionoutput);
897  }
898  return $questionoutput;
899 
900  }
901  else
902  {
903  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/ordering.js");
904 
905  $template->setCurrentBlock('form_submit_register');
906  $template->touchBlock('form_submit_register');
907  $template->parseCurrentBlock();
908 
909  if(count($jssolutions))
910  {
911  ksort($jssolutions);
912  $initial_order = array();
913  foreach($jssolutions as $key => $value)
914  {
915  if(is_object($this->object->getAnswer($value)))
916  {
917  $initial_order[] = 'id_' . $this->object->getAnswer($value)->getRandomID();
918  }
919  }
920 
921  $template->setVariable('INITIAL_ORDER', json_encode($initial_order));
922  }
923  else
924  {
925  $template->setVariable('INITIAL_ORDER', json_encode(array()));
926  }
927 
928  foreach ($keys as $idx)
929  {
930  $answer = $this->object->answers[$idx];
931  if ($this->object->getOrderingType() == OQ_PICTURES)
932  {
933  $template->setCurrentBlock("ordering_row_javascript_pictures");
934  $template->setVariable("PICTURE_HREF", $this->object->getImagePathWeb() . $answer->getAnswertext());
935  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getAnswertext();
936  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $answer->getAnswertext();
937  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
938  $template->setVariable("THUMB_HREF", $thumbweb);
939  $template->setVariable("THUMB_ALT", $this->lng->txt("thumbnail"));
940  $template->setVariable("THUMB_TITLE", $this->lng->txt("thumbnail"));
941  $template->setVariable("ENLARGE_HREF", ilUtil::getImagePath("enlarge.svg", FALSE));
942  $template->setVariable("ENLARGE_ALT", $this->lng->txt("enlarge"));
943  $template->setVariable("ENLARGE_TITLE", $this->lng->txt("enlarge"));
944  $template->setVariable("ANSWER_ID", $answer->getRandomID());
945  $template->parseCurrentBlock();
946  }
947  else
948  {
949  $template->setCurrentBlock("ordering_row_javascript_text");
950  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
951  $template->setVariable("ANSWER_ID", $answer->getRandomID());
952  $template->parseCurrentBlock();
953  }
954  }
955  if ($this->object->getOrderingType() == OQ_PICTURES)
956  {
957  $template->setVariable("RESET_POSITIONS", $this->lng->txt("reset_pictures"));
958  }
959  else
960  {
961  $template->setVariable("RESET_POSITIONS", $this->lng->txt("reset_definitions"));
962  }
963 
964  $questiontext = $this->object->getQuestion();
965  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
966  $template->setVariable("QUESTION_ID", $this->object->getId());
967  $questionoutput = $template->get();
968  if (!$show_question_only)
969  {
970  // get page object output
971  $questionoutput = $this->getILIASPage($questionoutput);
972  }
973  return $questionoutput;
974  }
975  }
976 
977  private function getRandomIdToAnswerMap()
978  {
979  $randomIdToAnswerMap = array();
980 
981  foreach($this->object->answers as $answer)
982  {
983  $randomIdToAnswerMap[$answer->getRandomId()] = $answer;
984  }
985 
986  return $randomIdToAnswerMap;
987  }
988 
989  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $user_post_solution = FALSE)
990  {
991  global $tpl;
992 
993  $tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_javascript.css", "Modules/TestQuestionPool"));
994 
995  // generate the question output
996  include_once "./Services/UICore/classes/class.ilTemplate.php";
997  $template = new ilTemplate("tpl.il_as_qpl_ordering_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
998 
999  $this->object->setOutputType(OUTPUT_JAVASCRIPT);
1000  // shuffle output
1001  $keys = array();
1002  if (is_array($user_post_solution))
1003  {
1004  $keys = $_SESSION["ordering_keys"];
1005  }
1006  else
1007  {
1008  $keys = array_keys($this->object->answers);
1009  shuffle($keys);
1010  }
1011  $_SESSION["ordering_keys"] = $keys;
1012 
1013 
1014  if ($this->object->getOrderingType() == OQ_NESTED_TERMS
1015  || $this->object->getOrderingType() == OQ_NESTED_PICTURES)
1016  {
1017 
1018  include_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
1019  include_once 'Modules/TestQuestionPool/classes/class.ilNestedOrderingGUI.php';
1020  $answerGUI = new ilNestedOrderingGUI($this->lng->txt("answers"), "answers");
1021  $answerGUI->setInstanceId('participant');
1022  $answerGUI->setOrderingType($this->object->getOrderingType());
1023 
1024  $answerMap = $this->getRandomIdToAnswerMap();
1025 
1026  $answerArray = array();
1027  $shuffleAnswers = false;
1028 
1029  if( is_array($user_post_solution) && isset($user_post_solution['answers_ordering__participant']) )
1030  {
1031  $answers_ordering = $_POST['answers_ordering__participant'];
1032  $user_solution_hierarchy = json_decode($answers_ordering);
1033  $with_random_id = true;
1034  $this->object->setLeveledOrdering($user_solution_hierarchy, $with_random_id);
1035 
1036  foreach($this->object->leveled_ordering as $randomId => $depth)
1037  {
1038  $answ = new ASS_AnswerOrdering(
1039  $answerMap[$randomId]->getAnswertext(), $randomId, $depth
1040  );
1041 
1042  $answerArray[] = $answ;
1043  }
1044  }
1045  else
1046  {
1047  include_once "./Modules/Test/classes/class.ilObjTest.php";
1048 
1049  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1050  {
1051  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1052  }
1053 
1054  $solutions =& $this->object->getSolutionValues($active_id, $pass);
1055 
1056  if( count($solutions) )
1057  {
1058  foreach($solutions as $solution)
1059  {
1060  list($randomId, $depth) = explode(':', $solution['value2']);
1061 
1062  $answ = new ASS_AnswerOrdering(
1063  $answerMap[$randomId]->getAnswertext(), $randomId, $depth
1064  );
1065 
1066  $answerArray[] = $answ;
1067  }
1068  }
1069  else
1070  {
1071  $answerArray = $this->object->answers;
1072  $shuffleAnswers = true;
1073  }
1074  }
1075 
1076  $answerGUI->setObjAnswersArray($answerArray, $shuffleAnswers);
1077 
1078  if($this->object->getOrderingType() == OQ_NESTED_PICTURES)
1079  {
1080  $answerGUI->setImagePath($this->object->getImagePath());
1081  $answerGUI->setImagePathWeb($this->object->getImagePathWeb());
1082  $answerGUI->setThumbPrefix($this->object->getThumbPrefix());
1083  }
1084 
1085  $template->setCurrentBlock('nested_ordering_output');
1086  $template->setVariable('NESTED_ORDERING',$answerGUI->getHtml($shuffleAnswers));
1087  $template->parseCurrentBlock();
1088  $questiontext = $this->object->getQuestion();
1089  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
1090  $questionoutput = $template->get();
1091  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1092  return $pageoutput;
1093  }
1094  else
1095  {
1096  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/ordering.js");
1097 
1098  // BEGIN: onsubmit form action for javascript enabled ordering questions
1099  $this->tpl->setVariable("ON_SUBMIT", "return $('div.ilVerticalOrderingQuestion').ilOrderingQuestion('saveOrder');");
1100  // END: onsubmit form action for javascript enabled ordering questions
1101 
1102  // get the solution of the user for the active pass or from the last pass if allowed
1103  if ($active_id)
1104  {
1105  $solutions = NULL;
1106  include_once "./Modules/Test/classes/class.ilObjTest.php";
1107  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
1108  {
1109  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
1110  }
1111  if (is_array($user_post_solution))
1112  {
1113  $solutions = array();
1114  foreach ($user_post_solution as $key => $value)
1115  {
1116  if (preg_match("/order_(\d+)/", $key, $matches))
1117  {
1118  foreach ($this->object->getAnswers() as $answeridx => $answer)
1119  {
1120  if ($answer->getRandomID() == $matches[1])
1121  {
1122  array_push($solutions, array("value1" => $answeridx, "value2" => $value));
1123  }
1124  }
1125  }
1126  }
1127  }
1128  else
1129  {
1130  $solutions =& $this->object->getSolutionValues($active_id, $pass);
1131  }
1132 
1133  $jssolutions = array();
1134  foreach ($solutions as $idx => $solution_value)
1135  {
1136  if ((strcmp($solution_value["value2"], "") != 0) && (strcmp($solution_value["value1"], "") != 0))
1137  {
1138  $jssolutions[$solution_value["value2"]] = $solution_value["value1"];
1139  }
1140  }
1141  if(count($jssolutions))
1142  {
1143  ksort($jssolutions);
1144  $initial_order = array();
1145  foreach($jssolutions as $key => $value)
1146  {
1147  if(is_object($this->object->getAnswer($value)))
1148  {
1149  $initial_order[] = 'id_' . $this->object->getAnswer($value)->getRandomID();
1150  }
1151  }
1152 
1153  $template->setVariable('INITIAL_ORDER', json_encode($initial_order));
1154  }
1155  else
1156  {
1157  $template->setVariable('INITIAL_ORDER', json_encode(array()));
1158  }
1159  }
1160 
1161  foreach ($keys as $idx)
1162  {
1163  $answer = $this->object->answers[$idx];
1164  if ($this->object->getOrderingType() == OQ_PICTURES)
1165  {
1166  $template->setCurrentBlock("ordering_row_javascript_pictures");
1167  $template->setVariable("PICTURE_HREF", $this->object->getImagePathWeb() . $answer->getAnswertext());
1168  $thumbweb = $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getAnswertext();
1169  $thumb = $this->object->getImagePath() . $this->object->getThumbPrefix() . $answer->getAnswertext();
1170  if (!@file_exists($thumb)) $this->object->rebuildThumbnails();
1171  $template->setVariable("THUMB_HREF", $thumbweb);
1172  $template->setVariable("THUMB_ALT", $this->lng->txt("thumbnail"));
1173  $template->setVariable("THUMB_TITLE", $this->lng->txt("thumbnail"));
1174  $template->setVariable("ENLARGE_HREF", ilUtil::getImagePath("enlarge.svg", FALSE));
1175  $template->setVariable("ENLARGE_ALT", $this->lng->txt("enlarge"));
1176  $template->setVariable("ENLARGE_TITLE", $this->lng->txt("enlarge"));
1177  $template->setVariable("ANSWER_ID", $answer->getRandomID());
1178  $template->parseCurrentBlock();
1179  }
1180  else
1181  {
1182  $template->setCurrentBlock("ordering_row_javascript_text");
1183  $template->setVariable("ANSWER_TEXT", $this->object->prepareTextareaOutput($answer->getAnswertext(), TRUE));
1184  $template->setVariable("ANSWER_ID", $answer->getRandomID());
1185  $template->parseCurrentBlock();
1186  }
1187  }
1188  if($this->object->getOrderingType() == OQ_PICTURES)
1189  {
1190  $template->setVariable("RESET_POSITIONS", $this->lng->txt("reset_pictures"));
1191  }
1192  else
1193  {
1194  $template->setVariable("RESET_POSITIONS", $this->lng->txt("reset_definitions"));
1195  }
1196 
1197  $questiontext = $this->object->getQuestion();
1198  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
1199  $template->setVariable("QUESTION_ID", $this->object->getId());
1200  $questionoutput = $template->get();
1201  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
1202  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/ordering.js");
1203  return $pageoutput;
1204  }
1205  }
1206 
1214  function setQuestionTabs()
1215  {
1216  global $rbacsystem, $ilTabs;
1217 
1218  $ilTabs->clearTargets();
1219 
1220  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
1221  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1222  $q_type = $this->object->getQuestionType();
1223 
1224  if (strlen($q_type))
1225  {
1226  $classname = $q_type . "GUI";
1227  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
1228  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
1229  }
1230 
1231  if ($_GET["q_id"])
1232  {
1233  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1234  {
1235  // edit page
1236  $ilTabs->addTarget("edit_page",
1237  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
1238  array("edit", "insert", "exec_pg"),
1239  "", "", $force_active);
1240  }
1241 
1242  $this->addTab_QuestionPreview($ilTabs);
1243  }
1244 
1245  $force_active = false;
1246  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
1247  {
1248  $url = "";
1249  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
1250  $commands = $_POST["cmd"];
1251  if (is_array($commands))
1252  {
1253  foreach ($commands as $key => $value)
1254  {
1255  if (preg_match("/^delete_.*/", $key, $matches))
1256  {
1257  $force_active = true;
1258  }
1259  }
1260  }
1261  // edit question properties
1262  $ilTabs->addTarget("edit_question",
1263  $url,
1264  array("orderNestedTerms","orderNestedPictures","editQuestion", "save", "saveEdit", "addanswers", "removeanswers", "changeToPictures", "uploadanswers", "changeToText", "upanswers", "downanswers", "originalSyncForm"),
1265  $classname, "", $force_active);
1266  }
1267 
1268  // add tab for question feedback within common class assQuestionGUI
1269  $this->addTab_QuestionFeedback($ilTabs);
1270 
1271  // add tab for question hint within common class assQuestionGUI
1272  $this->addTab_QuestionHints($ilTabs);
1273 
1274  // add tab for question's suggested solution within common class assQuestionGUI
1275  $this->addTab_SuggestedSolution($ilTabs, $classname);
1276 
1277  // Assessment of questions sub menu entry
1278  if ($_GET["q_id"])
1279  {
1280  $ilTabs->addTarget("statistics",
1281  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
1282  array("assessment"),
1283  $classname, "");
1284  }
1285 
1286  $this->addBackTab($ilTabs);
1287  }
1288 
1289  function getSpecificFeedbackOutput($active_id, $pass)
1290  {
1291  if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($this->object->getAnswers()) )
1292  {
1293  return '';
1294  }
1295 
1296  $output = '<table class="test_specific_feedback"><tbody>';
1297 
1298  foreach($this->object->getAnswers() as $idx => $answer)
1299  {
1300  $feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
1301  $this->object->getId(), $idx
1302  );
1303 
1304  $output .= "<tr><td>{$answer->getAnswerText()}</td><td>{$feedback}</td></tr>";
1305  }
1306 
1307  $output .= '</tbody></table>';
1308 
1309  return $this->object->prepareTextareaOutput($output, TRUE);
1310  }
1311 
1312  private function getDepthRecursive($child, $ordering_depth)
1313  {
1314  if(is_array($child->children))
1315  {
1316  foreach($child->children as $grand_child)
1317  {
1318  $ordering_depth++;
1319  $this->leveled_ordering[] = $ordering_depth;
1320  $this->getDepthRecursive($grand_child, $ordering_depth);
1321  }
1322  }
1323  else
1324  {
1325  $ordering_depth++;
1326  $this->leveled_ordering[] = $ordering_depth;
1327  }
1328  }
1329 
1330  public function setLeveledOrdering($new_hierarchy)
1331  {
1332  foreach($new_hierarchy as $id)
1333  {
1334  $ordering_depth = 0;
1335  $this->leveled_ordering[] = $ordering_depth;
1336 
1337  if(is_array($id->children))
1338  {
1339  foreach($id->children as $child)
1340  {
1341  $this->getDepthRecursive($child, $ordering_depth);
1342  }
1343  }
1344  }
1345  }
1346 
1347  private function getOldLeveledOrdering()
1348  {
1349  global $ilDB;
1350 
1351  $res = $ilDB->queryF('SELECT depth FROM qpl_a_ordering WHERE question_fi = %s ORDER BY solution_order ASC',
1352  array('integer'), array($this->object->getId()));
1353  while($row = $ilDB->fetchAssoc($res))
1354  {
1355  $this->old_ordering_depth[] = $row['depth'];
1356  }
1358  }
1359 
1370  {
1371  return array();
1372  }
1373 
1384  {
1385  return array();
1386  }
1387 
1396  public function getAggregatedAnswersView($relevant_answers)
1397  {
1398  return $this->renderAggregateView(
1399  $this->aggregateAnswers( $relevant_answers, $this->object->getAnswers() ) )->get();
1400  }
1401 
1402  public function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
1403  {
1404  $passdata = array(); // Regroup answers into units of passes.
1405  foreach($relevant_answers_chosen as $answer_chosen)
1406  {
1407  $passdata[$answer_chosen['active_fi'].'-'. $answer_chosen['pass']][$answer_chosen['value2']] = $answer_chosen['value1'];
1408  }
1409 
1410  $variants = array(); // Determine unique variants.
1411  foreach($passdata as $key => $data)
1412  {
1413  $hash = md5(implode('-', $data));
1414  $value_set = false;
1415  foreach ($variants as $vkey => $variant)
1416  {
1417  if ($variant['hash'] == $hash)
1418  {
1419  $variant['count']++;
1420  $value_set = true;
1421  }
1422  }
1423  if (!$value_set)
1424  {
1425  $variants[$key]['hash'] = $hash;
1426  $variants[$key]['count'] = 1;
1427  }
1428  }
1429 
1430  $aggregate = array(); // Render aggregate from variant.
1431  foreach ($variants as $key => $variant_entry)
1432  {
1433  $variant = $passdata[$key];
1434 
1435  foreach($variant as $variant_key => $variant_line)
1436  {
1437  $i = 0;
1438  $aggregated_info_for_answer['count'] = $variant_entry['count'];
1439  foreach ($answers_defined_on_question as $answer)
1440  {
1441  $i++;
1442  $aggregated_info_for_answer[$i . ' - ' . $answer->getAnswerText()]
1443  = $passdata[$key][$i];
1444  }
1445 
1446  }
1447  $aggregate[] = $aggregated_info_for_answer;
1448  }
1449  return $aggregate;
1450  }
1451 
1457  public function renderAggregateView($aggregate)
1458  {
1459  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
1460 
1461  foreach ($aggregate as $line_data)
1462  {
1463  $tpl->setCurrentBlock( 'aggregaterow' );
1464  $count = array_shift($line_data);
1465  $html = '<ul>';
1466  foreach($line_data as $key => $line)
1467  {
1468  $html .= '<li>'. ++$line .'&nbsp;-&nbsp;' .$key. '</li>';
1469  }
1470  $html .= '</ul>';
1471  $tpl->setVariable( 'COUNT', $count );
1472  $tpl->setVariable( 'OPTION', $html );
1473 
1474  $tpl->parseCurrentBlock();
1475  }
1476  return $tpl;
1477  }
1478 }