ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.assSingleChoice.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.assQuestion.php';
5 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8 require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9 require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
10 require_once 'Modules/TestQuestionPool/interfaces/interface.ilAssSpecificFeedbackOptionLabelProvider.php';
11 
26 {
34  public $answers;
35 
44  public $output_type;
45 
51  protected $thumb_size;
52 
59  protected $feedback_setting;
60 
75  public function __construct(
76  $title = "",
77  $comment = "",
78  $author = "",
79  $owner = -1,
80  $question = "",
82  ) {
84  $this->thumb_size = 150;
85  $this->output_type = $output_type;
86  $this->answers = array();
87  $this->shuffle = 1;
88  $this->feedback_setting = 2;
89  }
90 
97  public function isComplete()
98  {
99  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0)) {
100  foreach ($this->answers as $answer) {
101  if ((strlen($answer->getAnswertext()) == 0) && (strlen($answer->getImage()) == 0)) {
102  return false;
103  }
104  }
105  return true;
106  } else {
107  return false;
108  }
109  }
110 
117  public function saveToDb($original_id = "")
118  {
120  global $DIC;
121  $ilDB = $DIC['ilDB'];
122 
124 
125  // kann das weg?
126  $oldthumbsize = 0;
127  if ($this->isSingleline && ($this->getThumbSize())) {
128  // get old thumbnail size
129  $result = $ilDB->queryF(
130  "SELECT thumb_size FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
131  array("integer"),
132  array($this->getId())
133  );
134  if ($result->numRows() == 1) {
135  $data = $ilDB->fetchAssoc($result);
136  $oldthumbsize = $data['thumb_size'];
137  }
138  }
139 
140 
142 
144 
145  parent::saveToDb($original_id);
146  }
147 
148  /*
149  * Rebuild the thumbnail images with a new thumbnail size
150  */
151  protected function rebuildThumbnails()
152  {
153  if ($this->isSingleline && ($this->getThumbSize())) {
154  foreach ($this->getAnswers() as $answer) {
155  if (strlen($answer->getImage())) {
156  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
157  }
158  }
159  }
160  }
161 
162  public function getThumbPrefix()
163  {
164  return "thumb.";
165  }
166 
167  protected function generateThumbForFile($path, $file)
168  {
169  $filename = $path . $file;
170  if (@file_exists($filename)) {
171  $thumbpath = $path . $this->getThumbPrefix() . $file;
172  $path_info = @pathinfo($filename);
173  $ext = "";
174  switch (strtoupper($path_info['extension'])) {
175  case 'PNG':
176  $ext = 'PNG';
177  break;
178  case 'GIF':
179  $ext = 'GIF';
180  break;
181  default:
182  $ext = 'JPEG';
183  break;
184  }
185  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
186  }
187  }
188 
196  public function loadFromDb($question_id)
197  {
198  global $DIC;
199  $ilDB = $DIC['ilDB'];
200 
201  $hasimages = 0;
202 
203  $result = $ilDB->queryF(
204  "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",
205  array("integer"),
206  array($question_id)
207  );
208  if ($result->numRows() == 1) {
209  $data = $ilDB->fetchAssoc($result);
210  $this->setId($question_id);
211  $this->setObjId($data["obj_fi"]);
212  $this->setTitle($data["title"]);
213  $this->setNrOfTries($data['nr_of_tries']);
214  $this->setComment($data["description"]);
215  $this->setOriginalId($data["original_id"]);
216  $this->setAuthor($data["author"]);
217  $this->setPoints($data["points"]);
218  $this->setOwner($data["owner"]);
219  include_once("./Services/RTE/classes/class.ilRTE.php");
220  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
221  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
222  $this->setShuffle($shuffle);
223  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
224  $this->setThumbSize($data['thumb_size']);
225  $this->isSingleline = ($data['allow_images']) ? false : true;
226  $this->lastChange = $data['tstamp'];
227  $this->feedback_setting = $data['feedback_setting'];
228 
229  try {
233  }
234 
235  try {
236  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
237  } catch (ilTestQuestionPoolException $e) {
238  }
239  }
240 
241  $result = $ilDB->queryF(
242  "SELECT * FROM qpl_a_sc WHERE question_fi = %s ORDER BY aorder ASC",
243  array('integer'),
244  array($question_id)
245  );
246  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
247  if ($result->numRows() > 0) {
248  while ($data = $ilDB->fetchAssoc($result)) {
249  $imagefilename = $this->getImagePath() . $data["imagefile"];
250  if (!@file_exists($imagefilename)) {
251  $data["imagefile"] = "";
252  }
253  include_once("./Services/RTE/classes/class.ilRTE.php");
254  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
255  array_push($this->answers, new ASS_AnswerBinaryStateImage($data["answertext"], $data["points"], $data["aorder"], 1, $data["imagefile"]));
256  }
257  }
258 
259  parent::loadFromDb($question_id);
260  }
261 
267  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
268  {
269  if ($this->id <= 0) {
270  // The question has not been saved. It cannot be duplicated
271  return;
272  }
273  // duplicate the question in database
274  $this_id = $this->getId();
275  $thisObjId = $this->getObjId();
276 
277  $clone = $this;
278  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
280  $clone->id = -1;
281 
282  if ((int) $testObjId > 0) {
283  $clone->setObjId($testObjId);
284  }
285 
286  if ($title) {
287  $clone->setTitle($title);
288  }
289 
290  if ($author) {
291  $clone->setAuthor($author);
292  }
293  if ($owner) {
294  $clone->setOwner($owner);
295  }
296  if ($for_test) {
297  $clone->saveToDb($original_id);
298  } else {
299  $clone->saveToDb();
300  }
301 
302  // copy question page content
303  $clone->copyPageOfQuestion($this_id);
304 
305  // copy XHTML media objects
306  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
307  // duplicate the images
308  $clone->duplicateImages($this_id, $thisObjId);
309 
310  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
311 
312  return $clone->id;
313  }
314 
320  public function copyObject($target_questionpool_id, $title = "")
321  {
322  if ($this->id <= 0) {
323  // The question has not been saved. It cannot be duplicated
324  return;
325  }
326  // duplicate the question in database
327  $clone = $this;
328  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
330  $clone->id = -1;
331  $source_questionpool_id = $this->getObjId();
332  $clone->setObjId($target_questionpool_id);
333  if ($title) {
334  $clone->setTitle($title);
335  }
336  $clone->saveToDb();
337  // copy question page content
338  $clone->copyPageOfQuestion($original_id);
339  // copy XHTML media objects
340  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
341  // duplicate the image
342  $clone->copyImages($original_id, $source_questionpool_id);
343 
344  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
345 
346  return $clone->id;
347  }
348 
349  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
350  {
351  if ($this->id <= 0) {
352  // The question has not been saved. It cannot be duplicated
353  return;
354  }
355 
356  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
357 
358  $sourceQuestionId = $this->id;
359  $sourceParentId = $this->getObjId();
360 
361  // duplicate the question in database
362  $clone = $this;
363  $clone->id = -1;
364 
365  $clone->setObjId($targetParentId);
366 
367  if ($targetQuestionTitle) {
368  $clone->setTitle($targetQuestionTitle);
369  }
370 
371  $clone->saveToDb();
372  // copy question page content
373  $clone->copyPageOfQuestion($sourceQuestionId);
374  // copy XHTML media objects
375  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
376  // duplicate the image
377  $clone->copyImages($sourceQuestionId, $sourceParentId);
378 
379  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
380 
381  return $clone->id;
382  }
383 
391  public function getOutputType()
392  {
393  return $this->output_type;
394  }
395 
404  {
405  $this->output_type = $output_type;
406  }
407 
421  public function addAnswer(
422  $answertext = "",
423  $points = 0.0,
424  $order = 0,
425  $answerimage = ""
426  ) {
427  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
428  $answertext = $this->getHtmlQuestionContentPurifier()->purify($answertext);
429  if (array_key_exists($order, $this->answers)) {
430  // insert answer
431  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, $order, 1, $answerimage);
432  $newchoices = array();
433  for ($i = 0; $i < $order; $i++) {
434  array_push($newchoices, $this->answers[$i]);
435  }
436  array_push($newchoices, $answer);
437  for ($i = $order; $i < count($this->answers); $i++) {
438  $changed = $this->answers[$i];
439  $changed->setOrder($i + 1);
440  array_push($newchoices, $changed);
441  }
442  $this->answers = $newchoices;
443  } else {
444  // add answer
445  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, count($this->answers), 1, $answerimage);
446  array_push($this->answers, $answer);
447  }
448  }
449 
457  public function getAnswerCount()
458  {
459  return count($this->answers);
460  }
461 
471  public function getAnswer($index = 0)
472  {
473  if ($index < 0) {
474  return null;
475  }
476  if (count($this->answers) < 1) {
477  return null;
478  }
479  if ($index >= count($this->answers)) {
480  return null;
481  }
482 
483  return $this->answers[$index];
484  }
485 
494  public function deleteAnswer($index = 0)
495  {
496  if ($index < 0) {
497  return;
498  }
499  if (count($this->answers) < 1) {
500  return;
501  }
502  if ($index >= count($this->answers)) {
503  return;
504  }
505  $answer = $this->answers[$index];
506  if (strlen($answer->getImage())) {
507  $this->deleteImage($answer->getImage());
508  }
509  unset($this->answers[$index]);
510  $this->answers = array_values($this->answers);
511  for ($i = 0; $i < count($this->answers); $i++) {
512  if ($this->answers[$i]->getOrder() > $index) {
513  $this->answers[$i]->setOrder($i);
514  }
515  }
516  }
517 
524  public function flushAnswers()
525  {
526  $this->answers = array();
527  }
528 
535  public function getMaximumPoints()
536  {
537  $points = 0;
538  foreach ($this->answers as $key => $value) {
539  if ($value->getPoints() > $points) {
540  $points = $value->getPoints();
541  }
542  }
543  return $points;
544  }
545 
556  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
557  {
558  if ($returndetails) {
559  throw new ilTestException('return details not implemented for ' . __METHOD__);
560  }
561 
562  global $DIC;
563  $ilDB = $DIC['ilDB'];
564 
565  $found_values = array();
566  if (is_null($pass)) {
567  $pass = $this->getSolutionMaxPass($active_id);
568  }
569  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
570  while ($data = $ilDB->fetchAssoc($result)) {
571  if (strcmp($data["value1"], "") != 0) {
572  array_push($found_values, $data["value1"]);
573  }
574  }
575  $points = 0;
576  foreach ($this->answers as $key => $answer) {
577  if (count($found_values) > 0) {
578  if (in_array($key, $found_values)) {
579  $points += $answer->getPoints();
580  }
581  }
582  }
583 
584  return $points;
585  }
586 
588  {
589  $participantSolution = $previewSession->getParticipantsSolution();
590 
591  $points = 0;
592 
593  foreach ($this->answers as $key => $answer) {
594  if (is_numeric($participantSolution) && $key == $participantSolution) {
595  $points = $answer->getPoints();
596  }
597  }
598 
599  $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
600 
601  return $this->ensureNonNegativePoints($reachedPoints);
602  }
603 
612  public function saveWorkingData($active_id, $pass = null, $authorized = true)
613  {
614  global $DIC;
615  $ilDB = $DIC['ilDB'];
616  $ilUser = $DIC['ilUser'];
617 
618  if (is_null($pass)) {
619  include_once "./Modules/Test/classes/class.ilObjTest.php";
620  $pass = ilObjTest::_getPass($active_id);
621  }
622 
623  $entered_values = 0;
624 
625  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $ilDB, $active_id, $pass, $authorized) {
626  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized);
627  $row = $ilDB->fetchAssoc($result);
628  $update = $row["solution_id"];
629 
630  if ($update) {
631  if (strlen($_POST["multiple_choice_result"])) {
632  $this->updateCurrentSolution($update, $_POST["multiple_choice_result"], null, $authorized);
633  $entered_values++;
634  } else {
635  $this->removeSolutionRecordById($update);
636  }
637  } else {
638  if (strlen($_POST["multiple_choice_result"])) {
639  $this->saveCurrentSolution($active_id, $pass, $_POST['multiple_choice_result'], null, $authorized);
640  $entered_values++;
641  }
642  }
643  });
644 
645  if ($entered_values) {
646  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
648  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
649  }
650  } else {
651  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
653  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
654  }
655  }
656 
657  return true;
658  }
659 
660  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
661  {
662  if (strlen($_POST['multiple_choice_result' . $this->getId() . 'ID'])) {
663  $previewSession->setParticipantsSolution($_POST['multiple_choice_result' . $this->getId() . 'ID']);
664  } else {
665  $previewSession->setParticipantsSolution(null);
666  }
667  }
668 
669  public function saveAdditionalQuestionDataToDb()
670  {
672  global $DIC;
673  $ilDB = $DIC['ilDB'];
674 
675  // save additional data
676  $ilDB->manipulateF(
677  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
678  array( "integer" ),
679  array( $this->getId() )
680  );
681 
682  $ilDB->manipulateF(
683  "INSERT INTO " . $this->getAdditionalTableName(
684  ) . " (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
685  array( "integer", "text", "text", "integer" ),
686  array(
687  $this->getId(),
688  $this->getShuffle(),
689  ($this->isSingleline) ? "0" : "1",
690  (strlen($this->getThumbSize()) == 0) ? null : $this->getThumbSize()
691  )
692  );
693  }
694 
695  public function saveAnswerSpecificDataToDb()
696  {
698  global $DIC;
699  $ilDB = $DIC['ilDB'];
700  if (!$this->isSingleline) {
701  ilUtil::delDir($this->getImagePath());
702  }
703  $ilDB->manipulateF(
704  "DELETE FROM qpl_a_sc WHERE question_fi = %s",
705  array( 'integer' ),
706  array( $this->getId() )
707  );
708 
709  foreach ($this->answers as $key => $value) {
711  $answer_obj = $this->answers[$key];
712  $next_id = $ilDB->nextId('qpl_a_sc');
713  $ilDB->manipulateF(
714  "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
715  array( 'integer', 'integer', 'text', 'float', 'integer', 'text', 'integer' ),
716  array(
717  $next_id,
718  $this->getId(),
719  ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 0),
720  $answer_obj->getPoints(),
721  $answer_obj->getOrder(),
722  $answer_obj->getImage(),
723  time()
724  )
725  );
726  }
727  $this->rebuildThumbnails();
728  }
729 
736  public function getQuestionType()
737  {
738  return "assSingleChoice";
739  }
740 
747  public function getAdditionalTableName()
748  {
749  return "qpl_qst_sc";
750  }
751 
758  public function getAnswerTableName()
759  {
760  return "qpl_a_sc";
761  }
762 
771  public function setImageFile($image_filename, $image_tempfilename = "")
772  {
773  $result = 0;
774  if (!empty($image_tempfilename)) {
775  $image_filename = str_replace(" ", "_", $image_filename);
776  $imagepath = $this->getImagePath();
777  if (!file_exists($imagepath)) {
778  ilUtil::makeDirParents($imagepath);
779  }
780  //if (!move_uploaded_file($image_tempfilename, $imagepath . $image_filename))
781  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath . $image_filename)) {
782  $result = 2;
783  } else {
784  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
785  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
786  if (!preg_match("/^image/", $mimetype)) {
787  unlink($imagepath . $image_filename);
788  $result = 1;
789  } else {
790  // create thumbnail file
791  if ($this->isSingleline && ($this->getThumbSize())) {
792  $this->generateThumbForFile($imagepath, $image_filename);
793  }
794  }
795  }
796  }
797  return $result;
798  }
799 
806  public function deleteImage($image_filename)
807  {
808  $imagepath = $this->getImagePath();
809  @unlink($imagepath . $image_filename);
810  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
811  @unlink($thumbpath);
812  }
813 
814  public function duplicateImages($question_id, $objectId = null)
815  {
816  global $DIC;
817  $ilLog = $DIC['ilLog'];
818  $imagepath = $this->getImagePath();
819  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
820 
821  if ((int) $objectId > 0) {
822  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
823  }
824 
825  foreach ($this->answers as $answer) {
826  $filename = $answer->getImage();
827  if (strlen($filename)) {
828  if (!file_exists($imagepath)) {
829  ilUtil::makeDirParents($imagepath);
830  }
831  if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
832  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
833  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
834  }
835  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
836  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
837  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
838  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
839  }
840  }
841  }
842  }
843  }
844 
845  public function copyImages($question_id, $source_questionpool)
846  {
848  global $DIC;
849  $ilLog = $DIC['ilLog'];
850 
851  $imagepath = $this->getImagePath();
852  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
853  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
854  foreach ($this->answers as $answer) {
855  $filename = $answer->getImage();
856  if (strlen($filename)) {
857  if (!file_exists($imagepath)) {
858  ilUtil::makeDirParents($imagepath);
859  }
860 
861  if (file_exists($imagepath_original . $filename)) {
862  if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
863  $ilLog->warning(sprintf(
864  "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
865  $imagepath_original . $filename,
866  $imagepath . $filename,
867  $question_id,
868  $this->id,
869  $source_questionpool,
870  $this->obj_id
871  ));
872  }
873  }
874 
875  if (file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
876  if (!copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
877  $ilLog->warning(sprintf(
878  "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
879  $imagepath_original . $this->getThumbPrefix() . $filename,
880  $imagepath . $this->getThumbPrefix() . $filename,
881  $question_id,
882  $this->id,
883  $source_questionpool,
884  $this->obj_id
885  ));
886  }
887  }
888  }
889  }
890  }
891 
895  protected function syncImages()
896  {
897  global $DIC;
898  $ilLog = $DIC['ilLog'];
899  $question_id = $this->getOriginalId();
900  $imagepath = $this->getImagePath();
901  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
902  ilUtil::delDir($imagepath_original);
903  foreach ($this->answers as $answer) {
904  $filename = $answer->getImage();
905  if (strlen($filename)) {
906  if (@file_exists($imagepath . $filename)) {
907  if (!file_exists($imagepath)) {
908  ilUtil::makeDirParents($imagepath);
909  }
910  if (!file_exists($imagepath_original)) {
911  ilUtil::makeDirParents($imagepath_original);
912  }
913  if (!@copy($imagepath . $filename, $imagepath_original . $filename)) {
914  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
915  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
916  }
917  }
918  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename)) {
919  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename)) {
920  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
921  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
922  }
923  }
924  }
925  }
926  }
927 
932  public function getRTETextWithMediaObjects()
933  {
934  $text = parent::getRTETextWithMediaObjects();
935  foreach ($this->answers as $index => $answer) {
936  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), 0, $index);
937  $answer_obj = $this->answers[$index];
938  $text .= $answer_obj->getAnswertext();
939  }
940  return $text;
941  }
942 
946  public function &getAnswers()
947  {
948  return $this->answers;
949  }
950 
954  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
955  {
956  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
957 
958  $solution = $this->getSolutionValues($active_id, $pass);
959  $i = 1;
960  foreach ($this->getAnswers() as $id => $answer) {
961  $worksheet->setCell($startrow + $i, 0, $answer->getAnswertext());
962  $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
963  if (
964  count($solution) > 0 &&
965  isset($solution[0]) &&
966  is_array($solution[0]) &&
967  strlen($solution[0]['value1']) > 0 && $id == $solution[0]['value1']
968  ) {
969  $worksheet->setCell($startrow + $i, 1, 1);
970  } else {
971  $worksheet->setCell($startrow + $i, 1, 0);
972  }
973  $i++;
974  }
975 
976  return $startrow + $i + 1;
977  }
978 
979  public function getThumbSize()
980  {
981  return $this->thumb_size;
982  }
983 
984  public function setThumbSize($a_size)
985  {
986  $this->thumb_size = $a_size;
987  }
988 
993  {
994  foreach ($this->getAnswers() as $answer) {
995  /* @var ASS_AnswerBinaryStateImage $answer */
996  $answer->setAnswertext($migrator->migrateToLmContent($answer->getAnswertext()));
997  }
998  }
999 
1003  public function toJSON()
1004  {
1005  include_once("./Services/RTE/classes/class.ilRTE.php");
1006  $result = array();
1007  $result['id'] = (int) $this->getId();
1008  $result['type'] = (string) $this->getQuestionType();
1009  $result['title'] = (string) $this->getTitle();
1010  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1011  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1012  $result['shuffle'] = (bool) $this->getShuffle();
1013 
1014  $result['feedback'] = array(
1015  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1016  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1017  );
1018 
1019  $answers = array();
1020  $has_image = false;
1021  foreach ($this->getAnswers() as $key => $answer_obj) {
1022  if ((string) $answer_obj->getImage()) {
1023  $has_image = true;
1024  }
1025  array_push($answers, array(
1026  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1027  'html_id' => (int) $this->getId() . '_' . $key,
1028  "points" => (float) $answer_obj->getPoints(),
1029  "order" => (int) $answer_obj->getOrder(),
1030  "image" => (string) $answer_obj->getImage(),
1031  "feedback" => $this->formatSAQuestion(
1032  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
1033  )
1034  ));
1035  }
1036  $result['answers'] = $answers;
1037  if ($has_image) {
1038  $result['path'] = $this->getImagePathWeb();
1039  $result['thumb'] = $this->getThumbSize();
1040  }
1041 
1042  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1043  $result['mobs'] = $mobs;
1044 
1045  return json_encode($result);
1046  }
1047 
1048  public function removeAnswerImage($index)
1049  {
1050  $answer = $this->answers[$index];
1051  if (is_object($answer)) {
1052  $this->deleteImage($answer->getImage());
1053  $answer->setImage('');
1054  }
1055  }
1056 
1057  public function getMultilineAnswerSetting()
1058  {
1059  global $DIC;
1060  $ilUser = $DIC['ilUser'];
1061 
1062  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1063  if ($multilineAnswerSetting != 1) {
1064  $multilineAnswerSetting = 0;
1065  }
1066  return $multilineAnswerSetting;
1067  }
1068 
1069  public function setMultilineAnswerSetting($a_setting = 0)
1070  {
1071  global $DIC;
1072  $ilUser = $DIC['ilUser'];
1073  $ilUser->writePref("tst_multiline_answers", $a_setting);
1074  }
1075 
1085  public function setSpecificFeedbackSetting($a_feedback_setting)
1086  {
1087  $this->feedback_setting = $a_feedback_setting;
1088  }
1089 
1099  public function getSpecificFeedbackSetting()
1100  {
1101  if ($this->feedback_setting) {
1102  return $this->feedback_setting;
1103  } else {
1104  return 1;
1105  }
1106  }
1107 
1109  {
1110  return 'feedback_correct_sc_mc';
1111  }
1112 
1123  public function isAnswered($active_id, $pass = null)
1124  {
1125  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1126 
1127  return $numExistingSolutionRecords > 0;
1128  }
1129 
1140  public static function isObligationPossible($questionId)
1141  {
1142  return true;
1143  }
1144 
1153  public function getOperators($expression)
1154  {
1155  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1157  }
1158 
1163  public function getExpressionTypes()
1164  {
1165  return array(
1169  );
1170  }
1171 
1180  public function getUserQuestionResult($active_id, $pass)
1181  {
1183  global $DIC;
1184  $ilDB = $DIC['ilDB'];
1185  $result = new ilUserQuestionResult($this, $active_id, $pass);
1186 
1187  $maxStep = $this->lookupMaxStep($active_id, $pass);
1188 
1189  if ($maxStep !== null) {
1190  $data = $ilDB->queryF(
1191  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1192  array("integer", "integer", "integer","integer"),
1193  array($active_id, $pass, $this->getId(), $maxStep)
1194  );
1195  } else {
1196  $data = $ilDB->queryF(
1197  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1198  array("integer", "integer", "integer"),
1199  array($active_id, $pass, $this->getId())
1200  );
1201  }
1202 
1203  $row = $ilDB->fetchAssoc($data);
1204 
1205  if ($row != null) {
1206  ++$row["value1"];
1207  $result->addKeyValue($row["value1"], $row["value1"]);
1208  }
1209 
1210  $points = $this->calculateReachedPoints($active_id, $pass);
1211  $max_points = $this->getMaximumPoints();
1212 
1213  $result->setReachedPercentage(($points / $max_points) * 100);
1214 
1215  return $result;
1216  }
1217 
1226  public function getAvailableAnswerOptions($index = null)
1227  {
1228  if ($index !== null) {
1229  return $this->getAnswer($index);
1230  } else {
1231  return $this->getAnswers();
1232  }
1233  }
1234 
1238  protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1239  {
1240  parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1241 
1242  $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1243  $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1244 
1245  ilUtil::delDir($origImagePath);
1246  if (is_dir($dupImagePath)) {
1247  ilUtil::makeDirParents($origImagePath);
1248  ilUtil::rCopy($dupImagePath, $origImagePath);
1249  }
1250  }
1251 }
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getOutputType()
Gets the single choice output type which is either OUTPUT_ORDER (=0) or OUTPUT_RANDOM (=1)...
getId()
Gets the id of the assQuestion object.
saveToDb($original_id="")
Saves the question to the database.
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
generateThumbForFile($path, $file)
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
Class iQuestionCondition.
static getMimeType($a_file, $a_external=null)
get mime type for file
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static getNumExistingSolutionRecords($activeId, $pass, $questionId)
returns the number of existing solution records for the given test active / pass and given question i...
$data
Definition: storeScorm.php:23
$result
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
Abstract basic class which is to be extended by the concrete assessment question type classes...
Class for answers with a binary state indicator.
setOutputType($output_type=OUTPUT_ORDER)
Sets the output type of the assSingleChoice object.
setMultilineAnswerSetting($a_setting=0)
& getAnswers()
Returns a reference to the answers array.
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
{}
getAnswerCount()
Returns the number of answers.
ensureNonNegativePoints($points)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
isComplete()
Returns true, if a single choice question is complete for use.
setId($id=-1)
Sets the id of the assQuestion object.
copyObject($target_questionpool_id, $title="")
Copies an assSingleChoice object.
getQuestionType()
Returns the question type of the question.
getAnswerTableName()
Returns the name of the answer table in the database.
getImagePathWeb()
Returns the web image path for web accessable images of a question.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
loadFromDb($question_id)
Loads a assSingleChoice object from a database.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
setNrOfTries($a_nr_of_tries)
setSpecificFeedbackSetting($a_feedback_setting)
Sets the feedback settings in effect for the question.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assSingleChoiceQuestion.
getAnswer($index=0)
Returns an answer with a given index.
setShuffle($shuffle=true)
Sets the shuffle flag.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
getOperators($expression)
Get all available operations for a specific question.
getObjId()
Get the object id of the container object.
getShuffle()
Gets the shuffle flag.
Base Exception for all Exceptions relating to Modules/Test.
$index
Definition: metadata.php:128
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
getSpecificFeedbackSetting()
Gets the current feedback settings in effect for the question.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
removeSolutionRecordById($solutionId)
deleteImage($image_filename)
Deletes an image file.
static _getLogLanguage()
retrieve the log language for assessment logging
setAuthor($author="")
Sets the authors name of the assQuestion object.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
$mobs
Class ilUserQuestionResult.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{}
isAnswered($active_id, $pass=null)
returns boolean wether the question is answered during test pass or not
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
Class for single choice questions.
deleteAnswer($index=0)
Deletes an answer with a given index.
Interface ilObjAnswerScoringAdjustable.
toJSON()
Returns a JSON representation of the question.
addAnswer( $answertext="", $points=0.0, $order=0, $answerimage="")
Adds a possible answer for a single choice question.
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $output_type=OUTPUT_ORDER)
assSingleChoice constructor
getQuestion()
Gets the question string of the question object.
syncImages()
Sync images of a MC question on synchronisation with the original question.
static convertImage( $a_from, $a_to, $a_target_format="", $a_geometry="", $a_background_color="")
convert image
$ilUser
Definition: imgupload.php:18
flushAnswers()
Deletes all answers.
updateCurrentSolution($solutionId, $value1, $value2, $authorized=true)
getAdditionalTableName()
Returns the name of the additional question data table in the database.
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
$filename
Definition: buildRTE.php:89
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
setImageFile($image_filename, $image_tempfilename="")
Sets the image file and uploads the image to the object&#39;s image directory.
setQuestion($question="")
Sets the question string of the question object.
duplicateImages($question_id, $objectId=null)
Interface ilObjQuestionScoringAdjustable.
__construct(Container $dic, ilPlugin $plugin)
buildImagePath($questionId, $parentObjectId)
global $ilDB
setOriginalId($original_id)
$DIC
Definition: xapitoken.php:46
getExpressionTypes()
Get all available expression types for a specific question.
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getTitle()
Gets the title string of the assQuestion object.
const OUTPUT_ORDER
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
setTitle($title="")
Sets the title string of the assQuestion object.
setObjId($obj_id=0)
Set the object id of the container object.
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
setComment($comment="")
Sets the comment string of the assQuestion object.
$_POST["username"]
savePreviewData(ilAssQuestionPreviewSession $previewSession)
$i
Definition: metadata.php:24
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.