ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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  {
34  parent::__construct();
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->isTestPresentationContext()) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
235  if (strlen($feedback))
236  {
237  $cssClass = ( $this->hasCorrectSolution($active_id, $pass) ?
239  );
240 
241  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
242  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
243  }
244  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
245 
246  $solutionoutput = $solutiontemplate->get();
247  if (!$show_question_only)
248  {
249  // get page object output
250  $solutionoutput = $this->getILIASPage($solutionoutput);
251  }
252  return $solutionoutput;
253  }
254 
255  function getPreview($show_question_only = FALSE, $showInlineFeedback = false)
256  {
257  $solutions = is_object($this->getPreviewSession()) ? (array)$this->getPreviewSession()->getParticipantsSolution() : array();
258  // generate the question output
259  include_once "./Services/UICore/classes/class.ilTemplate.php";
260  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
261  $width = $this->object->getMaxTextboxWidth();
262  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++)
263  {
264  $template->setCurrentBlock("textsubset_row");
265  foreach ($solutions as $idx => $solution_value)
266  {
267  if ($idx == $i)
268  {
269  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . $solution_value."\"");
270  }
271  }
272  $template->setVariable("COUNTER", $i+1);
273  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i+1));
274  $template->setVariable("TEXTFIELD_SIZE", $width);
275  $template->parseCurrentBlock();
276  }
277  $questiontext = $this->object->getQuestion();
278  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
279  $questionoutput = $template->get();
280  if (!$show_question_only)
281  {
282  // get page object output
283  $questionoutput = $this->getILIASPage($questionoutput);
284  }
285  return $questionoutput;
286  }
287 
288  function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE, $inlineFeedback = false)
289  {
290  // get the solution of the user for the active pass or from the last pass if allowed
291  $user_solution = "";
292  if ($active_id)
293  {
294  $solutions = NULL;
295  // hey: prevPassSolutions - obsolete due to central check
296  #include_once "./Modules/Test/classes/class.ilObjTest.php";
297  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
298  #{
299  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
300  #}
301  // hey.
302  $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass);
303  }
304 
305  // generate the question output
306  include_once "./Services/UICore/classes/class.ilTemplate.php";
307  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
308  $width = $this->object->getMaxTextboxWidth();
309  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++)
310  {
311  $template->setCurrentBlock("textsubset_row");
312  foreach ($solutions as $idx => $solution_value)
313  {
314  if ($idx == $i)
315  {
316  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . ilUtil::prepareFormOutput($solution_value["value1"])."\"");
317  }
318  }
319  $template->setVariable("COUNTER", $i+1);
320  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i+1));
321  $template->setVariable("TEXTFIELD_SIZE", $width);
322  $template->parseCurrentBlock();
323  }
324  $questiontext = $this->object->getQuestion();
325  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
326  $questionoutput = $template->get();
327  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
328  return $pageoutput;
329  }
330 
338  function setQuestionTabs()
339  {
340  global $rbacsystem, $ilTabs;
341 
342  $ilTabs->clearTargets();
343 
344  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
345  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
346  $q_type = $this->object->getQuestionType();
347 
348  if (strlen($q_type))
349  {
350  $classname = $q_type . "GUI";
351  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
352  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
353  }
354 
355  if ($_GET["q_id"])
356  {
357  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
358  {
359  // edit page
360  $ilTabs->addTarget("edit_page",
361  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
362  array("edit", "insert", "exec_pg"),
363  "", "", $force_active);
364  }
365 
366  $this->addTab_QuestionPreview($ilTabs);
367  }
368 
369  $force_active = false;
370  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
371  {
372  $url = "";
373  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
374  // edit question properties
375  $ilTabs->addTarget("edit_question",
376  $url,
377  array("editQuestion", "save", "saveEdit", "addanswers", "removeanswers", "originalSyncForm"),
378  $classname, "", $force_active);
379  }
380 
381  // add tab for question feedback within common class assQuestionGUI
382  $this->addTab_QuestionFeedback($ilTabs);
383 
384  // add tab for question hint within common class assQuestionGUI
385  $this->addTab_QuestionHints($ilTabs);
386 
387  // add tab for question's suggested solution within common class assQuestionGUI
388  $this->addTab_SuggestedSolution($ilTabs, $classname);
389 
390  // Assessment of questions sub menu entry
391  if ($_GET["q_id"])
392  {
393  $ilTabs->addTarget("statistics",
394  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
395  array("assessment"),
396  $classname, "");
397  }
398 
399  $this->addBackTab($ilTabs);
400  }
401 
402  function getSpecificFeedbackOutput($active_id, $pass)
403  {
404  $output = "";
405  return $this->object->prepareTextareaOutput($output, TRUE);
406  }
407 
409  {
410  $this->object->setCorrectAnswers( $_POST["correctanswers"] );
411  $this->object->setTextRating( $_POST["text_rating"] );
412  }
413 
415  {
416  // Delete all existing answers and create new answers from the form data
417  $this->object->flushAnswers();
418  foreach ($_POST['answers']['answer'] as $index => $answer)
419  {
420  $answertext = $answer;
421  $this->object->addAnswer( $answertext, $_POST['answers']['points'][$index], $index );
422  }
423  }
424 
426  {
427  // number of requested answers
428  $correctanswers = new ilNumberInputGUI($this->lng->txt( "nr_of_correct_answers" ), "correctanswers");
429  $correctanswers->setMinValue( 1 );
430  $correctanswers->setDecimals( 0 );
431  $correctanswers->setSize( 3 );
432  $correctanswers->setValue( $this->object->getCorrectAnswers() );
433  $correctanswers->setRequired( true );
434  $form->addItem( $correctanswers );
435 
436  // maximum available points
437  $points = new ilNumberInputGUI($this->lng->txt( "maximum_points" ), "points");
438  $points->setMinValue(0.0);
439  $points->setMinvalueShouldBeGreater(true);
440  $points->setSize( 6 );
441  $points->setDisabled( true );
442  $points->allowDecimals(true);
443  $points->setValue( $this->object->getMaximumPoints() );
444  $points->setRequired( false );
445  $form->addItem( $points );
446 
447  // text rating
448  $textrating = new ilSelectInputGUI($this->lng->txt( "text_rating" ), "text_rating");
449  $text_options = array(
450  "ci" => $this->lng->txt( "cloze_textgap_case_insensitive" ),
451  "cs" => $this->lng->txt( "cloze_textgap_case_sensitive" )
452  );
453  if (!$this->object->getSelfAssessmentEditingMode())
454  {
455  $text_options["l1"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "1" );
456  $text_options["l2"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "2" );
457  $text_options["l3"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "3" );
458  $text_options["l4"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "4" );
459  $text_options["l5"] = sprintf( $this->lng->txt( "cloze_textgap_levenshtein_of" ), "5" );
460  }
461  $textrating->setOptions( $text_options );
462  $textrating->setValue( $this->object->getTextRating() );
463  $form->addItem( $textrating );
464  return $form;
465  }
466 
468  {
469  // Choices
470  include_once "./Modules/TestQuestionPool/classes/class.ilAnswerWizardInputGUI.php";
471  $choices = new ilAnswerWizardInputGUI($this->lng->txt( "answers" ), "answers");
472  $choices->setRequired( true );
473  $choices->setQuestionObject( $this->object );
474  $choices->setSingleline( true );
475  $choices->setAllowMove( false );
476  $choices->setMinValue(0.0);
477  if ($this->object->getAnswerCount() == 0)
478  $this->object->addAnswer( "", 0, 0 );
479  $choices->setValues( $this->object->getAnswers() );
480  $form->addItem( $choices );
481  return $form;
482  }
483 
484 
495  {
496  return array();
497  }
498 
509  {
510  return array();
511  }
512 
521  public function getAggregatedAnswersView($relevant_answers)
522  {
523  return $this->renderAggregateView(
524  $this->aggregateAnswers( $relevant_answers ) )->get();
525  }
526 
527  public function aggregateAnswers($relevant_answers_chosen)
528  {
529  $aggregate = array();
530 
531  foreach ($relevant_answers_chosen as $relevant_answer)
532  {
533  if ( array_key_exists($relevant_answer['value1'], $aggregate) )
534  {
535  $aggregate[$relevant_answer['value1']]++;
536  }
537  else
538  {
539  $aggregate[$relevant_answer['value1']] = 1;
540  }
541  }
542  return $aggregate;
543  }
544 
550  public function renderAggregateView($aggregate)
551  {
552  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
553 
554  foreach ($aggregate as $key => $value)
555  {
556  $tpl->setCurrentBlock( 'aggregaterow' );
557  $tpl->setVariable( 'OPTION', $key );
558  $tpl->setVariable( 'COUNT', $value );
559  $tpl->parseCurrentBlock();
560  }
561  return $tpl;
562  }
563 }
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
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
This class represents a selection list property in a property form.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
This class represents a property form user interface.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
$_GET["client_id"]
getPreview($show_question_only=FALSE, $showInlineFeedback=false)
getTestOutput($active_id, $pass=NULL, $is_postponed=FALSE, $use_post_solutions=FALSE, $inlineFeedback=false)
getSpecificFeedbackOutput($active_id, $pass)
Class for TextSubset questions.
addItem($a_item)
Add Item (Property, SectionHeader).
$url
Definition: shib_logout.php:72
getQuestionTemplate()
get question template
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
populateTaxonomyFormSection(ilPropertyFormGUI $form)
removeanswers()
Remove an answer.
This class represents a single choice wizard property in a property form.
setMinValue($a_minvalue, $a_display_always=false)
Set Minimum Value.
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.
special template class to simplify handling of ITX/PEAR
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
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.
setOptions($a_options)
Set Options.
Basic GUI class for assessment questions.
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
getAnswerFeedbackOutput($active_id, $pass)
Returns the answer generic feedback depending on the results of the question.
$errors
Multiple choice question GUI representation.
addBackTab(ilTabsGUI $ilTabs)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
editQuestion($checkonly=FALSE)
Creates an output of the edit form for the question.
Interface ilGuiAnswerScoringAdjustable.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
Interface ilGuiQuestionScoringAdjustable.
__construct($id=-1)
assTextSubsetGUI constructor
setQuestionTabs()
Sets the ILIAS tabs for this question type.
aggregateAnswers($relevant_answers_chosen)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
setRequired($a_required)
Set Required.
addanswers()
Add a new answer.
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.