ILIAS  release_7 Revision v7.30-3-g800a261c036
class.assNumericGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Modules/TestQuestionPool/classes/class.assQuestionGUI.php';
5require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiQuestionScoringAdjustable.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilGuiAnswerScoringAdjustable.php';
7require_once './Modules/Test/classes/inc.AssessmentConstants.php';
8
26{
36 public function __construct($id = -1)
37 {
39 require_once './Modules/TestQuestionPool/classes/class.assNumeric.php';
40 $this->object = new assNumeric();
41 if ($id >= 0) {
42 $this->object->loadFromDb($id);
43 }
44 }
45
46 public function getCommand($cmd)
47 {
48 if (substr($cmd, 0, 6) == "delete") {
49 $cmd = "delete";
50 }
51 return $cmd;
52 }
53
57 protected function writePostData($always = false)
58 {
59 $hasErrors = (!$always) ? $this->editQuestion(true) : false;
60 if (!$hasErrors) {
61 require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
66 return 0;
67 }
68 return 1;
69 }
70
78 public function editQuestion($checkonly = false)
79 {
80 $save = $this->isSaveCommand();
81 $this->getQuestionTemplate();
82
83 include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
84 $form = new ilPropertyFormGUI();
85 $this->editForm = $form;
86
87 $form->setFormAction($this->ctrl->getFormAction($this));
88 $form->setTitle($this->outQuestionType());
89 $form->setMultipart(true);
90 $form->setTableWidth("100%");
91 $form->setId("assnumeric");
92
96 $this->populateTaxonomyFormSection($form);
98
99 $errors = false;
100
101 if ($save) {
102 $form->setValuesByPost();
103 $errors = !$form->checkInput();
104 $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
105
106 $lower = $form->getItemByPostVar('lowerlimit');
107 $upper = $form->getItemByPostVar('upperlimit');
108
109 if (!$this->checkRange($lower->getValue(), $upper->getValue())) {
110 global $DIC;
111 $lower->setAlert($DIC->language()->txt('qpl_numeric_lower_needs_valid_lower_alert'));
112 $upper->setAlert($DIC->language()->txt('qpl_numeric_upper_needs_valid_upper_alert'));
113 ilUtil::sendFailure($DIC->language()->txt("form_input_not_valid"));
114 $errors = true;
115 }
116
117 if ($errors) {
118 $checkonly = false;
119 }
120 }
121
122 if (!$checkonly) {
123 $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
124 }
125 return $errors;
126 }
127
135 public function checkRange($lower, $upper)
136 {
137 include_once "./Services/Math/classes/class.EvalMath.php";
138 $eval = new EvalMath();
139 $eval->suppress_errors = true;
140 if (($eval->e($lower) !== false) and ($eval->e($upper) !== false)) {
141 if ($eval->e($lower) <= $eval->e($upper)) {
142 return true;
143 } else {
144 return false;
145 }
146 }
147 return false;
148 }
149
156 {
157 return true;
158 }
159
175 public function getSolutionOutput(
176 $active_id,
177 $pass = null,
178 $graphicalOutput = false,
179 $result_output = false,
180 $show_question_only = true,
181 $show_feedback = false,
182 $show_correct_solution = false,
183 $show_manual_scoring = false,
184 $show_question_text = true
185 ) {
186 // get the solution of the user for the active pass or from the last pass if allowed
187 $solutions = array();
188 if (($active_id > 0) && (!$show_correct_solution)) {
189 $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
190 } else {
191 array_push($solutions, array("value1" => sprintf($this->lng->txt("value_between_x_and_y"), $this->object->getLowerLimit(), $this->object->getUpperLimit())));
192 }
193
194 // generate the question output
195 require_once './Services/UICore/classes/class.ilTemplate.php';
196 $template = new ilTemplate("tpl.il_as_qpl_numeric_output_solution.html", true, true, "Modules/TestQuestionPool");
197 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
198 if (is_array($solutions)) {
199 if (($active_id > 0) && (!$show_correct_solution)) {
200 if ($graphicalOutput) {
201 if ($this->object->getStep() === null) {
202 $reached_points = $this->object->getReachedPoints($active_id, $pass);
203 } else {
204 $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
205 }
206 // output of ok/not ok icons for user entered solutions
207 if ($reached_points == $this->object->getMaximumPoints()) {
208 $template->setCurrentBlock("icon_ok");
209 $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
210 $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
211 $template->parseCurrentBlock();
212 } else {
213 $template->setCurrentBlock("icon_ok");
214 $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
215 $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
216 $template->parseCurrentBlock();
217 }
218 }
219 }
220 foreach ($solutions as $solution) {
221 $template->setVariable("NUMERIC_VALUE", $solution["value1"]);
222 }
223 if (count($solutions) == 0) {
224 $template->setVariable("NUMERIC_VALUE", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
225 }
226 }
227 $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
228 if ($show_question_text == true) {
229 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
230 }
231 $questionoutput = $template->get();
232 //$feedback = ($show_feedback) ? $this->getAnswerFeedbackOutput($active_id, $pass) : ""; // Moving new method
233 // due to deprecation.
234 $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getGenericFeedbackOutput($active_id, $pass) : "";
235 if (strlen($feedback)) {
236 $cssClass = (
237 $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 // get page object output
249 $solutionoutput = $this->getILIASPage($solutionoutput);
250 }
251 return $solutionoutput;
252 }
253
259 public function getPreview($show_question_only = false, $showInlineFeedback = false)
260 {
261 // generate the question output
262 require_once './Services/UICore/classes/class.ilTemplate.php';
263 $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", true, true, "Modules/TestQuestionPool");
264 if (is_object($this->getPreviewSession())) {
265 $template->setVariable("NUMERIC_VALUE", " value=\"" . $this->getPreviewSession()->getParticipantsSolution() . "\"");
266 }
267 $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
268 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
269 $questionoutput = $template->get();
270 if (!$show_question_only) {
271 // get page object output
272 $questionoutput = $this->getILIASPage($questionoutput);
273 }
274 return $questionoutput;
275 }
276
285 // hey: prevPassSolutions - pass will be always available from now on
286 public function getTestOutput($active_id, $pass, $is_postponed = false, $use_post_solutions = false, $inlineFeedback)
287 // hey.
288 {
289 $solutions = null;
290 // get the solution of the user for the active pass or from the last pass if allowed
291 if ($use_post_solutions !== false) {
292 $solutions = array(
293 array('value1' => $use_post_solutions['numeric_result'])
294 );
295 } elseif ($active_id) {
296
297 // hey: prevPassSolutions - obsolete due to central check
298 #include_once "./Modules/Test/classes/class.ilObjTest.php";
299 #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
300 #{
301 # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
302 #}
303 $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
304 // hey.
305 }
306
307 // generate the question output
308 require_once './Services/UICore/classes/class.ilTemplate.php';
309 $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", true, true, "Modules/TestQuestionPool");
310 if (is_array($solutions)) {
311 foreach ($solutions as $solution) {
312 $template->setVariable("NUMERIC_VALUE", " value=\"" . $solution["value1"] . "\"");
313 }
314 }
315 $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
316 $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
317 $questionoutput = $template->get();
318 $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
319 return $pageoutput;
320 }
321
328 public function getSpecificFeedbackOutput($userSolution)
329 {
330 $output = "";
331 return $this->object->prepareTextareaOutput($output, true);
332 }
333
335 {
336 $this->object->setMaxChars($_POST["maxchars"]);
337 }
338
340 {
341 $this->object->setLowerLimit($_POST['lowerlimit']);
342 $this->object->setUpperLimit($_POST['upperlimit']);
343 $this->object->setPoints($_POST['points']);
344 }
345
347 {
348 // maxchars
349 $maxchars = new ilNumberInputGUI($this->lng->txt("maxchars"), "maxchars");
350 $maxchars->setInfo($this->lng->txt('qpl_maxchars_info_numeric_question'));
351 $maxchars->setSize(10);
352 $maxchars->setDecimals(0);
353 $maxchars->setMinValue(1);
354 $maxchars->setRequired(true);
355 if ($this->object->getMaxChars() > 0) {
356 $maxchars->setValue($this->object->getMaxChars());
357 }
358 $form->addItem($maxchars);
359 }
360
362 {
363 // points
364 $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
365 $points->allowDecimals(true);
366 $points->setValue($this->object->getPoints() > 0 ? $this->object->getPoints() : '');
367 $points->setRequired(true);
368 $points->setSize(3);
369 $points->setMinValue(0.0);
370 $points->setMinvalueShouldBeGreater(true);
371 $form->addItem($points);
372
373 $header = new ilFormSectionHeaderGUI();
374 $header->setTitle($this->lng->txt("range"));
375 $form->addItem($header);
376
377 // lower bound
378 $lower_limit = new ilFormulaInputGUI($this->lng->txt("range_lower_limit"), "lowerlimit");
379 $lower_limit->setSize(25);
380 $lower_limit->setMaxLength(20);
381 $lower_limit->setRequired(true);
382 $lower_limit->setValue($this->object->getLowerLimit());
383 $form->addItem($lower_limit);
384
385 // upper bound
386 $upper_limit = new ilFormulaInputGUI($this->lng->txt("range_upper_limit"), "upperlimit");
387 $upper_limit->setSize(25);
388 $upper_limit->setMaxLength(20);
389 $upper_limit->setRequired(true);
390 $upper_limit->setValue($this->object->getUpperLimit());
391 $form->addItem($upper_limit);
392
393 // reset input length, if max chars are set
394 if ($this->object->getMaxChars() > 0) {
395 $lower_limit->setSize($this->object->getMaxChars());
396 $lower_limit->setMaxLength($this->object->getMaxChars());
397 $upper_limit->setSize($this->object->getMaxChars());
398 $upper_limit->setMaxLength($this->object->getMaxChars());
399 }
400 }
401
412 {
413 return array();
414 }
415
426 {
427 return array();
428 }
429
438 public function getAggregatedAnswersView($relevant_answers)
439 {
440 return $this->renderAggregateView(
441 $this->aggregateAnswers($relevant_answers)
442 )->get();
443 }
444
445 public function aggregateAnswers($relevant_answers_chosen)
446 {
447 $aggregate = array();
448
449 foreach ($relevant_answers_chosen as $relevant_answer) {
450 if (array_key_exists($relevant_answer['value1'], $aggregate)) {
451 $aggregate[$relevant_answer['value1']]++;
452 } else {
453 $aggregate[$relevant_answer['value1']] = 1;
454 }
455 }
456 return $aggregate;
457 }
458
464 public function renderAggregateView($aggregate)
465 {
466 $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
467
468 $tpl->setCurrentBlock('headercell');
469 $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
470 $tpl->parseCurrentBlock();
471
472 $tpl->setCurrentBlock('headercell');
473 $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
474 $tpl->parseCurrentBlock();
475
476 foreach ($aggregate as $key => $value) {
477 $tpl->setCurrentBlock('aggregaterow');
478 $tpl->setVariable('OPTION', $key);
479 $tpl->setVariable('COUNT', $value);
480 $tpl->parseCurrentBlock();
481 }
482 return $tpl;
483 }
484
485 public function getAnswersFrequency($relevantAnswers, $questionIndex)
486 {
487 $answers = array();
488
489 foreach ($relevantAnswers as $ans) {
490 if (!isset($answers[$ans['value1']])) {
491 $answers[$ans['value1']] = array(
492 'answer' => $ans['value1'], 'frequency' => 0
493 );
494 }
495
496 $answers[$ans['value1']]['frequency']++;
497 }
498
499 return $answers;
500 }
501
503 {
504 // points
505 $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
506 $points->allowDecimals(true);
507 $points->setValue($this->object->getPoints() > 0 ? $this->object->getPoints() : '');
508 $points->setRequired(true);
509 $points->setSize(3);
510 $points->setMinValue(0.0);
511 $points->setMinvalueShouldBeGreater(true);
512 $form->addItem($points);
513
514 $header = new ilFormSectionHeaderGUI();
515 $header->setTitle($this->lng->txt("range"));
516 $form->addItem($header);
517
518 // lower bound
519 $lower_limit = new ilFormulaInputGUI($this->lng->txt("range_lower_limit"), "lowerlimit");
520 $lower_limit->setSize(25);
521 $lower_limit->setMaxLength(20);
522 $lower_limit->setRequired(true);
523 $lower_limit->setValue($this->object->getLowerLimit());
524 $form->addItem($lower_limit);
525
526 // upper bound
527 $upper_limit = new ilFormulaInputGUI($this->lng->txt("range_upper_limit"), "upperlimit");
528 $upper_limit->setSize(25);
529 $upper_limit->setMaxLength(20);
530 $upper_limit->setRequired(true);
531 $upper_limit->setValue($this->object->getUpperLimit());
532 $form->addItem($upper_limit);
533
534 // reset input length, if max chars are set
535 if ($this->object->getMaxChars() > 0) {
536 $lower_limit->setSize($this->object->getMaxChars());
537 $lower_limit->setMaxLength($this->object->getMaxChars());
538 $upper_limit->setSize($this->object->getMaxChars());
539 $upper_limit->setMaxLength($this->object->getMaxChars());
540 }
541 }
542
547 {
548 $this->object->setPoints((float) $form->getInput('points'));
549 $this->object->setLowerLimit((float) $form->getInput('lowerlimit'));
550 $this->object->setUpperLimit((float) $form->getInput('upperlimit'));
551 }
552}
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Numeric question GUI representation.
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
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.
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
checkRange($lower, $upper)
Checks the range limits.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
__construct($id=-1)
assNumericGUI constructor
aggregateAnswers($relevant_answers_chosen)
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
getPreview($show_question_only=false, $showInlineFeedback=false)
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
getSpecificFeedbackOutput($userSolution)
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
renderAggregateView($aggregate)
getAnswersFrequency($relevantAnswers, $questionIndex)
writePostData($always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
getTestOutput($active_id, $pass, $is_postponed=false, $use_post_solutions=false, $inlineFeedback)
Class for numeric questions.
Basic GUI class for assessment questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.
getILIASPage($html="")
Returns the ILIAS Page around a question.
getQuestionTemplate()
get question template
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
hasCorrectSolution($activeId, $passIndex)
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question,...
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
This class represents a section header in a property form.
This class represents a formula text property in a property form.
This class represents a number property in a property form.
This class represents a property form user interface.
addItem($a_item)
Add Item (Property, SectionHeader).
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
special template class to simplify handling of ITX/PEAR
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
global $DIC
Definition: goto.php:24
$errors
Definition: imgupload.php:49
Interface ilGuiAnswerScoringAdjustable.
Interface ilGuiQuestionScoringAdjustable.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc