ILIAS  release_4-4 Revision
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 
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 {
35  public function __construct($id = -1)
36  {
37  parent::__construct();
38  require_once './Modules/TestQuestionPool/classes/class.assNumeric.php';
39  $this->object = new assNumeric();
40  if ($id >= 0)
41  {
42  $this->object->loadFromDb($id);
43  }
44  }
45 
46  function getCommand($cmd)
47  {
48  if (substr($cmd, 0, 6) == "delete")
49  {
50  $cmd = "delete";
51  }
52  return $cmd;
53  }
54 
62  public function writePostData($always = false)
63  {
64  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
65  if (!$hasErrors)
66  {
70  $this->saveTaxonomyAssignments();
71  return 0;
72  }
73  return 1;
74  }
75 
83  public function editQuestion($checkonly = FALSE)
84  {
85  $save = $this->isSaveCommand();
86  $this->getQuestionTemplate();
87 
88  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
89  $form = new ilPropertyFormGUI();
90  $form->setFormAction($this->ctrl->getFormAction($this));
91  $form->setTitle($this->outQuestionType());
92  $form->setMultipart(TRUE);
93  $form->setTableWidth("100%");
94  $form->setId("assnumeric");
95 
96  $this->addBasicQuestionFormProperties( $form );
97  $this->populateQuestionSpecificFormPart( $form );
98  $this->populateAnswerSpecificFormPart( $form );
99  $this->populateTaxonomyFormSection($form);
100  $this->addQuestionFormCommandButtons($form);
101 
102  $errors = false;
103 
104  if ($save)
105  {
106  $form->setValuesByPost();
107  $errors = !$form->checkInput();
108  $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
109  if ($errors) $checkonly = false;
110  }
111 
112  if (!$checkonly) $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
113  return $errors;
114  }
115 
123  public function checkRange()
124  {
125  include_once "./Services/Math/classes/class.EvalMath.php";
126  $eval = new EvalMath();
127  $eval->suppress_errors = TRUE;
128  if (($eval->e($_POST["rang_lower_limit"]) !== FALSE) AND ($eval->e($_POST ["range_upper_limit"]) !== FALSE))
129  {
130  if ($eval->e($_POST["rang_lower_limit"]) < $eval->e($_POST["range_upper_limit"]))
131  {
132  return TRUE;
133  }
134  else
135  {
136  return FALSE;
137  }
138  }
139  return FALSE;
140  }
141 
149  public function outQuestionForTest($formaction, $active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE)
150  {
151  $test_output = $this->getTestOutput($active_id, $pass, $is_postponed, $use_post_solutions);
152  $this->tpl->setVariable("QUESTION_OUTPUT", $test_output);
153  $this->tpl->setVariable("FORMACTION", $formaction);
154  }
155 
172  $active_id,
173  $pass = NULL,
174  $graphicalOutput = FALSE,
175  $result_output = FALSE,
176  $show_question_only = TRUE,
177  $show_feedback = FALSE,
178  $show_correct_solution = FALSE,
179  $show_manual_scoring = FALSE,
180  $show_question_text = TRUE
181  )
182  {
183  // get the solution of the user for the active pass or from the last pass if allowed
184  $solutions = array();
185  if (($active_id > 0) && (!$show_correct_solution))
186  {
187  $solutions =& $this->object->getSolutionValues($active_id, $pass);
188  }
189  else
190  {
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  {
200  if (($active_id > 0) && (!$show_correct_solution))
201  {
202  if ($graphicalOutput)
203  {
204  // output of ok/not ok icons for user entered solutions
205  if ($this->object->getReachedPoints($active_id, $pass) == $this->object->getMaximumPoints())
206  {
207  $template->setCurrentBlock("icon_ok");
208  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.png"));
209  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
210  $template->parseCurrentBlock();
211  }
212  else
213  {
214  $template->setCurrentBlock("icon_ok");
215  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.png"));
216  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
217  $template->parseCurrentBlock();
218  }
219  }
220  }
221  foreach ($solutions as $solution)
222  {
223  $template->setVariable("NUMERIC_VALUE", $solution["value1"]);
224  }
225  if (count($solutions) == 0)
226  {
227  $template->setVariable("NUMERIC_VALUE", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
228  }
229  }
230  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
231  $questiontext = $this->object->getQuestion();
232  if ($show_question_text==true)
233  {
234  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
235  }
236  $questionoutput = $template->get();
237  //$feedback = ($show_feedback) ? $this->getAnswerFeedbackOutput($active_id, $pass) : ""; // Moving new method
238  // due to deprecation.
239  $feedback = ($show_feedback) ? $this->getGenericFeedbackOutput($active_id, $pass) : "";
240  if (strlen($feedback)) $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput( $feedback, true ));
241  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
242 
243  $solutionoutput = $solutiontemplate->get();
244  if (!$show_question_only)
245  {
246  // get page object output
247  $solutionoutput = '<div class="ilc_question_Standard">'.$solutionoutput."</div>";
248  }
249  return $solutionoutput;
250  }
251 
257  public function getPreview($show_question_only = FALSE)
258  {
259  // generate the question output
260  require_once './Services/UICore/classes/class.ilTemplate.php';
261  $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
262  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
263  $questiontext = $this->object->getQuestion();
264  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
265  $questionoutput = $template->get();
266  if (!$show_question_only)
267  {
268  // get page object output
269  $questionoutput = $this->getILIASPage($questionoutput);
270  }
271  return $questionoutput;
272  }
273 
282  public function getTestOutput($active_id, $pass = NULL, $is_postponed = FALSE, $use_post_solutions = FALSE)
283  {
284  $solutions = NULL;
285  // get the solution of the user for the active pass or from the last pass if allowed
286  if ($active_id)
287  {
288 
289  require_once './Modules/Test/classes/class.ilObjTest.php';
290  if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
291  {
292  if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
293  }
294  $solutions =& $this->object->getSolutionValues($active_id, $pass);
295  }
296 
297  // generate the question output
298  require_once './Services/UICore/classes/class.ilTemplate.php';
299  $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", TRUE, TRUE, "Modules/TestQuestionPool");
300  if (is_array($solutions))
301  {
302  foreach ($solutions as $solution)
303  {
304  $template->setVariable("NUMERIC_VALUE", " value=\"".$solution["value1"]."\"");
305  }
306  }
307  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
308  $questiontext = $this->object->getQuestion();
309  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($questiontext, TRUE));
310  $questionoutput = $template->get();
311  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
312  return $pageoutput;
313  }
314 
320  public function setQuestionTabs()
321  {
324  global $rbacsystem, $ilTabs;
325 
326  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
327  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
328  $q_type = $this->object->getQuestionType();
329 
330  if (strlen($q_type))
331  {
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  {
339  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
340  {
341  // edit page
342  $ilTabs->addTarget("edit_page",
343  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
344  array("edit", "insert", "exec_pg"),
345  "", "", $force_active);
346  }
347 
348  // edit page
349  $ilTabs->addTarget("preview",
350  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "preview"),
351  array("preview"),
352  "ilAssQuestionPageGUI", "", $force_active);
353  }
354 
355  $force_active = false;
356  if ($rbacsystem->checkAccess('write', $_GET["ref_id"]))
357  {
358  $url = "";
359  if ($classname) $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
360  // edit question properties
361  $ilTabs->addTarget("edit_question",
362  $url,
363  array("editQuestion", "save", "cancel", "saveEdit", "originalSyncForm"),
364  $classname, "", $force_active);
365  }
366 
367  // add tab for question feedback within common class assQuestionGUI
368  $this->addTab_QuestionFeedback($ilTabs);
369 
370  // add tab for question hint within common class assQuestionGUI
371  $this->addTab_QuestionHints($ilTabs);
372 
373  if ($_GET["q_id"])
374  {
375  $ilTabs->addTarget("solution_hint",
376  $this->ctrl->getLinkTargetByClass($classname, "suggestedsolution"),
377  array("suggestedsolution", "saveSuggestedSolution", "outSolutionExplorer", "cancel",
378  "addSuggestedSolution","cancelExplorer", "linkChilds", "removeSuggestedSolution"
379  ),
380  $classname,
381  ""
382  );
383  }
384 
385  // Assessment of questions sub menu entry
386  if ($_GET["q_id"])
387  {
388  $ilTabs->addTarget("statistics",
389  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
390  array("assessment"),
391  $classname, "");
392  }
393 
394  if (($_GET["calling_test"] > 0) || ($_GET["test_ref_id"] > 0))
395  {
396  $ref_id = $_GET["calling_test"];
397  if (strlen($ref_id) == 0)
398  {
399  $ref_id = $_GET["test_ref_id"];
400  }
401 
402  global $___test_express_mode;
403  if (!$_GET['test_express_mode'] && !$___test_express_mode) {
404  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), "ilias.php?baseClass=ilObjTestGUI&cmd=questions&ref_id=$ref_id");
405  }
406  else {
408  $ilTabs->setBackTarget($this->lng->txt("backtocallingtest"), $link);
409  }
410  }
411  else
412  {
413  $ilTabs->setBackTarget($this->lng->txt("qpl"), $this->ctrl->getLinkTargetByClass("ilobjquestionpoolgui", "questions"));
414  }
415  }
416 
423  public function getSpecificFeedbackOutput($active_id, $pass)
424  {
425  $output = "";
426  return $this->object->prepareTextareaOutput($output, TRUE);
427  }
428 
429  public function writeQuestionSpecificPostData($always = false)
430  {
431  $this->object->setMaxChars( $_POST["maxchars"] );
432  }
433 
434  public function writeAnswerSpecificPostData($always = false)
435  {
436  $this->object->setLowerLimit( $_POST['lowerlimit'] );
437  $this->object->setUpperLimit( $_POST['upperlimit'] );
438  $this->object->setPoints( $_POST['points'] );
439  }
440 
442  {
443  // maxchars
444  $maxchars = new ilNumberInputGUI($this->lng->txt( "maxchars" ), "maxchars");
445  $maxchars->setInfo($this->lng->txt('qpl_maxchars_info_numeric_question'));
446  $maxchars->setSize( 10 );
447  $maxchars->setDecimals( 0 );
448  $maxchars->setMinValue( 1 );
449  $maxchars->setRequired( true );
450  if ($this->object->getMaxChars() > 0)
451  {
452  $maxchars->setValue($this->object->getMaxChars());
453  }
454  $form->addItem( $maxchars );
455  }
456 
458  {
459  // points
460  $points = new ilNumberInputGUI($this->lng->txt( "points" ), "points");
461  $points->allowDecimals(true);
462  $points->setValue( $this->object->getPoints() > 0 ? $this->object->getPoints() : '' );
463  $points->setRequired( TRUE );
464  $points->setSize( 3 );
465  $points->setMinValue( 0.0 );
466  $points->setMinvalueShouldBeGreater( true );
467  $form->addItem( $points );
468 
469  $header = new ilFormSectionHeaderGUI();
470  $header->setTitle( $this->lng->txt( "range" ) );
471  $form->addItem( $header );
472 
473  // lower bound
474  $lower_limit = new ilFormulaInputGUI($this->lng->txt( "range_lower_limit" ), "lowerlimit");
475  $lower_limit->setSize( 25 );
476  $lower_limit->setMaxLength( 20 );
477  $lower_limit->setRequired( true );
478  $lower_limit->setValue( $this->object->getLowerLimit() );
479  $form->addItem( $lower_limit );
480 
481  // upper bound
482  $upper_limit = new ilFormulaInputGUI($this->lng->txt( "range_upper_limit" ), "upperlimit");
483  $upper_limit->setSize( 25 );
484  $upper_limit->setMaxLength( 20 );
485  $upper_limit->setRequired( true );
486  $upper_limit->setValue( $this->object->getUpperLimit() );
487  $form->addItem( $upper_limit );
488 
489  // reset input length, if max chars are set
490  if( $this->object->getMaxChars() > 0 )
491  {
492  $lower_limit->setSize( $this->object->getMaxChars() );
493  $lower_limit->setMaxLength( $this->object->getMaxChars() );
494  $upper_limit->setSize( $this->object->getMaxChars() );
495  $upper_limit->setMaxLength( $this->object->getMaxChars() );
496  }
497  }
498 
509  {
510  return array();
511  }
512 
523  {
524  return array('maxchars');
525  }
526 
528  {
529  $element = $form->getItemByPostvar('maxchars');
530  $_POST['maxchars'] = $this->object->getMaxChars();
531  $element->setValue( $this->object->getMaxChars() );
532  }
541  public function getAggregatedAnswersView($relevant_answers)
542  {
543  $passcount = count($relevant_answers);
544  foreach($relevant_answers as $pass)
545  {
546  $actives[$pass['active_fi']] = $pass['active_fi'];
547  }
548  $usercount = count($actives);
549  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_header.html', true, true, "Modules/TestQuestionPool");
550  $tpl->setVariable('HEADERTEXT', $this->lng->txt('overview'));
551  $tpl->setVariable('NUMBER_OF_USERS_INFO', $this->lng->txt('number_of_users'));
552  $tpl->setVariable('NUMBER_OF_USERS', $usercount);
553  $tpl->setVariable('NUMBER_OF_PASSES_INFO', $this->lng->txt('number_of_passes'));
554  $tpl->setVariable('NUMBER_OF_PASSES', $passcount);
555 
556  return $tpl->get() . $this->renderAggregateView(
557  $this->aggregateAnswers( $relevant_answers ) )->get();
558  }
559 
560  public function aggregateAnswers($relevant_answers_chosen)
561  {
562  $aggregate = array();
563 
564  foreach ($relevant_answers_chosen as $relevant_answer)
565  {
566  if ( array_key_exists($relevant_answer['value1'], $aggregate) )
567  {
568  $aggregate[$relevant_answer['value1']]++;
569  }
570  else
571  {
572  $aggregate[$relevant_answer['value1']] = 1;
573  }
574  }
575  return $aggregate;
576  }
577 
583  public function renderAggregateView($aggregate)
584  {
585  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
586  $tpl->setVariable( 'OPTION_HEADER', $this->lng->txt('answer') );
587  $tpl->setVariable( 'COUNT_HEADER', $this->lng->txt('count') );
588  $tpl->setVariable( 'AGGREGATION_HEADER', $this->lng->txt('aggregated_answers_header') );
589  asort($aggregate);
590  foreach ($aggregate as $answer => $count)
591  {
592  $tpl->setCurrentBlock( 'aggregaterow' );
593  $tpl->setVariable( 'OPTION', $answer );
594  $tpl->setVariable( 'COUNT', $count );
595  $tpl->parseCurrentBlock();
596  }
597  return $tpl;
598  }
599 }
This class represents a formula text property in a property form.
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
writeQuestionSpecificPostData($always=false)
Extracts the question specific values from $_POST and applies them to the data object.
$_POST['username']
Definition: cron.php:12
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"]
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
This class represents a section header in a property form.
outQuestionForTest($formaction, $active_id, $pass=NULL, $is_postponed=FALSE, $use_post_solutions=FALSE)
aggregateAnswers($relevant_answers_chosen)
getSpecificFeedbackOutput($active_id, $pass)
$cmd
Definition: sahs_server.php:35
$errors
resetFormValuesForSuppressedPostvars($form)
addItem($a_item)
Add Item (Property, SectionHeader).
writePostData($always=false)
Evaluates a posted edit form and writes the form data in the question object.
getQuestionTemplate()
get question template
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getTestOutput($active_id, $pass=NULL, $is_postponed=FALSE, $use_post_solutions=FALSE)
allowDecimals($a_value)
Toggle Decimals.
setInfo($a_info)
Set Information Text.
Numeric question GUI representation.
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 getReturnToPageLink($q_id=null)
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.
checkRange()
Checks the range limits.
special template class to simplify handling of ITX/PEAR
setSize($a_size)
Set Size.
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
Basic GUI class for assessment questions.
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
Class for numeric questions.
$ref_id
Definition: sahs_server.php:39
writeAnswerSpecificPostData($always=false)
Extracts the answer specific values from $_POST and applies them to the data object.
__construct($id=-1)
assNumericGUI constructor
Interface ilGuiAnswerScoringAdjustable.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="")
output question page
renderAggregateView($aggregate)
getPreview($show_question_only=FALSE)
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
Interface ilGuiQuestionScoringAdjustable.
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
editQuestion($checkonly=FALSE)
Creates an output of the edit form for the question.
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.