ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assErrorText.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
6 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
7 
20 {
21  protected $errortext;
22  protected $textsize;
23  protected $errordata;
24  protected $points_wrong;
25 
38  function __construct(
39  $title = "",
40  $comment = "",
41  $author = "",
42  $owner = -1,
43  $question = ""
44  )
45  {
47  $this->errortext = "";
48  $this->textsize = 100.0;
49  $this->errordata = array();
50  }
51 
57  public function isComplete()
58  {
59  if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0))
60  {
61  return true;
62  }
63  else
64  {
65  return false;
66  }
67  }
68 
73  public function saveToDb($original_id = "")
74  {
75  global $ilDB;
76 
78 
79  // save additional data
80  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
81  array("integer"),
82  array($this->getId())
83  );
84 
85  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, errortext, textsize, points_wrong) VALUES (%s, %s, %s, %s)",
86  array("integer", "text", "float", "float"),
87  array(
88  $this->getId(),
89  $this->getErrorText(),
90  $this->getTextSize(),
91  $this->getPointsWrong()
92  )
93  );
94 
95  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_errortext WHERE question_fi = %s",
96  array('integer'),
97  array($this->getId())
98  );
99 
100  $sequence = 0;
101  foreach ($this->errordata as $object)
102  {
103  $next_id = $ilDB->nextId('qpl_a_errortext');
104  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_errortext (answer_id, question_fi, text_wrong, text_correct, points, sequence) VALUES (%s, %s, %s, %s, %s, %s)",
105  array('integer','integer','text','text','float', 'integer'),
106  array(
107  $next_id,
108  $this->getId(),
109  $object->text_wrong,
110  $object->text_correct,
111  $object->points,
112  $sequence++
113  )
114  );
115  }
116 
118  }
119 
126  public function loadFromDb($question_id)
127  {
128  global $ilDB;
129 
130  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
131  array("integer"),
132  array($question_id)
133  );
134  if ($result->numRows() == 1)
135  {
136  $data = $ilDB->fetchAssoc($result);
137  $this->setId($question_id);
138  $this->setObjId($data["obj_fi"]);
139  $this->setTitle($data["title"]);
140  $this->setComment($data["description"]);
141  $this->setOriginalId($data["original_id"]);
142  $this->setNrOfTries($data['nr_of_tries']);
143  $this->setAuthor($data["author"]);
144  $this->setPoints($data["points"]);
145  $this->setOwner($data["owner"]);
146  include_once("./Services/RTE/classes/class.ilRTE.php");
147  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
148  $this->setErrorText($data["errortext"]);
149  $this->setTextSize($data["textsize"]);
150  $this->setPointsWrong($data["points_wrong"]);
151  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
152  }
153 
154  $result = $ilDB->queryF("SELECT * FROM qpl_a_errortext WHERE question_fi = %s ORDER BY sequence ASC",
155  array('integer'),
156  array($question_id)
157  );
158  include_once "./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
159  if ($result->numRows() > 0)
160  {
161  while ($data = $ilDB->fetchAssoc($result))
162  {
163  array_push($this->errordata, new assAnswerErrorText($data["text_wrong"], $data["text_correct"], $data["points"]));
164  }
165  }
166 
167  parent::loadFromDb($question_id);
168  }
169 
173  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
174  {
175  if ($this->id <= 0)
176  {
177  // The question has not been saved. It cannot be duplicated
178  return;
179  }
180  // duplicate the question in database
181  $this_id = $this->getId();
182 
183  if( (int)$testObjId > 0 )
184  {
185  $thisObjId = $this->getObjId();
186  }
187 
188  $clone = $this;
189  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
191  $clone->id = -1;
192 
193  if( (int)$testObjId > 0 )
194  {
195  $clone->setObjId($testObjId);
196  }
197 
198  if ($title)
199  {
200  $clone->setTitle($title);
201  }
202 
203  if ($author)
204  {
205  $clone->setAuthor($author);
206  }
207  if ($owner)
208  {
209  $clone->setOwner($owner);
210  }
211 
212  if ($for_test)
213  {
214  $clone->saveToDb($original_id);
215  }
216  else
217  {
218  $clone->saveToDb();
219  }
220  // copy question page content
221  $clone->copyPageOfQuestion($this_id);
222  // copy XHTML media objects
223  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
224  // duplicate the generic feedback
225  $clone->duplicateGenericFeedback($this_id);
226  // duplicate the specific feedback
227  $clone->duplicateSpecificFeedback($this_id);
228 
229  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
230  return $clone->id;
231  }
232 
236  public function copyObject($target_questionpool, $title = "")
237  {
238  if ($this->id <= 0)
239  {
240  // The question has not been saved. It cannot be duplicated
241  return;
242  }
243  // duplicate the question in database
244  $clone = $this;
245  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
247  $clone->id = -1;
248  $source_questionpool = $this->getObjId();
249  $clone->setObjId($target_questionpool);
250  if ($title)
251  {
252  $clone->setTitle($title);
253  }
254  $clone->saveToDb();
255 
256  // copy question page content
257  $clone->copyPageOfQuestion($original_id);
258  // copy XHTML media objects
259  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
260  // duplicate the generic feedback
261  $clone->duplicateGenericFeedback($original_id);
262  // duplicate the specific feedback
263  $clone->duplicateSpecificFeedback($original_id);
264 
265  $clone->onCopy($this->getObjId(), $this->getId());
266 
267  return $clone->id;
268  }
269 
275  public function getMaximumPoints()
276  {
277  $maxpoints = 0.0;
278  foreach ($this->errordata as $object)
279  {
280  if ($object->points > 0) $maxpoints += $object->points;
281  }
282  return $maxpoints;
283  }
284 
295  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
296  {
297  if( $returndetails )
298  {
299  throw new ilTestException('return details not implemented for '.__METHOD__);
300  }
301 
302  global $ilDB;
303 
304  $found_values = array();
305  if (is_null($pass))
306  {
307  $pass = $this->getSolutionMaxPass($active_id);
308  }
309  $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
310  array('integer','integer','integer'),
311  array($active_id, $this->getId(), $pass)
312  );
313  while ($row = $ilDB->fetchAssoc($result))
314  {
315  array_push($found_values, $row['value1']);
316  }
317  $points = $this->getPointsForSelectedPositions($found_values);
318  return $points;
319  }
320 
321  /*
322  * Change the selection during a test when a user selects/deselects a word without using javascript
323  */
324  public function toggleSelection($position, $active_id, $pass = null)
325  {
326  global $ilDB;
327  global $ilUser;
328 
329  if (is_null($pass))
330  {
331  include_once "./Modules/Test/classes/class.ilObjTest.php";
332  $pass = ilObjTest::_getPass($active_id);
333  }
334 
335  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s AND value1 = %s",
336  array('integer','integer','integer', 'text'),
337  array($active_id, $this->getId(), $pass, $position)
338  );
339  if ($affectedRows == 0)
340  {
341  $next_id = $ilDB->nextId('tst_solutions');
342  $affectedRows = $ilDB->insert("tst_solutions", array(
343  "solution_id" => array("integer", $next_id),
344  "active_fi" => array("integer", $active_id),
345  "question_fi" => array("integer", $this->getId()),
346  "value1" => array("clob", $position),
347  "value2" => array("clob", null),
348  "pass" => array("integer", $pass),
349  "tstamp" => array("integer", time())
350  ));
351  }
352  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
354  {
355  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
356  }
357  $this->calculateReachedPoints($active_id, $pass);
358  }
359 
368  public function saveWorkingData($active_id, $pass = NULL)
369  {
370  global $ilDB;
371  global $ilUser;
372 
373  if (is_null($pass))
374  {
375  include_once "./Modules/Test/classes/class.ilObjTest.php";
376  $pass = ilObjTest::_getPass($active_id);
377  }
378 
379  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
380  array('integer','integer','integer'),
381  array($active_id, $this->getId(), $pass)
382  );
383 
384  $entered_values = false;
385  if (strlen($_POST["qst_" . $this->getId()]))
386  {
387  $selected = split(",", $_POST["qst_" . $this->getId()]);
388  foreach ($selected as $position)
389  {
390  $next_id = $ilDB->nextId('tst_solutions');
391  $affectedRows = $ilDB->insert("tst_solutions", array(
392  "solution_id" => array("integer", $next_id),
393  "active_fi" => array("integer", $active_id),
394  "question_fi" => array("integer", $this->getId()),
395  "value1" => array("clob", $position),
396  "value2" => array("clob", null),
397  "pass" => array("integer", $pass),
398  "tstamp" => array("integer", time())
399  ));
400  }
401  $entered_values = true;
402  }
403  if ($entered_values)
404  {
405  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
407  {
408  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
409  }
410  }
411  else
412  {
413  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
415  {
416  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
417  }
418  }
419 
420  return true;
421  }
422 
431  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
432  {
433  // nothing to rework!
434  }
435 
441  public function getQuestionType()
442  {
443  return "assErrorText";
444  }
445 
451  public function getAdditionalTableName()
452  {
453  return "qpl_qst_errortext";
454  }
455 
461  public function getAnswerTableName()
462  {
463  return "qpl_a_errortext";
464  }
465 
470  public function getRTETextWithMediaObjects()
471  {
473  return $text;
474  }
475 
487  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
488  {
489  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
490  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
491  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
492 
493  $i= 0;
494  $selections = array();
495  $solutions =& $this->getSolutionValues($active_id, $pass);
496  if (is_array($solutions))
497  {
498  foreach ($solutions as $solution)
499  {
500  array_push($selections, $solution['value1']);
501  }
502  $errortext_value = join(",", $selections);
503  }
504  $errortext = $this->createErrorTextExport($selections);
505  $errortext = preg_replace("/#HREF\d+/is", "javascript:void(0);", $errortext);
506  $i++;
507  $worksheet->writeString($startrow+$i, 0, ilExcelUtils::_convert_text($errortext));
508  $i++;
509  return $startrow + $i + 1;
510  }
511 
524  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
525  {
526  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php";
527  $import = new assErrorTextImport($this);
528  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
529  }
530 
537  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
538  {
539  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assErrorTextExport.php";
540  $export = new assErrorTextExport($this);
541  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
542  }
543 
549  public function getBestSolution($active_id, $pass)
550  {
551  $user_solution = array();
552  return $user_solution;
553  }
554 
555  public function getErrorsFromText($a_text = "")
556  {
557  if (strlen($a_text) == 0) $a_text = $this->getErrorText();
558  preg_match_all("/#([^\s]+)/is", $a_text, $matches);
559  if (is_array($matches[1]))
560  {
561  return $matches[1];
562  }
563  else
564  {
565  return array();
566  }
567  }
568 
569  public function setErrorData($a_data)
570  {
571  include_once "./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
572  $temp = $this->errordata;
573  $this->errordata = array();
574  foreach ($a_data as $error)
575  {
576  $text_correct = "";
577  $points = 0.0;
578  foreach ($temp as $object)
579  {
580  if (strcmp($object->text_wrong, $error) == 0)
581  {
582  $text_correct = $object->text_correct;
583  $points = $object->points;
584  continue;
585  }
586  }
587  array_push($this->errordata, new assAnswerErrorText($error, $text_correct, $points));
588  }
589  }
590 
591  public function createErrorTextOutput($selections = null, $graphicalOutput = false, $correct_solution = false)
592  {
593  $counter = 0;
594  $errorcounter = 0;
595  include_once "./Services/Utilities/classes/class.ilStr.php";
596  if (!is_array($selections)) $selections = array();
597  $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
598  foreach ($textarray as $textidx => $text)
599  {
600  $items = preg_split("/\s+/", $text);
601  foreach ($items as $idx => $item)
602  {
603  if (strpos($item, '#') === 0)
604  {
605  $item = ilStr::substr($item, 1, ilStr::strlen($item));
606  if ($correct_solution)
607  {
608  $errorobject = $this->errordata[$errorcounter];
609  if (is_object($errorobject))
610  {
611  $item = strlen($errorobject->text_correct) ? $errorobject->text_correct : '&nbsp;';
612  }
613  $errorcounter++;
614  }
615  }
616  $class = '';
617  $img = '';
618  if (in_array($counter, $selections))
619  {
620  $class = ' class="sel"';
621  if ($graphicalOutput)
622  {
623  if ($this->getPointsForSelectedPositions(array($counter)) >= 0)
624  {
625  $img = ' <img src="' . ilUtil::getImagePath("icon_ok.png") . '" alt="' . $this->lng->txt("answer_is_right") . '" title="' . $this->lng->txt("answer_is_right") . '" /> ';
626  }
627  else
628  {
629  $img = ' <img src="' . ilUtil::getImagePath("icon_not_ok.png") . '" alt="' . $this->lng->txt("answer_is_wrong") . '" title="' . $this->lng->txt("answer_is_wrong") . '" /> ';
630  }
631  }
632  }
633  $items[$idx] = '<a' . $class . ' href="#HREF' . $idx . '" onclick="javascript: return false;">' . ($item == '&nbsp;' ? $item : ilUtil::prepareFormOutput($item)) . '</a>' . $img;
634  $counter++;
635  }
636  $textarray[$textidx] = '<p>' . join($items, " ") . '</p>';
637  }
638  return join($textarray, "\n");
639  }
640 
641  public function createErrorTextExport($selections = null)
642  {
643  $counter = 0;
644  $errorcounter = 0;
645  include_once "./Services/Utilities/classes/class.ilStr.php";
646  if (!is_array($selections)) $selections = array();
647  $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
648  foreach ($textarray as $textidx => $text)
649  {
650  $items = preg_split("/\s+/", $text);
651  foreach ($items as $idx => $item)
652  {
653  if (strpos($item, '#') === 0)
654  {
655  $item = ilStr::substr($item, 1, ilStr::strlen($item));
656  if ($correct_solution)
657  {
658  $errorobject = $this->errordata[$errorcounter];
659  if (is_object($errorobject))
660  {
661  $item = $errorobject->text_correct;
662  }
663  $errorcounter++;
664  }
665  }
666  $word = "";
667  if (in_array($counter, $selections))
668  {
669  $word .= '#';
670  }
671  $word .= ilUtil::prepareFormOutput($item);
672  if (in_array($counter, $selections))
673  {
674  $word .= '#';
675  }
676  $items[$idx] = $word;
677  $counter++;
678  }
679  $textarray[$textidx] = join($items, " ");
680  }
681  return join($textarray, "\n");
682  }
683 
684  public function getBestSelection($withPositivePointsOnly = true)
685  {
686  $words = array();
687  $counter = 0;
688  $errorcounter = 0;
689  $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
690  foreach ($textarray as $textidx => $text)
691  {
692  $items = preg_split("/\s+/", $text);
693  foreach ($items as $word)
694  {
695  $points = $this->getPointsWrong();
696  $isErrorItem = false;
697  if (strpos($word, '#') === 0)
698  {
699  $errorobject = $this->errordata[$errorcounter];
700  if (is_object($errorobject))
701  {
702  $points = $errorobject->points;
703  $isErrorItem = true;
704  }
705  $errorcounter++;
706  }
707  $words[$counter] = array("word" => $word, "points" => $points, "isError" => $isErrorItem);
708  $counter++;
709  }
710  }
711  $selections = array();
712  foreach ($words as $idx => $word)
713  {
714  if (!$withPositivePointsOnly && $word['isError'] || $withPositivePointsOnly && $word['points'] > 0)
715  {
716  array_push($selections, $idx);
717  }
718  }
719  return $selections;
720  }
721 
722  protected function getPointsForSelectedPositions($positions)
723  {
724  $words = array();
725  $counter = 0;
726  $errorcounter = 0;
727  $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
728  foreach ($textarray as $textidx => $text)
729  {
730  $items = preg_split("/\s+/", $text);
731  foreach ($items as $word)
732  {
733  $points = $this->getPointsWrong();
734  if (strpos($word, '#') === 0)
735  {
736  $errorobject = $this->errordata[$errorcounter];
737  if (is_object($errorobject))
738  {
739  $points = $errorobject->points;
740  }
741  $errorcounter++;
742  }
743  $words[$counter] = array("word" => $word, "points" => $points);
744  $counter++;
745  }
746  }
747  $total = 0;
748  foreach ($positions as $position)
749  {
750  $total += $words[$position]['points'];
751  }
752  return $total;
753  }
754 
758  public function flushErrorData()
759  {
760  $this->errordata = array();
761  }
762 
763  public function addErrorData($text_wrong, $text_correct, $points)
764  {
765  include_once "./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
766  array_push($this->errordata, new assAnswerErrorText($text_wrong, $text_correct, $points));
767  }
768 
774  public function getErrorData()
775  {
776  return $this->errordata;
777  }
778 
784  public function getErrorText()
785  {
786  return $this->errortext;
787  }
788 
794  public function setErrorText($a_value)
795  {
796  $this->errortext = $a_value;
797  }
798 
804  public function getTextSize()
805  {
806  return $this->textsize;
807  }
808 
814  public function setTextSize($a_value)
815  {
816  // in self-assesment-mode value should always be set (and must not be null)
817  if($a_value === null)
818  {
819  $a_value = 100;
820  }
821  $this->textsize = $a_value;
822  }
823 
829  public function getPointsWrong()
830  {
831  return $this->points_wrong;
832  }
833 
839  public function setPointsWrong($a_value)
840  {
841  $this->points_wrong = $a_value;
842  }
843 
847  public function __get($value)
848  {
849  switch ($value)
850  {
851  case "errortext":
852  return $this->getErrorText();
853  break;
854  case "textsize":
855  return $this->getTextSize();
856  break;
857  case "points_wrong":
858  return $this->getPointsWrong();
859  break;
860  default:
861  return parent::__get($value);
862  break;
863  }
864  }
865 
869  public function __set($key, $value)
870  {
871  switch ($key)
872  {
873  case "errortext":
874  $this->setErrorText($value);
875  break;
876  case "textsize":
877  $this->setTextSize($value);
878  break;
879  case "points_wrong":
880  $this->setPointsWrong($value);
881  break;
882  default:
883  parent::__set($key, $value);
884  break;
885  }
886  }
887 
888 
892  public function toJSON()
893  {
894  include_once("./Services/RTE/classes/class.ilRTE.php");
895  $result = array();
896  $result['id'] = (int) $this->getId();
897  $result['type'] = (string) $this->getQuestionType();
898  $result['title'] = (string) $this->getTitle();
899  $result['question'] = $this->formatSAQuestion($this->getQuestion());
900  $result['text'] = (string) ilRTE::_replaceMediaObjectImageSrc($this->getErrorText(), 0);
901  $result['nr_of_tries'] = (int) $this->getNrOfTries();
902  $result['shuffle'] = (bool) $this->getShuffle();
903  $result['feedback'] = array(
904  "onenotcorrect" => ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(0), 0),
905  "allcorrect" => ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(1), 0)
906  );
907 
908  $answers = array();
909  foreach ($this->getErrorData() as $idx => $answer_obj)
910  {
911  array_push($answers, array(
912  "answertext_wrong" => (string) $answer_obj->text_wrong,
913  "answertext_correct" => (string) $answer_obj->text_correct,
914  "points" => (float)$answer_obj->points,
915  "order" => (int)$idx+1
916  ));
917  }
918  $result['correct_answers'] = $answers;
919 
920  $answers = array();
921  $textarray = preg_split("/[\n\r]+/", $this->getErrorText());
922  foreach ($textarray as $textidx => $text)
923  {
924  $items = preg_split("/\s+/", trim($text));
925  foreach ($items as $idx => $item)
926  {
927  if(substr($item, 0, 1) == "#")
928  {
929  $item = substr($item, 1);
930 
931  // #14115 - add position to correct answer
932  foreach($result["correct_answers"] as $aidx => $answer)
933  {
934  if($answer["answertext_wrong"] == $item && !$answer["pos"])
935  {
936  $result["correct_answers"][$aidx]["pos"] = $textidx."_".($idx+1);
937  break;
938  }
939  }
940  }
941  array_push($answers, array(
942  "answertext" => (string) ilUtil::prepareFormOutput($item),
943  "order" => $textidx."_".($idx+1)
944  ));
945  }
946  if($textidx != sizeof($textarray)-1)
947  {
948  array_push($answers, array(
949  "answertext" => "###",
950  "order" => $textidx."_".($idx+2)
951  ));
952  }
953  }
954  $result['answers'] = $answers;
955 
956  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
957  $result['mobs'] = $mobs;
958 
959  return json_encode($result);
960  }
961 
969  function saveFeedbackSingleAnswer($answer_index, $feedback)
970  {
971  global $ilDB;
972 
973  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_fb_errortext WHERE question_fi = %s AND answer = %s",
974  array('integer','integer'),
975  array($this->getId(), $answer_index)
976  );
977  if (strlen($feedback))
978  {
979  include_once("./Services/RTE/classes/class.ilRTE.php");
980  $next_id = $ilDB->nextId('qpl_fb_errortext');
981 
983  $ilDB->insert('qpl_fb_errortext', array(
984  'feedback_id' => array( 'integer', $next_id ),
985  'question_fi' => array( 'integer', $this->getId() ),
986  'answer' => array( 'integer', $answer_index ),
987  'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc($feedback, 0) ),
988  'tstamp' => array( 'integer', time() ),
989  )
990  );
991  }
992  }
993 
1001  function getFeedbackSingleAnswer($answer_index)
1002  {
1003  global $ilDB;
1004 
1005  $feedback = "";
1006  $result = $ilDB->queryF("SELECT * FROM qpl_fb_errortext WHERE question_fi = %s AND answer = %s",
1007  array('integer','integer'),
1008  array($this->getId(), $answer_index)
1009  );
1010  if ($result->numRows())
1011  {
1012  $row = $ilDB->fetchAssoc($result);
1013  include_once("./Services/RTE/classes/class.ilRTE.php");
1014  $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
1015  }
1016  return $feedback;
1017  }
1018 
1025  function duplicateSpecificFeedback($original_id)
1026  {
1027  global $ilDB;
1028 
1029  $feedback = "";
1030  $result = $ilDB->queryF("SELECT * FROM qpl_fb_errortext WHERE question_fi = %s",
1031  array('integer'),
1032  array($original_id)
1033  );
1034  if ($result->numRows())
1035  {
1036  while ($row = $ilDB->fetchAssoc($result))
1037  {
1038  $next_id = $ilDB->nextId('qpl_fb_errortext');
1040  $ilDB->insert('qpl_fb_errortext', array(
1041  'feedback_id' => array( 'integer', $next_id ),
1042  'question_fi' => array( 'integer', $this->getId() ),
1043  'answer' => array( 'integer', $row["answer"] ),
1044  'feedback' => array( 'clob', $row["feedback"] ),
1045  'tstamp' => array( 'integer', time() ),
1046  )
1047  );
1048  }
1049  }
1050  }
1051 
1052  protected function deleteFeedbackSpecific($question_id)
1053  {
1054  global $ilDB;
1055  $ilDB->manipulateF(
1056  'DELETE
1057  FROM qpl_fb_errortext
1058  WHERE question_fi = %s',
1059  array('integer'),
1060  array($question_id)
1061  );
1062  }
1063 }