ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 require_once 'Modules/TestQuestionPool/interfaces/interface.ilAssSpecificFeedbackOptionLabelProvider.php';
11 
28 {
36  var $answers;
37 
47 
48  public $isSingleline;
49  public $lastChange;
51 
53  protected $thumb_size;
54 
58  public function setIsSingleline($isSingleline)
59  {
60  $this->isSingleline = $isSingleline;
61  }
62 
66  public function getIsSingleline()
67  {
68  return $this->isSingleline;
69  }
70 
74  public function setLastChange($lastChange)
75  {
76  $this->lastChange = $lastChange;
77  }
78 
82  public function getLastChange()
83  {
84  return $this->lastChange;
85  }
86 
101  public function __construct(
102  $title = "",
103  $comment = "",
104  $author = "",
105  $owner = -1,
106  $question = "",
107  $output_type = OUTPUT_ORDER
108  )
109  {
110  parent::__construct($title, $comment, $author, $owner, $question);
111  $this->output_type = $output_type;
112  $this->thumb_size = 150;
113  $this->answers = array();
114  $this->shuffle = 1;
115  }
116 
123  function isComplete()
124  {
125  if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->getMaximumPoints() > 0))
126  {
127  return true;
128  }
129  else
130  {
131  return false;
132  }
133  }
134 
140  public function saveToDb($original_id = "")
141  {
145 
146  $this->ensureNoInvalidObligation($this->getId());
147  parent::saveToDb($original_id);
148  }
149 
153  protected function rebuildThumbnails()
154  {
155  if ($this->isSingleline && ($this->getThumbSize()))
156  {
157  foreach ($this->getAnswers() as $answer)
158  {
159  if (strlen($answer->getImage()))
160  {
161  $this->generateThumbForFile($this->getImagePath(), $answer->getImage());
162  }
163  }
164  }
165  }
166 
170  public function getThumbPrefix()
171  {
172  return "thumb.";
173  }
174 
179  protected function generateThumbForFile($path, $file)
180  {
181  $filename = $path . $file;
182  if (@file_exists($filename))
183  {
184  $thumbpath = $path . $this->getThumbPrefix() . $file;
185  $path_info = @pathinfo($filename);
186  $ext = "";
187  switch (strtoupper($path_info['extension']))
188  {
189  case 'PNG':
190  $ext = 'PNG';
191  break;
192  case 'GIF':
193  $ext = 'GIF';
194  break;
195  default:
196  $ext = 'JPEG';
197  break;
198  }
199  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbSize());
200  }
201  }
202 
208  public function loadFromDb($question_id)
209  {
210  global $ilDB;
211  $hasimages = 0;
212 
213  $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",
214  array("integer"),
215  array($question_id)
216  );
217  if ($result->numRows() == 1)
218  {
219  $data = $ilDB->fetchAssoc($result);
220  $this->setId($question_id);
221  $this->setObjId($data["obj_fi"]);
222  $this->setTitle($data["title"]);
223  $this->setNrOfTries($data['nr_of_tries']);
224  $this->setComment($data["description"]);
225  $this->setOriginalId($data["original_id"]);
226  $this->setAuthor($data["author"]);
227  $this->setPoints($data["points"]);
228  $this->setOwner($data["owner"]);
229  include_once("./Services/RTE/classes/class.ilRTE.php");
230  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
231  $shuffle = (is_null($data['shuffle'])) ? true : $data['shuffle'];
232  $this->setShuffle($shuffle);
233  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
234  $this->setThumbSize($data['thumb_size']);
235  $this->isSingleline = ($data['allow_images']) ? false : true;
236  $this->lastChange = $data['tstamp'];
237  $this->feedback_setting = $data['feedback_setting'];
238 
239  try
240  {
241  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
242  }
244  {
245  }
246  }
247 
248  $result = $ilDB->queryF("SELECT * FROM qpl_a_mc WHERE question_fi = %s ORDER BY aorder ASC",
249  array('integer'),
250  array($question_id)
251  );
252  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
253  if ($result->numRows() > 0)
254  {
255  while ($data = $ilDB->fetchAssoc($result))
256  {
257  $imagefilename = $this->getImagePath() . $data["imagefile"];
258  if (!@file_exists($imagefilename))
259  {
260  $data["imagefile"] = "";
261  }
262  include_once("./Services/RTE/classes/class.ilRTE.php");
263  $data["answertext"] = ilRTE::_replaceMediaObjectImageSrc($data["answertext"], 1);
264  array_push($this->answers, new ASS_AnswerMultipleResponseImage($data["answertext"], $data["points"], $data["aorder"], $data["points_unchecked"], $data["imagefile"]));
265  }
266  }
267 
268  parent::loadFromDb($question_id);
269  }
270 
274  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
275  {
276  if ($this->id <= 0)
277  {
278  // The question has not been saved. It cannot be duplicated
279  return;
280  }
281  // duplicate the question in database
282  $this_id = $this->getId();
283  $thisObjId = $this->getObjId();
284 
285  $clone = $this;
286  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
288  $clone->id = -1;
289 
290  if( (int)$testObjId > 0 )
291  {
292  $clone->setObjId($testObjId);
293  }
294 
295  if ($title)
296  {
297  $clone->setTitle($title);
298  }
299 
300  if ($author)
301  {
302  $clone->setAuthor($author);
303  }
304  if ($owner)
305  {
306  $clone->setOwner($owner);
307  }
308 
309  if ($for_test)
310  {
311  $clone->saveToDb($original_id);
312  }
313  else
314  {
315  $clone->saveToDb();
316  }
317 
318  // copy question page content
319  $clone->copyPageOfQuestion($this_id);
320  // copy XHTML media objects
321  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
322  // duplicate the images
323  $clone->duplicateImages($this_id, $thisObjId);
324 
325  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
326 
327  return $clone->id;
328  }
329 
333  public function copyObject($target_questionpool_id, $title = "")
334  {
335  if ($this->id <= 0)
336  {
337  // The question has not been saved. It cannot be duplicated
338  return;
339  }
340  // duplicate the question in database
341  $clone = $this;
342  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
344  $clone->id = -1;
345  $source_questionpool_id = $this->getObjId();
346  $clone->setObjId($target_questionpool_id);
347  if ($title)
348  {
349  $clone->setTitle($title);
350  }
351  $clone->saveToDb();
352  // copy question page content
353  $clone->copyPageOfQuestion($original_id);
354  // copy XHTML media objects
355  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
356  // duplicate the image
357  $clone->copyImages($original_id, $source_questionpool_id);
358 
359  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
360 
361  return $clone->id;
362  }
363 
364  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
365  {
366  if ($this->id <= 0)
367  {
368  // The question has not been saved. It cannot be duplicated
369  return;
370  }
371 
372  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
373 
374  $sourceQuestionId = $this->id;
375  $sourceParentId = $this->getObjId();
376 
377  // duplicate the question in database
378  $clone = $this;
379  $clone->id = -1;
380 
381  $clone->setObjId($targetParentId);
382 
383  if ($targetQuestionTitle)
384  {
385  $clone->setTitle($targetQuestionTitle);
386  }
387 
388  $clone->saveToDb();
389  // copy question page content
390  $clone->copyPageOfQuestion($sourceQuestionId);
391  // copy XHTML media objects
392  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
393  // duplicate the image
394  $clone->copyImages($sourceQuestionId, $sourceParentId);
395 
396  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
397 
398  return $clone->id;
399  }
400 
407  public function getOutputType()
408  {
409  return $this->output_type;
410  }
411 
419  public function setOutputType($output_type = OUTPUT_ORDER)
420  {
421  $this->output_type = $output_type;
422  }
423 
437  public function addAnswer(
438  $answertext = "",
439  $points = 0.0,
440  $points_unchecked = 0.0,
441  $order = 0,
442  $answerimage = ""
443  )
444  {
445  include_once "./Modules/TestQuestionPool/classes/class.assAnswerMultipleResponseImage.php";
446  if (array_key_exists($order, $this->answers))
447  {
448  // insert answer
449  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, $order, $points_unchecked, $answerimage);
450  $newchoices = array();
451  for ($i = 0; $i < $order; $i++)
452  {
453  array_push($newchoices, $this->answers[$i]);
454  }
455  array_push($newchoices, $answer);
456  for ($i = $order; $i < count($this->answers); $i++)
457  {
458  $changed = $this->answers[$i];
459  $changed->setOrder($i+1);
460  array_push($newchoices, $changed);
461  }
462  $this->answers = $newchoices;
463  }
464  else
465  {
466  // add answer
467  $answer = new ASS_AnswerMultipleResponseImage($answertext, $points, count($this->answers), $points_unchecked, $answerimage);
468  array_push($this->answers, $answer);
469  }
470  }
471 
478  public function getAnswerCount()
479  {
480  return count($this->answers);
481  }
482 
491  public function getAnswer($index = 0)
492  {
493  if ($index < 0) return NULL;
494  if (count($this->answers) < 1) return NULL;
495  if ($index >= count($this->answers)) return NULL;
496 
497  return $this->answers[$index];
498  }
499 
507  public function deleteAnswer($index = 0)
508  {
509  if ($index < 0) return;
510  if (count($this->answers) < 1) return;
511  if ($index >= count($this->answers)) return;
512  $answer = $this->answers[$index];
513  if (strlen($answer->getImage())) $this->deleteImage($answer->getImage());
514  unset($this->answers[$index]);
515  $this->answers = array_values($this->answers);
516  for ($i = 0; $i < count($this->answers); $i++)
517  {
518  if ($this->answers[$i]->getOrder() > $index)
519  {
520  $this->answers[$i]->setOrder($i);
521  }
522  }
523  }
524 
530  public function flushAnswers()
531  {
532  $this->answers = array();
533  }
534 
540  public function getMaximumPoints()
541  {
542  $points = 0;
543  $allpoints = 0;
544  foreach ($this->answers as $key => $value)
545  {
546  if ($value->getPoints() > $value->getPointsUnchecked())
547  {
548  $allpoints += $value->getPoints();
549  }
550  else
551  {
552  $allpoints += $value->getPointsUnchecked();
553  }
554  }
555  return $allpoints;
556  }
557 
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 
592  $points = $this->calculateReachedPointsForSolution($found_values, $active_id);
593 
594  return $points;
595  }
596 
605  public function saveWorkingData($active_id, $pass = NULL, $authorized = true)
606  {
608  global $ilDB;
609 
610  if (is_null($pass))
611  {
612  include_once "./Modules/Test/classes/class.ilObjTest.php";
613  $pass = ilObjTest::_getPass($active_id);
614  }
615 
616  $entered_values = 0;
617 
618  $this->getProcessLocker()->requestUserSolutionUpdateLock();
619 
620  $this->removeCurrentSolution($active_id, $pass, $authorized);
621 
622  $solutionSubmit = $this->getSolutionSubmit();
623 
624  foreach($solutionSubmit as $value)
625  {
626  if (strlen($value))
627  {
628  $this->saveCurrentSolution($active_id, $pass, $value, null, $authorized);
629  $entered_values++;
630  }
631  }
632 
633  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
634 
635  if ($entered_values)
636  {
637  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
639  {
640  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
641  }
642  }
643  else
644  {
645  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
647  {
648  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
649  }
650  }
651 
652  return true;
653  }
654 
655  public function saveAdditionalQuestionDataToDb()
656  {
658  global $ilDB;
659  $oldthumbsize = 0;
660  if ($this->isSingleline && ($this->getThumbSize()))
661  {
662  // get old thumbnail size
663  $result = $ilDB->queryF( "SELECT thumb_size FROM " . $this->getAdditionalTableName(
664  ) . " WHERE question_fi = %s",
665  array( "integer" ),
666  array( $this->getId() )
667  );
668  if ($result->numRows() == 1)
669  {
670  $data = $ilDB->fetchAssoc( $result );
671  $oldthumbsize = $data['thumb_size'];
672  }
673  }
674 
675  if (!$this->isSingleline)
676  {
677  ilUtil::delDir( $this->getImagePath() );
678  }
679 
680  // save additional data
681  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
682  array( "integer" ),
683  array( $this->getId() )
684  );
685 
686  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName()
687  . " (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
688  array( "integer", "text", "text", "integer" ),
689  array(
690  $this->getId(),
691  $this->getShuffle(),
692  ($this->isSingleline) ? "0" : "1",
693  (strlen( $this->getThumbSize() ) == 0) ? null : $this->getThumbSize()
694  )
695  );
696  }
697 
698  public function saveAnswerSpecificDataToDb()
699  {
701  global $ilDB;
702  $ilDB->manipulateF( "DELETE FROM qpl_a_mc WHERE question_fi = %s",
703  array( 'integer' ),
704  array( $this->getId() )
705  );
706 
707  foreach ($this->answers as $key => $value)
708  {
709  $answer_obj = $this->answers[$key];
710  $next_id = $ilDB->nextId( 'qpl_a_mc' );
711  $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)",
712  array( 'integer', 'integer', 'text', 'float', 'float', 'integer', 'text', 'integer' ),
713  array(
714  $next_id,
715  $this->getId(),
716  ilRTE::_replaceMediaObjectImageSrc( $answer_obj->getAnswertext(), 0 ),
717  $answer_obj->getPoints(),
718  $answer_obj->getPointsUnchecked(),
719  $answer_obj->getOrder(),
720  $answer_obj->getImage(),
721  time()
722  )
723  );
724  }
725  $this->rebuildThumbnails();
726  }
727 
735  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
736  {
737  // nothing to rework!
738  }
739 
740  function syncWithOriginal()
741  {
742  if ($this->getOriginalId())
743  {
744  $this->syncImages();
745  parent::syncWithOriginal();
746  }
747  }
748 
754  public function getQuestionType()
755  {
756  return "assMultipleChoice";
757  }
758 
764  public function getAdditionalTableName()
765  {
766  return "qpl_qst_mc";
767  }
768 
774  public function getAnswerTableName()
775  {
776  return "qpl_a_mc";
777  }
778 
786  public function setImageFile($image_filename, $image_tempfilename = "")
787  {
788  $result = 0;
789  if (!empty($image_tempfilename))
790  {
791  $image_filename = str_replace(" ", "_", $image_filename);
792  $imagepath = $this->getImagePath();
793  if (!file_exists($imagepath))
794  {
795  ilUtil::makeDirParents($imagepath);
796  }
797  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
798  {
799  $result = 2;
800  }
801  else
802  {
803  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
804  $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
805  if (!preg_match("/^image/", $mimetype))
806  {
807  unlink($imagepath . $image_filename);
808  $result = 1;
809  }
810  else
811  {
812  // create thumbnail file
813  if ($this->isSingleline && ($this->getThumbSize()))
814  {
815  $this->generateThumbForFile($imagepath, $image_filename);
816  }
817  }
818  }
819  }
820  return $result;
821  }
822 
828  protected function deleteImage($image_filename)
829  {
830  $imagepath = $this->getImagePath();
831  @unlink($imagepath . $image_filename);
832  $thumbpath = $imagepath . $this->getThumbPrefix() . $image_filename;
833  @unlink($thumbpath);
834  }
835 
836  function duplicateImages($question_id, $objectId = null)
837  {
839  global $ilLog;
840 
841  $imagepath = $this->getImagePath();
842  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
843 
844  if( (int)$objectId > 0 )
845  {
846  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
847  }
848 
849  foreach ($this->answers as $answer)
850  {
851  $filename = $answer->getImage();
852  if (strlen($filename))
853  {
854  if (!file_exists($imagepath))
855  {
856  ilUtil::makeDirParents($imagepath);
857  }
858  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
859  {
860  $ilLog->warning(sprintf(
861  "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
862  $imagepath_original . $filename, $imagepath . $filename,
863  $question_id, $this->id, $objectId, $this->obj_id
864  ));
865  }
866  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
867  {
868  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
869  {
870  $ilLog->warning(sprintf(
871  "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
872  $imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename,
873  $question_id, $this->id, $objectId, $this->obj_id
874  ));
875  }
876  }
877  }
878  }
879  }
880 
881  function copyImages($question_id, $source_questionpool)
882  {
883  global $ilLog;
884  $imagepath = $this->getImagePath();
885  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
886  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
887  foreach ($this->answers as $answer)
888  {
889  $filename = $answer->getImage();
890  if (strlen($filename))
891  {
892  if (!file_exists($imagepath))
893  {
894  ilUtil::makeDirParents($imagepath);
895  }
896  if (!@copy($imagepath_original . $filename, $imagepath . $filename))
897  {
898  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
899  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
900  }
901  if (@file_exists($imagepath_original. $this->getThumbPrefix(). $filename))
902  {
903  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename))
904  {
905  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
906  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
907  }
908  }
909  }
910  }
911  }
912 
916  protected function syncImages()
917  {
918  global $ilLog;
919 
920  $imagepath = $this->getImagePath();
921 
922  $question_id = $this->getOriginalId();
923  $originalObjId = parent::lookupParentObjId($this->getOriginalId());
924  $imagepath_original = $this->getImagePath($question_id, $originalObjId);
925 
926  ilUtil::delDir($imagepath_original);
927  foreach ($this->answers as $answer)
928  {
929  $filename = $answer->getImage();
930  if (strlen($filename))
931  {
932  if (@file_exists($imagepath . $filename))
933  {
934  if (!file_exists($imagepath))
935  {
936  ilUtil::makeDirParents($imagepath);
937  }
938  if (!file_exists($imagepath_original))
939  {
940  ilUtil::makeDirParents($imagepath_original);
941  }
942  if (!@copy($imagepath . $filename, $imagepath_original . $filename))
943  {
944  $ilLog->write("image could not be duplicated!!!!", $ilLog->ERROR);
945  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
946  }
947  }
948  if (@file_exists($imagepath . $this->getThumbPrefix() . $filename))
949  {
950  if (!@copy($imagepath . $this->getThumbPrefix() . $filename, $imagepath_original . $this->getThumbPrefix() . $filename))
951  {
952  $ilLog->write("image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
953  $ilLog->write("object: " . print_r($this, TRUE), $ilLog->ERROR);
954  }
955  }
956  }
957  }
958  }
959 
964  {
965  $text = parent::getRTETextWithMediaObjects();
966  foreach ($this->answers as $index => $answer)
967  {
968  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
969  $answer_obj = $this->answers[$index];
970  $text .= $answer_obj->getAnswertext();
971  }
972  return $text;
973  }
974 
978  function &getAnswers()
979  {
980  return $this->answers;
981  }
982 
995  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
996  {
997  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
998  $solution = $this->getSolutionValues($active_id, $pass);
999  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
1000  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
1001  $i = 1;
1002  foreach ($this->getAnswers() as $id => $answer)
1003  {
1004  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($answer->getAnswertext()), $format_bold);
1005  $checked = FALSE;
1006  foreach ($solution as $solutionvalue)
1007  {
1008  if ($id == $solutionvalue["value1"])
1009  {
1010  $checked = TRUE;
1011  }
1012  }
1013  if ($checked)
1014  {
1015  $worksheet->write($startrow + $i, 1, 1);
1016  }
1017  else
1018  {
1019  $worksheet->write($startrow + $i, 1, 0);
1020  }
1021  $i++;
1022  }
1023  return $startrow + $i + 1;
1024  }
1025 
1026  public function getThumbSize()
1027  {
1028  return $this->thumb_size;
1029  }
1030 
1031  public function setThumbSize($a_size)
1032  {
1033  $this->thumb_size = $a_size;
1034  }
1035 
1040  {
1041  foreach($this->getAnswers() as $answer)
1042  {
1043  /* @var ASS_AnswerBinaryStateImage $answer */
1044  $answer->setAnswertext( $migrator->migrateToLmContent($answer->getAnswertext()) );
1045  }
1046  }
1047 
1051  public function toJSON()
1052  {
1053  require_once './Services/RTE/classes/class.ilRTE.php';
1054  $result = array();
1055  $result['id'] = (int) $this->getId();
1056  $result['type'] = (string) $this->getQuestionType();
1057  $result['title'] = (string) $this->getTitle();
1058  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1059  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1060  $result['shuffle'] = (bool) $this->getShuffle();
1061  $result['feedback'] = array(
1062  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1063  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1064  );
1065 
1066  $answers = array();
1067  $has_image = false;
1068  foreach ($this->getAnswers() as $key => $answer_obj)
1069  {
1070  if((string) $answer_obj->getImage())
1071  {
1072  $has_image = true;
1073  }
1074  array_push($answers, array(
1075  "answertext" => (string) $this->formatSAQuestion($answer_obj->getAnswertext()),
1076  "points_checked" => (float) $answer_obj->getPointsChecked(),
1077  "points_unchecked" => (float) $answer_obj->getPointsUnchecked(),
1078  "order" => (int) $answer_obj->getOrder(),
1079  "image" => (string) $answer_obj->getImage(),
1080  "feedback" => $this->formatSAQuestion(
1081  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
1082  )
1083  ));
1084  }
1085  $result['answers'] = $answers;
1086 
1087  if($has_image)
1088  {
1089  $result['path'] = $this->getImagePathWeb();
1090  $result['thumb'] = $this->getThumbSize();
1091  }
1092 
1093  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1094  $result['mobs'] = $mobs;
1095 
1096  return json_encode($result);
1097  }
1098 
1099  public function removeAnswerImage($index)
1100  {
1101  $answer = $this->answers[$index];
1102  if (is_object($answer))
1103  {
1104  $this->deleteImage($answer->getImage());
1105  $answer->setImage('');
1106  }
1107  }
1108 
1110  {
1111  global $ilUser;
1112 
1113  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
1114  if ($multilineAnswerSetting != 1)
1115  {
1116  $multilineAnswerSetting = 0;
1117  }
1118  return $multilineAnswerSetting;
1119  }
1120 
1121  function setMultilineAnswerSetting($a_setting = 0)
1122  {
1123  global $ilUser;
1124  $ilUser->writePref("tst_multiline_answers", $a_setting);
1125  }
1126 
1136  function setSpecificFeedbackSetting($a_feedback_setting)
1137  {
1138  $this->feedback_setting = $a_feedback_setting;
1139  }
1140 
1151  {
1152  if ($this->feedback_setting)
1153  {
1154  return $this->feedback_setting;
1155  }
1156  else
1157  {
1158  return 1;
1159  }
1160  }
1161 
1163  {
1164  return 'feedback_correct_sc_mc';
1165  }
1166 
1178  public function isAnswered($active_id, $pass = NULL)
1179  {
1180  $numExistingSolutionRecords = assQuestion::getNumExistingSolutionRecords($active_id, $pass, $this->getId());
1181 
1182  return $numExistingSolutionRecords > 0;
1183  }
1184 
1196  public static function isObligationPossible($questionId)
1197  {
1199  global $ilDB;
1200 
1201  $query = "
1202  SELECT SUM(points) points_for_checked_answers
1203  FROM qpl_a_mc
1204  WHERE question_fi = %s AND points > 0
1205  ";
1206 
1207  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1208 
1209  $row = $ilDB->fetchAssoc($res);
1210 
1211  return $row['points_for_checked_answers'] > 0;
1212  }
1213 
1222  public function ensureNoInvalidObligation($questionId)
1223  {
1225  global $ilDB;
1226 
1227  $query = "
1228  SELECT SUM(qpl_a_mc.points) points_for_checked_answers,
1229  test_question_id
1230 
1231  FROM tst_test_question
1232 
1233  INNER JOIN qpl_a_mc
1234  ON qpl_a_mc.question_fi = tst_test_question.question_fi
1235 
1236  WHERE tst_test_question.question_fi = %s
1237  AND tst_test_question.obligatory = 1
1238 
1239  GROUP BY test_question_id
1240  ";
1241 
1242  $res = $ilDB->queryF($query, array('integer'), array($questionId));
1243 
1244  $updateTestQuestionIds = array();
1245 
1246  while( $row = $ilDB->fetchAssoc($res) )
1247  {
1248  if( $row['points_for_checked_answers'] <= 0 )
1249  {
1250  $updateTestQuestionIds[] = $row['test_question_id'];
1251  }
1252  }
1253 
1254  if( count($updateTestQuestionIds) )
1255  {
1256  $test_question_id__IN__updateTestQuestionIds = $ilDB->in(
1257  'test_question_id', $updateTestQuestionIds, false, 'integer'
1258  );
1259 
1260  $query = "
1261  UPDATE tst_test_question
1262  SET obligatory = 0
1263  WHERE $test_question_id__IN__updateTestQuestionIds
1264  ";
1265 
1266  $ilDB->manipulate($query);
1267  }
1268  }
1269 
1273  protected function getSolutionSubmit()
1274  {
1275  $solutionSubmit = array();
1276  foreach($_POST as $key => $value)
1277  {
1278  if(preg_match("/^multiple_choice_result_(\d+)/", $key))
1279  {
1280  if(strlen($value))
1281  {
1282  $solutionSubmit[] = $value;
1283  }
1284  }
1285  }
1286  return $solutionSubmit;
1287  }
1288 
1294  protected function calculateReachedPointsForSolution($found_values, $active_id = 0)
1295  {
1296  $points = 0;
1297  foreach($this->answers as $key => $answer)
1298  {
1299  if(in_array($key, $found_values))
1300  {
1301  $points += $answer->getPoints();
1302  } else
1303  {
1304  $points += $answer->getPointsUnchecked();
1305  }
1306  }
1307  if($active_id)
1308  {
1309  include_once "./Modules/Test/classes/class.ilObjTest.php";
1310  $mc_scoring = ilObjTest::_getMCScoring($active_id);
1311  if(($mc_scoring == 0) && (count($found_values) == 0))
1312  {
1313  $points = 0;
1314  }
1315  }
1316  return $points;
1317  }
1318 
1327  public function getOperators($expression)
1328  {
1329  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1331  }
1332 
1337  public function getExpressionTypes()
1338  {
1339  return array(
1344  );
1345  }
1346 
1355  public function getUserQuestionResult($active_id, $pass)
1356  {
1358  global $ilDB;
1359  $result = new ilUserQuestionResult($this, $active_id, $pass);
1360 
1361  $maxStep = $this->lookupMaxStep($active_id, $pass);
1362 
1363  if( $maxStep !== null )
1364  {
1365  $data = $ilDB->queryF(
1366  "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1367  array("integer", "integer", "integer","integer"),
1368  array($active_id, $pass, $this->getId(), $maxStep)
1369  );
1370  }
1371  else
1372  {
1373  $data = $ilDB->queryF(
1374  "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1375  array("integer", "integer", "integer"),
1376  array($active_id, $pass, $this->getId())
1377  );
1378  }
1379 
1380  while($row = $ilDB->fetchAssoc($data))
1381  {
1382  $result->addKeyValue($row["value1"], $row["value1"]);
1383  }
1384 
1385  $points = $this->calculateReachedPoints($active_id, $pass);
1386  $max_points = $this->getMaximumPoints();
1387 
1388  $result->setReachedPercentage(($points/$max_points) * 100);
1389 
1390  return $result;
1391  }
1392 
1401  public function getAvailableAnswerOptions($index = null)
1402  {
1403  if($index !== null)
1404  {
1405  return $this->getAnswer($index);
1406  }
1407  else
1408  {
1409  return $this->getAnswers();
1410  }
1411  }
1412 }
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
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.
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.
isAnswered($active_id, $pass=NULL)
returns boolean wether the question is answered during test pass or not
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.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true)
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.
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
Base Exception for all Exceptions relating to Modules/Test.
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.
$data
$mobs
Class ilUserQuestionResult.
getAnswerCount()
Returns the number of answers.
removeCurrentSolution($active_id, $pass, $authorized=true, $ignoredSolutionIds=array())
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.
saveWorkingData($active_id, $pass=NULL, $authorized=true)
Saves the learners input of the question to the database.
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, $authorizedSolution=true, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
static getMimeType($a_file, $a_external=false)
get mime type for file
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)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
$text
getAnswerTableName()
Returns the name of the answer table in the database.
getSolutionValues($active_id, $pass=NULL, $authorized=true)
Loads solutions of a given user from the database an returns it.
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)
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.