ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assMultipleChoice.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 
22 {
30  var $answers;
31 
41 
47  protected $thumb_size;
48 
63  function __construct(
64  $title = "",
65  $comment = "",
66  $author = "",
67  $owner = -1,
68  $question = "",
70  )
71  {
73  $this->output_type = $output_type;
74  $this->thumb_size = 150;
75  $this->answers = array();
76  $this->shuffle = 1;
77  }
78 
85  function isComplete()
86  {
87  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0))
88  {
89  return true;
90  }
91  else
92  {
93  return false;
94  }
95  }
96 
103  function saveToDb($original_id = "")
104  {
105  global $ilDB;
106 
108 
109  $oldthumbsize = 0;
110  if ($this->isSingleline && ($this->getThumbSize()))
111  {
112  // get old thumbnail size
113  $result = $ilDB->queryF("SELECT thumb_size FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
114  array("integer"),
115  array($this->getId())
116  );
117  if ($result->numRows() == 1)
118  {
119  $data = $ilDB->fetchAssoc($result);
120  $oldthumbsize = $data['thumb_size'];
121  }
122  }
123  if (!$this->isSingleline)
124  {
125  ilUtil::delDir($this->getImagePath());
126  }
127 
128  // save additional data
129  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
130  array("integer"),
131  array($this->getId())
132  );
133 
134  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
135  array("integer", "text", "text", "integer"),
136  array(
137  $this->getId(),
138  $this->getShuffle(),
139  ($this->isSingleline) ? "0" : "1",
140  (strlen($this->getThumbSize()) == 0) ? null : $this->getThumbSize()
141  )
142  );
143 
144  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_a_mc WHERE question_fi = %s",
145  array('integer'),
146  array($this->getId())
147  );
148 
149  foreach ($this->answers as $key => $value)
150  {
151  $answer_obj = $this->answers[$key];
152  $next_id = $ilDB->nextId('qpl_a_mc');
153  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_mc (answer_id, question_fi, answertext, points, points_unchecked, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
154  array('integer','integer','text','float','float','integer','text', 'integer'),
155  array(
156  $next_id,
157  $this->getId(),
158  ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 0),
159  $answer_obj->getPoints(),
160  $answer_obj->getPointsUnchecked(),
161  $answer_obj->getOrder(),
162  $answer_obj->getImage(),
163  time()
164  )
165  );
166  }
167 
168  $this->ensureNoInvalidObligation($this->getId());
169 
170  $this->rebuildThumbnails();
171 
173  }
174 
175  public function saveFeedbackSetting($a_feedback_setting)
176  {
177  global $ilDB;
178  $ilDB->manipulate(
179  'UPDATE qpl_qst_mc
180  SET feedback_setting = ' . $ilDB->quote($a_feedback_setting,'integer') . '
181  WHERE question_fi = ' .$ilDB->quote($this->getId(), 'integer'));
182  }
183 
184  /*
185  * Rebuild the thumbnail images with a new thumbnail size
186  */
187  protected function rebuildThumbnails()
188  {
189  if ($this->isSingleline && ($this->getThumbSize()))
190  {
191  foreach ($this->getAnswers() as $answer)
192  {
193  if (strlen($answer->getImage()))
194  {
195  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
196  }
197  }
198  }
199  }
200 
201  public function getThumbPrefix()
202  {
203  return "thumb.";
204  }
205 
206  protected function generateThumbForFile($path, $file)
207  {
208  $filename = $path . $file;
209  if (@file_exists($filename))
210  {
211  $thumbpath = $path . $this->getThumbPrefix() . $file;
212  $path_info = @pathinfo($filename);
213  $ext = "";
214  switch (strtoupper($path_info['extension']))
215  {
216  case 'PNG':
217  $ext = 'PNG';
218  break;
219  case 'GIF':
220  $ext = 'GIF';
221  break;
222  default:
223  $ext = 'JPEG';
224  break;
225  }
226  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
227  }
228  }
229 
236  function loadFromDb($question_id)
237  {
238  global $ilDB;
239  $hasimages = 0;
240 
241  $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",
242  array("integer"),
243  array($question_id)
244  );
245  if ($result->numRows() == 1)
246  {
247  $data = $ilDB->fetchAssoc($result);
248  $this->setId($question_id);
249  $this->setObjId($data["obj_fi"]);
250  $this->setTitle($data["title"]);
251  $this->setNrOfTries($data['nr_of_tries']);
252  $this->setComment($data["description"]);
253  $this->setOriginalId($data["original_id"]);
254  $this->setAuthor($data["author"]);
255  $this->setPoints($data["points"]);
256  $this->setOwner($data["owner"]);
257  include_once("./Services/RTE/classes/class.ilRTE.php");
258  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
259  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
260  $this->setShuffle($shuffle);
261  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
262  $this->setThumbSize($data['thumb_size']);
263  $this->isSingleline = ($data['allow_images']) ? false : true;
264  $this->lastChange = $data['tstamp'];
265  $this->feedback_setting = $data['feedback_setting'];
266  }
267 
268  $result = $ilDB->queryF("SELECT * FROM qpl_a_mc WHERE question_fi = %s ORDER BY aorder ASC",
269  array('integer'),
270  array($question_id)
271  );
272  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
273  if ($result->numRows() > 0)
274  {
275  while ($data = $ilDB->fetchAssoc($result))
276  {
277  $imagefilename = $this->getImagePath() . $data["imagefile"];
278  if (!@file_exists($imagefilename))
279  {
280  $data["imagefile"] = "";
281  }
282  include_once("./Services/RTE/classes/class.ilRTE.php");
283  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
284  array_push($this->answers, new ASS_AnswerMultipleResponseImage($data["answertext"], $data["points"], $data["aorder"], $data["points_unchecked"], $data["imagefile"]));
285  }
286  }
287 
288  parent::loadFromDb($question_id);
289  }
290 
296  function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
297  {
298  if ($this->id <= 0)
299  {
300  // The question has not been saved. It cannot be duplicated
301  return;
302  }
303  // duplicate the question in database
304  $this_id = $this->getId();
305 
306  if( (int)$testObjId > 0 )
307  {
308  $thisObjId = $this->getObjId();
309  }
310 
311  $clone = $this;
312  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
314  $clone->id = -1;
315 
316  if( (int)$testObjId > 0 )
317  {
318  $clone->setObjId($testObjId);
319  }
320 
321  if ($title)
322  {
323  $clone->setTitle($title);
324  }
325 
326  if ($author)
327  {
328  $clone->setAuthor($author);
329  }
330  if ($owner)
331  {
332  $clone->setOwner($owner);
333  }
334 
335  if ($for_test)
336  {
337  $clone->saveToDb($original_id);
338  }
339  else
340  {
341  $clone->saveToDb();
342  }
343 
344  // copy question page content
345  $clone->copyPageOfQuestion($this_id);
346  // copy XHTML media objects
347  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
348  // duplicate the images
349  $clone->duplicateImages($this_id, $thisObjId);
350  // duplicate the generic feedback
351  $clone->duplicateGenericFeedback($this_id);
352  // duplicate the answer specific feedback
353  $clone->duplicateFeedbackAnswer($this_id);
354 
355  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
356 
357  return $clone->id;
358  }
359 
365  function copyObject($target_questionpool, $title = "")
366  {
367  if ($this->id <= 0)
368  {
369  // The question has not been saved. It cannot be duplicated
370  return;
371  }
372  // duplicate the question in database
373  $clone = $this;
374  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
376  $clone->id = -1;
377  $source_questionpool = $this->getObjId();
378  $clone->setObjId($target_questionpool);
379  if ($title)
380  {
381  $clone->setTitle($title);
382  }
383  $clone->saveToDb();
384 
385  // copy question page content
386  $clone->copyPageOfQuestion($original_id);
387  // copy XHTML media objects
388  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
389  // duplicate the image
390  $clone->copyImages($original_id, $source_questionpool);
391  // duplicate the generic feedback
392  $clone->duplicateGenericFeedback($original_id);
393  // duplicate the answer specific feedback
394  $clone->duplicateFeedbackAnswer($original_id);
395 
396  $clone->onDuplicate($source_questionpool, $this->getId(), $clone->getObjId(), $clone->getId());
397 
398  $clone->onCopy($this->getObjId(), $this->getId());
399  return $clone->id;
400  }
401 
409  function getOutputType()
410  {
411  return $this->output_type;
412  }
413 
422  {
423  $this->output_type = $output_type;
424  }
425 
439  function addAnswer(
440  $answertext = "",
441  $points = 0.0,
442  $points_unchecked = 0.0,
443  $order = 0,
444  $answerimage = ""
445  )
446  {
447  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
448  if (array_key_exists($order, $this->answers))
449  {
450  // insert answer
451  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, $order, $points_unchecked, $answerimage);
452  $newchoices = array();
453  for ($i = 0; $i < $order; $i++)
454  {
455  array_push($newchoices, $this->answers[$i]);
456  }
457  array_push($newchoices, $answer);
458  for ($i = $order; $i < count($this->answers); $i++)
459  {
460  $changed = $this->answers[$i];
461  $changed->setOrder($i+1);
462  array_push($newchoices, $changed);
463  }
464  $this->answers = $newchoices;
465  }
466  else
467  {
468  // add answer
469  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, count($this->answers), $points_unchecked, $answerimage);
470  array_push($this->answers, $answer);
471  }
472  }
473 
481  function getAnswerCount()
482  {
483  return count($this->answers);
484  }
485 
495  function getAnswer($index = 0)
496  {
497  if ($index < 0) return NULL;
498  if (count($this->answers) < 1) return NULL;
499  if ($index >= count($this->answers)) return NULL;
500 
501  return $this->answers[$index];
502  }
503 
512  function deleteAnswer($index = 0)
513  {
514  if ($index < 0) return;
515  if (count($this->answers) < 1) return;
516  if ($index >= count($this->answers)) return;
517  $answer = $this->answers[$index];
518  if (strlen($answer->getImage())) $this->deleteImage($answer->getImage());
519  unset($this->answers[$index]);
520  $this->answers = array_values($this->answers);
521  for ($i = 0; $i < count($this->answers); $i++)
522  {
523  if ($this->answers[$i]->getOrder() > $index)
524  {
525  $this->answers[$i]->setOrder($i);
526  }
527  }
528  }
529 
536  function flushAnswers()
537  {
538  $this->answers = array();
539  }
540 
547  function getMaximumPoints()
548  {
549  $points = 0;
550  $allpoints = 0;
551  foreach ($this->answers as $key => $value)
552  {
553  if ($value->getPoints() > $value->getPointsUnchecked())
554  {
555  $allpoints += $value->getPoints();
556  }
557  else
558  {
559  $allpoints += $value->getPointsUnchecked();
560  }
561  }
562  return $allpoints;
563  }
564 
575  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
576  {
577  if( $returndetails )
578  {
579  throw new ilTestException('return details not implemented for '.__METHOD__);
580  }
581 
582  global $ilDB;
583 
584  $found_values = array();
585  if (is_null($pass))
586  {
587  $pass = $this->getSolutionMaxPass($active_id);
588  }
589  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
590  array('integer','integer','integer'),
591  array($active_id, $this->getId(), $pass)
592  );
593  while ($data = $ilDB->fetchAssoc($result))
594  {
595  if (strcmp($data["value1"], "") != 0)
596  {
597  array_push($found_values, $data["value1"]);
598  }
599  }
600  $points = 0;
601  foreach ($this->answers as $key => $answer)
602  {
603  if (in_array($key, $found_values))
604  {
605  $points += $answer->getPoints();
606  }
607  else
608  {
609  $points += $answer->getPointsUnchecked();
610  }
611  }
612  include_once "./Modules/Test/classes/class.ilObjTest.php";
613  $mc_scoring = ilObjTest::_getMCScoring($active_id);
614  if (($mc_scoring == 0) && (count($found_values) == 0))
615  {
616  $points = 0;
617  }
618  return $points;
619  }
620 
629  public function saveWorkingData($active_id, $pass = NULL)
630  {
631  global $ilDB;
632  global $ilUser;
633 
634  if (is_null($pass))
635  {
636  include_once "./Modules/Test/classes/class.ilObjTest.php";
637  $pass = ilObjTest::_getPass($active_id);
638  }
639 
640  $entered_values = 0;
641  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
642  array('integer','integer','integer'),
643  array($active_id, $this->getId(), $pass)
644  );
645  foreach ($_POST as $key => $value)
646  {
647  if (preg_match("/^multiple_choice_result_(\d+)/", $key, $matches))
648  {
649  if (strlen($value))
650  {
651  $next_id = $ilDB->nextId('tst_solutions');
652  $affectedRows = $ilDB->insert("tst_solutions", array(
653  "solution_id" => array("integer", $next_id),
654  "active_fi" => array("integer", $active_id),
655  "question_fi" => array("integer", $this->getId()),
656  "value1" => array("clob", $value),
657  "value2" => array("clob", null),
658  "pass" => array("integer", $pass),
659  "tstamp" => array("integer", time())
660  ));
661  $entered_values++;
662  }
663  }
664  }
665  if ($entered_values)
666  {
667  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
669  {
670  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
671  }
672  }
673  else
674  {
675  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
677  {
678  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
679  }
680  }
681 
682  return true;
683  }
684 
693  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
694  {
695  // nothing to rework!
696  }
697 
703  function syncFeedbackSingleAnswers()
704  {
705  global $ilDB;
706 
707  $feedback = "";
708 
709  // delete generic feedback of the original
710  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_fb_mc WHERE question_fi = %s",
711  array('integer'),
712  array($this->original_id)
713  );
714 
715  // get generic feedback of the actual question
716  $result = $ilDB->queryF("SELECT * FROM qpl_fb_mc WHERE question_fi = %s",
717  array('integer'),
718  array($this->getId())
719  );
720  // save generic feedback to the original
721  if ($result->numRows())
722  {
723  while ($row = $ilDB->fetchAssoc($result))
724  {
725  $next_id = $ilDB->nextId('qpl_fb_mc');
727  $ilDB->insert('qpl_fb_mc', array(
728  'feedback_id' => array( 'integer', $next_id ),
729  'question_fi' => array( 'integer', $this->original_id ),
730  'answer' => array( 'integer', $row["answer"] ),
731  'feedback' => array( 'clob', $row["feedback"] ),
732  'tstamp' => array( 'integer', time() ),
733  )
734  );
735  }
736  }
737  }
738 
739  function syncWithOriginal()
740  {
741  if ($this->getOriginalId())
742  {
743  $this->syncFeedbackSingleAnswers();
744  $this->syncImages();
746  }
747  }
748 
755  function getQuestionType()
756  {
757  return "assMultipleChoice";
758  }
759 
767  {
768  return "qpl_qst_mc";
769  }
770 
778  {
779  return "qpl_a_mc";
780  }
781 
790  function setImageFile($image_filename, $image_tempfilename = "")
791  {
792  $result = 0;
793  if (!empty($image_tempfilename))
794  {
795  $image_filename = str_replace(" ", "_", $image_filename);
796  $imagepath = $this->getImagePath();
797  if (!file_exists($imagepath))
798  {
799  ilUtil::makeDirParents($imagepath);
800  }
801  //if (!move_uploaded_file($image_tempfilename, $imagepath . $image_filename))
802  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
803  {
804  $result = 2;
805  }
806  else
807  {
808  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
809  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
810  if (!preg_match("/^image/", $mimetype))
811  {
812  unlink($imagepath . $image_filename);
813  $result = 1;
814  }
815  else
816  {
817  // create thumbnail file
818  if ($this->isSingleline && ($this->getThumbSize()))
819  {
820  $this->generateThumbForFile($imagepath, $image_filename);
821  }
822  }
823  }
824  }
825  return $result;
826  }
827 
834  function deleteImage($image_filename)
835  {
836  $imagepath = $this->getImagePath();
837  @unlink($imagepath . $image_filename);
838  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
839  @unlink($thumbpath);
840  }
841 
842  function duplicateImages($question_id, $objectId = null)
843  {
844  global $ilLog;
845  $imagepath = $this->getImagePath();
846  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
847 
848  if( (int)$objectId > 0 )
849  {
850  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
851  }
852 
853  foreach ($this->answers as $answer)
854  {
855  $filename = $answer->getImage();
856  if (strlen($filename))
857  {
858  if (!file_exists($imagepath))
859  {
860  ilUtil::makeDirParents($imagepath);
861  }
862  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
863  {
864  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
865  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
866  }
867  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
868  {
869  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
870  {
871  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
872  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
873  }
874  }
875  }
876  }
877  }
878 
879  function copyImages($question_id, $source_questionpool)
880  {
881  global $ilLog;
882  $imagepath = $this->getImagePath();
883  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
884  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
885  foreach ($this->answers as $answer)
886  {
887  $filename = $answer->getImage();
888  if (strlen($filename))
889  {
890  if (!file_exists($imagepath))
891  {
892  ilUtil::makeDirParents($imagepath);
893  }
894  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
895  {
896  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
897  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
898  }
899  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
900  {
901  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
902  {
903  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
904  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
905  }
906  }
907  }
908  }
909  }
910 
914  protected function syncImages()
915  {
916  global $ilLog;
917 
918  $imagepath = $this->getImagePath();
919 
920  $question_id = $this->getOriginalId();
921  $originalObjId = parent::lookupOriginalParentObjId($this->getOriginalId());
922  $imagepath_original = $this->getImagePath($question_id, $originalObjId);
923 
924  ilUtil::delDir($imagepath_original);
925  foreach ($this->answers as $answer)
926  {
927  $filename = $answer->getImage();
928  if (strlen($filename))
929  {
930  if (@file_exists($imagepath . $filename))
931  {
932  if (!file_exists($imagepath))
933  {
934  ilUtil::makeDirParents($imagepath);
935  }
936  if (!file_exists($imagepath_original))
937  {
938  ilUtil::makeDirParents($imagepath_original);
939  }
940  if (!@copy($imagepath . $filename, $imagepath_original . $filename))
941  {
942  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
943  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
944  }
945  }
946  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename))
947  {
948  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename))
949  {
950  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
951  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
952  }
953  }
954  }
955  }
956  }
957 
965  function saveFeedbackSingleAnswer($answer_index, $feedback)
966  {
967  global $ilDB;
968 
969  $affectedRows = $ilDB->manipulateF("DELETE FROM qpl_fb_mc WHERE question_fi = %s AND answer = %s",
970  array('integer','integer'),
971  array($this->getId(), $answer_index)
972  );
973  if (strlen($feedback))
974  {
975  include_once("./Services/RTE/classes/class.ilRTE.php");
976  $next_id = $ilDB->nextId('qpl_fb_mc');
978  $ilDB->insert('qpl_fb_mc', array(
979  'feedback_id' => array( 'integer', $next_id ),
980  'question_fi' => array( 'integer', $this->getId() ),
981  'answer' => array( 'integer', $answer_index ),
982  'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0 ) ),
983  'tstamp' => array( 'integer', time() ),
984  )
985  );
986  }
987  }
988 
996  function getFeedbackSingleAnswer($answer_index)
997  {
998  global $ilDB;
999 
1000  $feedback = "";
1001  $result = $ilDB->queryF("SELECT * FROM qpl_fb_mc WHERE question_fi = %s AND answer = %s",
1002  array('integer','integer'),
1003  array($this->getId(), $answer_index)
1004  );
1005  if ($result->numRows())
1006  {
1007  $row = $ilDB->fetchAssoc($result);
1008  include_once("./Services/RTE/classes/class.ilRTE.php");
1009  $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
1010  }
1011  return $feedback;
1012  }
1013 
1020  function duplicateFeedbackAnswer($original_id)
1021  {
1022  global $ilDB;
1023 
1024  $feedback = "";
1025  $result = $ilDB->queryF("SELECT * FROM qpl_fb_mc WHERE question_fi = %s",
1026  array('integer'),
1027  array($original_id)
1028  );
1029  if ($result->numRows())
1030  {
1031  while ($row = $ilDB->fetchAssoc($result))
1032  {
1033  $next_id = $ilDB->nextId('qpl_fb_mc');
1035  $ilDB->insert('qpl_fb_mc', array(
1036  'feedback_id' => array( 'integer', $next_id ),
1037  'question_fi' => array( 'integer', $this->getId() ),
1038  'answer' => array( 'integer', $row["answer"] ),
1039  'feedback' => array( 'clob', $row["feedback"] ),
1040  'tstamp' => array( 'integer', time() ),
1041  )
1042  );
1043  }
1044  }
1045  }
1046 
1052  {
1054  foreach ($this->answers as $index => $answer)
1055  {
1056  $text .= $this->getFeedbackSingleAnswer($index);
1057  $answer_obj = $this->answers[$index];
1058  $text .= $answer_obj->getAnswertext();
1059  }
1060  return $text;
1061  }
1062 
1066  function &getAnswers()
1067  {
1068  return $this->answers;
1069  }
1070 
1083  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
1084  {
1085  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
1086  $solution = $this->getSolutionValues($active_id, $pass);
1087  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
1088  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
1089  $i = 1;
1090  foreach ($this->getAnswers() as $id => $answer)
1091  {
1092  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($answer->getAnswertext()), $format_bold);
1093  $checked = FALSE;
1094  foreach ($solution as $solutionvalue)
1095  {
1096  if ($id == $solutionvalue["value1"])
1097  {
1098  $checked = TRUE;
1099  }
1100  }
1101  if ($checked)
1102  {
1103  $worksheet->write($startrow + $i, 1, 1);
1104  }
1105  else
1106  {
1107  $worksheet->write($startrow + $i, 1, 0);
1108  }
1109  $i++;
1110  }
1111  return $startrow + $i + 1;
1112  }
1113 
1114  public function getThumbSize()
1115  {
1116  return $this->thumb_size;
1117  }
1118 
1119  public function setThumbSize($a_size)
1120  {
1121  $this->thumb_size = $a_size;
1122  }
1123 
1127  public function toJSON()
1128  {
1129  include_once("./Services/RTE/classes/class.ilRTE.php");
1130  $result = array();
1131  $result['id'] = (int) $this->getId();
1132  $result['type'] = (string) $this->getQuestionType();
1133  $result['title'] = (string) $this->getTitle();
1134  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1135  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1136  $result['shuffle'] = (bool) $this->getShuffle();
1137  $result['feedback'] = array(
1138  "onenotcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(0), 0)),
1139  "allcorrect" => nl2br(ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackGeneric(1), 0))
1140  );
1141 
1142  $answers = array();
1143  $has_image = false;
1144  foreach ($this->getAnswers() as $key => $answer_obj)
1145  {
1146  if((string) $answer_obj->getImage())
1147  {
1148  $has_image = true;
1149  }
1150  array_push($answers, array(
1151  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1152  "points_checked" => (float) $answer_obj->getPointsChecked(),
1153  "points_unchecked" => (float) $answer_obj->getPointsUnchecked(),
1154  "order" => (int) $answer_obj->getOrder(),
1155  "image" => (string) $answer_obj->getImage(),
1156  "feedback" => ilRTE::_replaceMediaObjectImageSrc($this->getFeedbackSingleAnswer($key), 0)
1157  ));
1158  }
1159  $result['answers'] = $answers;
1160 
1161  if($has_image)
1162  {
1163  $result['path'] = $this->getImagePathWeb();
1164  $result['thumb'] = $this->getThumbSize();
1165  }
1166 
1167  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1168  $result['mobs'] = $mobs;
1169 
1170  return json_encode($result);
1171  }
1172 
1173  public function removeAnswerImage($index)
1174  {
1175  $answer = $this->answers[$index];
1176  if (is_object($answer))
1177  {
1178  $this->deleteImage($answer->getImage());
1179  $answer->setImage('');
1180  }
1181  }
1182 
1184  {
1185  global $ilUser;
1186 
1187  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1188  if ($multilineAnswerSetting != 1)
1189  {
1190  $multilineAnswerSetting = 0;
1191  }
1192  return $multilineAnswerSetting;
1193  }
1194 
1195  function setMultilineAnswerSetting($a_setting = 0)
1196  {
1197  global $ilUser;
1198  $ilUser->writePref("tst_multiline_answers", $a_setting);
1199  }
1200 
1210  function setFeedbackSetting($a_feedback_setting)
1211  {
1212  $this->feedback_setting = $a_feedback_setting;
1213  }
1214 
1225  {
1226  if ($this->feedback_setting)
1227  {
1228  return $this->feedback_setting;
1229  }
1230  else
1231  {
1232  return 1;
1233  }
1234  }
1235 
1246  public function isAnswered($active_id, $pass)
1247  {
1248  $answered = assQuestion::doesSolutionRecordsExist($active_id, $pass, $this->getId());
1249 
1250  return $answered;
1251  }
1252 
1264  public static function isObligationPossible($questionId)
1265  {
1266  global $ilDB;
1267 
1268  $query = "
1269  SELECT SUM(points) points_for_checked_answers
1270  FROM qpl_a_mc
1271  WHERE question_fi = %s
1272  ";
1273 
1274  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1275 
1276  $row = $ilDB->fetchAssoc($res);
1277 
1278  return $row['points_for_checked_answers'] > 0;
1279  }
1280 
1290  public function ensureNoInvalidObligation($questionId)
1291  {
1292  global $ilDB;
1293 
1294  $query = "
1295  SELECT SUM(qpl_a_mc.points) points_for_checked_answers,
1296  test_question_id
1297 
1298  FROM tst_test_question
1299 
1300  INNER JOIN qpl_a_mc
1301  ON qpl_a_mc.question_fi = tst_test_question.question_fi
1302 
1303  WHERE tst_test_question.question_fi = %s
1304  AND tst_test_question.obligatory = 1
1305 
1306  GROUP BY test_question_id
1307  ";
1308 
1309  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1310 
1311  $updateTestQuestionIds = array();
1312 
1313  while( $row = $ilDB->fetchAssoc($res) )
1314  {
1315  if( $row['points_for_checked_answers'] <= 0 )
1316  {
1317  $updateTestQuestionIds[] = $row['test_question_id'];
1318  }
1319  }
1320 
1321  if( count($updateTestQuestionIds) )
1322  {
1323  $test_question_id__IN__updateTestQuestionIds = $ilDB->in(
1324  'test_question_id', $updateTestQuestionIds, false, 'integer'
1325  );
1326 
1327  $query = "
1328  UPDATE tst_test_question
1329  SET obligatory = 0
1330  WHERE $test_question_id__IN__updateTestQuestionIds
1331  ";
1332 
1333  $ilDB->manipulate($query);
1334  }
1335  }
1336 }
1337 
1338 ?>