ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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  ) {
83  parent::__construct($title, $comment, $author, $owner, $question);
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 {
230  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
231  } catch (ilTestQuestionPoolException $e) {
232  }
233  }
234 
235  $result = $ilDB->queryF(
236  "SELECT * FROM qpl_a_sc WHERE question_fi = %s ORDER BY aorder ASC",
237  array('integer'),
238  array($question_id)
239  );
240  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
241  if ($result->numRows() > 0) {
242  while ($data = $ilDB->fetchAssoc($result)) {
243  $imagefilename = $this->getImagePath() . $data["imagefile"];
244  if (!@file_exists($imagefilename)) {
245  $data["imagefile"] = "";
246  }
247  include_once("./Services/RTE/classes/class.ilRTE.php");
248  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
249  array_push($this->answers, new ASS_AnswerBinaryStateImage($data["answertext"], $data["points"], $data["aorder"], 1, $data["imagefile"]));
250  }
251  }
252 
253  parent::loadFromDb($question_id);
254  }
255 
261  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
262  {
263  if ($this->id <= 0) {
264  // The question has not been saved. It cannot be duplicated
265  return;
266  }
267  // duplicate the question in database
268  $this_id = $this->getId();
269  $thisObjId = $this->getObjId();
270 
271  $clone = $this;
272  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
274  $clone->id = -1;
275 
276  if ((int) $testObjId > 0) {
277  $clone->setObjId($testObjId);
278  }
279 
280  if ($title) {
281  $clone->setTitle($title);
282  }
283 
284  if ($author) {
285  $clone->setAuthor($author);
286  }
287  if ($owner) {
288  $clone->setOwner($owner);
289  }
290  if ($for_test) {
291  $clone->saveToDb($original_id);
292  } else {
293  $clone->saveToDb();
294  }
295 
296  // copy question page content
297  $clone->copyPageOfQuestion($this_id);
298 
299  // copy XHTML media objects
300  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
301  // duplicate the images
302  $clone->duplicateImages($this_id, $thisObjId);
303 
304  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
305 
306  return $clone->id;
307  }
308 
314  public function copyObject($target_questionpool_id, $title = "")
315  {
316  if ($this->id <= 0) {
317  // The question has not been saved. It cannot be duplicated
318  return;
319  }
320  // duplicate the question in database
321  $clone = $this;
322  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
324  $clone->id = -1;
325  $source_questionpool_id = $this->getObjId();
326  $clone->setObjId($target_questionpool_id);
327  if ($title) {
328  $clone->setTitle($title);
329  }
330  $clone->saveToDb();
331  // copy question page content
332  $clone->copyPageOfQuestion($original_id);
333  // copy XHTML media objects
334  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
335  // duplicate the image
336  $clone->copyImages($original_id, $source_questionpool_id);
337 
338  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
339 
340  return $clone->id;
341  }
342 
343  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
344  {
345  if ($this->id <= 0) {
346  // The question has not been saved. It cannot be duplicated
347  return;
348  }
349 
350  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
351 
352  $sourceQuestionId = $this->id;
353  $sourceParentId = $this->getObjId();
354 
355  // duplicate the question in database
356  $clone = $this;
357  $clone->id = -1;
358 
359  $clone->setObjId($targetParentId);
360 
361  if ($targetQuestionTitle) {
362  $clone->setTitle($targetQuestionTitle);
363  }
364 
365  $clone->saveToDb();
366  // copy question page content
367  $clone->copyPageOfQuestion($sourceQuestionId);
368  // copy XHTML media objects
369  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
370  // duplicate the image
371  $clone->copyImages($sourceQuestionId, $sourceParentId);
372 
373  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
374 
375  return $clone->id;
376  }
377 
385  public function getOutputType()
386  {
387  return $this->output_type;
388  }
389 
398  {
399  $this->output_type = $output_type;
400  }
401 
415  public function addAnswer(
416  $answertext = "",
417  $points = 0.0,
418  $order = 0,
419  $answerimage = ""
420  ) {
421  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
422  if (array_key_exists($order, $this->answers)) {
423  // insert answer
424  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, $order, 1, $answerimage);
425  $newchoices = array();
426  for ($i = 0; $i < $order; $i++) {
427  array_push($newchoices, $this->answers[$i]);
428  }
429  array_push($newchoices, $answer);
430  for ($i = $order; $i < count($this->answers); $i++) {
431  $changed = $this->answers[$i];
432  $changed->setOrder($i + 1);
433  array_push($newchoices, $changed);
434  }
435  $this->answers = $newchoices;
436  } else {
437  // add answer
438  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, count($this->answers), 1, $answerimage);
439  array_push($this->answers, $answer);
440  }
441  }
442 
450  public function getAnswerCount()
451  {
452  return count($this->answers);
453  }
454 
464  public function getAnswer($index = 0)
465  {
466  if ($index < 0) {
467  return null;
468  }
469  if (count($this->answers) < 1) {
470  return null;
471  }
472  if ($index >= count($this->answers)) {
473  return null;
474  }
475 
476  return $this->answers[$index];
477  }
478 
487  public function deleteAnswer($index = 0)
488  {
489  if ($index < 0) {
490  return;
491  }
492  if (count($this->answers) < 1) {
493  return;
494  }
495  if ($index >= count($this->answers)) {
496  return;
497  }
498  $answer = $this->answers[$index];
499  if (strlen($answer->getImage())) {
500  $this->deleteImage($answer->getImage());
501  }
502  unset($this->answers[$index]);
503  $this->answers = array_values($this->answers);
504  for ($i = 0; $i < count($this->answers); $i++) {
505  if ($this->answers[$i]->getOrder() > $index) {
506  $this->answers[$i]->setOrder($i);
507  }
508  }
509  }
510 
517  public function flushAnswers()
518  {
519  $this->answers = array();
520  }
521 
528  public function getMaximumPoints()
529  {
530  $points = 0;
531  foreach ($this->answers as $key => $value) {
532  if ($value->getPoints() > $points) {
533  $points = $value->getPoints();
534  }
535  }
536  return $points;
537  }
538 
549  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
550  {
551  if ($returndetails) {
552  throw new ilTestException('return details not implemented for ' . __METHOD__);
553  }
554 
555  global $DIC;
556  $ilDB = $DIC['ilDB'];
557 
558  $found_values = array();
559  if (is_null($pass)) {
560  $pass = $this->getSolutionMaxPass($active_id);
561  }
562  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
563  while ($data = $ilDB->fetchAssoc($result)) {
564  if (strcmp($data["value1"], "") != 0) {
565  array_push($found_values, $data["value1"]);
566  }
567  }
568  $points = 0;
569  foreach ($this->answers as $key => $answer) {
570  if (count($found_values) > 0) {
571  if (in_array($key, $found_values)) {
572  $points += $answer->getPoints();
573  }
574  }
575  }
576 
577  return $points;
578  }
579 
581  {
582  $participantSolution = $previewSession->getParticipantsSolution();
583 
584  $points = 0;
585 
586  foreach ($this->answers as $key => $answer) {
587  if (is_numeric($participantSolution) && $key == $participantSolution) {
588  $points = $answer->getPoints();
589  }
590  }
591 
592  $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
593 
594  return $this->ensureNonNegativePoints($reachedPoints);
595  }
596 
605  public function saveWorkingData($active_id, $pass = null, $authorized = true)
606  {
607  global $DIC;
608  $ilDB = $DIC['ilDB'];
609  $ilUser = $DIC['ilUser'];
610 
611  if (is_null($pass)) {
612  include_once "./Modules/Test/classes/class.ilObjTest.php";
613  $pass = ilObjTest::_getPass($active_id);
614  }
615 
616  $entered_values = 0;
617 
618  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $ilDB, $active_id, $pass, $authorized) {
619  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized);
620  $row = $ilDB->fetchAssoc($result);
621  $update = $row["solution_id"];
622 
623  if ($update) {
624  if (strlen($_POST["multiple_choice_result"])) {
625  $this->updateCurrentSolution($update, $_POST["multiple_choice_result"], null, $authorized);
626  $entered_values++;
627  } else {
628  $this->removeSolutionRecordById($update);
629  }
630  } else {
631  if (strlen($_POST["multiple_choice_result"])) {
632  $this->saveCurrentSolution($active_id, $pass, $_POST['multiple_choice_result'], null, $authorized);
633  $entered_values++;
634  }
635  }
636  });
637 
638  if ($entered_values) {
639  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
641  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
642  }
643  } else {
644  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
646  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
647  }
648  }
649 
650  return true;
651  }
652 
653  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
654  {
655  if (strlen($_POST['multiple_choice_result' . $this->getId() . 'ID'])) {
656  $previewSession->setParticipantsSolution($_POST['multiple_choice_result' . $this->getId() . 'ID']);
657  } else {
658  $previewSession->setParticipantsSolution(null);
659  }
660  }
661 
662  public function saveAdditionalQuestionDataToDb()
663  {
665  global $DIC;
666  $ilDB = $DIC['ilDB'];
667 
668  // save additional data
669  $ilDB->manipulateF(
670  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
671  array( "integer" ),
672  array( $this->getId() )
673  );
674 
675  $ilDB->manipulateF(
676  "INSERT INTO " . $this->getAdditionalTableName(
677  ) . " (question_fi, shuffle, allow_images, thumb_size, feedback_setting) VALUES (%s, %s, %s, %s, %s)",
678  array( "integer", "text", "text", "integer", 'integer' ),
679  array(
680  $this->getId(),
681  $this->getShuffle(),
682  ($this->isSingleline) ? "0" : "1",
683  (strlen($this->getThumbSize()) == 0) ? null : $this->getThumbSize(),
684  (int) $this->getSpecificFeedbackSetting()
685  )
686  );
687  }
688 
689  public function saveAnswerSpecificDataToDb()
690  {
692  global $DIC;
693  $ilDB = $DIC['ilDB'];
694  if (!$this->isSingleline) {
695  ilUtil::delDir($this->getImagePath());
696  }
697  $ilDB->manipulateF(
698  "DELETE FROM qpl_a_sc WHERE question_fi = %s",
699  array( 'integer' ),
700  array( $this->getId() )
701  );
702 
703  foreach ($this->answers as $key => $value) {
705  $answer_obj = $this->answers[$key];
706  $next_id = $ilDB->nextId('qpl_a_sc');
707  $ilDB->manipulateF(
708  "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
709  array( 'integer', 'integer', 'text', 'float', 'integer', 'text', 'integer' ),
710  array(
711  $next_id,
712  $this->getId(),
713  ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 0),
714  $answer_obj->getPoints(),
715  $answer_obj->getOrder(),
716  $answer_obj->getImage(),
717  time()
718  )
719  );
720  }
721  $this->rebuildThumbnails();
722  }
723 
730  public function getQuestionType()
731  {
732  return "assSingleChoice";
733  }
734 
741  public function getAdditionalTableName()
742  {
743  return "qpl_qst_sc";
744  }
745 
752  public function getAnswerTableName()
753  {
754  return "qpl_a_sc";
755  }
756 
765  public function setImageFile($image_filename, $image_tempfilename = "")
766  {
767  $result = 0;
768  if (!empty($image_tempfilename)) {
769  $image_filename = str_replace(" ", "_", $image_filename);
770  $imagepath = $this->getImagePath();
771  if (!file_exists($imagepath)) {
772  ilUtil::makeDirParents($imagepath);
773  }
774  //if (!move_uploaded_file($image_tempfilename, $imagepath . $image_filename))
775  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath . $image_filename)) {
776  $result = 2;
777  } else {
778  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
779  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
780  if (!preg_match("/^image/", $mimetype)) {
781  unlink($imagepath . $image_filename);
782  $result = 1;
783  } else {
784  // create thumbnail file
785  if ($this->isSingleline && ($this->getThumbSize())) {
786  $this->generateThumbForFile($imagepath, $image_filename);
787  }
788  }
789  }
790  }
791  return $result;
792  }
793 
800  public function deleteImage($image_filename)
801  {
802  $imagepath = $this->getImagePath();
803  @unlink($imagepath . $image_filename);
804  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
805  @unlink($thumbpath);
806  }
807 
808  public function duplicateImages($question_id, $objectId = null)
809  {
810  global $DIC;
811  $ilLog = $DIC['ilLog'];
812  $imagepath = $this->getImagePath();
813  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
814 
815  if ((int) $objectId > 0) {
816  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
817  }
818 
819  foreach ($this->answers as $answer) {
820  $filename = $answer->getImage();
821  if (strlen($filename)) {
822  if (!file_exists($imagepath)) {
823  ilUtil::makeDirParents($imagepath);
824  }
825  if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
826  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
827  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
828  }
829  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
830  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
831  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
832  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
833  }
834  }
835  }
836  }
837  }
838 
839  public function copyImages($question_id, $source_questionpool)
840  {
842  global $DIC;
843  $ilLog = $DIC['ilLog'];
844 
845  $imagepath = $this->getImagePath();
846  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
847  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
848  foreach ($this->answers as $answer) {
849  $filename = $answer->getImage();
850  if (strlen($filename)) {
851  if (!file_exists($imagepath)) {
852  ilUtil::makeDirParents($imagepath);
853  }
854 
855  if (file_exists($imagepath_original . $filename)) {
856  if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
857  $ilLog->warning(sprintf(
858  "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
859  $imagepath_original . $filename,
860  $imagepath . $filename,
861  $question_id,
862  $this->id,
863  $source_questionpool,
864  $this->obj_id
865  ));
866  }
867  }
868 
869  if (file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
870  if (!copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
871  $ilLog->warning(sprintf(
872  "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
873  $imagepath_original . $this->getThumbPrefix() . $filename,
874  $imagepath . $this->getThumbPrefix() . $filename,
875  $question_id,
876  $this->id,
877  $source_questionpool,
878  $this->obj_id
879  ));
880  }
881  }
882  }
883  }
884  }
885 
889  protected function syncImages()
890  {
891  global $DIC;
892  $ilLog = $DIC['ilLog'];
893  $question_id = $this->getOriginalId();
894  $imagepath = $this->getImagePath();
895  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
896  ilUtil::delDir($imagepath_original);
897  foreach ($this->answers as $answer) {
898  $filename = $answer->getImage();
899  if (strlen($filename)) {
900  if (@file_exists($imagepath . $filename)) {
901  if (!file_exists($imagepath)) {
902  ilUtil::makeDirParents($imagepath);
903  }
904  if (!file_exists($imagepath_original)) {
905  ilUtil::makeDirParents($imagepath_original);
906  }
907  if (!@copy($imagepath . $filename, $imagepath_original . $filename)) {
908  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
909  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
910  }
911  }
912  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename)) {
913  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename)) {
914  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
915  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
916  }
917  }
918  }
919  }
920  }
921 
926  public function getRTETextWithMediaObjects()
927  {
928  $text = parent::getRTETextWithMediaObjects();
929  foreach ($this->answers as $index => $answer) {
930  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), 0, $index);
931  $answer_obj = $this->answers[$index];
932  $text .= $answer_obj->getAnswertext();
933  }
934  return $text;
935  }
936 
940  public function &getAnswers()
941  {
942  return $this->answers;
943  }
944 
948  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
949  {
950  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
951 
952  $solution = $this->getSolutionValues($active_id, $pass);
953  $i = 1;
954  foreach ($this->getAnswers() as $id => $answer) {
955  $worksheet->setCell($startrow + $i, 0, $answer->getAnswertext());
956  $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
957  if (
958  count($solution) > 0 &&
959  isset($solution[0]) &&
960  is_array($solution[0]) &&
961  strlen($solution[0]['value1']) > 0 && $id == $solution[0]['value1']
962  ) {
963  $worksheet->setCell($startrow + $i, 1, 1);
964  } else {
965  $worksheet->setCell($startrow + $i, 1, 0);
966  }
967  $i++;
968  }
969 
970  return $startrow + $i + 1;
971  }
972 
973  public function getThumbSize()
974  {
975  return $this->thumb_size;
976  }
977 
978  public function setThumbSize($a_size)
979  {
980  $this->thumb_size = $a_size;
981  }
982 
987  {
988  foreach ($this->getAnswers() as $answer) {
989  /* @var ASS_AnswerBinaryStateImage $answer */
990  $answer->setAnswertext($migrator->migrateToLmContent($answer->getAnswertext()));
991  }
992  }
993 
997  public function toJSON()
998  {
999  include_once("./Services/RTE/classes/class.ilRTE.php");
1000  $result = array();
1001  $result['id'] = (int) $this->getId();
1002  $result['type'] = (string) $this->getQuestionType();
1003  $result['title'] = (string) $this->getTitle();
1004  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1005  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1006  $result['shuffle'] = (bool) $this->getShuffle();
1007 
1008  $result['feedback'] = array(
1009  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1010  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1011  );
1012 
1013  $answers = array();
1014  $has_image = false;
1015  foreach ($this->getAnswers() as $key => $answer_obj) {
1016  if ((string) $answer_obj->getImage()) {
1017  $has_image = true;
1018  }
1019  array_push($answers, array(
1020  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1021  'html_id' => (int) $this->getId() . '_' . $key,
1022  "points" => (float) $answer_obj->getPoints(),
1023  "order" => (int) $answer_obj->getOrder(),
1024  "image" => (string) $answer_obj->getImage(),
1025  "feedback" => $this->formatSAQuestion(
1026  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
1027  )
1028  ));
1029  }
1030  $result['answers'] = $answers;
1031  if ($has_image) {
1032  $result['path'] = $this->getImagePathWeb();
1033  $result['thumb'] = $this->getThumbSize();
1034  }
1035 
1036  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1037  $result['mobs'] = $mobs;
1038 
1039  return json_encode($result);
1040  }
1041 
1042  public function removeAnswerImage($index)
1043  {
1044  $answer = $this->answers[$index];
1045  if (is_object($answer)) {
1046  $this->deleteImage($answer->getImage());
1047  $answer->setImage('');
1048  }
1049  }
1050 
1051  public function createRandomSolution($active_id, $pass)
1052  {
1053  $value = rand(0, count($this->answers) - 1);
1054  $_POST["multiple_choice_result"] = (strlen($value)) ? (string) $value : '0';
1055  $this->saveWorkingData($active_id, $pass);
1056  $this->calculateResultsFromSolution($active_id, $pass);
1057  }
1058 
1059  public function getMultilineAnswerSetting()
1060  {
1061  global $DIC;
1062  $ilUser = $DIC['ilUser'];
1063 
1064  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1065  if ($multilineAnswerSetting != 1) {
1066  $multilineAnswerSetting = 0;
1067  }
1068  return $multilineAnswerSetting;
1069  }
1070 
1071  public function setMultilineAnswerSetting($a_setting = 0)
1072  {
1073  global $DIC;
1074  $ilUser = $DIC['ilUser'];
1075  $ilUser->writePref("tst_multiline_answers", $a_setting);
1076  }
1077 
1087  public function setSpecificFeedbackSetting($a_feedback_setting)
1088  {
1089  $this->feedback_setting = $a_feedback_setting;
1090  }
1091 
1101  public function getSpecificFeedbackSetting()
1102  {
1103  if ($this->feedback_setting) {
1104  return $this->feedback_setting;
1105  } else {
1106  return 1;
1107  }
1108  }
1109 
1111  {
1112  return 'feedback_correct_sc_mc';
1113  }
1114 
1125  public function isAnswered($active_id, $pass = null)
1126  {
1127  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1128 
1129  return $numExistingSolutionRecords > 0;
1130  }
1131 
1142  public static function isObligationPossible($questionId)
1143  {
1144  return true;
1145  }
1146 
1155  public function getOperators($expression)
1156  {
1157  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1159  }
1160 
1165  public function getExpressionTypes()
1166  {
1167  return array(
1171  );
1172  }
1173 
1182  public function getUserQuestionResult($active_id, $pass)
1183  {
1185  global $DIC;
1186  $ilDB = $DIC['ilDB'];
1187  $result = new ilUserQuestionResult($this, $active_id, $pass);
1188 
1189  $maxStep = $this->lookupMaxStep($active_id, $pass);
1190 
1191  if ($maxStep !== null) {
1192  $data = $ilDB->queryF(
1193  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1194  array("integer", "integer", "integer","integer"),
1195  array($active_id, $pass, $this->getId(), $maxStep)
1196  );
1197  } else {
1198  $data = $ilDB->queryF(
1199  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1200  array("integer", "integer", "integer"),
1201  array($active_id, $pass, $this->getId())
1202  );
1203  }
1204 
1205  $row = $ilDB->fetchAssoc($data);
1206 
1207  if ($row != null) {
1208  ++$row["value1"];
1209  $result->addKeyValue($row["value1"], $row["value1"]);
1210  }
1211 
1212  $points = $this->calculateReachedPoints($active_id, $pass);
1213  $max_points = $this->getMaximumPoints();
1214 
1215  $result->setReachedPercentage(($points / $max_points) * 100);
1216 
1217  return $result;
1218  }
1219 
1228  public function getAvailableAnswerOptions($index = null)
1229  {
1230  if ($index !== null) {
1231  return $this->getAnswer($index);
1232  } else {
1233  return $this->getAnswers();
1234  }
1235  }
1236 
1240  protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1241  {
1242  parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1243 
1244  $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1245  $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1246 
1247  ilUtil::delDir($origImagePath);
1248  if (is_dir($dupImagePath)) {
1249  ilUtil::makeDirParents($origImagePath);
1250  ilUtil::rCopy($dupImagePath, $origImagePath);
1251  }
1252  }
1253 }
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)
$path
Definition: aliased.php:25
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...
$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.
global $DIC
Definition: saml.php:7
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)
calculateResultsFromSolution($active_id, $pass=null, $obligationsEnabled=false)
Calculates the question results from a previously saved question solution.
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. ...
$index
Definition: metadata.php:60
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.
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.
createRandomSolution($active_id, $pass)
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)
Class for single choice questions.
deleteAnswer($index=0)
Deletes an answer with a given index.
$text
Definition: errorreport.php:18
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
$row
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.
buildImagePath($questionId, $parentObjectId)
global $ilDB
setOriginalId($original_id)
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...
$i
Definition: disco.tpl.php:19
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
$key
Definition: croninfo.php:18
setComment($comment="")
Sets the comment string of the assQuestion object.
$_POST["username"]
savePreviewData(ilAssQuestionPreviewSession $previewSession)
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
$data
Definition: bench.php:6