ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 = "",
107  )
108  {
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());
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 
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();
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  {
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" => ilRTE::_replaceMediaObjectImageSrc(
1060  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key), 0
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 }