ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
25 {
33  public function __construct($id = -1)
34  {
35  parent::__construct();
36  require_once './Modules/TestQuestionPool/classes/class.assTextSubset.php';
37  $this->object = new assTextSubset();
38  if ($id >= 0) {
39  $this->object->loadFromDb($id);
40  }
41  }
42 
46  protected function writePostData($always = false)
47  {
48  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
49  if (!$hasErrors) {
50  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
54  $this->saveTaxonomyAssignments();
55  return 0;
56  }
57  return 1;
58  }
59 
63  public function editQuestion($checkonly = false)
64  {
65  $save = $this->isSaveCommand();
66  $this->getQuestionTemplate();
67 
68  require_once './Services/Form/classes/class.ilPropertyFormGUI.php';
69  $form = new ilPropertyFormGUI();
70  $this->editForm = $form;
71 
72  $form->setFormAction($this->ctrl->getFormAction($this));
73  $form->setTitle($this->outQuestionType());
74  $form->setMultipart(false);
75  $form->setTableWidth("100%");
76  $form->setId("asstextsubset");
77 
83 
84  $errors = false;
85  if ($save) {
86  $form->setValuesByPost();
87  $points = $form->getItemByPostVar('points');
88  $points->setValue($this->object->getMaximumPoints());
89  $errors = !$form->checkInput();
90  $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
91  if ($errors) {
92  $checkonly = false;
93  }
94  }
95 
96  if (!$checkonly) {
97  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
98  }
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 
130  {
131  return true;
132  }
133 
147  public function getSolutionOutput(
148  $active_id,
149  $pass = null,
150  $graphicalOutput = false,
151  $result_output = false,
152  $show_question_only = true,
153  $show_feedback = false,
154  $show_correct_solution = false,
155  $show_manual_scoring = false,
156  $show_question_text = true
157  ) {
158  // get the solution of the user for the active pass or from the last pass if allowed
159  $solutions = array();
160  if (($active_id > 0) && (!$show_correct_solution)) {
161  $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
162  } else {
163  $rank = array();
164  foreach ($this->object->answers as $answer) {
165  if ($answer->getPoints() > 0) {
166  if (!is_array($rank[$answer->getPoints()])) {
167  $rank[$answer->getPoints()] = array();
168  }
169  array_push($rank[$answer->getPoints()], $answer->getAnswertext());
170  }
171  }
172  krsort($rank, SORT_NUMERIC);
173  foreach ($rank as $index => $bestsolutions) {
174  array_push($solutions, array("value1" => join(",", $bestsolutions), "points" => $index));
175  }
176  }
177 
178  // generate the question output
179  include_once "./Services/UICore/classes/class.ilTemplate.php";
180  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output_solution.html", true, true, "Modules/TestQuestionPool");
181  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
182  $available_answers = &$this->object->getAvailableAnswers();
183  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++) {
184  if ((!$test_id) && (strcmp($solutions[$i]["value1"], "") == 0)) {
185  } else {
186  if (($active_id > 0) && (!$show_correct_solution)) {
187  if ($graphicalOutput) {
188  // output of ok/not ok icons for user entered solutions
189  $index = $this->object->isAnswerCorrect($available_answers, $solutions[$i]["value1"]);
190  $correct = false;
191  if ($index !== false) {
192  unset($available_answers[$index]);
193  $correct = true;
194  }
195  if ($correct) {
196  $template->setCurrentBlock("icon_ok");
197  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
198  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
199  $template->parseCurrentBlock();
200  } else {
201  $template->setCurrentBlock("icon_ok");
202  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
203  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
204  $template->parseCurrentBlock();
205  }
206  }
207  }
208  $template->setCurrentBlock("textsubset_row");
209  $template->setVariable("SOLUTION", $solutions[$i]["value1"]);
210  $template->setVariable("COUNTER", $i + 1);
211  if ($result_output) {
212  $points = $solutions[$i]["points"];
213  $resulttext = ($points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
214  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $points));
215  }
216  $template->parseCurrentBlock();
217  }
218  }
219  $questiontext = $this->object->getQuestion();
220  if ($show_question_text == true) {
221  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
222  }
223  $questionoutput = $template->get();
224  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getAnswerFeedbackOutput($active_id, $pass) : "";
225  if (strlen($feedback)) {
226  $cssClass = (
227  $this->hasCorrectSolution($active_id, $pass) ?
229  );
230 
231  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
232  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
233  }
234  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
235 
236  $solutionoutput = $solutiontemplate->get();
237  if (!$show_question_only) {
238  // get page object output
239  $solutionoutput = $this->getILIASPage($solutionoutput);
240  }
241  return $solutionoutput;
242  }
243 
244  public function getPreview($show_question_only = false, $showInlineFeedback = false)
245  {
246  $solutions = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : array();
247  // generate the question output
248  include_once "./Services/UICore/classes/class.ilTemplate.php";
249  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", true, true, "Modules/TestQuestionPool");
250  $width = $this->object->getMaxTextboxWidth();
251  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++) {
252  $template->setCurrentBlock("textsubset_row");
253  foreach ($solutions as $idx => $solution_value) {
254  if ($idx == $i) {
255  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . $solution_value . "\"");
256  }
257  }
258  $template->setVariable("COUNTER", $i + 1);
259  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i + 1));
260  $template->setVariable("TEXTFIELD_SIZE", $width);
261  $template->parseCurrentBlock();
262  }
263  $questiontext = $this->object->getQuestion();
264  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
265  $questionoutput = $template->get();
266  if (!$show_question_only) {
267  // get page object output
268  $questionoutput = $this->getILIASPage($questionoutput);
269  }
270  return $questionoutput;
271  }
272 
273  public function getTestOutput($active_id, $pass = null, $is_postponed = false, $use_post_solutions = false, $inlineFeedback = false)
274  {
275  // get the solution of the user for the active pass or from the last pass if allowed
276  $user_solution = "";
277  if ($active_id) {
278  $solutions = null;
279  // hey: prevPassSolutions - obsolete due to central check
280  #include_once "./Modules/Test/classes/class.ilObjTest.php";
281  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
282  #{
283  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
284  #}
285  // hey.
286  $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass);
287  }
288 
289  // generate the question output
290  include_once "./Services/UICore/classes/class.ilTemplate.php";
291  $template = new ilTemplate("tpl.il_as_qpl_textsubset_output.html", true, true, "Modules/TestQuestionPool");
292  $width = $this->object->getMaxTextboxWidth();
293  for ($i = 0; $i < $this->object->getCorrectAnswers(); $i++) {
294  $template->setCurrentBlock("textsubset_row");
295  foreach ($solutions as $idx => $solution_value) {
296  if ($idx == $i) {
297  $template->setVariable("TEXTFIELD_VALUE", " value=\"" . ilUtil::prepareFormOutput($solution_value["value1"]) . "\"");
298  }
299  }
300  $template->setVariable("COUNTER", $i + 1);
301  $template->setVariable("TEXTFIELD_ID", sprintf("%02d", $i + 1));
302  $template->setVariable("TEXTFIELD_SIZE", $width);
303  $template->parseCurrentBlock();
304  }
305  $questiontext = $this->object->getQuestion();
306  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, true));
307  $questionoutput = $template->get();
308  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
309  return $pageoutput;
310  }
311 
319  public function setQuestionTabs()
320  {
321  global $DIC;
322  $rbacsystem = $DIC['rbacsystem'];
323  $ilTabs = $DIC['ilTabs'];
324 
325  $ilTabs->clearTargets();
326 
327  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
328  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
329  $q_type = $this->object->getQuestionType();
330 
331  if (strlen($q_type)) {
332  $classname = $q_type . "GUI";
333  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
334  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
335  }
336 
337  if ($_GET["q_id"]) {
338  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
339  // edit page
340  $ilTabs->addTarget(
341  "edit_page",
342  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
343  array("edit", "insert", "exec_pg"),
344  "",
345  "",
346  $force_active
347  );
348  }
349 
350  $this->addTab_QuestionPreview($ilTabs);
351  }
352 
353  $force_active = false;
354  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
355  $url = "";
356  if ($classname) {
357  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
358  }
359  // edit question properties
360  $ilTabs->addTarget(
361  "edit_question",
362  $url,
363  array("editQuestion", "save", "saveEdit", "addanswers", "removeanswers", "originalSyncForm"),
364  $classname,
365  "",
366  $force_active
367  );
368  }
369 
370  // add tab for question feedback within common class assQuestionGUI
371  $this->addTab_QuestionFeedback($ilTabs);
372 
373  // add tab for question hint within common class assQuestionGUI
374  $this->addTab_QuestionHints($ilTabs);
375 
376  // add tab for question's suggested solution within common class assQuestionGUI
377  $this->addTab_SuggestedSolution($ilTabs, $classname);
378 
379  // Assessment of questions sub menu entry
380  if ($_GET["q_id"]) {
381  $ilTabs->addTarget(
382  "statistics",
383  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
384  array("assessment"),
385  $classname,
386  ""
387  );
388  }
389 
390  $this->addBackTab($ilTabs);
391  }
392 
393  public function getSpecificFeedbackOutput($userSolution)
394  {
395  $output = "";
396  return $this->object->prepareTextareaOutput($output, true);
397  }
398 
400  {
401  $this->object->setCorrectAnswers($_POST["correctanswers"]);
402  $this->object->setTextRating($_POST["text_rating"]);
403  }
404 
406  {
407  // Delete all existing answers and create new answers from the form data
408  $this->object->flushAnswers();
409  foreach ($_POST['answers']['answer'] as $index => $answer) {
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->allowDecimals(true);
433  $points->setValue($this->object->getMaximumPoints());
434  $points->setRequired(false);
435  $form->addItem($points);
436 
437  // text rating
438  $textrating = new ilSelectInputGUI($this->lng->txt("text_rating"), "text_rating");
439  $text_options = array(
440  "ci" => $this->lng->txt("cloze_textgap_case_insensitive"),
441  "cs" => $this->lng->txt("cloze_textgap_case_sensitive")
442  );
443  if (!$this->object->getSelfAssessmentEditingMode()) {
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  }
469  $choices->setValues($this->object->getAnswers());
470  $form->addItem($choices);
471  return $form;
472  }
473 
474 
485  {
486  return array();
487  }
488 
499  {
500  return array();
501  }
502 
511  public function getAggregatedAnswersView($relevant_answers)
512  {
513  return $this->renderAggregateView(
514  $this->aggregateAnswers($relevant_answers)
515  )->get();
516  }
517 
518  public function aggregateAnswers($relevant_answers_chosen)
519  {
520  $aggregate = array();
521 
522  foreach ($relevant_answers_chosen as $relevant_answer) {
523  if (array_key_exists($relevant_answer['value1'], $aggregate)) {
524  $aggregate[$relevant_answer['value1']]++;
525  } else {
526  $aggregate[$relevant_answer['value1']] = 1;
527  }
528  }
529  return $aggregate;
530  }
531 
537  public function renderAggregateView($aggregate)
538  {
539  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
540 
541  foreach ($aggregate as $key => $value) {
542  $tpl->setCurrentBlock('aggregaterow');
543  $tpl->setVariable('OPTION', $key);
544  $tpl->setVariable('COUNT', $value);
545  $tpl->parseCurrentBlock();
546  }
547  return $tpl;
548  }
549 
550  public function getAnswersFrequency($relevantAnswers, $questionIndex)
551  {
552  $answers = array();
553 
554  foreach ($relevantAnswers as $ans) {
555  if (!isset($answers[$ans['value1']])) {
556  $answers[$ans['value1']] = array(
557  'answer' => $ans['value1'], 'frequency' => 0
558  );
559  }
560 
561  $answers[$ans['value1']]['frequency']++;
562  }
563 
564  return $answers;
565  }
566 
568  {
569  // Choices
570  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssAnswerCorrectionsInputGUI.php';
571  $choices = new ilAssAnswerCorrectionsInputGUI($this->lng->txt("answers"), "answers");
572  $choices->setRequired(true);
573  $choices->setQuestionObject($this->object);
574  $choices->setValues($this->object->getAnswers());
575  $form->addItem($choices);
576 
577  return $form;
578  }
579 
584  {
585  $points = $form->getInput('answers')['points'];
586 
587  foreach ($this->object->getAnswers() as $index => $answer) {
588  /* @var ASS_AnswerBinaryStateImage $answer */
589  $answer->setPoints((float) $points[$index]);
590  }
591  }
592 }
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
getPreview($show_question_only=false, $showInlineFeedback=false)
This class represents a selection list property in a property form.
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.
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
$template
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...
global $DIC
Definition: saml.php:7
$_GET["client_id"]
if(!array_key_exists('StateId', $_REQUEST)) $id
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
Class for TextSubset questions.
addItem($a_item)
Add Item (Property, SectionHeader).
$index
Definition: metadata.php:60
getQuestionTemplate()
get question template
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
removeanswers()
Remove an answer.
This class represents a single choice wizard property in a property form.
getAnswersFrequency($relevantAnswers, $questionIndex)
setMinValue($a_minvalue, $a_display_always=false)
Set Minimum Value.
if(isset($_POST['submit'])) $form
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)
{}
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...
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
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.
getTestOutput($active_id, $pass=null, $is_postponed=false, $use_post_solutions=false, $inlineFeedback=false)
$errors
Definition: index.php:6
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
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.
$i
Definition: disco.tpl.php:19
Interface ilGuiAnswerScoringAdjustable.
$url
Interface ilGuiQuestionScoringAdjustable.
__construct($id=-1)
assTextSubsetGUI constructor
setQuestionTabs()
Sets the ILIAS tabs for this question type.
aggregateAnswers($relevant_answers_chosen)
$key
Definition: croninfo.php:18
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
$_POST["username"]
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.
getSpecificFeedbackOutput($userSolution)