ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 $ilDB;
121 
123 
124  // kann das weg?
125  $oldthumbsize = 0;
126  if ($this->isSingleline && ($this->getThumbSize())) {
127  // get old thumbnail size
128  $result = $ilDB->queryF(
129  "SELECT thumb_size FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
130  array("integer"),
131  array($this->getId())
132  );
133  if ($result->numRows() == 1) {
134  $data = $ilDB->fetchAssoc($result);
135  $oldthumbsize = $data['thumb_size'];
136  }
137  }
138 
139 
141 
143 
144  parent::saveToDb($original_id);
145  }
146 
147  /*
148  * Rebuild the thumbnail images with a new thumbnail size
149  */
150  protected function rebuildThumbnails()
151  {
152  if ($this->isSingleline && ($this->getThumbSize())) {
153  foreach ($this->getAnswers() as $answer) {
154  if (strlen($answer->getImage())) {
155  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
156  }
157  }
158  }
159  }
160 
161  public function getThumbPrefix()
162  {
163  return "thumb.";
164  }
165 
166  protected function generateThumbForFile($path, $file)
167  {
168  $filename = $path . $file;
169  if (@file_exists($filename)) {
170  $thumbpath = $path . $this->getThumbPrefix() . $file;
171  $path_info = @pathinfo($filename);
172  $ext = "";
173  switch (strtoupper($path_info['extension'])) {
174  case 'PNG':
175  $ext = 'PNG';
176  break;
177  case 'GIF':
178  $ext = 'GIF';
179  break;
180  default:
181  $ext = 'JPEG';
182  break;
183  }
184  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
185  }
186  }
187 
195  public function loadFromDb($question_id)
196  {
197  global $ilDB;
198 
199  $hasimages = 0;
200 
201  $result = $ilDB->queryF(
202  "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",
203  array("integer"),
204  array($question_id)
205  );
206  if ($result->numRows() == 1) {
207  $data = $ilDB->fetchAssoc($result);
208  $this->setId($question_id);
209  $this->setObjId($data["obj_fi"]);
210  $this->setTitle($data["title"]);
211  $this->setNrOfTries($data['nr_of_tries']);
212  $this->setComment($data["description"]);
213  $this->setOriginalId($data["original_id"]);
214  $this->setAuthor($data["author"]);
215  $this->setPoints($data["points"]);
216  $this->setOwner($data["owner"]);
217  include_once("./Services/RTE/classes/class.ilRTE.php");
218  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
219  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
220  $this->setShuffle($shuffle);
221  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
222  $this->setThumbSize($data['thumb_size']);
223  $this->isSingleline = ($data['allow_images']) ? false : true;
224  $this->lastChange = $data['tstamp'];
225  $this->feedback_setting = $data['feedback_setting'];
226 
227  try {
228  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
229  } catch (ilTestQuestionPoolException $e) {
230  }
231  }
232 
233  $result = $ilDB->queryF(
234  "SELECT * FROM qpl_a_sc WHERE question_fi = %s ORDER BY aorder ASC",
235  array('integer'),
236  array($question_id)
237  );
238  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
239  if ($result->numRows() > 0) {
240  while ($data = $ilDB->fetchAssoc($result)) {
241  $imagefilename = $this->getImagePath() . $data["imagefile"];
242  if (!@file_exists($imagefilename)) {
243  $data["imagefile"] = "";
244  }
245  include_once("./Services/RTE/classes/class.ilRTE.php");
246  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
247  array_push($this->answers, new ASS_AnswerBinaryStateImage($data["answertext"], $data["points"], $data["aorder"], 1, $data["imagefile"]));
248  }
249  }
250 
251  parent::loadFromDb($question_id);
252  }
253 
259  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
260  {
261  if ($this->id <= 0) {
262  // The question has not been saved. It cannot be duplicated
263  return;
264  }
265  // duplicate the question in database
266  $this_id = $this->getId();
267  $thisObjId = $this->getObjId();
268 
269  $clone = $this;
270  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
272  $clone->id = -1;
273 
274  if ((int) $testObjId > 0) {
275  $clone->setObjId($testObjId);
276  }
277 
278  if ($title) {
279  $clone->setTitle($title);
280  }
281 
282  if ($author) {
283  $clone->setAuthor($author);
284  }
285  if ($owner) {
286  $clone->setOwner($owner);
287  }
288  if ($for_test) {
289  $clone->saveToDb($original_id);
290  } else {
291  $clone->saveToDb();
292  }
293 
294  // copy question page content
295  $clone->copyPageOfQuestion($this_id);
296 
297  // copy XHTML media objects
298  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
299  // duplicate the images
300  $clone->duplicateImages($this_id, $thisObjId);
301 
302  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
303 
304  return $clone->id;
305  }
306 
312  public function copyObject($target_questionpool_id, $title = "")
313  {
314  if ($this->id <= 0) {
315  // The question has not been saved. It cannot be duplicated
316  return;
317  }
318  // duplicate the question in database
319  $clone = $this;
320  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
322  $clone->id = -1;
323  $source_questionpool_id = $this->getObjId();
324  $clone->setObjId($target_questionpool_id);
325  if ($title) {
326  $clone->setTitle($title);
327  }
328  $clone->saveToDb();
329  // copy question page content
330  $clone->copyPageOfQuestion($original_id);
331  // copy XHTML media objects
332  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
333  // duplicate the image
334  $clone->copyImages($original_id, $source_questionpool_id);
335 
336  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
337 
338  return $clone->id;
339  }
340 
341  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
342  {
343  if ($this->id <= 0) {
344  // The question has not been saved. It cannot be duplicated
345  return;
346  }
347 
348  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
349 
350  $sourceQuestionId = $this->id;
351  $sourceParentId = $this->getObjId();
352 
353  // duplicate the question in database
354  $clone = $this;
355  $clone->id = -1;
356 
357  $clone->setObjId($targetParentId);
358 
359  if ($targetQuestionTitle) {
360  $clone->setTitle($targetQuestionTitle);
361  }
362 
363  $clone->saveToDb();
364  // copy question page content
365  $clone->copyPageOfQuestion($sourceQuestionId);
366  // copy XHTML media objects
367  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
368  // duplicate the image
369  $clone->copyImages($sourceQuestionId, $sourceParentId);
370 
371  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
372 
373  return $clone->id;
374  }
375 
383  public function getOutputType()
384  {
385  return $this->output_type;
386  }
387 
396  {
397  $this->output_type = $output_type;
398  }
399 
413  public function addAnswer(
414  $answertext = "",
415  $points = 0.0,
416  $order = 0,
417  $answerimage = ""
418  ) {
419  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
420  if (array_key_exists($order, $this->answers)) {
421  // insert answer
422  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, $order, 1, $answerimage);
423  $newchoices = array();
424  for ($i = 0; $i < $order; $i++) {
425  array_push($newchoices, $this->answers[$i]);
426  }
427  array_push($newchoices, $answer);
428  for ($i = $order; $i < count($this->answers); $i++) {
429  $changed = $this->answers[$i];
430  $changed->setOrder($i+1);
431  array_push($newchoices, $changed);
432  }
433  $this->answers = $newchoices;
434  } else {
435  // add answer
436  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, count($this->answers), 1, $answerimage);
437  array_push($this->answers, $answer);
438  }
439  }
440 
448  public function getAnswerCount()
449  {
450  return count($this->answers);
451  }
452 
462  public function getAnswer($index = 0)
463  {
464  if ($index < 0) {
465  return null;
466  }
467  if (count($this->answers) < 1) {
468  return null;
469  }
470  if ($index >= count($this->answers)) {
471  return null;
472  }
473 
474  return $this->answers[$index];
475  }
476 
485  public function deleteAnswer($index = 0)
486  {
487  if ($index < 0) {
488  return;
489  }
490  if (count($this->answers) < 1) {
491  return;
492  }
493  if ($index >= count($this->answers)) {
494  return;
495  }
496  $answer = $this->answers[$index];
497  if (strlen($answer->getImage())) {
498  $this->deleteImage($answer->getImage());
499  }
500  unset($this->answers[$index]);
501  $this->answers = array_values($this->answers);
502  for ($i = 0; $i < count($this->answers); $i++) {
503  if ($this->answers[$i]->getOrder() > $index) {
504  $this->answers[$i]->setOrder($i);
505  }
506  }
507  }
508 
515  public function flushAnswers()
516  {
517  $this->answers = array();
518  }
519 
526  public function getMaximumPoints()
527  {
528  $points = 0;
529  foreach ($this->answers as $key => $value) {
530  if ($value->getPoints() > $points) {
531  $points = $value->getPoints();
532  }
533  }
534  return $points;
535  }
536 
547  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
548  {
549  if ($returndetails) {
550  throw new ilTestException('return details not implemented for ' . __METHOD__);
551  }
552 
553  global $ilDB;
554 
555  $found_values = array();
556  if (is_null($pass)) {
557  $pass = $this->getSolutionMaxPass($active_id);
558  }
559  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
560  while ($data = $ilDB->fetchAssoc($result)) {
561  if (strcmp($data["value1"], "") != 0) {
562  array_push($found_values, $data["value1"]);
563  }
564  }
565  $points = 0;
566  foreach ($this->answers as $key => $answer) {
567  if (count($found_values) > 0) {
568  if (in_array($key, $found_values)) {
569  $points += $answer->getPoints();
570  }
571  }
572  }
573 
574  return $points;
575  }
576 
578  {
579  $participantSolution = $previewSession->getParticipantsSolution();
580 
581  $points = 0;
582 
583  foreach ($this->answers as $key => $answer) {
584  if (is_numeric($participantSolution) && $key == $participantSolution) {
585  $points = $answer->getPoints();
586  }
587  }
588 
589  $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
590 
591  return $this->ensureNonNegativePoints($reachedPoints);
592  }
593 
602  public function saveWorkingData($active_id, $pass = null, $authorized = true)
603  {
604  global $ilDB;
605  global $ilUser;
606 
607  if (is_null($pass)) {
608  include_once "./Modules/Test/classes/class.ilObjTest.php";
609  $pass = ilObjTest::_getPass($active_id);
610  }
611 
612  $entered_values = 0;
613 
614  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $ilDB, $active_id, $pass, $authorized) {
615  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized);
616  $row = $ilDB->fetchAssoc($result);
617  $update = $row["solution_id"];
618 
619  if ($update) {
620  if (strlen($_POST["multiple_choice_result"])) {
621  $this->updateCurrentSolution($update, $_POST["multiple_choice_result"], null, $authorized);
622  $entered_values++;
623  } else {
624  $this->removeSolutionRecordById($update);
625  }
626  } else {
627  if (strlen($_POST["multiple_choice_result"])) {
628  $this->saveCurrentSolution($active_id, $pass, $_POST['multiple_choice_result'], null, $authorized);
629  $entered_values++;
630  }
631  }
632  });
633 
634  if ($entered_values) {
635  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
637  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
638  }
639  } else {
640  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
642  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
643  }
644  }
645 
646  return true;
647  }
648 
649  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
650  {
651  if (strlen($_POST['multiple_choice_result' . $this->getId() . 'ID'])) {
652  $previewSession->setParticipantsSolution($_POST['multiple_choice_result' . $this->getId() . 'ID']);
653  } else {
654  $previewSession->setParticipantsSolution(null);
655  }
656  }
657 
658  public function saveAdditionalQuestionDataToDb()
659  {
661  global $ilDB;
662 
663  // save additional data
664  $ilDB->manipulateF(
665  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
666  array( "integer" ),
667  array( $this->getId() )
668  );
669 
670  $ilDB->manipulateF(
671  "INSERT INTO " . $this->getAdditionalTableName(
672  ) . " (question_fi, shuffle, allow_images, thumb_size, feedback_setting) VALUES (%s, %s, %s, %s, %s)",
673  array( "integer", "text", "text", "integer", 'integer' ),
674  array(
675  $this->getId(),
676  $this->getShuffle(),
677  ($this->isSingleline) ? "0" : "1",
678  (strlen($this->getThumbSize()) == 0) ? null : $this->getThumbSize(),
679  (int) $this->getSpecificFeedbackSetting()
680  )
681  );
682  }
683 
684  public function saveAnswerSpecificDataToDb()
685  {
687  global $ilDB;
688  if (!$this->isSingleline) {
689  ilUtil::delDir($this->getImagePath());
690  }
691  $ilDB->manipulateF(
692  "DELETE FROM qpl_a_sc WHERE question_fi = %s",
693  array( 'integer' ),
694  array( $this->getId() )
695  );
696 
697  foreach ($this->answers as $key => $value) {
699  $answer_obj = $this->answers[$key];
700  $next_id = $ilDB->nextId('qpl_a_sc');
701  $ilDB->manipulateF(
702  "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
703  array( 'integer', 'integer', 'text', 'float', 'integer', 'text', 'integer' ),
704  array(
705  $next_id,
706  $this->getId(),
707  ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 0),
708  $answer_obj->getPoints(),
709  $answer_obj->getOrder(),
710  $answer_obj->getImage(),
711  time()
712  )
713  );
714  }
715  $this->rebuildThumbnails();
716  }
717 
721  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
722  {
723  // nothing to rework!
724  }
725 
732  public function getQuestionType()
733  {
734  return "assSingleChoice";
735  }
736 
743  public function getAdditionalTableName()
744  {
745  return "qpl_qst_sc";
746  }
747 
754  public function getAnswerTableName()
755  {
756  return "qpl_a_sc";
757  }
758 
767  public function setImageFile($image_filename, $image_tempfilename = "")
768  {
769  $result = 0;
770  if (!empty($image_tempfilename)) {
771  $image_filename = str_replace(" ", "_", $image_filename);
772  $imagepath = $this->getImagePath();
773  if (!file_exists($imagepath)) {
774  ilUtil::makeDirParents($imagepath);
775  }
776  //if (!move_uploaded_file($image_tempfilename, $imagepath . $image_filename))
777  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath . $image_filename)) {
778  $result = 2;
779  } else {
780  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
781  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
782  if (!preg_match("/^image/", $mimetype)) {
783  unlink($imagepath . $image_filename);
784  $result = 1;
785  } else {
786  // create thumbnail file
787  if ($this->isSingleline && ($this->getThumbSize())) {
788  $this->generateThumbForFile($imagepath, $image_filename);
789  }
790  }
791  }
792  }
793  return $result;
794  }
795 
802  public function deleteImage($image_filename)
803  {
804  $imagepath = $this->getImagePath();
805  @unlink($imagepath . $image_filename);
806  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
807  @unlink($thumbpath);
808  }
809 
810  public function duplicateImages($question_id, $objectId = null)
811  {
812  global $ilLog;
813  $imagepath = $this->getImagePath();
814  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
815 
816  if ((int) $objectId > 0) {
817  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
818  }
819 
820  foreach ($this->answers as $answer) {
821  $filename = $answer->getImage();
822  if (strlen($filename)) {
823  if (!file_exists($imagepath)) {
824  ilUtil::makeDirParents($imagepath);
825  }
826  if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
827  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
828  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
829  }
830  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
831  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
832  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
833  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
834  }
835  }
836  }
837  }
838  }
839 
840  public function copyImages($question_id, $source_questionpool)
841  {
843  global $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 $ilLog;
892  $question_id = $this->getOriginalId();
893  $imagepath = $this->getImagePath();
894  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
895  ilUtil::delDir($imagepath_original);
896  foreach ($this->answers as $answer) {
897  $filename = $answer->getImage();
898  if (strlen($filename)) {
899  if (@file_exists($imagepath . $filename)) {
900  if (!file_exists($imagepath)) {
901  ilUtil::makeDirParents($imagepath);
902  }
903  if (!file_exists($imagepath_original)) {
904  ilUtil::makeDirParents($imagepath_original);
905  }
906  if (!@copy($imagepath . $filename, $imagepath_original . $filename)) {
907  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
908  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
909  }
910  }
911  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename)) {
912  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename)) {
913  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
914  $ilLog->write("object: " . print_r($this, true), $ilLog->ERROR);
915  }
916  }
917  }
918  }
919  }
920 
925  public function getRTETextWithMediaObjects()
926  {
927  $text = parent::getRTETextWithMediaObjects();
928  foreach ($this->answers as $index => $answer) {
929  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
930  $answer_obj = $this->answers[$index];
931  $text .= $answer_obj->getAnswertext();
932  }
933  return $text;
934  }
935 
939  public function &getAnswers()
940  {
941  return $this->answers;
942  }
943 
947  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
948  {
949  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
950 
951  $solution = $this->getSolutionValues($active_id, $pass);
952  $i = 1;
953  foreach ($this->getAnswers() as $id => $answer) {
954  $worksheet->setCell($startrow + $i, 0, $answer->getAnswertext());
955  $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
956  if (
957  count($solution) > 0 &&
958  isset($solution[0]) &&
959  is_array($solution[0]) &&
960  strlen($solution[0]['value1']) > 0 && $id == $solution[0]['value1']
961  ) {
962  $worksheet->setCell($startrow + $i, 1, 1);
963  } else {
964  $worksheet->setCell($startrow + $i, 1, 0);
965  }
966  $i++;
967  }
968 
969  return $startrow + $i + 1;
970  }
971 
972  public function getThumbSize()
973  {
974  return $this->thumb_size;
975  }
976 
977  public function setThumbSize($a_size)
978  {
979  $this->thumb_size = $a_size;
980  }
981 
986  {
987  foreach ($this->getAnswers() as $answer) {
988  /* @var ASS_AnswerBinaryStateImage $answer */
989  $answer->setAnswertext($migrator->migrateToLmContent($answer->getAnswertext()));
990  }
991  }
992 
996  public function toJSON()
997  {
998  include_once("./Services/RTE/classes/class.ilRTE.php");
999  $result = array();
1000  $result['id'] = (int) $this->getId();
1001  $result['type'] = (string) $this->getQuestionType();
1002  $result['title'] = (string) $this->getTitle();
1003  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1004  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1005  $result['shuffle'] = (bool) $this->getShuffle();
1006 
1007  $result['feedback'] = array(
1008  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1009  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1010  );
1011 
1012  $answers = array();
1013  $has_image = false;
1014  foreach ($this->getAnswers() as $key => $answer_obj) {
1015  if ((string) $answer_obj->getImage()) {
1016  $has_image = true;
1017  }
1018  array_push($answers, array(
1019  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1020  'html_id' => (int) $this->getId() . '_' . $key,
1021  "points" => (float) $answer_obj->getPoints(),
1022  "order" => (int) $answer_obj->getOrder(),
1023  "image" => (string) $answer_obj->getImage(),
1024  "feedback" => $this->formatSAQuestion(
1025  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
1026  )
1027  ));
1028  }
1029  $result['answers'] = $answers;
1030  if ($has_image) {
1031  $result['path'] = $this->getImagePathWeb();
1032  $result['thumb'] = $this->getThumbSize();
1033  }
1034 
1035  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1036  $result['mobs'] = $mobs;
1037 
1038  return json_encode($result);
1039  }
1040 
1041  public function removeAnswerImage($index)
1042  {
1043  $answer = $this->answers[$index];
1044  if (is_object($answer)) {
1045  $this->deleteImage($answer->getImage());
1046  $answer->setImage('');
1047  }
1048  }
1049 
1050  public function createRandomSolution($active_id, $pass)
1051  {
1052  $value = rand(0, count($this->answers)-1);
1053  $_POST["multiple_choice_result"] = (strlen($value)) ? (string) $value : '0';
1054  $this->saveWorkingData($active_id, $pass);
1055  $this->calculateResultsFromSolution($active_id, $pass);
1056  }
1057 
1058  public function getMultilineAnswerSetting()
1059  {
1060  global $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 $ilUser;
1072  $ilUser->writePref("tst_multiline_answers", $a_setting);
1073  }
1074 
1084  public function setSpecificFeedbackSetting($a_feedback_setting)
1085  {
1086  $this->feedback_setting = $a_feedback_setting;
1087  }
1088 
1098  public function getSpecificFeedbackSetting()
1099  {
1100  if ($this->feedback_setting) {
1101  return $this->feedback_setting;
1102  } else {
1103  return 1;
1104  }
1105  }
1106 
1108  {
1109  return 'feedback_correct_sc_mc';
1110  }
1111 
1122  public function isAnswered($active_id, $pass = null)
1123  {
1124  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1125 
1126  return $numExistingSolutionRecords > 0;
1127  }
1128 
1139  public static function isObligationPossible($questionId)
1140  {
1141  return true;
1142  }
1143 
1152  public function getOperators($expression)
1153  {
1154  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1156  }
1157 
1162  public function getExpressionTypes()
1163  {
1164  return array(
1168  );
1169  }
1170 
1179  public function getUserQuestionResult($active_id, $pass)
1180  {
1182  global $ilDB;
1183  $result = new ilUserQuestionResult($this, $active_id, $pass);
1184 
1185  $maxStep = $this->lookupMaxStep($active_id, $pass);
1186 
1187  if ($maxStep !== null) {
1188  $data = $ilDB->queryF(
1189  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1190  array("integer", "integer", "integer","integer"),
1191  array($active_id, $pass, $this->getId(), $maxStep)
1192  );
1193  } else {
1194  $data = $ilDB->queryF(
1195  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1196  array("integer", "integer", "integer"),
1197  array($active_id, $pass, $this->getId())
1198  );
1199  }
1200 
1201  $row = $ilDB->fetchAssoc($data);
1202 
1203  if ($row != null) {
1204  ++$row["value1"];
1205  $result->addKeyValue($row["value1"], $row["value1"]);
1206  }
1207 
1208  $points = $this->calculateReachedPoints($active_id, $pass);
1209  $max_points = $this->getMaximumPoints();
1210 
1211  $result->setReachedPercentage(($points/$max_points) * 100);
1212 
1213  return $result;
1214  }
1215 
1224  public function getAvailableAnswerOptions($index = null)
1225  {
1226  if ($index !== null) {
1227  return $this->getAnswer($index);
1228  } else {
1229  return $this->getAnswers();
1230  }
1231  }
1232 
1236  protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1237  {
1238  parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1239 
1240  $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1241  $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1242 
1243  ilUtil::delDir($origImagePath);
1244  if (is_dir($dupImagePath)) {
1245  ilUtil::makeDirParents($origImagePath);
1246  ilUtil::rCopy($dupImagePath, $origImagePath);
1247  }
1248  }
1249 }
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.
Add rich text string
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.
$worksheet
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.
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)
Create styles array
The data for the language used.
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.
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
{}
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.
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
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.