ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.assOrderingHorizontalGUI.php
Go to the documentation of this file.
1 <?php
2 
19 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
20 
36 {
45  public function __construct($id = -1)
46  {
48  $this->object = new assOrderingHorizontal();
49  $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
50  if ($id >= 0) {
51  $this->object->loadFromDb($id);
52  }
53  }
54 
55  public function getCommand($cmd)
56  {
57  return $cmd;
58  }
59 
63  protected function writePostData(bool $always = false): int
64  {
65  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
66  if (!$hasErrors) {
69  $this->saveTaxonomyAssignments();
70  return 0;
71  }
72  return 1;
73  }
74 
80  public function editQuestion($checkonly = false): bool
81  {
82  $save = $this->isSaveCommand();
83  $this->getQuestionTemplate();
84 
85  $form = new ilPropertyFormGUI();
86  $this->editForm = $form;
87 
88  $form->setFormAction($this->ctrl->getFormAction($this));
89  $form->setTitle($this->outQuestionType());
90  $form->setMultipart(false);
91  $form->setTableWidth("100%");
92  $form->setId("orderinghorizontal");
93 
94  $this->addBasicQuestionFormProperties($form);
96 
97 
98  $this->populateTaxonomyFormSection($form);
99 
100  $this->addQuestionFormCommandButtons($form);
101 
102  $errors = false;
103 
104  if ($save) {
105  $form->setValuesByPost();
106  $errors = !$form->checkInput();
107  $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
108  if ($errors) {
109  $checkonly = false;
110  }
111  }
112 
113  if (!$checkonly) {
114  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
115  }
116  return $errors;
117  }
118 
131  public function getSolutionOutput(
132  $active_id,
133  $pass = null,
134  $graphicalOutput = false,
135  $result_output = false,
136  $show_question_only = true,
137  $show_feedback = false,
138  $show_correct_solution = false,
139  $show_manual_scoring = false,
140  $show_question_text = true
141  ): string {
142 
143  $user_solutions = [];
144  if (($active_id > 0) && (!$show_correct_solution)) {
145  $user_solutions = $this->object->getSolutionValues($active_id, $pass);
146  }
147 
148  $show_inline_feedback = false;
149  return $this->renderSolutionOutput(
150  $user_solutions,
151  $active_id,
152  $pass,
153  $graphicalOutput,
154  $result_output,
155  $show_question_only,
156  $show_feedback,
157  $show_correct_solution,
158  $show_manual_scoring,
159  $show_question_text,
160  false,
161  $show_inline_feedback,
162  );
163  }
164 
165  public function renderSolutionOutput(
166  mixed $user_solutions,
167  int $active_id,
168  ?int $pass,
169  bool $graphical_output = false,
170  bool $result_output = false,
171  bool $show_question_only = true,
172  bool $show_feedback = false,
173  bool $show_correct_solution = false,
174  bool $show_manual_scoring = false,
175  bool $show_question_text = true,
176  bool $show_autosave_title = false,
177  bool $show_inline_feedback = false,
178  ): ?string {
179  $elements = [];
180  if (count($user_solutions) && strlen($user_solutions[0]['value1'])) {
181  $elements = explode("{::}", $user_solutions[0]['value1']);
182  }
183 
184  if (!count($elements)) {
185  $elements = $show_correct_solution ? $this->object->getOrderingElements() : $this->object->getRandomOrderingElements();
186  }
187 
188  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_output_solution.html", true, true, "Modules/TestQuestionPool");
189  foreach ($elements as $id => $element) {
190  $template->setCurrentBlock("element");
191  $template->setVariable("ELEMENT_ID", "sol_e_" . $this->object->getId() . "_$id");
192  $template->setVariable("ELEMENT_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($element));
193  $template->parseCurrentBlock();
194  }
195 
196  if (($active_id > 0) && (!$show_correct_solution)) {
197  if ($this->object->getStep() === null) {
198  $reached_points = $this->object->getReachedPoints($active_id, $pass);
199  } else {
200  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
201  }
202  if ($graphical_output) {
203  $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
204  if ($reached_points == $this->object->getMaximumPoints()) {
205  $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
206  } elseif ($reached_points > 0) {
207  $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_MOSTLY_OK);
208  }
209  $template->setCurrentBlock("icon_ok");
210  $template->setVariable("ICON_OK", $correctness_icon);
211  $template->parseCurrentBlock();
212  }
213  } else {
214  $reached_points = $this->object->getPoints();
215  }
216 
217  if ($result_output) {
218  $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
219  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
220  }
221  if ($show_question_text == true) {
222  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
223  }
224  // $template->setVariable("SOLUTION_TEXT", ilUtil::prepareFormOutput($solutionvalue));
225  if ($this->object->getTextSize() >= 10) {
226  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
227  }
228 
229  $questionoutput = $template->get();
230  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
231  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
232 
233 
234  $feedback = '';
235  if ($show_feedback) {
236  if (!$this->isTestPresentationContext()) {
237  $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
238  $feedback .= strlen($fb) ? $fb : '';
239  }
240  }
241  if (strlen($feedback)) {
242  $cssClass = (
243  $this->hasCorrectSolution($active_id, $pass) ?
245  );
246 
247  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
248  $solutiontemplate->setVariable("FEEDBACK", ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
249  }
250  $solutionoutput = $solutiontemplate->get();
251  if (!$show_question_only) {
252  // get page object output
253  $solutionoutput = $this->getILIASPage($solutionoutput);
254  }
255  return $solutionoutput;
256  }
257 
258 
259  public function getPreview($show_question_only = false, $showInlineFeedback = false): string
260  {
261  if (is_object($this->getPreviewSession()) && strlen((string) $this->getPreviewSession()->getParticipantsSolution())) {
262  $elements = (string) $this->getPreviewSession()->getParticipantsSolution();
263  $elements = $this->object->splitAndTrimOrderElementText($elements, $this->object->getAnswerSeparator());
264  } else {
265  $elements = $this->object->getRandomOrderingElements();
266  }
267 
268  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_preview.html", true, true, "Modules/TestQuestionPool");
269  $js = <<<JS
270 
271  $('#horizontal_{QUESTION_ID}').ilHorizontalOrderingQuestion({
272  result_value_selector : '.ilOrderingValue',
273  result_separator : '{::}'
274  });
275 
276 JS;
277  $js = str_replace('{QUESTION_ID}', $this->object->getId(), $js);
278  $this->tpl->addOnLoadCode($js);
279 
280  foreach ($elements as $id => $element) {
281  $template->setCurrentBlock("element");
282  $template->setVariable("ELEMENT_ID", "e_" . $this->object->getId() . "_$id");
283  $template->setVariable("ORDERING_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($element));
284  $template->setVariable("ELEMENT_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($element));
285  $template->parseCurrentBlock();
286  }
287  $template->setVariable("QUESTION_ID", $this->object->getId());
288  $template->setVariable("VALUE_ORDERRESULT", ' value="' . join('{::}', $elements) . '"');
289  if ($this->object->getTextSize() >= 10) {
290  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
291  }
292  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
293  $questionoutput = $template->get();
294  if (!$show_question_only) {
295  // get page object output
296  $questionoutput = $this->getILIASPage($questionoutput);
297  }
298  global $DIC; /* @var ILIAS\DI\Container $DIC */
299  if ($DIC->http()->agent()->isMobile() || $DIC->http()->agent()->isIpad()) {
302  $this->tpl->addJavaScript('./node_modules/@andxor/jquery-ui-touch-punch-fix/jquery.ui.touch-punch.js');
303  }
304  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/orderinghorizontal.js");
305  return $questionoutput;
306  }
307 
308  // hey: prevPassSolutions - pass will be always available from now on
309  public function getTestOutput($active_id, $pass, $is_postponed = false, $use_post_solutions = false, $show_feedback = false): string
310  // hey.
311  {
312  // generate the question output
313  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_output.html", true, true, "Modules/TestQuestionPool");
314  $js = <<<JS
315  $().ready(function() {
316  if (typeof $.fn.ilHorizontalOrderingQuestion != 'undefined') {
317  $('#horizontal_{QUESTION_ID}').ilHorizontalOrderingQuestion({
318  result_value_selector: '.ilOrderingValue',
319  result_separator: '{::}'
320  });
321  }
322  });
323 JS;
324  $js = str_replace('{QUESTION_ID}', $this->object->getId(), $js);
325  $this->tpl->addOnLoadCode($js);
326 
327 
328  $elements = $this->object->getRandomOrderingElements();
329 
330  if ($active_id) {
331  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
332  // hey.
333  if (is_array($solutions) && count($solutions) == 1) {
334  $elements = explode("{::}", $solutions[0]['value1']);
335  }
336  }
337  if (!is_array($solutions) || count($solutions) == 0) {
338  ilSession::set('qst_ordering_horizontal_elements', $elements);
339  } else {
340  ilSession::clear('qst_ordering_horizontal_elements');
341  }
342  foreach ($elements as $id => $element) {
343  $template->setCurrentBlock("element");
344  $template->setVariable("ELEMENT_ID", "e_" . $this->object->getId() . "_$id");
345  $template->setVariable("ORDERING_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($element));
346  $template->setVariable("ELEMENT_VALUE", ilLegacyFormElementsUtil::prepareFormOutput($element));
347  $template->parseCurrentBlock();
348  }
349  $template->setVariable("QUESTION_ID", $this->object->getId());
350  if ($this->object->getTextSize() >= 10) {
351  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->getTextSize() . "%;\"");
352  }
353  $template->setVariable("VALUE_ORDERRESULT", ' value="' . join('{::}', $elements) . '"');
354  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
355  $questionoutput = $template->get();
356  //if (!$show_question_only) {
357  // get page object output
358  $questionoutput = $this->getILIASPage($questionoutput);
359  //}
360  global $DIC; /* @var ILIAS\DI\Container $DIC */
361  if ($DIC->http()->agent()->isMobile() || $DIC->http()->agent()->isIpad()) {
364  $this->tpl->addJavaScript('./node_modules/@andxor/jquery-ui-touch-punch-fix/jquery.ui.touch-punch.js');
365  }
366  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/orderinghorizontal.js");
367  $questionoutput = $template->get();
368  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
369  return $pageoutput;
370  }
371 
372  public function getPresentationJavascripts(): array
373  {
374  global $DIC; /* @var ILIAS\DI\Container $DIC */
375 
376  $files = array();
377 
378  if ($DIC->http()->agent()->isMobile() || $DIC->http()->agent()->isIpad()) {
379  $files[] = './node_modules/@andxor/jquery-ui-touch-punch-fix/jquery.ui.touch-punch.js';
380  }
381 
382  return $files;
383  }
384 
385  public function getSpecificFeedbackOutput(array $userSolution): string
386  {
387  return '';
388  }
389 
391  {
392  $this->object->setTextSize((float) str_replace(',', '.', $this->request->raw('textsize') ?? '0.0'));
393  $this->object->setOrderText($this->request->raw('ordertext'));
394  $this->object->setPoints((float) str_replace(',', '.', $this->request->raw('points')));
395  }
396 
407  {
408  return array();
409  }
410 
412  {
413  // ordertext
414  $ordertext = new ilTextAreaInputGUI($this->lng->txt("ordertext"), "ordertext");
415  $ordertext->setValue((string) self::prepareTextareaOutput($this->object->getOrderText(), false, true));
416  $ordertext->setRequired(true);
417  $ordertext->setInfo(sprintf($this->lng->txt("ordertext_info"), $this->object->getSeparator()));
418  $ordertext->setRows(10);
419  $ordertext->setCols(80);
420  $form->addItem($ordertext);
421  // textsize
422  $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
423  $textsize->setValue($this->object->getTextSize());
424  $textsize->setInfo($this->lng->txt("textsize_info"));
425  $textsize->setSize(6);
426  $textsize->setMinValue(10);
427  $textsize->setRequired(false);
428  $form->addItem($textsize);
429  // points
430  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
431 
432  $points->allowDecimals(true);
433  // mbecker: Fix for mantis bug 7866: Predefined values schould make sense.
434  // This implements a default value of "1" for this question type.
435  if ($this->object->getPoints() == null) {
436  $points->setValue("1");
437  } else {
438  $points->setValue($this->object->getPoints());
439  }
440  $points->setRequired(true);
441  $points->setSize(3);
442  $points->setMinValue(0.0);
443  $points->setMinvalueShouldBeGreater(true);
444  $form->addItem($points);
445  return $form;
446  }
447 
454  public function getAggregatedAnswersView(array $relevant_answers): string
455  {
456  return $this->renderAggregateView(
457  $this->aggregateAnswers($relevant_answers, $this->object->getOrderText())
458  )->get();
459  }
460 
461  public function aggregateAnswers($relevant_answers_chosen, $answer_defined_on_question): array
462  {
463  $aggregate = array();
464  foreach ($relevant_answers_chosen as $answer) {
465  $answer = str_replace($this->object->getAnswerSeparator(), '&nbsp;&nbsp;-&nbsp;&nbsp;', $answer);
466  if (in_array($answer['value1'], $aggregate)) {
467  $aggregate[$answer['value1']] = $aggregate[$answer['value1']] + 1;
468  } else {
469  $aggregate[$answer['value1']] = 1;
470  }
471  }
472 
473  return $aggregate;
474  }
475 
481  public function renderAggregateView($aggregate): ilTemplate
482  {
483  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
484 
485  foreach ($aggregate as $key => $line_data) {
486  $tpl->setCurrentBlock('aggregaterow');
487  $tpl->setVariable('COUNT', $line_data);
488  $tpl->setVariable('OPTION', $key);
490  }
491  return $tpl;
492  }
493 
494  public function getAnswersFrequency($relevantAnswers, $questionIndex): array
495  {
496  $answers = array();
497 
498  foreach ($relevantAnswers as $ans) {
499  $md5 = md5($ans['value1']);
500 
501  if (!isset($answers[$md5])) {
502  $answer = str_replace(
503  $this->object->getAnswerSeparator(),
504  '&nbsp;&nbsp;-&nbsp;&nbsp;',
505  $ans['value1']
506  );
507 
508  $answers[$md5] = array(
509  'answer' => $answer, 'frequency' => 0
510  );
511  }
512 
513  $answers[$md5]['frequency']++;
514  }
515 
516  return $answers;
517  }
518 
520  {
521  // points
522  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
523 
524  $points->allowDecimals(true);
525  $points->setValue($this->object->getPoints());
526  $points->setRequired(true);
527  $points->setSize(3);
528  $points->setMinValue(0.0);
529  $points->setMinvalueShouldBeGreater(true);
530  $form->addItem($points);
531  }
532 
537  {
538  $this->object->setPoints((float) str_replace(',', '.', $form->getInput('points')));
539  }
540 }
hasCorrectSolution($activeId, $passIndex)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
generateCorrectnessIconsForCorrectness(int $correctness)
getAggregatedAnswersView(array $relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
setCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Sets the template to the given block.
renderSolutionOutput(mixed $user_solutions, int $active_id, ?int $pass, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_autosave_title=false, bool $show_inline_feedback=false,)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilGlobalPageTemplate $tpl
static prepareFormOutput($a_str, bool $a_strip=false)
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
global $DIC
Definition: feed.php:28
__construct(VocabulariesInterface $vocabularies)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
setErrorMessage(string $errormessage)
string $key
Consumer key/client ID value.
Definition: System.php:193
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.
static initjQueryUI(ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery-UI JS-File to the global template (see included_components.txt for included components)
aggregateAnswers($relevant_answers_chosen, $answer_defined_on_question)
Basic GUI class for assessment questions.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
__construct($id=-1)
assOrderingHorizontalGUI constructor
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
static initjQuery(ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
This class represents a text area property in a property form.
getPreview($show_question_only=false, $showInlineFeedback=false)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
getAnswersFrequency($relevantAnswers, $questionIndex)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static prepareTextareaOutput(string $txt_output, bool $prepare_for_latex_output=false, bool $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
static clear(string $a_var)
setVariable(string $variable, $value='')
Sets the given variable to the given value.
static set(string $a_var, $a_val)
Set a value.
getTestOutput($active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
getGenericFeedbackOutput(int $active_id, ?int $pass)