ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
class.assMultipleChoice.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 
27 {
35  var $answers;
36 
46 
47  public $isSingleline;
48  public $lastChange;
50 
52  protected $thumb_size;
53 
57  public function setIsSingleline($isSingleline)
58  {
59  $this->isSingleline = $isSingleline;
60  }
61 
65  public function getIsSingleline()
66  {
67  return $this->isSingleline;
68  }
69 
73  public function setLastChange($lastChange)
74  {
75  $this->lastChange = $lastChange;
76  }
77 
81  public function getLastChange()
82  {
83  return $this->lastChange;
84  }
85 
100  public function __construct(
101  $title = "",
102  $comment = "",
103  $author = "",
104  $owner = -1,
105  $question = "",
106  $output_type = OUTPUT_ORDER
107  )
108  {
109  parent::__construct($title, $comment, $author, $owner, $question);
110  $this->output_type = $output_type;
111  $this->thumb_size = 150;
112  $this->answers = array();
113  $this->shuffle = 1;
114  }
115 
122  function isComplete()
123  {
124  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0))
125  {
126  return true;
127  }
128  else
129  {
130  return false;
131  }
132  }
133 
139  public function saveToDb($original_id = "")
140  {
144 
145  $this->ensureNoInvalidObligation($this->getId());
146  parent::saveToDb($original_id);
147  }
148 
152  protected function rebuildThumbnails()
153  {
154  if ($this->isSingleline && ($this->getThumbSize()))
155  {
156  foreach ($this->getAnswers() as $answer)
157  {
158  if (strlen($answer->getImage()))
159  {
160  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
161  }
162  }
163  }
164  }
165 
169  public function getThumbPrefix()
170  {
171  return "thumb.";
172  }
173 
178  protected function generateThumbForFile($path, $file)
179  {
180  $filename = $path . $file;
181  if (@file_exists($filename))
182  {
183  $thumbpath = $path . $this->getThumbPrefix() . $file;
184  $path_info = @pathinfo($filename);
185  $ext = "";
186  switch (strtoupper($path_info['extension']))
187  {
188  case 'PNG':
189  $ext = 'PNG';
190  break;
191  case 'GIF':
192  $ext = 'GIF';
193  break;
194  default:
195  $ext = 'JPEG';
196  break;
197  }
198  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
199  }
200  }
201 
207  public function loadFromDb($question_id)
208  {
209  global $ilDB;
210  $hasimages = 0;
211 
212  $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",
213  array("integer"),
214  array($question_id)
215  );
216  if ($result->numRows() == 1)
217  {
218  $data = $ilDB->fetchAssoc($result);
219  $this->setId($question_id);
220  $this->setObjId($data["obj_fi"]);
221  $this->setTitle($data["title"]);
222  $this->setNrOfTries($data['nr_of_tries']);
223  $this->setComment($data["description"]);
224  $this->setOriginalId($data["original_id"]);
225  $this->setAuthor($data["author"]);
226  $this->setPoints($data["points"]);
227  $this->setOwner($data["owner"]);
228  include_once("./Services/RTE/classes/class.ilRTE.php");
229  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
230  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
231  $this->setShuffle($shuffle);
232  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
233  $this->setThumbSize($data['thumb_size']);
234  $this->isSingleline = ($data['allow_images']) ? false : true;
235  $this->lastChange = $data['tstamp'];
236  $this->feedback_setting = $data['feedback_setting'];
237 
238  try
239  {
240  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
241  }
243  {
244  }
245  }
246 
247  $result = $ilDB->queryF("SELECT * FROM qpl_a_mc WHERE question_fi = %s ORDER BY aorder ASC",
248  array('integer'),
249  array($question_id)
250  );
251  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
252  if ($result->numRows() > 0)
253  {
254  while ($data = $ilDB->fetchAssoc($result))
255  {
256  $imagefilename = $this->getImagePath() . $data["imagefile"];
257  if (!@file_exists($imagefilename))
258  {
259  $data["imagefile"] = "";
260  }
261  include_once("./Services/RTE/classes/class.ilRTE.php");
262  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
263  array_push($this->answers, new ASS_AnswerMultipleResponseImage($data["answertext"], $data["points"], $data["aorder"], $data["points_unchecked"], $data["imagefile"]));
264  }
265  }
266 
267  parent::loadFromDb($question_id);
268  }
269 
273  public 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 
308  if ($for_test)
309  {
310  $clone->saveToDb($original_id);
311  }
312  else
313  {
314  $clone->saveToDb();
315  }
316 
317  // copy question page content
318  $clone->copyPageOfQuestion($this_id);
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 
332  public function copyObject($target_questionpool_id, $title = "")
333  {
334  if ($this->id <= 0)
335  {
336  // The question has not been saved. It cannot be duplicated
337  return;
338  }
339  // duplicate the question in database
340  $clone = $this;
341  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
343  $clone->id = -1;
344  $source_questionpool_id = $this->getObjId();
345  $clone->setObjId($target_questionpool_id);
346  if ($title)
347  {
348  $clone->setTitle($title);
349  }
350  $clone->saveToDb();
351  // copy question page content
352  $clone->copyPageOfQuestion($original_id);
353  // copy XHTML media objects
354  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
355  // duplicate the image
356  $clone->copyImages($original_id, $source_questionpool_id);
357 
358  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
359 
360  return $clone->id;
361  }
362 
363  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
364  {
365  if ($this->id <= 0)
366  {
367  // The question has not been saved. It cannot be duplicated
368  return;
369  }
370 
371  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
372 
373  $sourceQuestionId = $this->id;
374  $sourceParentId = $this->getObjId();
375 
376  // duplicate the question in database
377  $clone = $this;
378  $clone->id = -1;
379 
380  $clone->setObjId($targetParentId);
381 
382  if ($targetQuestionTitle)
383  {
384  $clone->setTitle($targetQuestionTitle);
385  }
386 
387  $clone->saveToDb();
388  // copy question page content
389  $clone->copyPageOfQuestion($sourceQuestionId);
390  // copy XHTML media objects
391  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
392  // duplicate the image
393  $clone->copyImages($sourceQuestionId, $sourceParentId);
394 
395  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
396 
397  return $clone->id;
398  }
399 
406  public function getOutputType()
407  {
408  return $this->output_type;
409  }
410 
418  public function setOutputType($output_type = OUTPUT_ORDER)
419  {
420  $this->output_type = $output_type;
421  }
422 
436  public function addAnswer(
437  $answertext = "",
438  $points = 0.0,
439  $points_unchecked = 0.0,
440  $order = 0,
441  $answerimage = ""
442  )
443  {
444  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
445  if (array_key_exists($order, $this->answers))
446  {
447  // insert answer
448  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, $order, $points_unchecked, $answerimage);
449  $newchoices = array();
450  for ($i = 0; $i < $order; $i++)
451  {
452  array_push($newchoices, $this->answers[$i]);
453  }
454  array_push($newchoices, $answer);
455  for ($i = $order; $i < count($this->answers); $i++)
456  {
457  $changed = $this->answers[$i];
458  $changed->setOrder($i+1);
459  array_push($newchoices, $changed);
460  }
461  $this->answers = $newchoices;
462  }
463  else
464  {
465  // add answer
466  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, count($this->answers), $points_unchecked, $answerimage);
467  array_push($this->answers, $answer);
468  }
469  }
470 
477  public function getAnswerCount()
478  {
479  return count($this->answers);
480  }
481 
490  public function getAnswer($index = 0)
491  {
492  if ($index < 0) return NULL;
493  if (count($this->answers) < 1) return NULL;
494  if ($index >= count($this->answers)) return NULL;
495 
496  return $this->answers[$index];
497  }
498 
506  public function deleteAnswer($index = 0)
507  {
508  if ($index < 0) return;
509  if (count($this->answers) < 1) return;
510  if ($index >= count($this->answers)) return;
511  $answer = $this->answers[$index];
512  if (strlen($answer->getImage())) $this->deleteImage($answer->getImage());
513  unset($this->answers[$index]);
514  $this->answers = array_values($this->answers);
515  for ($i = 0; $i < count($this->answers); $i++)
516  {
517  if ($this->answers[$i]->getOrder() > $index)
518  {
519  $this->answers[$i]->setOrder($i);
520  }
521  }
522  }
523 
529  public function flushAnswers()
530  {
531  $this->answers = array();
532  }
533 
539  public function getMaximumPoints()
540  {
541  $points = 0;
542  $allpoints = 0;
543  foreach ($this->answers as $key => $value)
544  {
545  if ($value->getPoints() > $value->getPointsUnchecked())
546  {
547  $allpoints += $value->getPoints();
548  }
549  else
550  {
551  $allpoints += $value->getPointsUnchecked();
552  }
553  }
554  return $allpoints;
555  }
556 
568  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
569  {
570  if( $returndetails )
571  {
572  throw new ilTestException('return details not implemented for '.__METHOD__);
573  }
574 
575  global $ilDB;
576 
577  $found_values = array();
578  if (is_null($pass))
579  {
580  $pass = $this->getSolutionMaxPass($active_id);
581  }
582  $result = $this->getCurrentSolutionResultSet($active_id, $pass);
583  while ($data = $ilDB->fetchAssoc($result))
584  {
585  if (strcmp($data["value1"], "") != 0)
586  {
587  array_push($found_values, $data["value1"]);
588  }
589  }
590 
591  $points = $this->calculateReachedPointsForSolution($found_values, $active_id);
592 
593  return $points;
594  }
595 
604  public function saveWorkingData($active_id, $pass = NULL)
605  {
607  global $ilDB;
608 
609  if (is_null($pass))
610  {
611  include_once "./Modules/Test/classes/class.ilObjTest.php";
612  $pass = ilObjTest::_getPass($active_id);
613  }
614 
615  $entered_values = 0;
616 
617  $this->getProcessLocker()->requestUserSolutionUpdateLock();
618 
619  $this->removeCurrentSolution($active_id, $pass);
620 
621  $solutionSubmit = $this->getSolutionSubmit();
622 
623  foreach($solutionSubmit as $value)
624  {
625  if (strlen($value))
626  {
627  $this->saveCurrentSolution($active_id, $pass, $value, null);
628  $entered_values++;
629  }
630  }
631 
632  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
633 
634  if ($entered_values)
635  {
636  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
638  {
639  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
640  }
641  }
642  else
643  {
644  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
646  {
647  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
648  }
649  }
650 
651  return true;
652  }
653 
654  public function saveAdditionalQuestionDataToDb()
655  {
657  global $ilDB;
658  $oldthumbsize = 0;
659  if ($this->isSingleline && ($this->getThumbSize()))
660  {
661  // get old thumbnail size
662  $result = $ilDB->queryF( "SELECT thumb_size FROM " . $this->getAdditionalTableName(
663  ) . " WHERE question_fi = %s",
664  array( "integer" ),
665  array( $this->getId() )
666  );
667  if ($result->numRows() == 1)
668  {
669  $data = $ilDB->fetchAssoc( $result );
670  $oldthumbsize = $data['thumb_size'];
671  }
672  }
673 
674  if (!$this->isSingleline)
675  {
676  ilUtil::delDir( $this->getImagePath() );
677  }
678 
679  // save additional data
680  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
681  array( "integer" ),
682  array( $this->getId() )
683  );
684 
685  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName()
686  . " (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
687  array( "integer", "text", "text", "integer" ),
688  array(
689  $this->getId(),
690  $this->getShuffle(),
691  ($this->isSingleline) ? "0" : "1",
692  (strlen( $this->getThumbSize() ) == 0) ? null : $this->getThumbSize()
693  )
694  );
695  }
696 
697  public function saveAnswerSpecificDataToDb()
698  {
700  global $ilDB;
701  $ilDB->manipulateF( "DELETE FROM qpl_a_mc WHERE question_fi = %s",
702  array( 'integer' ),
703  array( $this->getId() )
704  );
705 
706  foreach ($this->answers as $key => $value)
707  {
708  $answer_obj = $this->answers[$key];
709  $next_id = $ilDB->nextId( 'qpl_a_mc' );
710  $ilDB->manipulateF( "INSERT INTO qpl_a_mc (answer_id, question_fi, answertext, points, points_unchecked, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
711  array( 'integer', 'integer', 'text', 'float', 'float', 'integer', 'text', 'integer' ),
712  array(
713  $next_id,
714  $this->getId(),
715  ilRTE::_replaceMediaObjectImageSrc( $answer_obj->getAnswertext(), 0 ),
716  $answer_obj->getPoints(),
717  $answer_obj->getPointsUnchecked(),
718  $answer_obj->getOrder(),
719  $answer_obj->getImage(),
720  time()
721  )
722  );
723  }
724  $this->rebuildThumbnails();
725  }
726 
734  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
735  {
736  // nothing to rework!
737  }
738 
739  function syncWithOriginal()
740  {
741  if ($this->getOriginalId())
742  {
743  $this->syncImages();
744  parent::syncWithOriginal();
745  }
746  }
747 
753  public function getQuestionType()
754  {
755  return "assMultipleChoice";
756  }
757 
763  public function getAdditionalTableName()
764  {
765  return "qpl_qst_mc";
766  }
767 
773  public function getAnswerTableName()
774  {
775  return "qpl_a_mc";
776  }
777 
785  public function setImageFile($image_filename, $image_tempfilename = "")
786  {
787  $result = 0;
788  if (!empty($image_tempfilename))
789  {
790  $image_filename = str_replace(" ", "_", $image_filename);
791  $imagepath = $this->getImagePath();
792  if (!file_exists($imagepath))
793  {
794  ilUtil::makeDirParents($imagepath);
795  }
796  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
797  {
798  $result = 2;
799  }
800  else
801  {
802  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
803  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
804  if (!preg_match("/^image/", $mimetype))
805  {
806  unlink($imagepath . $image_filename);
807  $result = 1;
808  }
809  else
810  {
811  // create thumbnail file
812  if ($this->isSingleline && ($this->getThumbSize()))
813  {
814  $this->generateThumbForFile($imagepath, $image_filename);
815  }
816  }
817  }
818  }
819  return $result;
820  }
821 
827  protected function deleteImage($image_filename)
828  {
829  $imagepath = $this->getImagePath();
830  @unlink($imagepath . $image_filename);
831  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
832  @unlink($thumbpath);
833  }
834 
835  function duplicateImages($question_id, $objectId = null)
836  {
837  global $ilLog;
838  $imagepath = $this->getImagePath();
839  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
840 
841  if( (int)$objectId > 0 )
842  {
843  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
844  }
845 
846  foreach ($this->answers as $answer)
847  {
848  $filename = $answer->getImage();
849  if (strlen($filename))
850  {
851  if (!file_exists($imagepath))
852  {
853  ilUtil::makeDirParents($imagepath);
854  }
855  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
856  {
857  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
858  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
859  }
860  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
861  {
862  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
863  {
864  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
865  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
866  }
867  }
868  }
869  }
870  }
871 
872  function copyImages($question_id, $source_questionpool)
873  {
874  global $ilLog;
875  $imagepath = $this->getImagePath();
876  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
877  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
878  foreach ($this->answers as $answer)
879  {
880  $filename = $answer->getImage();
881  if (strlen($filename))
882  {
883  if (!file_exists($imagepath))
884  {
885  ilUtil::makeDirParents($imagepath);
886  }
887  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
888  {
889  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
890  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
891  }
892  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
893  {
894  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
895  {
896  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
897  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
898  }
899  }
900  }
901  }
902  }
903 
907  protected function syncImages()
908  {
909  global $ilLog;
910 
911  $imagepath = $this->getImagePath();
912 
913  $question_id = $this->getOriginalId();
914  $originalObjId = parent::lookupParentObjId($this->getOriginalId());
915  $imagepath_original = $this->getImagePath($question_id, $originalObjId);
916 
917  ilUtil::delDir($imagepath_original);
918  foreach ($this->answers as $answer)
919  {
920  $filename = $answer->getImage();
921  if (strlen($filename))
922  {
923  if (@file_exists($imagepath . $filename))
924  {
925  if (!file_exists($imagepath))
926  {
927  ilUtil::makeDirParents($imagepath);
928  }
929  if (!file_exists($imagepath_original))
930  {
931  ilUtil::makeDirParents($imagepath_original);
932  }
933  if (!@copy($imagepath . $filename, $imagepath_original . $filename))
934  {
935  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
936  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
937  }
938  }
939  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename))
940  {
941  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename))
942  {
943  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
944  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
945  }
946  }
947  }
948  }
949  }
950 
955  {
956  $text = parent::getRTETextWithMediaObjects();
957  foreach ($this->answers as $index => $answer)
958  {
959  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
960  $answer_obj = $this->answers[$index];
961  $text .= $answer_obj->getAnswertext();
962  }
963  return $text;
964  }
965 
969  function &getAnswers()
970  {
971  return $this->answers;
972  }
973 
986  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
987  {
988  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
989  $solution = $this->getSolutionValues($active_id, $pass);
990  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
991  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
992  $i = 1;
993  foreach ($this->getAnswers() as $id => $answer)
994  {
995  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($answer->getAnswertext()), $format_bold);
996  $checked = FALSE;
997  foreach ($solution as $solutionvalue)
998  {
999  if ($id == $solutionvalue["value1"])
1000  {
1001  $checked = TRUE;
1002  }
1003  }
1004  if ($checked)
1005  {
1006  $worksheet->write($startrow + $i, 1, 1);
1007  }
1008  else
1009  {
1010  $worksheet->write($startrow + $i, 1, 0);
1011  }
1012  $i++;
1013  }
1014  return $startrow + $i + 1;
1015  }
1016 
1017  public function getThumbSize()
1018  {
1019  return $this->thumb_size;
1020  }
1021 
1022  public function setThumbSize($a_size)
1023  {
1024  $this->thumb_size = $a_size;
1025  }
1026 
1030  public function toJSON()
1031  {
1032  require_once './Services/RTE/classes/class.ilRTE.php';
1033  $result = array();
1034  $result['id'] = (int) $this->getId();
1035  $result['type'] = (string) $this->getQuestionType();
1036  $result['title'] = (string) $this->getTitle();
1037  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1038  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1039  $result['shuffle'] = (bool) $this->getShuffle();
1040  $result['feedback'] = array(
1041  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1042  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1043  );
1044 
1045  $answers = array();
1046  $has_image = false;
1047  foreach ($this->getAnswers() as $key => $answer_obj)
1048  {
1049  if((string) $answer_obj->getImage())
1050  {
1051  $has_image = true;
1052  }
1053  array_push($answers, array(
1054  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1055  "points_checked" => (float) $answer_obj->getPointsChecked(),
1056  "points_unchecked" => (float) $answer_obj->getPointsUnchecked(),
1057  "order" => (int) $answer_obj->getOrder(),
1058  "image" => (string) $answer_obj->getImage(),
1059  "feedback" => $this->formatSAQuestion(
1060  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
1061  )
1062  ));
1063  }
1064  $result['answers'] = $answers;
1065 
1066  if($has_image)
1067  {
1068  $result['path'] = $this->getImagePathWeb();
1069  $result['thumb'] = $this->getThumbSize();
1070  }
1071 
1072  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1073  $result['mobs'] = $mobs;
1074 
1075  return json_encode($result);
1076  }
1077 
1078  public function removeAnswerImage($index)
1079  {
1080  $answer = $this->answers[$index];
1081  if (is_object($answer))
1082  {
1083  $this->deleteImage($answer->getImage());
1084  $answer->setImage('');
1085  }
1086  }
1087 
1089  {
1090  global $ilUser;
1091 
1092  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1093  if ($multilineAnswerSetting != 1)
1094  {
1095  $multilineAnswerSetting = 0;
1096  }
1097  return $multilineAnswerSetting;
1098  }
1099 
1100  function setMultilineAnswerSetting($a_setting = 0)
1101  {
1102  global $ilUser;
1103  $ilUser->writePref("tst_multiline_answers", $a_setting);
1104  }
1105 
1115  function setSpecificFeedbackSetting($a_feedback_setting)
1116  {
1117  $this->feedback_setting = $a_feedback_setting;
1118  }
1119 
1130  {
1131  if ($this->feedback_setting)
1132  {
1133  return $this->feedback_setting;
1134  }
1135  else
1136  {
1137  return 1;
1138  }
1139  }
1140 
1152  public function isAnswered($active_id, $pass)
1153  {
1154  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1155 
1156  return $numExistingSolutionRecords > 0;
1157  }
1158 
1170  public static function isObligationPossible($questionId)
1171  {
1173  global $ilDB;
1174 
1175  $query = "
1176  SELECT SUM(points) points_for_checked_answers
1177  FROM qpl_a_mc
1178  WHERE question_fi = %s AND points > 0
1179  ";
1180 
1181  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1182 
1183  $row = $ilDB->fetchAssoc($res);
1184 
1185  return $row['points_for_checked_answers'] > 0;
1186  }
1187 
1196  public function ensureNoInvalidObligation($questionId)
1197  {
1199  global $ilDB;
1200 
1201  $query = "
1202  SELECT SUM(qpl_a_mc.points) points_for_checked_answers,
1203  test_question_id
1204 
1205  FROM tst_test_question
1206 
1207  INNER JOIN qpl_a_mc
1208  ON qpl_a_mc.question_fi = tst_test_question.question_fi
1209 
1210  WHERE tst_test_question.question_fi = %s
1211  AND tst_test_question.obligatory = 1
1212 
1213  GROUP BY test_question_id
1214  ";
1215 
1216  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1217 
1218  $updateTestQuestionIds = array();
1219 
1220  while( $row = $ilDB->fetchAssoc($res) )
1221  {
1222  if( $row['points_for_checked_answers'] <= 0 )
1223  {
1224  $updateTestQuestionIds[] = $row['test_question_id'];
1225  }
1226  }
1227 
1228  if( count($updateTestQuestionIds) )
1229  {
1230  $test_question_id__IN__updateTestQuestionIds = $ilDB->in(
1231  'test_question_id', $updateTestQuestionIds, false, 'integer'
1232  );
1233 
1234  $query = "
1235  UPDATE tst_test_question
1236  SET obligatory = 0
1237  WHERE $test_question_id__IN__updateTestQuestionIds
1238  ";
1239 
1240  $ilDB->manipulate($query);
1241  }
1242  }
1243 
1247  protected function getSolutionSubmit()
1248  {
1249  $solutionSubmit = array();
1250  foreach($_POST as $key => $value)
1251  {
1252  if(preg_match("/^multiple_choice_result_(\d+)/", $key))
1253  {
1254  if(strlen($value))
1255  {
1256  $solutionSubmit[] = $value;
1257  }
1258  }
1259  }
1260  return $solutionSubmit;
1261  }
1262 
1268  protected function calculateReachedPointsForSolution($found_values, $active_id = 0)
1269  {
1270  $points = 0;
1271  foreach($this->answers as $key => $answer)
1272  {
1273  if(in_array($key, $found_values))
1274  {
1275  $points += $answer->getPoints();
1276  } else
1277  {
1278  $points += $answer->getPointsUnchecked();
1279  }
1280  }
1281  if($active_id)
1282  {
1283  include_once "./Modules/Test/classes/class.ilObjTest.php";
1284  $mc_scoring = ilObjTest::_getMCScoring($active_id);
1285  if(($mc_scoring == 0) && (count($found_values) == 0))
1286  {
1287  $points = 0;
1288  }
1289  }
1290  return $points;
1291  }
1292 
1301  public function getOperators($expression)
1302  {
1303  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1305  }
1306 
1311  public function getExpressionTypes()
1312  {
1313  return array(
1318  );
1319  }
1320 
1329  public function getUserQuestionResult($active_id, $pass)
1330  {
1332  global $ilDB;
1333  $result = new ilUserQuestionResult($this, $active_id, $pass);
1334 
1335  $data = $ilDB->queryF(
1336  "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = (
1337  SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s
1338  )",
1339  array("integer", "integer", "integer","integer", "integer", "integer"),
1340  array($active_id, $pass, $this->getId(), $active_id, $pass, $this->getId())
1341  );
1342 
1343  while($row = $ilDB->fetchAssoc($data))
1344  {
1345  $result->addKeyValue($row["value1"], $row["value1"]);
1346  }
1347 
1348  $points = $this->calculateReachedPoints($active_id, $pass);
1349  $max_points = $this->getMaximumPoints();
1350 
1351  $result->setReachedPercentage(($points/$max_points) * 100);
1352 
1353  return $result;
1354  }
1355 
1364  public function getAvailableAnswerOptions($index = null)
1365  {
1366  if($index !== null)
1367  {
1368  return $this->getAnswer($index);
1369  }
1370  else
1371  {
1372  return $this->getAnswers();
1373  }
1374  }
1375 }
flushAnswers()
Deletes all answers.
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
calculateReachedPointsForSolution($found_values, $active_id=0)
static makeDirParents($a_dir)
Create a new directory and all parent directories.
getId()
Gets the id of the assQuestion object.
addAnswer( $answertext="", $points=0.0, $points_unchecked=0.0, $order=0, $answerimage="")
Adds a possible answer for a multiple choice question.
print $file
duplicateImages($question_id, $objectId=null)
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
toJSON()
Returns a JSON representation of the question.
Class iQuestionCondition.
generateThumbForFile($path, $file)
$_POST['username']
Definition: cron.php:12
isComplete()
Returns true, if a multiple choice question is complete for use.
isAnswered($active_id, $pass)
returns boolean wether the question is answered during test pass or not
static getNumExistingSolutionRecords($activeId, $pass, $questionId)
returns the number of existing solution records for the given test active / pass and given question i...
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assMultipleChoiceQuestion.
copyObject($target_questionpool_id, $title="")
Copies an assMultipleChoice object.
$result
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
rebuildThumbnails()
Rebuild the thumbnail images with a new thumbnail size.
& getSolutionValues($active_id, $pass=NULL)
Loads solutions of a given user from the database an returns it.
Abstract basic class which is to be extended by the concrete assessment question type classes...
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
_convert_text($a_text, $a_target="has been removed")
ASS_AnswerBinaryStateImage is a class for answers with a binary state indicator (checked/unchecked, set/unset) and an image file.
setId($id=-1)
Sets the id of the assQuestion object.
_getMCScoring($active_id)
Gets the scoring type for multiple choice questions.
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. ...
setOutputType($output_type=OUTPUT_ORDER)
Sets the output type of the assMultipleChoice object.
getQuestionType()
Returns the question type of the question.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
setNrOfTries($a_nr_of_tries)
_enabledAssessmentLogging()
check wether assessment logging is enabled or not
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
loadFromDb($question_id)
Loads a assMultipleChoice object from a database.
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...
Class for multiple choice tests.
getObjId()
Get the object id of the container object.
getShuffle()
Gets the shuffle flag.
Base Exception for all Exceptions relating to Modules/Test.
static getMimeType($a_file)
get mime type for file
saveToDb($original_id="")
Saves a assMultipleChoice object to a database.
deleteAnswer($index=0)
Deletes an answer with a given index.
reworkWorkingData($active_id, $pass, $obligationsAnswered)
Reworks the allready saved working data if neccessary.
setAuthor($author="")
Sets the authors name of the assQuestion object.
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
$mobs
Class ilUserQuestionResult.
getAnswerCount()
Returns the number of answers.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
getSpecificFeedbackSetting()
Gets the current feedback settings in effect for the question.
Interface ilObjAnswerScoringAdjustable.
getQuestion()
Gets the question string of the question object.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $output_type=OUTPUT_ORDER)
assMultipleChoice constructor
syncImages()
Sync images of a MC question on synchronisation with the original question.
getOperators($expression)
Get all available operations for a specific question.
setIsSingleline($isSingleline)
getAnswer($index=0)
Returns an answer with a given index.
& getAnswers()
Returns a reference to the answers array.
setSpecificFeedbackSetting($a_feedback_setting)
Sets the feedback settings in effect for the question.
deleteImage($image_filename)
Deletes an image file.
getExpressionTypes()
Get all available expression types for a specific question.
_getLogLanguage()
retrieve the log language for assessment logging
$filename
Definition: buildRTE.php:89
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
setImageFile($image_filename, $image_tempfilename="")
Sets the image file and uploads the image to the object&#39;s image directory.
calculateReachedPoints($active_id, $pass=NULL, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
global $ilUser
Definition: imgupload.php:15
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
Interface ilObjQuestionScoringAdjustable.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
$path
Definition: index.php:22
global $ilDB
setOriginalId($original_id)
getAnswerTableName()
Returns the name of the answer table in the database.
logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getTitle()
Gets the title string of the assQuestion object.
const OUTPUT_ORDER
getOutputType()
Gets the multiple choice output type which is either OUTPUT_ORDER (=0) or OUTPUT_RANDOM (=1)...
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.
setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
Creates an Excel worksheet for the detailed cumulated results of this question.
setMultilineAnswerSetting($a_setting=0)
copyImages($question_id, $source_questionpool)
saveWorkingData($active_id, $pass=NULL)
Saves the learners input of the question to the database.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.