ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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  var $answers;
35 
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 = "",
81  $output_type = OUTPUT_ORDER
82  )
83  {
84  parent::__construct($title, $comment, $author, $owner, $question);
85  $this->thumb_size = 150;
86  $this->output_type = $output_type;
87  $this->answers = array();
88  $this->shuffle = 1;
89  $this->feedback_setting = 2;
90  }
91 
98  function isComplete()
99  {
100  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0))
101  {
102  foreach ($this->answers as $answer)
103  {
104  if ((strlen($answer->getAnswertext()) == 0) && (strlen($answer->getImage()) == 0)) return false;
105  }
106  return true;
107  }
108  else
109  {
110  return false;
111  }
112  }
113 
120  public function saveToDb($original_id = "")
121  {
123  global $ilDB;
124 
126 
127  // kann das weg?
128  $oldthumbsize = 0;
129  if ($this->isSingleline && ($this->getThumbSize()))
130  {
131  // get old thumbnail size
132  $result = $ilDB->queryF("SELECT thumb_size FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
133  array("integer"),
134  array($this->getId())
135  );
136  if ($result->numRows() == 1)
137  {
138  $data = $ilDB->fetchAssoc($result);
139  $oldthumbsize = $data['thumb_size'];
140  }
141  }
142 
143 
145 
147 
148  parent::saveToDb($original_id);
149  }
150 
151  /*
152  * Rebuild the thumbnail images with a new thumbnail size
153  */
154  protected function rebuildThumbnails()
155  {
156  if ($this->isSingleline && ($this->getThumbSize()))
157  {
158  foreach ($this->getAnswers() as $answer)
159  {
160  if (strlen($answer->getImage()))
161  {
162  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
163  }
164  }
165  }
166  }
167 
168  public function getThumbPrefix()
169  {
170  return "thumb.";
171  }
172 
173  protected function generateThumbForFile($path, $file)
174  {
175  $filename = $path . $file;
176  if (@file_exists($filename))
177  {
178  $thumbpath = $path . $this->getThumbPrefix() . $file;
179  $path_info = @pathinfo($filename);
180  $ext = "";
181  switch (strtoupper($path_info['extension']))
182  {
183  case 'PNG':
184  $ext = 'PNG';
185  break;
186  case 'GIF':
187  $ext = 'GIF';
188  break;
189  default:
190  $ext = 'JPEG';
191  break;
192  }
193  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
194  }
195  }
196 
204  function loadFromDb($question_id)
205  {
206  global $ilDB;
207 
208  $hasimages = 0;
209 
210  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
211  array("integer"),
212  array($question_id)
213  );
214  if ($result->numRows() == 1)
215  {
216  $data = $ilDB->fetchAssoc($result);
217  $this->setId($question_id);
218  $this->setObjId($data["obj_fi"]);
219  $this->setTitle($data["title"]);
220  $this->setNrOfTries($data['nr_of_tries']);
221  $this->setComment($data["description"]);
222  $this->setOriginalId($data["original_id"]);
223  $this->setAuthor($data["author"]);
224  $this->setPoints($data["points"]);
225  $this->setOwner($data["owner"]);
226  include_once("./Services/RTE/classes/class.ilRTE.php");
227  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
228  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
229  $this->setShuffle($shuffle);
230  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
231  $this->setThumbSize($data['thumb_size']);
232  $this->isSingleline = ($data['allow_images']) ? false : true;
233  $this->lastChange = $data['tstamp'];
234  $this->feedback_setting = $data['feedback_setting'];
235 
236  try
237  {
238  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
239  }
241  {
242  }
243  }
244 
245  $result = $ilDB->queryF("SELECT * FROM qpl_a_sc WHERE question_fi = %s ORDER BY aorder ASC",
246  array('integer'),
247  array($question_id)
248  );
249  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
250  if ($result->numRows() > 0)
251  {
252  while ($data = $ilDB->fetchAssoc($result))
253  {
254  $imagefilename = $this->getImagePath() . $data["imagefile"];
255  if (!@file_exists($imagefilename))
256  {
257  $data["imagefile"] = "";
258  }
259  include_once("./Services/RTE/classes/class.ilRTE.php");
260  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
261  array_push($this->answers, new ASS_AnswerBinaryStateImage($data["answertext"], $data["points"], $data["aorder"], 1, $data["imagefile"]));
262  }
263  }
264 
265  parent::loadFromDb($question_id);
266  }
267 
273  function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
274  {
275  if ($this->id <= 0)
276  {
277  // The question has not been saved. It cannot be duplicated
278  return;
279  }
280  // duplicate the question in database
281  $this_id = $this->getId();
282  $thisObjId = $this->getObjId();
283 
284  $clone = $this;
285  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
287  $clone->id = -1;
288 
289  if( (int)$testObjId > 0 )
290  {
291  $clone->setObjId($testObjId);
292  }
293 
294  if ($title)
295  {
296  $clone->setTitle($title);
297  }
298 
299  if ($author)
300  {
301  $clone->setAuthor($author);
302  }
303  if ($owner)
304  {
305  $clone->setOwner($owner);
306  }
307  if ($for_test)
308  {
309  $clone->saveToDb($original_id);
310  }
311  else
312  {
313  $clone->saveToDb();
314  }
315 
316  // copy question page content
317  $clone->copyPageOfQuestion($this_id);
318 
319  // copy XHTML media objects
320  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
321  // duplicate the images
322  $clone->duplicateImages($this_id, $thisObjId);
323 
324  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
325 
326  return $clone->id;
327  }
328 
334  function copyObject($target_questionpool_id, $title = "")
335  {
336  if ($this->id <= 0)
337  {
338  // The question has not been saved. It cannot be duplicated
339  return;
340  }
341  // duplicate the question in database
342  $clone = $this;
343  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
345  $clone->id = -1;
346  $source_questionpool_id = $this->getObjId();
347  $clone->setObjId($target_questionpool_id);
348  if ($title)
349  {
350  $clone->setTitle($title);
351  }
352  $clone->saveToDb();
353  // copy question page content
354  $clone->copyPageOfQuestion($original_id);
355  // copy XHTML media objects
356  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
357  // duplicate the image
358  $clone->copyImages($original_id, $source_questionpool_id);
359 
360  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
361 
362  return $clone->id;
363  }
364 
365  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
366  {
367  if ($this->id <= 0)
368  {
369  // The question has not been saved. It cannot be duplicated
370  return;
371  }
372 
373  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
374 
375  $sourceQuestionId = $this->id;
376  $sourceParentId = $this->getObjId();
377 
378  // duplicate the question in database
379  $clone = $this;
380  $clone->id = -1;
381 
382  $clone->setObjId($targetParentId);
383 
384  if ($targetQuestionTitle)
385  {
386  $clone->setTitle($targetQuestionTitle);
387  }
388 
389  $clone->saveToDb();
390  // copy question page content
391  $clone->copyPageOfQuestion($sourceQuestionId);
392  // copy XHTML media objects
393  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
394  // duplicate the image
395  $clone->copyImages($sourceQuestionId, $sourceParentId);
396 
397  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
398 
399  return $clone->id;
400  }
401 
409  function getOutputType()
410  {
411  return $this->output_type;
412  }
413 
421  function setOutputType($output_type = OUTPUT_ORDER)
422  {
423  $this->output_type = $output_type;
424  }
425 
439  function addAnswer(
440  $answertext = "",
441  $points = 0.0,
442  $order = 0,
443  $answerimage = ""
444  )
445  {
446  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
447  if (array_key_exists($order, $this->answers))
448  {
449  // insert answer
450  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, $order, 1, $answerimage);
451  $newchoices = array();
452  for ($i = 0; $i < $order; $i++)
453  {
454  array_push($newchoices, $this->answers[$i]);
455  }
456  array_push($newchoices, $answer);
457  for ($i = $order; $i < count($this->answers); $i++)
458  {
459  $changed = $this->answers[$i];
460  $changed->setOrder($i+1);
461  array_push($newchoices, $changed);
462  }
463  $this->answers = $newchoices;
464  }
465  else
466  {
467  // add answer
468  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, count($this->answers), 1, $answerimage);
469  array_push($this->answers, $answer);
470  }
471  }
472 
480  function getAnswerCount()
481  {
482  return count($this->answers);
483  }
484 
494  function getAnswer($index = 0)
495  {
496  if ($index < 0) return NULL;
497  if (count($this->answers) < 1) return NULL;
498  if ($index >= count($this->answers)) return NULL;
499 
500  return $this->answers[$index];
501  }
502 
511  function deleteAnswer($index = 0)
512  {
513  if ($index < 0) return;
514  if (count($this->answers) < 1) return;
515  if ($index >= count($this->answers)) return;
516  $answer = $this->answers[$index];
517  if (strlen($answer->getImage())) $this->deleteImage($answer->getImage());
518  unset($this->answers[$index]);
519  $this->answers = array_values($this->answers);
520  for ($i = 0; $i < count($this->answers); $i++)
521  {
522  if ($this->answers[$i]->getOrder() > $index)
523  {
524  $this->answers[$i]->setOrder($i);
525  }
526  }
527  }
528 
535  function flushAnswers()
536  {
537  $this->answers = array();
538  }
539 
546  function getMaximumPoints()
547  {
548  $points = 0;
549  foreach ($this->answers as $key => $value)
550  {
551  if ($value->getPoints() > $points)
552  {
553  $points = $value->getPoints();
554  }
555  }
556  return $points;
557  }
558 
569  public function calculateReachedPoints($active_id, $pass = NULL, $authorizedSolution = true, $returndetails = FALSE)
570  {
571  if( $returndetails )
572  {
573  throw new ilTestException('return details not implemented for '.__METHOD__);
574  }
575 
576  global $ilDB;
577 
578  $found_values = array();
579  if (is_null($pass))
580  {
581  $pass = $this->getSolutionMaxPass($active_id);
582  }
583  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
584  while ($data = $ilDB->fetchAssoc($result))
585  {
586  if (strcmp($data["value1"], "") != 0)
587  {
588  array_push($found_values, $data["value1"]);
589  }
590  }
591  $points = 0;
592  foreach ($this->answers as $key => $answer)
593  {
594  if (count($found_values) > 0)
595  {
596  if (in_array($key, $found_values))
597  {
598  $points += $answer->getPoints();
599  }
600  }
601  }
602 
603  return $points;
604  }
605 
607  {
608  $participantSolution = $previewSession->getParticipantsSolution();
609 
610  $points = 0;
611 
612  foreach ($this->answers as $key => $answer)
613  {
614  if( is_numeric($participantSolution) && $key == $participantSolution )
615  {
616  $points = $answer->getPoints();
617  }
618  }
619 
620  $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
621 
622  return $this->ensureNonNegativePoints($reachedPoints);
623  }
624 
633  public function saveWorkingData($active_id, $pass = NULL, $authorized = true)
634  {
635  global $ilDB;
636  global $ilUser;
637 
638  if (is_null($pass))
639  {
640  include_once "./Modules/Test/classes/class.ilObjTest.php";
641  $pass = ilObjTest::_getPass($active_id);
642  }
643 
644  $entered_values = 0;
645 
646  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function() use (&$entered_values, $ilDB, $active_id, $pass, $authorized) {
647 
648  $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized);
649  $row = $ilDB->fetchAssoc($result);
650  $update = $row["solution_id"];
651 
652  if($update)
653  {
654  if(strlen($_POST["multiple_choice_result"]))
655  {
656  $this->updateCurrentSolution($update, $_POST["multiple_choice_result"], null, $authorized);
657  $entered_values++;
658  }
659  else
660  {
661  $this->removeSolutionRecordById($update);
662  }
663  }
664  else
665  {
666  if(strlen($_POST["multiple_choice_result"]))
667  {
668  $this->saveCurrentSolution($active_id, $pass, $_POST['multiple_choice_result'], null, $authorized);
669  $entered_values++;
670  }
671  }
672 
673  });
674 
675  if ($entered_values)
676  {
677  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
679  {
680  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
681  }
682  }
683  else
684  {
685  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
687  {
688  assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
689  }
690  }
691 
692  return true;
693  }
694 
695  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
696  {
697  if( strlen($_POST['multiple_choice_result'.$this->getId().'ID']) )
698  {
699  $previewSession->setParticipantsSolution($_POST['multiple_choice_result'.$this->getId().'ID']);
700  }
701  else
702  {
703  $previewSession->setParticipantsSolution(null);
704  }
705  }
706 
707  public function saveAdditionalQuestionDataToDb()
708  {
710  global $ilDB;
711 
712  // save additional data
713  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
714  array( "integer" ),
715  array( $this->getId() )
716  );
717 
718  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName(
719  ) . " (question_fi, shuffle, allow_images, thumb_size, feedback_setting) VALUES (%s, %s, %s, %s, %s)",
720  array( "integer", "text", "text", "integer", 'integer' ),
721  array(
722  $this->getId(),
723  $this->getShuffle(),
724  ($this->isSingleline) ? "0" : "1",
725  (strlen( $this->getThumbSize() ) == 0) ? null : $this->getThumbSize(),
726  (int)$this->getSpecificFeedbackSetting()
727  )
728  );
729  }
730 
731  public function saveAnswerSpecificDataToDb()
732  {
734  global $ilDB;
735  if (!$this->isSingleline)
736  {
737  ilUtil::delDir( $this->getImagePath() );
738  }
739  $ilDB->manipulateF( "DELETE FROM qpl_a_sc WHERE question_fi = %s",
740  array( 'integer' ),
741  array( $this->getId() )
742  );
743 
744  foreach ($this->answers as $key => $value)
745  {
747  $answer_obj = $this->answers[$key];
748  $next_id = $ilDB->nextId( 'qpl_a_sc' );
749  $ilDB->manipulateF( "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
750  array( 'integer', 'integer', 'text', 'float', 'integer', 'text', 'integer' ),
751  array(
752  $next_id,
753  $this->getId(),
754  ilRTE::_replaceMediaObjectImageSrc( $answer_obj->getAnswertext(), 0 ),
755  $answer_obj->getPoints(),
756  $answer_obj->getOrder(),
757  $answer_obj->getImage(),
758  time()
759  )
760  );
761  }
762  $this->rebuildThumbnails();
763  }
764 
768  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
769  {
770  // nothing to rework!
771  }
772 
779  function getQuestionType()
780  {
781  return "assSingleChoice";
782  }
783 
791  {
792  return "qpl_qst_sc";
793  }
794 
802  {
803  return "qpl_a_sc";
804  }
805 
814  function setImageFile($image_filename, $image_tempfilename = "")
815  {
816  $result = 0;
817  if (!empty($image_tempfilename))
818  {
819  $image_filename = str_replace(" ", "_", $image_filename);
820  $imagepath = $this->getImagePath();
821  if (!file_exists($imagepath))
822  {
823  ilUtil::makeDirParents($imagepath);
824  }
825  //if (!move_uploaded_file($image_tempfilename, $imagepath . $image_filename))
826  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
827  {
828  $result = 2;
829  }
830  else
831  {
832  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
833  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
834  if (!preg_match("/^image/", $mimetype))
835  {
836  unlink($imagepath . $image_filename);
837  $result = 1;
838  }
839  else
840  {
841  // create thumbnail file
842  if ($this->isSingleline && ($this->getThumbSize()))
843  {
844  $this->generateThumbForFile($imagepath, $image_filename);
845  }
846  }
847  }
848  }
849  return $result;
850  }
851 
858  function deleteImage($image_filename)
859  {
860  $imagepath = $this->getImagePath();
861  @unlink($imagepath . $image_filename);
862  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
863  @unlink($thumbpath);
864  }
865 
866  function duplicateImages($question_id, $objectId = null)
867  {
868  global $ilLog;
869  $imagepath = $this->getImagePath();
870  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
871 
872  if( (int)$objectId > 0 )
873  {
874  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
875  }
876 
877  foreach ($this->answers as $answer)
878  {
879  $filename = $answer->getImage();
880  if (strlen($filename))
881  {
882  if (!file_exists($imagepath))
883  {
884  ilUtil::makeDirParents($imagepath);
885  }
886  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
887  {
888  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
889  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
890  }
891  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
892  {
893  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
894  {
895  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
896  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
897  }
898  }
899  }
900  }
901  }
902 
903  function copyImages($question_id, $source_questionpool)
904  {
906  global $ilLog;
907 
908  $imagepath = $this->getImagePath();
909  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
910  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
911  foreach ($this->answers as $answer)
912  {
913  $filename = $answer->getImage();
914  if (strlen($filename))
915  {
916  if(!file_exists($imagepath))
917  {
918  ilUtil::makeDirParents($imagepath);
919  }
920 
921  if(file_exists($imagepath_original . $filename))
922  {
923  if(!copy($imagepath_original . $filename, $imagepath . $filename))
924  {
925  $ilLog->warning(sprintf(
926  "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
927  $imagepath_original . $filename, $imagepath . $filename,
928  $question_id, $this->id, $source_questionpool, $this->obj_id
929  ));
930  }
931  }
932 
933  if(file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
934  {
935  if(!copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
936  {
937  $ilLog->warning(sprintf(
938  "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
939  $imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename,
940  $question_id, $this->id, $source_questionpool, $this->obj_id
941  ));
942  }
943  }
944  }
945  }
946  }
947 
951  protected function syncImages()
952  {
953  global $ilLog;
954  $question_id = $this->getOriginalId();
955  $imagepath = $this->getImagePath();
956  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
957  ilUtil::delDir($imagepath_original);
958  foreach ($this->answers as $answer)
959  {
960  $filename = $answer->getImage();
961  if (strlen($filename))
962  {
963  if (@file_exists($imagepath . $filename))
964  {
965  if (!file_exists($imagepath))
966  {
967  ilUtil::makeDirParents($imagepath);
968  }
969  if (!file_exists($imagepath_original))
970  {
971  ilUtil::makeDirParents($imagepath_original);
972  }
973  if (!@copy($imagepath . $filename, $imagepath_original . $filename))
974  {
975  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
976  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
977  }
978  }
979  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename))
980  {
981  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename))
982  {
983  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
984  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
985  }
986  }
987  }
988  }
989  }
990 
996  {
997  $text = parent::getRTETextWithMediaObjects();
998  foreach ($this->answers as $index => $answer)
999  {
1000  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
1001  $answer_obj = $this->answers[$index];
1002  $text .= $answer_obj->getAnswertext();
1003  }
1004  return $text;
1005  }
1006 
1010  function &getAnswers()
1011  {
1012  return $this->answers;
1013  }
1014 
1018  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
1019  {
1020  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1021 
1022  $solution = $this->getSolutionValues($active_id, $pass);
1023  $i = 1;
1024  foreach ($this->getAnswers() as $id => $answer)
1025  {
1026  $worksheet->setCell($startrow + $i, 0,$answer->getAnswertext());
1027  $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
1028  if(
1029  count($solution) > 0 &&
1030  isset($solution[0]) &&
1031  is_array($solution[0]) &&
1032  strlen($solution[0]['value1']) > 0 && $id == $solution[0]['value1']
1033  )
1034  {
1035  $worksheet->setCell($startrow + $i, 1, 1);
1036  }
1037  else
1038  {
1039  $worksheet->setCell($startrow + $i, 1, 0);
1040  }
1041  $i++;
1042  }
1043 
1044  return $startrow + $i + 1;
1045  }
1046 
1047  public function getThumbSize()
1048  {
1049  return $this->thumb_size;
1050  }
1051 
1052  public function setThumbSize($a_size)
1053  {
1054  $this->thumb_size = $a_size;
1055  }
1056 
1061  {
1062  foreach($this->getAnswers() as $answer)
1063  {
1064  /* @var ASS_AnswerBinaryStateImage $answer */
1065  $answer->setAnswertext( $migrator->migrateToLmContent($answer->getAnswertext()) );
1066  }
1067  }
1068 
1072  public function toJSON()
1073  {
1074  include_once("./Services/RTE/classes/class.ilRTE.php");
1075  $result = array();
1076  $result['id'] = (int) $this->getId();
1077  $result['type'] = (string) $this->getQuestionType();
1078  $result['title'] = (string) $this->getTitle();
1079  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1080  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1081  $result['shuffle'] = (bool) $this->getShuffle();
1082 
1083  $result['feedback'] = array(
1084  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1085  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1086  );
1087 
1088  $answers = array();
1089  $has_image = false;
1090  foreach ($this->getAnswers() as $key => $answer_obj)
1091  {
1092  if((string) $answer_obj->getImage())
1093  {
1094  $has_image = true;
1095  }
1096  array_push($answers, array(
1097  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1098  'html_id' => (int) $this->getId() . '_' . $key,
1099  "points" => (float)$answer_obj->getPoints(),
1100  "order" => (int)$answer_obj->getOrder(),
1101  "image" => (string) $answer_obj->getImage(),
1102  "feedback" => $this->formatSAQuestion(
1103  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
1104  )
1105  ));
1106  }
1107  $result['answers'] = $answers;
1108  if($has_image)
1109  {
1110  $result['path'] = $this->getImagePathWeb();
1111  $result['thumb'] = $this->getThumbSize();
1112  }
1113 
1114  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1115  $result['mobs'] = $mobs;
1116 
1117  return json_encode($result);
1118  }
1119 
1120  public function removeAnswerImage($index)
1121  {
1122  $answer = $this->answers[$index];
1123  if (is_object($answer))
1124  {
1125  $this->deleteImage($answer->getImage());
1126  $answer->setImage('');
1127  }
1128  }
1129 
1130  function createRandomSolution($active_id, $pass)
1131  {
1132  $value = rand(0, count($this->answers)-1);
1133  $_POST["multiple_choice_result"] = (strlen($value)) ? (string)$value : '0';
1134  $this->saveWorkingData($active_id, $pass);
1135  $this->calculateResultsFromSolution($active_id, $pass);
1136  }
1137 
1139  {
1140  global $ilUser;
1141 
1142  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1143  if ($multilineAnswerSetting != 1)
1144  {
1145  $multilineAnswerSetting = 0;
1146  }
1147  return $multilineAnswerSetting;
1148  }
1149 
1150  function setMultilineAnswerSetting($a_setting = 0)
1151  {
1152  global $ilUser;
1153  $ilUser->writePref("tst_multiline_answers", $a_setting);
1154  }
1155 
1165  public function setSpecificFeedbackSetting($a_feedback_setting)
1166  {
1167  $this->feedback_setting = $a_feedback_setting;
1168  }
1169 
1179  public function getSpecificFeedbackSetting()
1180  {
1181  if ($this->feedback_setting)
1182  {
1183  return $this->feedback_setting;
1184  }
1185  else
1186  {
1187  return 1;
1188  }
1189  }
1190 
1192  {
1193  return 'feedback_correct_sc_mc';
1194  }
1195 
1206  public function isAnswered($active_id, $pass = NULL)
1207  {
1208  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1209 
1210  return $numExistingSolutionRecords > 0;
1211  }
1212 
1223  public static function isObligationPossible($questionId)
1224  {
1225  return true;
1226  }
1227 
1236  public function getOperators($expression)
1237  {
1238  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1240  }
1241 
1246  public function getExpressionTypes()
1247  {
1248  return array(
1252  );
1253  }
1254 
1263  public function getUserQuestionResult($active_id, $pass)
1264  {
1266  global $ilDB;
1267  $result = new ilUserQuestionResult($this, $active_id, $pass);
1268 
1269  $maxStep = $this->lookupMaxStep($active_id, $pass);
1270 
1271  if( $maxStep !== null )
1272  {
1273  $data = $ilDB->queryF(
1274  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1275  array("integer", "integer", "integer","integer"),
1276  array($active_id, $pass, $this->getId(), $maxStep)
1277  );
1278  }
1279  else
1280  {
1281  $data = $ilDB->queryF(
1282  "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1283  array("integer", "integer", "integer"),
1284  array($active_id, $pass, $this->getId())
1285  );
1286  }
1287 
1288  $row = $ilDB->fetchAssoc($data);
1289 
1290  if($row != null)
1291  {
1292  ++$row["value1"];
1293  $result->addKeyValue($row["value1"], $row["value1"]);
1294  }
1295 
1296  $points = $this->calculateReachedPoints($active_id, $pass);
1297  $max_points = $this->getMaximumPoints();
1298 
1299  $result->setReachedPercentage(($points/$max_points) * 100);
1300 
1301  return $result;
1302  }
1303 
1312  public function getAvailableAnswerOptions($index = null)
1313  {
1314  if($index !== null)
1315  {
1316  return $this->getAnswer($index);
1317  }
1318  else
1319  {
1320  return $this->getAnswers();
1321  }
1322  }
1323 
1327  protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1328  {
1329  parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1330 
1331  $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1332  $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1333 
1334  ilUtil::delDir($origImagePath);
1335  if(is_dir($dupImagePath))
1336  {
1337  ilUtil::makeDirParents($origImagePath);
1338  ilUtil::rCopy($dupImagePath, $origImagePath);
1339  }
1340  }
1341 }
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.
$worksheet
Class iQuestionCondition.
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)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
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. ...
Add rich text string
The name of the decorator.
loadFromDb($question_id)
Loads a assSingleChoice object from a database.
calculateResultsFromSolution($active_id, $pass=NULL, $obligationsEnabled=false)
Calculates the question results from a previously saved question solution.
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.
getSpecificFeedbackSetting()
Gets the current feedback settings in effect for the question.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
isAnswered($active_id, $pass=NULL)
returns boolean wether the question is answered during test pass or not
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)
{}
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.
$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.
calculateReachedPoints($active_id, $pass=NULL, $authorizedSolution=true, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
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 ...
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
{}
static getMimeType($a_file, $a_external=false)
get mime type for file
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.
static convertImage($a_from, $a_to, $a_target_format="", $a_geometry="", $a_background_color="")
convert image
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...
$text
getSolutionValues($active_id, $pass=NULL, $authorized=true)
Loads solutions of a given user from the database an returns it.
getTitle()
Gets the title string of the assQuestion object.
saveWorkingData($active_id, $pass=NULL, $authorized=true)
Saves the learners input of the question to the database.
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
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.