ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.assOrderingHorizontalGUI.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/Test/classes/inc.AssessmentConstants.php';
7 
23 {
32  public function __construct($id = -1)
33  {
34  parent::__construct();
35  include_once "./Modules/TestQuestionPool/classes/class.assOrderingHorizontal.php";
36  $this->object = new assOrderingHorizontal();
37  $this->setErrorMessage($this->lng->txt("msg_form_save_error"));
38  if ($id >= 0) {
39  $this->object->loadFromDb($id);
40  }
41  }
42 
43  public function getCommand($cmd)
44  {
45  return $cmd;
46  }
47 
51  protected function writePostData($always = false)
52  {
53  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
54  if (!$hasErrors) {
55  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
58  $this->saveTaxonomyAssignments();
59  return 0;
60  }
61  return 1;
62  }
63 
69  public function editQuestion($checkonly = false)
70  {
71  $save = $this->isSaveCommand();
72  $this->getQuestionTemplate();
73 
74  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
75  $form = new ilPropertyFormGUI();
76  $this->editForm = $form;
77 
78  $form->setFormAction($this->ctrl->getFormAction($this));
79  $form->setTitle($this->outQuestionType());
80  $form->setMultipart(false);
81  $form->setTableWidth("100%");
82  $form->setId("orderinghorizontal");
83 
86 
87 
89 
91 
92  $errors = false;
93 
94  if ($save) {
95  $form->setValuesByPost();
96  $errors = !$form->checkInput();
97  $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
98  if ($errors) {
99  $checkonly = false;
100  }
101  }
102 
103  if (!$checkonly) {
104  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
105  }
106  return $errors;
107  }
108 
115  {
116  return true;
117  }
118 
132  public function getSolutionOutput(
133  $active_id,
134  $pass = null,
135  $graphicalOutput = false,
136  $result_output = false,
137  $show_question_only = true,
138  $show_feedback = false,
139  $show_correct_solution = false,
140  $show_manual_scoring = false,
141  $show_question_text = true
142  ) {
143  // get the solution of the user for the active pass or from the last pass if allowed
144  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_output_solution.html", true, true, "Modules/TestQuestionPool");
145 
146  //$solutionvalue = "";
147  if (($active_id > 0) && (!$show_correct_solution)) {
148  $elements = [];
149  $solutions = $this->object->getSolutionValues($active_id, $pass, !$this->getUseIntermediateSolution());
150  if (strlen($solutions[0]["value1"])) {
151  $elements = explode("{::}", $solutions[0]["value1"]);
152  }
153 
154  if (!count($elements)) {
155  $elements = $this->object->getRandomOrderingElements();
156  }
157 
158  foreach ($elements as $id => $element) {
159  $template->setCurrentBlock("element");
160  $template->setVariable("ELEMENT_ID", "sol_e_" . $this->object->getId() . "_$id");
161  $template->setVariable("ELEMENT_VALUE", ilUtil::prepareFormOutput($element));
162  $template->parseCurrentBlock();
163  }
164 
165  //$solutionvalue = str_replace("{::}", " ", $solutions[0]["value1"]);
166  } else {
167  $elements = $this->object->getOrderingElements();
168  foreach ($elements as $id => $element) {
169  $template->setCurrentBlock("element");
170  $template->setVariable("ELEMENT_ID", "sol_e_" . $this->object->getId() . "_$id");
171  $template->setVariable("ELEMENT_VALUE", ilUtil::prepareFormOutput($element));
172  $template->parseCurrentBlock();
173  }
174  //$solutionvalue = join($this->object->getOrderingElements(), " ");
175  }
176 
177  if (($active_id > 0) && (!$show_correct_solution)) {
178  if ($this->object->getStep() === null) {
179  $reached_points = $this->object->getReachedPoints($active_id, $pass);
180  } else {
181  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
182  }
183  if ($graphicalOutput) {
184  // output of ok/not ok icons for user entered solutions
185  if ($reached_points == $this->object->getMaximumPoints()) {
186  $template->setCurrentBlock("icon_ok");
187  $template->setVariable("ICON_OK", ilUtil::getImagePath("icon_ok.svg"));
188  $template->setVariable("TEXT_OK", $this->lng->txt("answer_is_right"));
189  $template->parseCurrentBlock();
190  } else {
191  $template->setCurrentBlock("icon_ok");
192  if ($reached_points > 0) {
193  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_mostly_ok.svg"));
194  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_not_correct_but_positive"));
195  } else {
196  $template->setVariable("ICON_NOT_OK", ilUtil::getImagePath("icon_not_ok.svg"));
197  $template->setVariable("TEXT_NOT_OK", $this->lng->txt("answer_is_wrong"));
198  }
199  $template->parseCurrentBlock();
200  }
201  }
202  } else {
203  $reached_points = $this->object->getPoints();
204  }
205 
206  if ($result_output) {
207  $resulttext = ($reached_points == 1) ? "(%s " . $this->lng->txt("point") . ")" : "(%s " . $this->lng->txt("points") . ")";
208  $template->setVariable("RESULT_OUTPUT", sprintf($resulttext, $reached_points));
209  }
210  if ($show_question_text == true) {
211  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
212  }
213  // $template->setVariable("SOLUTION_TEXT", ilUtil::prepareFormOutput($solutionvalue));
214  if ($this->object->textsize >= 10) {
215  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->textsize . "%;\"");
216  }
217 
218  $questionoutput = $template->get();
219  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
220  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
221 
222 
223  $feedback = '';
224  if ($show_feedback) {
225  if (!$this->isTestPresentationContext()) {
226  $fb = $this->getGenericFeedbackOutput($active_id, $pass);
227  $feedback .= strlen($fb) ? $fb : '';
228  }
229 
230  $fb = $this->getSpecificFeedbackOutput(array());
231  $feedback .= strlen($fb) ? $fb : '';
232  }
233  if (strlen($feedback)) {
234  $cssClass = (
235  $this->hasCorrectSolution($active_id, $pass) ?
237  );
238 
239  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
240  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
241  }
242  $solutionoutput = $solutiontemplate->get();
243  if (!$show_question_only) {
244  // get page object output
245  $solutionoutput = $this->getILIASPage($solutionoutput);
246  }
247  return $solutionoutput;
248  }
249 
250  public function getPreview($show_question_only = false, $showInlineFeedback = false)
251  {
252  if (is_object($this->getPreviewSession()) && strlen((string) $this->getPreviewSession()->getParticipantsSolution())) {
253  $elements = (string) $this->getPreviewSession()->getParticipantsSolution();
254  $elements = $this->object->splitAndTrimOrderElementText($elements, $this->object->getAnswerSeparator());
255  } else {
256  $elements = $this->object->getRandomOrderingElements();
257  }
258 
259  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_preview.html", true, true, "Modules/TestQuestionPool");
260  foreach ($elements as $id => $element) {
261  $template->setCurrentBlock("element");
262  $template->setVariable("ELEMENT_ID", "e_" . $this->object->getId() . "_$id");
263  $template->setVariable("ORDERING_VALUE", ilUtil::prepareFormOutput($element));
264  $template->setVariable("ELEMENT_VALUE", ilUtil::prepareFormOutput($element));
265  $template->parseCurrentBlock();
266  }
267  $template->setVariable("QUESTION_ID", $this->object->getId());
268  $template->setVariable("VALUE_ORDERRESULT", ' value="' . join('{::}', $elements) . '"');
269  if ($this->object->textsize >= 10) {
270  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->textsize . "%;\"");
271  }
272  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
273  $questionoutput = $template->get();
274  if (!$show_question_only) {
275  // get page object output
276  $questionoutput = $this->getILIASPage($questionoutput);
277  }
278  global $DIC; /* @var ILIAS\DI\Container $DIC */
279  if ($DIC['ilBrowser']->isMobile() || $DIC['ilBrowser']->isIpad()) {
280  $this->tpl->addJavaScript('./libs/bower/bower_components/jqueryui-touch-punch/jquery.ui.touch-punch.min.js');
281  }
282  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/orderinghorizontal.js");
283  return $questionoutput;
284  }
285 
286  // hey: prevPassSolutions - pass will be always available from now on
287  public function getTestOutput($active_id, $pass, $is_postponed = false, $use_post_solutions = false, $show_feedback = false)
288  // hey.
289  {
290  // generate the question output
291  $template = new ilTemplate("tpl.il_as_qpl_orderinghorizontal_output.html", true, true, "Modules/TestQuestionPool");
292  $elements = $this->object->getRandomOrderingElements();
293 
294  if ($active_id) {
295  // hey: prevPassSolutions - obsolete due to central check
296  #$solutions = NULL;
297  #include_once "./Modules/Test/classes/class.ilObjTest.php";
298  #if (!ilObjTest::_getUsePreviousAnswers($active_id, true))
299  #{
300  # if (is_null($pass)) $pass = ilObjTest::_getPass($active_id);
301  #}
302  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
303  // hey.
304  if (is_array($solutions) && count($solutions) == 1) {
305  $elements = explode("{::}", $solutions[0]["value1"]);
306  }
307  }
308  if (!is_array($solutions) || count($solutions) == 0) {
309  $_SESSION['qst_ordering_horizontal_elements'] = $elements;
310  } else {
311  unset($_SESSION['qst_ordering_horizontal_elements']);
312  }
313  foreach ($elements as $id => $element) {
314  $template->setCurrentBlock("element");
315  $template->setVariable("ELEMENT_ID", "e_" . $this->object->getId() . "_$id");
316  $template->setVariable("ORDERING_VALUE", ilUtil::prepareFormOutput($element));
317  $template->setVariable("ELEMENT_VALUE", ilUtil::prepareFormOutput($element));
318  $template->parseCurrentBlock();
319  }
320  $template->setVariable("QUESTION_ID", $this->object->getId());
321  if ($this->object->textsize >= 10) {
322  $template->setVariable("STYLE", " style=\"font-size: " . $this->object->textsize . "%;\"");
323  }
324  $template->setVariable("VALUE_ORDERRESULT", ' value="' . join('{::}', $elements) . '"');
325  $template->setVariable("QUESTIONTEXT", $this->object->prepareTextareaOutput($this->object->getQuestion(), true));
326  $questionoutput = $template->get();
327  if (!$show_question_only) {
328  // get page object output
329  $questionoutput = $this->getILIASPage($questionoutput);
330  }
331  global $DIC; /* @var ILIAS\DI\Container $DIC */
332  if ($DIC['ilBrowser']->isMobile() || $DIC['ilBrowser']->isIpad()) {
333  $this->tpl->addJavaScript('./libs/bower/bower_components/jqueryui-touch-punch/jquery.ui.touch-punch.min.js');
334  }
335  $this->tpl->addJavascript("./Modules/TestQuestionPool/templates/default/orderinghorizontal.js");
336  $questionoutput = $template->get();
337  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
338  return $pageoutput;
339  }
340 
346  public function saveFeedback()
347  {
348  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
349  $errors = $this->feedback(true);
350  $this->object->saveFeedbackGeneric(0, $_POST["feedback_incomplete"]);
351  $this->object->saveFeedbackGeneric(1, $_POST["feedback_complete"]);
352  $this->object->cleanupMediaObjectUsage();
353  parent::saveFeedback();
354  }
355 
363  public function setQuestionTabs()
364  {
365  global $DIC;
366  $rbacsystem = $DIC['rbacsystem'];
367  $ilTabs = $DIC['ilTabs'];
368 
369  $ilTabs->clearTargets();
370 
371  $this->ctrl->setParameterByClass("ilAssQuestionPageGUI", "q_id", $_GET["q_id"]);
372  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
373  $q_type = $this->object->getQuestionType();
374 
375  if (strlen($q_type)) {
376  $classname = $q_type . "GUI";
377  $this->ctrl->setParameterByClass(strtolower($classname), "sel_question_types", $q_type);
378  $this->ctrl->setParameterByClass(strtolower($classname), "q_id", $_GET["q_id"]);
379  }
380 
381  if ($_GET["q_id"]) {
382  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
383  // edit page
384  $ilTabs->addTarget(
385  "edit_page",
386  $this->ctrl->getLinkTargetByClass("ilAssQuestionPageGUI", "edit"),
387  array("edit", "insert", "exec_pg"),
388  "",
389  "",
390  $force_active
391  );
392  }
393 
394  $this->addTab_QuestionPreview($ilTabs);
395  }
396 
397  $force_active = false;
398  if ($rbacsystem->checkAccess('write', $_GET["ref_id"])) {
399  $url = "";
400  if ($classname) {
401  $url = $this->ctrl->getLinkTargetByClass($classname, "editQuestion");
402  }
403  $commands = $_POST["cmd"];
404  if (is_array($commands)) {
405  foreach ($commands as $key => $value) {
406  if (preg_match("/^suggestrange_.*/", $key, $matches)) {
407  $force_active = true;
408  }
409  }
410  }
411  // edit question properties
412  $ilTabs->addTarget(
413  "edit_question",
414  $url,
415  array("editQuestion", "save", "saveEdit", "originalSyncForm"),
416  $classname,
417  "",
418  $force_active
419  );
420  }
421 
422  // add tab for question feedback within common class assQuestionGUI
423  $this->addTab_QuestionFeedback($ilTabs);
424 
425  // add tab for question hint within common class assQuestionGUI
426  $this->addTab_QuestionHints($ilTabs);
427 
428  // add tab for question's suggested solution within common class assQuestionGUI
429  $this->addTab_SuggestedSolution($ilTabs, $classname);
430 
431  // Assessment of questions sub menu entry
432  if ($_GET["q_id"]) {
433  $ilTabs->addTarget(
434  "statistics",
435  $this->ctrl->getLinkTargetByClass($classname, "assessment"),
436  array("assessment"),
437  $classname,
438  ""
439  );
440  }
441 
442  $this->addBackTab($ilTabs);
443  }
444 
445  public function getSpecificFeedbackOutput($userSolution)
446  {
447  if (strpos($this->object->getOrderText(), '::')) {
448  $answers = explode('::', $this->object->getOrderText());
449  } else {
450  $answers = explode(' ', $this->object->getOrderText());
451  }
452 
453  if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
454  return '';
455  }
456 
457  $output = '<table class="test_specific_feedback"><tbody>';
458 
459  foreach ($answers as $idx => $answer) {
460  $feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
461  $this->object->getId(),
462  0,
463  $idx
464  );
465 
466  $output .= "<tr><td>{$answer}</td><td>{$feedback}</td></tr>";
467  }
468 
469  $output .= '</tbody></table>';
470 
471  return $this->object->prepareTextareaOutput($output, true);
472  }
473 
475  {
476  $this->object->setTextSize($_POST["textsize"]);
477  $this->object->setOrderText($_POST["ordertext"]);
478  $this->object->setPoints($_POST["points"]);
479  }
480 
491  {
492  return array();
493  }
494 
496  {
497  // ordertext
498  $ordertext = new ilTextAreaInputGUI($this->lng->txt("ordertext"), "ordertext");
499  $ordertext->setValue($this->object->prepareTextareaOutput($this->object->getOrderText()));
500  $ordertext->setRequired(true);
501  $ordertext->setInfo(sprintf($this->lng->txt("ordertext_info"), $this->object->separator));
502  $ordertext->setRows(10);
503  $ordertext->setCols(80);
504  $form->addItem($ordertext);
505  // textsize
506  $textsize = new ilNumberInputGUI($this->lng->txt("textsize"), "textsize");
507  $textsize->setValue($this->object->getTextSize());
508  $textsize->setInfo($this->lng->txt("textsize_info"));
509  $textsize->setSize(6);
510  $textsize->setMinValue(10);
511  $textsize->setRequired(false);
512  $form->addItem($textsize);
513  // points
514  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
515 
516  $points->allowDecimals(true);
517  // mbecker: Fix for mantis bug 7866: Predefined values schould make sense.
518  // This implements a default value of "1" for this question type.
519  if ($this->object->getPoints() == null) {
520  $points->setValue("1");
521  } else {
522  $points->setValue($this->object->getPoints());
523  }
524  $points->setRequired(true);
525  $points->setSize(3);
526  $points->setMinValue(0.0);
527  $points->setMinvalueShouldBeGreater(true);
528  $form->addItem($points);
529  }
530 
539  public function getAggregatedAnswersView($relevant_answers)
540  {
541  return $this->renderAggregateView(
542  $this->aggregateAnswers($relevant_answers, $this->object->getOrderText())
543  )->get();
544  }
545 
546  public function aggregateAnswers($relevant_answers_chosen, $answer_defined_on_question)
547  {
548  $aggregate = array();
549  foreach ($relevant_answers_chosen as $answer) {
550  $answer = str_replace($this->object->getAnswerSeparator(), '&nbsp;&nbsp;-&nbsp;&nbsp;', $answer);
551  if (in_array($answer['value1'], $aggregate)) {
552  $aggregate[$answer['value1']] = $aggregate[$answer['value1']] + 1;
553  } else {
554  $aggregate[$answer['value1']] = 1;
555  }
556  }
557 
558  return $aggregate;
559  }
560 
566  public function renderAggregateView($aggregate)
567  {
568  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
569 
570  foreach ($aggregate as $key => $line_data) {
571  $tpl->setCurrentBlock('aggregaterow');
572  $tpl->setVariable('COUNT', $line_data);
573  $tpl->setVariable('OPTION', $key);
574  $tpl->parseCurrentBlock();
575  }
576  return $tpl;
577  }
578 
579  public function getAnswersFrequency($relevantAnswers, $questionIndex)
580  {
581  $answers = array();
582 
583  foreach ($relevantAnswers as $ans) {
584  $md5 = md5($ans['value1']);
585 
586  if (!isset($answers[$md5])) {
587  $answer = str_replace(
588  $this->object->getAnswerSeparator(),
589  '&nbsp;&nbsp;-&nbsp;&nbsp;',
590  $ans['value1']
591  );
592 
593  $answers[$md5] = array(
594  'answer' => $answer, 'frequency' => 0
595  );
596  }
597 
598  $answers[$md5]['frequency']++;
599  }
600 
601  return $answers;
602  }
603 
605  {
606  // points
607  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
608 
609  $points->allowDecimals(true);
610  $points->setValue($this->object->getPoints());
611  $points->setRequired(true);
612  $points->setSize(3);
613  $points->setMinValue(0.0);
614  $points->setMinvalueShouldBeGreater(true);
615  $form->addItem($points);
616  }
617 
622  {
623  $this->object->setPoints((float) $form->getInput('points'));
624  }
625 }
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
hasCorrectSolution($activeId, $passIndex)
addTab_QuestionPreview(ilTabsGUI $tabsGUI)
Class for horizontal ordering questions.
addBasicQuestionFormProperties($form)
Add basic question form properties: assessment: title, author, description, question, working time.
setValue($a_value)
Set Value.
$_SESSION["AccountId"]
addTab_QuestionHints(ilTabsGUI $tabs)
adds the hints tab to ilTabsGUI
$template
This class represents a property form user interface.
saveFeedback()
Saves the feedback for a single choice question.
global $DIC
Definition: saml.php:7
$_GET["client_id"]
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
if(!array_key_exists('StateId', $_REQUEST)) $id
setValue($a_value)
Set Value.
The assOrderingHorizontalGUI class encapsulates the GUI representation for horizontal ordering questi...
addItem($a_item)
Add Item (Property, SectionHeader).
getQuestionTemplate()
get question template
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getUseIntermediateSolution()
Get if intermediate solution should be used for solution output.
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
allowDecimals($a_value)
Toggle Decimals.
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
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
getAggregatedAnswersView($relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
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.
aggregateAnswers($relevant_answers_chosen, $answer_defined_on_question)
addTab_QuestionFeedback(ilTabsGUI $tabs)
adds the feedback tab to ilTabsGUI
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
Basic GUI class for assessment questions.
setErrorMessage($errormessage)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
$errors
Definition: index.php:6
__construct($id=-1)
assOrderingHorizontalGUI constructor
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
output question page
setQuestionTabs()
Sets the ILIAS tabs for this question type.
This class represents a text area property in a property form.
addBackTab(ilTabsGUI $ilTabs)
getPreview($show_question_only=false, $showInlineFeedback=false)
getAnswersFrequency($relevantAnswers, $questionIndex)
$url
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getGenericFeedbackOutput($active_id, $pass)
Returns the answer specific feedback for the question.
Interface ilGuiQuestionScoringAdjustable.
$key
Definition: croninfo.php:18
$_POST["username"]
getTestOutput($active_id, $pass, $is_postponed=false, $use_post_solutions=false, $show_feedback=false)
addTab_SuggestedSolution(ilTabsGUI $tabs, $classname)
addQuestionFormCommandButtons($form)
Add the command buttons of a question properties form.