ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assTextSubsetGUI.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 {
32  public function __construct($id = -1)
33  {
35  require_once './Modules/TestQuestionPool/classes/class.assTextSubset.php';
36  $this->object = new assTextSubset();
37  if ($id >= 0)
38  {
39  $this->object->loadFromDb($id);
40  }
41  }
42 
50  public function writePostData($always = false)
51  {
52  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
53  if (!$hasErrors)
54  {
55  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
59  $this->saveTaxonomyAssignments();
60  return 0;
61  }
62  return 1;
63  }
64 
68  public function editQuestion($checkonly = FALSE)
69  {
70  $save = $this->isSaveCommand();
71  $this->getQuestionTemplate();
72 
73  require_once './Services/Form/classes/class.ilPropertyFormGUI.php';
74  $form = new ilPropertyFormGUI();
75  $form->setFormAction($this->ctrl->getFormAction($this));
76  $form->setTitle($this->outQuestionType());
77  $form->setMultipart(FALSE);
78  $form->setTableWidth("100%");
79  $form->setId("asstextsubset");
80 
81  $this->addBasicQuestionFormProperties($form);
82  $this->populateQuestionSpecificFormPart( $form );
83  $this->populateAnswerSpecificFormPart( $form );
84  $this->populateTaxonomyFormSection($form);
85  $this->addQuestionFormCommandButtons($form);
86 
87  $errors = false;
88  if ($save)
89  {
90  $form->setValuesByPost();
91  $points = $form->getItemByPostVar('points');
92  $points->setValue($this->object->getMaximumPoints());
93  $errors = !$form->checkInput();
94  $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
95  if ($errors) $checkonly = false;
96  }
97 
98  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
99  return $errors;
100  }
101 
105  public function addanswers()
106  {
107  $this->writePostData(true);
108  $position = key($_POST['cmd']['addanswers']);
109  $this->object->addAnswer("", 0, $position+1);
110  $this->editQuestion();
111  }
112 
116  public function removeanswers()
117  {
118  $this->writePostData(true);
119  $position = key($_POST['cmd']['removeanswers']);
120  $this->object->deleteAnswer($position);
121  $this->editQuestion();
122  }
123 
138  $active_id,
139  $pass = NULL,
140  $graphicalOutput = FALSE,
141  $result_output = FALSE,
142  $show_question_only = TRUE,
143  $show_feedback = FALSE,
144  $show_correct_solution = FALSE,
145  $show_manual_scoring = FALSE,
146  $show_question_text = TRUE
147  )
148  {
149  // get the solution of the user for the active pass or from the last pass if allowed
150  $solutions = array();
151  if (($active_id > 0) && (!$show_correct_solution))
152  {
153  $solutions =& $this->object->getSolutionValues($active_id, $pass);
154  }
155  else
156  {
157  $rank = array();
158  foreach ($this->object->answers as $answer)
159  {
160  if ($answer->getPoints() > 0)
161  {
162  if (!is_array($rank[$answer->getPoints()]))
163  {
164  $rank[$answer->getPoints()] = array();
165  }
166  array_push($rank[$answer->getPoints()], $answer->getAnswertext());
167  }
168  }
169  krsort($rank, SORT_NUMERIC);
170  foreach ($rank as $index => $bestsolutions)
171  {
172  array_push($solutions, array("value1" => join(",", $bestsolutions), "points" => $index));
173  }
174  }
175 
176  // generate the question output
177  include_once "./Services/UICore/classes/class.ilTemplate.php";
178  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
179  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
180  $available_answers =& $this->object->getAvailableAnswers();
181  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++)
182  {
183  if ((!$test_id) && (strcmp($solutions[$i]["value1"], "") == 0))
184  {
185  }
186  else
187  {
188  if (($active_id > 0) && (!$show_correct_solution))
189  {
190  if ($graphicalOutput)
191  {
192  // output of ok/not ok icons for user entered solutions
193  $index = $this->object->isAnswerCorrect($available_answers, $solutions[$i]["value1"]);
194  $correct = FALSE;
195  if ($index !== FALSE)
196  {
197  unset($available_answers[$index]);
198  $correct = TRUE;
199  }
200  if ($correct)
201  {
202  $template->setCurrentBlock("icon_ok");
203  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
204  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
205  $template->parseCurrentBlock();
206  }
207  else
208  {
209  $template->setCurrentBlock("icon_ok");
210  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
211  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
212  $template->parseCurrentBlock();
213  }
214  }
215  }
216  $template->setCurrentBlock("textsubset_row");
217  $template->setVariable("SOLUTION", $solutions[$i]["value1"]);
218  $template->setVariable("COUNTER", $i+1);
219  if ($result_output)
220  {
221  $points = $solutions[$i]["points"];
222  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
223  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
224  }
225  $template->parseCurrentBlock();
226  }
227  }
228  $questiontext = $this->object->getQuestion();
229  if ($show_question_text==true)
230  {
231  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
232  }
233  $questionoutput = $template->get();
234  $feedback = ($show_feedback) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
235  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true));
236  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
237 
238  $solutionoutput = $solutiontemplate->get();
239  if (!$show_question_only)
240  {
241  // get page object output
242  $solutionoutput = $this->getILIASPage($solutionoutput);
243  }
244  return $solutionoutput;
245  }
246 
247  function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
248  {
249  $solutions = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
250  // generate the question output
251  include_once "./Services/UICore/classes/class.ilTemplate.php";
252  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
253  $width = $this->object->getMaxTextboxWidth();
254  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++)
255  {
256  $template->setCurrentBlock("textsubset_row");
257  foreach ($solutions as $idx => $solution_value)
258  {
259  if ($idx == $i)
260  {
261  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . $solution_value."\"");
262  }
263  }
264  $template->setVariable("COUNTER", $i+1);
265  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i+1));
266  $template->setVariable("TEXTFIELD_SIZE", $width);
267  $template->parseCurrentBlock();
268  }
269  $questiontext = $this->object->getQuestion();
270  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
271  $questionoutput = $template->get();
272  if (!$show_question_only)
273  {
274  // get page object output
275  $questionoutput = $this->getILIASPage($questionoutput);
276  }
277  return $questionoutput;
278  }
279 
280  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE)
281  {
282  // get the solution of the user for the active pass or from the last pass if allowed
283  $user_solution = "";
284  if ($active_id)
285  {
286  $solutions = NULL;
287  include_once "./Modules/Test/classes/class.ilObjTest.php";
288  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
289  {
290  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
291  }
292  $solutions =& $this->object->getSolutionValues($active_id, $pass);
293  }
294 
295  // generate the question output
296  include_once "./Services/UICore/classes/class.ilTemplate.php";
297  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
298  $width = $this->object->getMaxTextboxWidth();
299  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++)
300  {
301  $template->setCurrentBlock("textsubset_row");
302  foreach ($solutions as $idx => $solution_value)
303  {
304  if ($idx == $i)
305  {
306  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . ilUtil::prepareFormOutput($solution_value["value1"])."\"");
307  }
308  }
309  $template->setVariable("COUNTER", $i+1);
310  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i+1));
311  $template->setVariable("TEXTFIELD_SIZE", $width);
312  $template->parseCurrentBlock();
313  }
314  $questiontext = $this->object->getQuestion();
315  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
316  $questionoutput = $template->get();
317  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
318  return $pageoutput;
319  }
320 
328  function setQuestionTabs()
329  {
330  global $rbacsystem, $ilTabs;
331 
332  $ilTabs->clearTargets();
333 
334  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
335  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
336  $q_type = $this->object->getQuestionType();
337 
338  if (strlen($q_type))
339  {
340  $classname = $q_type . "GUI";
341  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
342  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
343  }
344 
345  if ($_GET["q_id"])
346  {
347  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
348  {
349  // edit page
350  $ilTabs->addTarget("edit_page",
351  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
352  array("edit", "insert", "exec_pg"),
353  "", "", $force_active);
354  }
355 
356  $this->addTab_QuestionPreview($ilTabs);
357  }
358 
359  $force_active = false;
360  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
361  {
362  $url = "";
363  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
364  // edit question properties
365  $ilTabs->addTarget("edit_question",
366  $url,
367  array("editQuestion", "save", "saveEdit", "addanswers", "removeanswers", "originalSyncForm"),
368  $classname, "", $force_active);
369  }
370 
371  // add tab for question feedback within common class assQuestionGUI
372  $this->addTab_QuestionFeedback($ilTabs);
373 
374  // add tab for question hint within common class assQuestionGUI
375  $this->addTab_QuestionHints($ilTabs);
376 
377  // add tab for question's suggested solution within common class assQuestionGUI
378  $this->addTab_SuggestedSolution($ilTabs, $classname);
379 
380  // Assessment of questions sub menu entry
381  if ($_GET["q_id"])
382  {
383  $ilTabs->addTarget("statistics",
384  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
385  array("assessment"),
386  $classname, "");
387  }
388 
389  $this->addBackTab($ilTabs);
390  }
391 
392  function getSpecificFeedbackOutput($active_id, $pass)
393  {
394  $output = "";
395  return $this->object->prepareTextareaOutput($output, TRUE);
396  }
397 
399  {
400  $this->object->setCorrectAnswers( $_POST["correctanswers"] );
401  $this->object->setTextRating( $_POST["text_rating"] );
402  }
403 
405  {
406  // Delete all existing answers and create new answers from the form data
407  $this->object->flushAnswers();
408  foreach ($_POST['answers']['answer'] as $index => $answer)
409  {
410  $answertext = $answer;
411  $this->object->addAnswer( $answertext, $_POST['answers']['points'][$index], $index );
412  }
413  }
414 
416  {
417  // number of requested answers
418  $correctanswers = new ilNumberInputGUI($this->lng->txt( "nr_of_correct_answers" ), "correctanswers");
419  $correctanswers->setMinValue( 1 );
420  $correctanswers->setDecimals( 0 );
421  $correctanswers->setSize( 3 );
422  $correctanswers->setValue( $this->object->getCorrectAnswers() );
423  $correctanswers->setRequired( true );
424  $form->addItem( $correctanswers );
425 
426  // maximum available points
427  $points = new ilNumberInputGUI($this->lng->txt( "maximum_points" ), "points");
428  $points->setMinValue(0.0);
429  $points->setMinvalueShouldBeGreater(true);
430  $points->setSize( 6 );
431  $points->setDisabled( true );
432  $points->setValue( $this->object->getMaximumPoints() );
433  $points->setRequired( false );
434  $form->addItem( $points );
435 
436  // text rating
437  $textrating = new ilSelectInputGUI($this->lng->txt( "text_rating" ), "text_rating");
438  $text_options = array(
439  "ci" => $this->lng->txt( "cloze_textgap_case_insensitive" ),
440  "cs" => $this->lng->txt( "cloze_textgap_case_sensitive" )
441  );
442  if (!$this->object->getSelfAssessmentEditingMode())
443  {
444  $text_options["l1"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "1" );
445  $text_options["l2"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "2" );
446  $text_options["l3"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "3" );
447  $text_options["l4"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "4" );
448  $text_options["l5"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "5" );
449  }
450  $textrating->setOptions( $text_options );
451  $textrating->setValue( $this->object->getTextRating() );
452  $form->addItem( $textrating );
453  return $form;
454  }
455 
457  {
458  // Choices
459  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
460  $choices = new ilAnswerWizardInputGUI($this->lng->txt( "answers" ), "answers");
461  $choices->setRequired( true );
462  $choices->setQuestionObject( $this->object );
463  $choices->setSingleline( true );
464  $choices->setAllowMove( false );
465  $choices->setMinValue(0.0);
466  if ($this->object->getAnswerCount() == 0)
467  $this->object->addAnswer( "", 0, 0 );
468  $choices->setValues( $this->object->getAnswers() );
469  $form->addItem( $choices );
470  return $form;
471  }
472 
473 
484  {
485  return array();
486  }
487 
498  {
499  return array();
500  }
501 
510  public function getAggregatedAnswersView($relevant_answers)
511  {
512  return $this->renderAggregateView(
513  $this->aggregateAnswers( $relevant_answers ) )->get();
514  }
515 
516  public function aggregateAnswers($relevant_answers_chosen)
517  {
518  $aggregate = array();
519 
520  foreach ($relevant_answers_chosen as $relevant_answer)
521  {
522  if ( array_key_exists($relevant_answer['value1'], $aggregate) )
523  {
524  $aggregate[$relevant_answer['value1']]++;
525  }
526  else
527  {
528  $aggregate[$relevant_answer['value1']] = 1;
529  }
530  }
531  return $aggregate;
532  }
533 
539  public function renderAggregateView($aggregate)
540  {
541  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
542 
543  foreach ($aggregate as $key => $value)
544  {
545  $tpl->setCurrentBlock( 'aggregaterow' );
546  $tpl->setVariable( 'OPTION', $key );
547  $tpl->setVariable( 'COUNT', $value );
548  $tpl->parseCurrentBlock();
549  }
550  return $tpl;
551  }
552 }