ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.assOrderingQuestion.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 
11 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssOrderingElementList.php';
12 
14 
30 {
31  const ORDERING_ELEMENT_FORM_FIELD_POSTVAR = 'order_elems';
32 
33  const ORDERING_ELEMENT_FORM_CMD_UPLOAD_IMG = 'uploadElementImage';
34  const ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG = 'removeElementImage'; //might actually go away - use ORDERING_ELEMENT_FORM_CMD_UPLOAD_IMG
35 
36  const OQ_PICTURES = 0;
37  const OQ_TERMS = 1;
38  const OQ_NESTED_PICTURES = 2;
39  const OQ_NESTED_TERMS = 3;
40 
41  const OQ_CT_PICTURES = 'pics';
42  const OQ_CT_TERMS = 'terms';
43 
44  const VALID_UPLOAD_SUFFIXES = ["jpg", "jpeg", "png", "gif"];
45 
46 
51 
56  protected $ordering_type;
57 
63  public $thumb_geometry = 100;
64 
71 
72  public $old_ordering_depth = array();
73  public $leveled_ordering = array();
74 
78  protected $oq_repository = null;
79 
92  public function __construct(
93  $title = "",
94  $comment = "",
95  $author = "",
96  $owner = -1,
97  $question = "",
99  ) {
101  $this->orderingElementList = new ilAssOrderingElementList();
102  $this->ordering_type = $ordering_type;
103  }
104 
110  public function isComplete() : bool
111  {
112  $elements = array_filter(
113  $this->getOrderingElementList()->getElements(),
114  function ($element) {
115  return trim($element->getContent()) != '';
116  }
117  );
118  $has_at_least_two_elements = count($elements) > 1;
119 
120  $complete = $this->getAuthor()
121  && $this->getTitle()
122  && $this->getQuestion()
123  && $this->getMaximumPoints()
124  && $has_at_least_two_elements;
125 
126  return $complete;
127  }
128 
129 
130 
131  protected function getRepository() : ILIAS\TA\Questions\Ordering\assOrderingQuestionDatabaseRepository
132  {
133  if (is_null($this->oq_repository)) {
134  global $DIC;
135  $ilDB = $DIC['ilDB'];
136  $this->oq_repository = new OQRepository($ilDB);
137  }
138  return $this->oq_repository;
139  }
140 
141 
149  public function saveToDb($original_id = "")
150  {
151  if ($original_id == '') {
152  $this->saveQuestionDataToDb();
153  } else {
154  $this->saveQuestionDataToDb((int) $original_id);
155  }
157  parent::saveToDb($original_id);
158  }
159 
167  public function loadFromDb($question_id)
168  {
169  global $DIC;
170  $ilDB = $DIC['ilDB'];
171 
172  $result = $ilDB->queryF(
173  "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",
174  array("integer"),
175  array($question_id)
176  );
177  if ($result->numRows() == 1) {
178  $data = $ilDB->fetchAssoc($result);
179  $this->setId($question_id);
180  $this->setObjId($data["obj_fi"]);
181  $this->setTitle($data["title"]);
182  $this->setComment($data["description"]);
183  $this->setOriginalId($data["original_id"]);
184  $this->setAuthor($data["author"]);
185  $this->setNrOfTries($data['nr_of_tries']);
186  $this->setPoints($data["points"]);
187  $this->setOwner($data["owner"]);
188  include_once("./Services/RTE/classes/class.ilRTE.php");
189  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
190  $this->ordering_type = strlen($data["ordering_type"]) ? $data["ordering_type"] : OQ_TERMS;
191  $this->thumb_geometry = $data["thumb_geometry"];
192  $this->element_height = $data["element_height"];
193  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
194 
195  try {
199  }
200 
201  try {
202  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
203  } catch (ilTestQuestionPoolException $e) {
204  }
205  }
206 
207  parent::loadFromDb($question_id);
208  }
209 
215  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
216  {
217  if ($this->id <= 0) {
218  // The question has not been saved. It cannot be duplicated
219  return;
220  }
221  // duplicate the question in database
222  $this_id = $this->getId();
223  $thisObjId = $this->getObjId();
224 
225  $clone = clone $this;
227  $clone->id = -1;
228 
229  if ((int) $testObjId > 0) {
230  $clone->setObjId($testObjId);
231  }
232 
233  if ($title) {
234  $clone->setTitle($title);
235  }
236  if ($author) {
237  $clone->setAuthor($author);
238  }
239  if ($owner) {
240  $clone->setOwner($owner);
241  }
242  if ($for_test) {
243  $clone->saveToDb($original_id);
244  } else {
245  $clone->saveToDb();
246  }
247 
248  //$list = $this->getRepository()->getOrderingList($original_id)
249  $list = $this->getRepository()->getOrderingList($this_id)
250  ->withQuestionId($clone->getId());
251  $list->distributeNewRandomIdentifiers();
252  $clone->setOrderingElementList($list);
253  $clone->saveToDb();
254 
255  $clone->copyPageOfQuestion($this_id);
256  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
257  $clone->duplicateImages($this_id, $thisObjId, $clone->getId(), $testObjId);
258 
259  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
260  return $clone->getId();
261  }
262 
268  public function copyObject($target_questionpool_id, $title = "")
269  {
270  if ($this->id <= 0) {
271  // The question has not been saved. It cannot be duplicated
272  return;
273  }
274  // duplicate the question in database
275  $clone = clone $this;
276  $this_id = $this->getId();
278  $clone->id = -1;
279  $source_questionpool_id = $this->getObjId();
280  $clone->setObjId($target_questionpool_id);
281  if ($title) {
282  $clone->setTitle($title);
283  }
284  $clone->saveToDb();
285 
286  $list = $this->getRepository()->getOrderingList($this_id)
287  ->withQuestionId($clone->getId());
288  $list->distributeNewRandomIdentifiers();
289  $clone->setOrderingElementList($list);
290  $clone->saveToDb();
291 
292  $clone->copyPageOfQuestion($original_id);
293  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
294  $clone->duplicateImages($original_id, $source_questionpool_id, $clone->getId(), $target_questionpool_id);
295 
296  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
297 
298  return $clone->getId();
299  }
300 
301  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
302  {
303  if ($this->getId() <= 0) {
304  throw new RuntimeException('The question has not been saved. It cannot be duplicated');
305  }
306 
307  include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
308 
309  $sourceQuestionId = $this->id;
310  $sourceParentId = $this->getObjId();
311 
312  // duplicate the question in database
313  $clone = clone $this;
314  $clone->id = -1;
315 
316  $clone->setObjId($targetParentId);
317 
318  if ($targetQuestionTitle) {
319  $clone->setTitle($targetQuestionTitle);
320  }
321 
322  $clone->saveToDb();
323 
324  $list = $this->getRepository()->getOrderingList($this->getId())
325  ->withQuestionId($clone->getId());
326  $list->distributeNewRandomIdentifiers();
327  $clone->setOrderingElementList($list);
328  $clone->saveToDb();
329 
330  // copy question page content
331  $clone->copyPageOfQuestion($sourceQuestionId);
332  // copy XHTML media objects
333  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
334  // duplicate the image
335  $clone->duplicateImages($sourceQuestionId, $sourceParentId, $clone->getId(), $clone->getObjId());
336 
337  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
338 
339  return $clone->id;
340  }
341 
342  public function duplicateImages($src_question_id, $src_object_id, $dest_question_id, $dest_object_id)
343  {
344  global $DIC;
345  $ilLog = $DIC['ilLog'];
346  if ($this->isImageOrderingType()) {
347  $imagepath_original = $this->getImagePath($src_question_id, $src_object_id);
348  $imagepath = $this->getImagePath($dest_question_id, $dest_object_id);
349 
350  if (!file_exists($imagepath)) {
351  ilUtil::makeDirParents($imagepath);
352  }
353  foreach ($this->getOrderingElementList() as $element) {
354  $filename = $element->getContent();
355 
356  if($filename === "" || $filename === null) {
357  continue;
358  }
359 
360  if (!file_exists($imagepath_original . $filename)
361  || !copy($imagepath_original . $filename, $imagepath . $filename)) {
362  $ilLog->write("image could not be duplicated!!!!");
363  $ilLog->write($imagepath_original . $filename);
364  $ilLog->write($imagepath . $filename);
365  }
366  if (file_exists($imagepath_original . $this->getThumbPrefix() . $filename)
367  && !copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
368  $ilLog->write("image thumbnail could not be duplicated!!!!");
369  }
370  }
371  }
372  }
373 
379  public function copyImages($question_id, $source_questionpool)
380  {
381  global $DIC;
382  $ilLog = $DIC['ilLog'];
383  if ($this->getOrderingType() == OQ_PICTURES) {
384  $imagepath = $this->getImagePath();
385  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
386  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
387  if (!file_exists($imagepath)) {
388  ilUtil::makeDirParents($imagepath);
389  }
390  foreach ($this->getOrderingElementList() as $element) {
391  $filename = $element->getContent();
392  if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
393  $ilLog->write("Ordering Question image could not be copied: ${imagepath_original}${filename}");
394  }
395  if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
396  if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
397  $ilLog->write("Ordering Question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
398  }
399  }
400  }
401  }
402  }
403 
404  protected function getValidOrderingTypes() : array
405  {
406  return [
411  ];
412  }
413 
415  {
416  if (!in_array($ordering_type, $this->getValidOrderingTypes())) {
417  throw new \InvalidArgumentException('Must be valid ordering type.');
418  }
419  $this->ordering_type = $ordering_type;
420  }
421 
422  public function getOrderingType()
423  {
424  return $this->ordering_type;
425  }
426 
427  public function isOrderingTypeNested()
428  {
429  $nested = [
432  ];
433  return in_array($this->getOrderingType(), $nested);
434  }
435 
436  public function isImageOrderingType()
437  {
438  $with_images = [
441  ];
442  return in_array($this->getOrderingType(), $with_images);
443  }
444 
445  public function setContentType($ct)
446  {
447  if (!in_array($ct, [
448  self::OQ_CT_PICTURES,
449  self::OQ_CT_TERMS
450  ])) {
451  throw new \InvalidArgumentException("use OQ content-type", 1);
452  }
453  if ($ct == self::OQ_CT_PICTURES) {
454  if ($this->isOrderingTypeNested()) {
456  } else {
458  }
459  $this->setThumbGeometry($this->getThumbGeometry());
460  }
461  if ($ct == self::OQ_CT_TERMS) {
462  if ($this->isOrderingTypeNested()) {
464  } else {
466  }
467  }
468  }
469 
470  public function setNestingType(bool $nesting)
471  {
472  if ($nesting) {
473  if ($this->isImageOrderingType()) {
475  } else {
477  }
478  } else {
479  if ($this->isImageOrderingType()) {
481  } else {
483  }
484  }
485  }
486 
488  {
489  return $this->isImageOrderingType();
490  }
491 
498  public function getOrderingElementListForSolutionOutput($forceCorrectSolution, $activeId, $passIndex, $getUseIntermediateSolution = false)
499  {
500  if ($forceCorrectSolution || !$activeId || $passIndex === null) {
501  return $this->getOrderingElementList();
502  }
503 
504  $solutionValues = $this->getSolutionValues($activeId, $passIndex, !$getUseIntermediateSolution);
505 
506  if (!count($solutionValues)) {
507  return $this->getShuffledOrderingElementList();
508  }
509 
510  return $this->getSolutionOrderingElementList($this->fetchIndexedValuesFromValuePairs($solutionValues));
511  }
512 
523  {
524  if ($inputGUI->isPostSubmit($lastPost)) {
525  return $this->fetchSolutionListFromFormSubmissionData($lastPost);
526  }
527 
528  // hey: prevPassSolutions - pass will be always available from now on
529  #if( $pass === null && !ilObjTest::_getUsePreviousAnswers($activeId, true) )
530  #// condition looks strange? yes - keep it null when previous solutions not enabled (!)
531  #{
532  # $pass = ilObjTest::_getPass($activeId);
533  #}
534  // hey.
535 
536  $indexedSolutionValues = $this->fetchIndexedValuesFromValuePairs(
537  // hey: prevPassSolutions - obsolete due to central check
538  $this->getTestOutputSolutions($activeId, $pass)
539  // hey.
540  );
541 
542  if (count($indexedSolutionValues)) {
543  return $this->getSolutionOrderingElementList($indexedSolutionValues);
544  }
545 
546  return $this->getShuffledOrderingElementList();
547  }
548 
555  {
556  $value2 = explode(':', $value2);
557 
558  $randomIdentifier = $value2[0];
559  $selectedPosition = $value1;
560  $selectedIndentation = $value2[1];
561 
562  $element = $this->getOrderingElementList()->getElementByRandomIdentifier($randomIdentifier)->getClone();
563 
564  $element->setPosition($selectedPosition);
565  $element->setIndentation($selectedIndentation);
566 
567  return $element;
568  }
569 
576  {
577  $solutionIdentifier = $value1;
578  $selectedPosition = ($value2 - 1);
579  $selectedIndentation = 0;
580 
581  $element = $this->getOrderingElementList()->getElementBySolutionIdentifier($solutionIdentifier)->getClone();
582 
583  $element->setPosition($selectedPosition);
584  $element->setIndentation($selectedIndentation);
585 
586  return $element;
587  }
588 
594  public function getSolutionOrderingElementList($indexedSolutionValues)
595  {
596  $solutionOrderingList = new ilAssOrderingElementList();
597  $solutionOrderingList->setQuestionId($this->getId());
598 
599  foreach ($indexedSolutionValues as $value1 => $value2) {
600  if ($this->isOrderingTypeNested()) {
601  $element = $this->getSolutionValuePairBrandedOrderingElementByRandomIdentifier($value1, $value2);
602  } else {
603  $element = $this->getSolutionValuePairBrandedOrderingElementBySolutionIdentifier($value1, $value2);
604  }
605 
606  $solutionOrderingList->addElement($element);
607  }
608 
609  if (!$this->getOrderingElementList()->hasSameElementSetByRandomIdentifiers($solutionOrderingList)) {
610  throw new ilTestQuestionPoolException('inconsistent solution values given');
611  }
612 
613  return $solutionOrderingList;
614  }
615 
622  {
623  $shuffledRandomIdentifierIndex = $this->getShuffler()->shuffle(
624  $this->getOrderingElementList()->getRandomIdentifierIndex()
625  );
626 
627  $shuffledElementList = $this->getOrderingElementList()->getClone();
628  $shuffledElementList->reorderByRandomIdentifiers($shuffledRandomIdentifierIndex);
629  $shuffledElementList->resetElementsIndentations();
630 
631  return $shuffledElementList;
632  }
633 
637  public function getOrderingElementList()
638  {
639  return $this->getRepository()->getOrderingList($this->getId());
640  }
641 
645  public function setOrderingElementList(ilAssOrderingElementList $list) : void
646  {
647  $list = $list->withQuestionId($this->getId());
648  $elements = $list->getElements();
649  $nu = [];
650  foreach ($elements as $e) {
651  $nu[] = $list->ensureValidIdentifiers($e);
652  }
653  $list = $list->withElements($nu);
654  $this->getRepository()->updateOrderingList($list);
655  }
656 
663  public function getAnswer($index = 0)
664  {
665  if (!$this->getOrderingElementList()->elementExistByPosition($index)) {
666  return null;
667  }
668 
669  return $this->getOrderingElementList()->getElementByPosition($index);
670  }
671 
680  public function deleteAnswer($randomIdentifier)
681  {
682  $this->getOrderingElementList()->removeElement(
683  $this->getOrderingElementList()->getElementByRandomIdentifier($randomIdentifier)
684  );
685  $this->getOrderingElementList()->saveToDb();
686  }
687 
695  public function getAnswerCount()
696  {
697  return $this->getOrderingElementList()->countElements();
698  }
699 
710  public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
711  {
712  if ($returndetails) {
713  throw new ilTestException('return details not implemented for ' . __METHOD__);
714  }
715 
716  if (is_null($pass)) {
717  $pass = $this->getSolutionMaxPass($active_id);
718  }
719 
720  $solutionValuePairs = $this->getSolutionValues($active_id, $pass, $authorizedSolution);
721 
722  if (!count($solutionValuePairs)) {
723  return 0;
724  }
725 
726  $indexedSolutionValues = $this->fetchIndexedValuesFromValuePairs($solutionValuePairs);
727  $solutionOrderingElementList = $this->getSolutionOrderingElementList($indexedSolutionValues);
728 
729  return $this->calculateReachedPointsForSolution($solutionOrderingElementList);
730  }
731 
733  {
734  if (!$previewSession->hasParticipantSolution()) {
735  return 0;
736  }
737 
738  $solutionOrderingElementList = unserialize(
739  $previewSession->getParticipantsSolution()
740  );
741 
742  $reachedPoints = $this->calculateReachedPointsForSolution($solutionOrderingElementList);
743  $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $reachedPoints);
744 
745  return $this->ensureNonNegativePoints($reachedPoints);
746  }
747 
754  public function getMaximumPoints()
755  {
756  return $this->getPoints();
757  }
758 
759  /*
760  * Returns the encrypted save filename of a matching picture
761  * Images are saved with an encrypted filename to prevent users from
762  * cheating by guessing the solution from the image filename
763  *
764  * @param string $filename Original filename
765  * @return string Encrypted filename
766  */
768  {
769  $extension = "";
770  if (preg_match("/.*\\.(\\w+)$/", $filename, $matches)) {
771  $extension = $matches[1];
772  }
773  return md5($filename) . "." . $extension;
774  }
775 
776  protected function cleanImagefiles()
777  {
778  if ($this->getOrderingType() == self::OQ_PICTURES) {
779  if (@file_exists($this->getImagePath())) {
780  $contents = ilUtil::getDir($this->getImagePath());
781  foreach ($contents as $f) {
782  if (strcmp($f['type'], 'file') == 0) {
783  $found = false;
784  foreach ($this->getOrderingElementList() as $orderElement) {
785  if (strcmp($f['entry'], $orderElement->getContent()) == 0) {
786  $found = true;
787  }
788  if (strcmp($f['entry'], $this->getThumbPrefix() . $orderElement->getContent()) == 0) {
789  $found = true;
790  }
791  }
792  if (!$found) {
793  if (@file_exists($this->getImagePath() . $f['entry'])) {
794  @unlink($this->getImagePath() . $f['entry']);
795  }
796  }
797  }
798  }
799  }
800  } else {
801  if (@file_exists($this->getImagePath())) {
802  ilUtil::delDir($this->getImagePath());
803  }
804  }
805  }
806 
807  /*
808  * Deletes an imagefile from the system if the file is deleted manually
809  *
810  * @param string $filename Image file filename
811  * @return boolean Success
812  */
813  public function dropImageFile($imageFilename)
814  {
815  if (!strlen($imageFilename)) {
816  return false;
817  }
818 
819  $result = @unlink($this->getImagePath() . $imageFilename);
820  $result = $result & @unlink($this->getImagePath() . $this->getThumbPrefix() . $imageFilename);
821 
822  return $result;
823  }
824 
825  public function isImageFileStored($imageFilename)
826  {
827  if (!strlen($imageFilename)) {
828  return false;
829  }
830 
831  if (!file_exists($this->getImagePath() . $imageFilename)) {
832  return false;
833  }
834 
835  return is_file($this->getImagePath() . $imageFilename);
836  }
837 
838  public function isImageReplaced(ilAssOrderingElement $newElement, ilAssOrderingElement $oldElement)
839  {
840  if (!$this->hasOrderingTypeUploadSupport()) {
841  return false;
842  }
843 
844  if (!$newElement->getContent()) {
845  return false;
846  }
847 
848  return $newElement->getContent() != $oldElement->getContent();
849  }
850 
851 
852  public function storeImageFile(string $upload_file, string $upload_name) : ?string
853  {
854  $suffix = strtolower(array_pop(explode(".", $upload_name)));
855  if (!in_array($suffix, self::VALID_UPLOAD_SUFFIXES)) {
856  return null;
857  }
858 
859  $this->ensureImagePathExists();
860  $target_filename = $this->buildHashedImageFilename($upload_name, true);
861  $target_filepath = $this->getImagePath() . $target_filename;
862  if (ilUtil::moveUploadedFile($upload_file, $target_filename, $target_filepath)) {
863  $thumb_path = $this->getImagePath() . $this->getThumbPrefix() . $target_filename;
864  if ($this->getThumbGeometry()) {
865  ilUtil::convertImage($target_filepath, $thumb_path, "JPEG", $this->getThumbGeometry());
866  }
867  return $target_filename;
868  }
869 
870  return null;
871  }
872 
880  public function validateSolutionSubmit()
881  {
882  $submittedSolutionList = $this->getSolutionListFromPostSubmit();
883 
884  if (!$submittedSolutionList->hasElements()) {
885  return true;
886  }
887 
888  return $this->getOrderingElementList()->hasSameElementSetByRandomIdentifiers($submittedSolutionList);
889  }
890 
899  public function saveWorkingData($active_id, $pass = null, $authorized = true)
900  {
901  $entered_values = 0;
902 
903  if (is_null($pass)) {
904  include_once "./Modules/Test/classes/class.ilObjTest.php";
905  $pass = ilObjTest::_getPass($active_id);
906  }
907 
908  $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(
909  function () use (&$entered_values, $active_id, $pass, $authorized) {
910  $this->removeCurrentSolution($active_id, $pass, $authorized);
911 
912  foreach ($this->getSolutionListFromPostSubmit() as $orderingElement) {
913  $value1 = $orderingElement->getStorageValue1($this->getOrderingType());
914  $value2 = $orderingElement->getStorageValue2($this->getOrderingType());
915 
916  $this->saveCurrentSolution($active_id, $pass, $value1, trim($value2), $authorized);
917 
918  $entered_values++;
919  }
920  }
921  );
922 
923  if ($entered_values) {
924  $this->log($active_id, 'log_user_entered_values');
925  } else {
926  $this->log($active_id, 'log_user_not_entered_values');
927  }
928 
929  return true;
930  }
931 
932  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
933  {
934  if ($this->validateSolutionSubmit()) {
935  $previewSession->setParticipantsSolution(serialize($this->getSolutionListFromPostSubmit()));
936  }
937  }
938 
939  public function saveAdditionalQuestionDataToDb()
940  {
942  global $DIC;
943  $ilDB = $DIC['ilDB'];
944 
945  // save additional data
946  $ilDB->manipulateF(
947  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
948  array( "integer" ),
949  array( $this->getId() )
950  );
951 
952  $ilDB->manipulateF(
953  "INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, ordering_type, thumb_geometry, element_height)
954  VALUES (%s, %s, %s, %s)",
955  array( "integer", "text", "integer", "integer" ),
956  array(
957  $this->getId(),
958  $this->ordering_type,
959  $this->getThumbGeometry(),
960  ($this->getElementHeight() > 20) ? $this->getElementHeight() : null
961  )
962  );
963  }
964 
965 
966  protected function getQuestionRepository() : ILIAS\TA\Questions\Ordering\assOrderingQuestionDatabaseRepository
967  {
968  global $DIC;
969  $ilDB = $DIC['ilDB'];
970  return new \ILIAS\TA\Questions\Ordering\assOrderingQuestionDatabaseRepository($ilDB);
971  }
972 
973  public function saveAnswerSpecificDataToDb()
974  {
975  }
976 
983  public function getQuestionType()
984  {
985  return "assOrderingQuestion";
986  }
987 
994  public function getAdditionalTableName()
995  {
996  return "qpl_qst_ordering";
997  }
998 
1005  public function getAnswerTableName()
1006  {
1007  return "qpl_a_ordering";
1008  }
1009 
1014  public function getRTETextWithMediaObjects()
1015  {
1016  $text = parent::getRTETextWithMediaObjects();
1017 
1018  foreach ($this->getOrderingElementList() as $orderingElement) {
1019  $text .= $orderingElement->getContent();
1020  }
1021 
1022  return $text;
1023  }
1024 
1029  public function getOrderElements()
1030  {
1031  return $this->getOrderingElementList()->getRandomIdentifierIndexedElements();
1032  }
1033 
1040  public function supportsJavascriptOutput()
1041  {
1042  return true;
1043  }
1044 
1045  public function supportsNonJsOutput()
1046  {
1047  return false;
1048  }
1049 
1053  public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
1054  {
1055  parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1056 
1057  $solutions = $this->getSolutionValues($active_id, $pass);
1058  $sol = array();
1059  foreach ($solutions as $solution) {
1060  $sol[$solution["value1"]] = $solution["value2"];
1061  }
1062  asort($sol);
1063  $sol = array_keys($sol);
1064 
1065  $i = 1;
1066  foreach ($sol as $idx) {
1067  foreach ($solutions as $solution) {
1068  if ($solution["value1"] == $idx) {
1069  $worksheet->setCell($startrow + $i, 0, $solution["value2"]);
1070  $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
1071  }
1072  }
1073  $element = $this->getOrderingElementList()->getElementBySolutionIdentifier($idx);
1074  $worksheet->setCell($startrow + $i, 2, $element->getContent());
1075  $i++;
1076  }
1077 
1078  return $startrow + $i + 1;
1079  }
1080 
1081  /*
1082  * Get the thumbnail geometry
1083  *
1084  * @return integer Geometry
1085  */
1086  public function getThumbGeometry()
1087  {
1088  return $this->thumb_geometry;
1089  }
1090 
1091  public function getThumbSize()
1092  {
1093  return $this->getThumbGeometry();
1094  }
1095 
1096  /*
1097  * Set the thumbnail geometry
1098  *
1099  * @param integer $a_geometry Geometry
1100  */
1101  public function setThumbGeometry($a_geometry)
1102  {
1103  $this->thumb_geometry = ((int) $a_geometry < 1) ? 100 : $a_geometry;
1104  }
1105 
1106  /*
1107  * Get the minimum element height
1108  *
1109  * @return integer Height
1110  */
1111  public function getElementHeight()
1112  {
1113  return $this->element_height;
1114  }
1115 
1116  /*
1117  * Set the minimum element height
1118  *
1119  * @param integer $a_height Height
1120  */
1121  public function setElementHeight($a_height)
1122  {
1123  $this->element_height = ($a_height < 20) ? "" : $a_height;
1124  }
1125 
1126  /*
1127  * Rebuild the thumbnail images with a new thumbnail size
1128  */
1129  public function rebuildThumbnails()
1130  {
1131  if ($this->isImageOrderingType()) {
1132  foreach ($this->getOrderElements() as $orderingElement) {
1133  $this->generateThumbForFile($this->getImagePath(), $orderingElement->getContent());
1134  }
1135  }
1136  }
1137 
1138  public function getThumbPrefix()
1139  {
1140  return "thumb.";
1141  }
1142 
1143  protected function generateThumbForFile($path, $file)
1144  {
1145  $filename = $path . $file;
1146  if (@file_exists($filename)) {
1147  $thumbpath = $path . $this->getThumbPrefix() . $file;
1148  $path_info = @pathinfo($filename);
1149  $ext = "";
1150  switch (strtoupper($path_info['extension'])) {
1151  case 'PNG':
1152  $ext = 'PNG';
1153  break;
1154  case 'GIF':
1155  $ext = 'GIF';
1156  break;
1157  default:
1158  $ext = 'JPEG';
1159  break;
1160  }
1161  ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1162  }
1163  }
1164 
1168  public function toJSON()
1169  {
1170  include_once("./Services/RTE/classes/class.ilRTE.php");
1171  $result = array();
1172  $result['id'] = (int) $this->getId();
1173  $result['type'] = (string) $this->getQuestionType();
1174  $result['title'] = (string) $this->getTitle();
1175  $result['question'] = $this->formatSAQuestion($this->getQuestion());
1176  $result['nr_of_tries'] = (int) $this->getNrOfTries();
1177  $result['shuffle'] = (bool) true;
1178  $result['points'] = $this->getPoints();
1179  $result['feedback'] = array(
1180  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1181  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1182  );
1183  if ($this->getOrderingType() == self::OQ_PICTURES) {
1184  $result['path'] = $this->getImagePathWeb();
1185  }
1186 
1187  $counter = 1;
1188  $answers = array();
1189  foreach ($this->getOrderingElementList() as $orderingElement) {
1190  $answers[$counter] = $orderingElement->getContent();
1191  $counter++;
1192  }
1193  $answers = $this->getShuffler()->shuffle($answers);
1194  $arr = array();
1195  foreach ($answers as $order => $answer) {
1196  array_push($arr, array(
1197  "answertext" => (string) $answer,
1198  "order" => (int) $order
1199  ));
1200  }
1201  $result['answers'] = $arr;
1202 
1203  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1204  $result['mobs'] = $mobs;
1205 
1206  return json_encode($result);
1207  }
1208 
1214  {
1215  if ($this->isImageOrderingType()) {
1216  return $this->buildOrderingImagesInputGui();
1217  }
1218  return $this->buildOrderingTextsInputGui();
1219  }
1220 
1221 
1226  {
1227  switch (true) {
1228  case $formField instanceof ilAssNestedOrderingElementsInputGUI:
1229  $formField->setInteractionEnabled(true);
1230  $formField->setNestingEnabled($this->isOrderingTypeNested());
1231  break;
1232 
1233  case $formField instanceof ilAssOrderingTextsInputGUI:
1234  case $formField instanceof ilAssOrderingImagesInputGUI:
1235  default:
1236 
1237  $formField->setEditElementOccuranceEnabled(true);
1238  $formField->setEditElementOrderEnabled(true);
1239  }
1240  }
1241 
1246  {
1247  $formField->setInfo($this->lng->txt('ordering_answer_sequence_info'));
1248  $formField->setTitle($this->lng->txt('answers'));
1249  }
1250 
1254  public function buildOrderingTextsInputGui()
1255  {
1256  $formDataConverter = $this->buildOrderingTextsFormDataConverter();
1257 
1258  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssOrderingTextsInputGUI.php';
1259 
1260  $orderingElementInput = new ilAssOrderingTextsInputGUI(
1261  $formDataConverter,
1262  self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
1263  );
1264 
1265  $this->initOrderingElementFormFieldLabels($orderingElementInput);
1266 
1267  return $orderingElementInput;
1268  }
1269 
1274  {
1275  $formDataConverter = $this->buildOrderingImagesFormDataConverter();
1276 
1277  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssOrderingImagesInputGUI.php';
1278 
1279  $orderingElementInput = new ilAssOrderingImagesInputGUI(
1280  $formDataConverter,
1281  self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
1282  );
1283 
1284  $orderingElementInput->setImageUploadCommand(self::ORDERING_ELEMENT_FORM_CMD_UPLOAD_IMG);
1285  $orderingElementInput->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
1286 
1287  $this->initOrderingElementFormFieldLabels($orderingElementInput);
1288 
1289  return $orderingElementInput;
1290  }
1291 
1296  {
1297  $formDataConverter = $this->buildNestedOrderingFormDataConverter();
1298 
1299  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssNestedOrderingElementsInputGUI.php';
1300 
1301  $orderingElementInput = new ilAssNestedOrderingElementsInputGUI(
1302  $formDataConverter,
1303  self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
1304  );
1305 
1306  $orderingElementInput->setUniquePrefix($this->getId());
1307  $orderingElementInput->setOrderingType($this->getOrderingType());
1308  $orderingElementInput->setElementImagePath($this->getImagePathWeb());
1309  $orderingElementInput->setThumbPrefix($this->getThumbPrefix());
1310 
1311  $this->initOrderingElementFormFieldLabels($orderingElementInput);
1312 
1313  return $orderingElementInput;
1314  }
1315 
1316 
1322  public function fetchSolutionListFromFormSubmissionData($userSolutionPost)
1323  {
1324  $orderingGUI = $this->buildNestedOrderingElementInputGui();
1326  $orderingGUI->setValueByArray($userSolutionPost);
1327 
1328  if (!$orderingGUI->checkInput()) {
1329  require_once 'Modules/Test/exceptions/class.ilTestException.php';
1330  throw new ilTestException('error on validating user solution post');
1331  }
1332 
1333  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssOrderingElementList.php';
1334  $solutionOrderingElementList = ilAssOrderingElementList::buildInstance($this->getId());
1335 
1336  $storedElementList = $this->getOrderingElementList();
1337 
1338  foreach ($orderingGUI->getElementList($this->getId()) as $submittedElement) {
1339  $solutionElement = $storedElementList->getElementByRandomIdentifier(
1340  $submittedElement->getRandomIdentifier()
1341  )->getClone();
1342 
1343  $solutionElement->setPosition($submittedElement->getPosition());
1344 
1345  if ($this->isOrderingTypeNested()) {
1346  $solutionElement->setIndentation($submittedElement->getIndentation());
1347  }
1348 
1349  $solutionOrderingElementList->addElement($solutionElement);
1350  }
1351 
1352  return $solutionOrderingElementList;
1353  }
1354 
1359 
1364  {
1365  if ($this->postSolutionOrderingElementList === null) {
1367  $this->postSolutionOrderingElementList = $list;
1368  }
1369 
1371  }
1372 
1376  public function getSolutionPostSubmit()
1377  {
1378  return $this->fetchSolutionSubmit($_POST);
1379  }
1380 
1386  protected function calculateReachedPointsForSolution(ilAssOrderingElementList $solutionOrderingElementList)
1387  {
1388  $reachedPoints = $this->getPoints();
1389 
1390  foreach ($this->getOrderingElementList() as $correctElement) {
1391  $userElement = $solutionOrderingElementList->getElementByPosition($correctElement->getPosition());
1392 
1393  if (!$correctElement->isSameElement($userElement)) {
1394  $reachedPoints = 0;
1395  break;
1396  }
1397  }
1398 
1399  return $reachedPoints;
1400  }
1401 
1410  public function getOperators($expression)
1411  {
1412  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1414  }
1415 
1420  public function getExpressionTypes()
1421  {
1422  return array(
1427  );
1428  }
1429 
1438  public function getUserQuestionResult($active_id, $pass)
1439  {
1441  global $DIC;
1442  $ilDB = $DIC['ilDB'];
1443  $result = new ilUserQuestionResult($this, $active_id, $pass);
1444 
1445  $maxStep = $this->lookupMaxStep($active_id, $pass);
1446 
1447  if ($maxStep !== null) {
1448  $data = $ilDB->queryF(
1449  "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s ORDER BY value1 ASC ",
1450  array("integer", "integer", "integer","integer"),
1451  array($active_id, $pass, $this->getId(), $maxStep)
1452  );
1453  } else {
1454  $data = $ilDB->queryF(
1455  "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s ORDER BY value1 ASC ",
1456  array("integer", "integer", "integer"),
1457  array($active_id, $pass, $this->getId())
1458  );
1459  }
1460 
1461  $elements = array();
1462  while ($row = $ilDB->fetchAssoc($data)) {
1463  $newKey = explode(":", $row["value2"]);
1464 
1465  foreach ($this->getOrderingElementList() as $answer) {
1466  // Images nut supported
1467  if (!$this->isOrderingTypeNested()) {
1468  if ($answer->getSolutionIdentifier() == $row["value1"]) {
1469  $elements[$row["value2"]] = $answer->getSolutionIdentifier() + 1;
1470  break;
1471  }
1472  } else {
1473  if ($answer->getRandomIdentifier() == $newKey[0]) {
1474  $elements[$row["value1"]] = $answer->getSolutionIdentifier() + 1;
1475  break;
1476  }
1477  }
1478  }
1479  }
1480 
1481  ksort($elements);
1482 
1483  foreach (array_values($elements) as $element) {
1484  $result->addKeyValue($element, $element);
1485  }
1486 
1487  $points = $this->calculateReachedPoints($active_id, $pass);
1488  $max_points = $this->getMaximumPoints();
1489 
1490  $result->setReachedPercentage(($points / $max_points) * 100);
1491 
1492  return $result;
1493  }
1494 
1503  public function getAvailableAnswerOptions($index = null)
1504  {
1505  if ($index !== null) {
1506  return $this->getOrderingElementList()->getElementByPosition($index);
1507  }
1508 
1509  return $this->getOrderingElementList()->getElements();
1510  }
1511 
1515  protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1516  {
1517  parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1518  $this->duplicateImages($dupQuestionId, $dupParentObjId, $origQuestionId, $origParentObjId);
1519  }
1520 
1521  // fau: testNav - new function getTestQuestionConfig()
1526  // hey: refactored identifiers
1528  // hey.
1529  {
1530  // hey: refactored identifiers
1531  return parent::buildTestPresentationConfig()
1532  // hey.
1533  ->setIsUnchangedAnswerPossible(true)
1534  ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
1535  }
1536  // fau.
1537 
1538  protected function ensureImagePathExists()
1539  {
1540  if (!file_exists($this->getImagePath())) {
1542  }
1543  }
1544 
1548  public function fetchSolutionSubmit($formSubmissionDataStructure)
1549  {
1550  $solutionSubmit = array();
1551 
1552  if (isset($formSubmissionDataStructure['orderresult'])) {
1553  $orderresult = $formSubmissionDataStructure['orderresult'];
1554 
1555  if (strlen($orderresult)) {
1556  $orderarray = explode(":", $orderresult);
1557  $ordervalue = 1;
1558  foreach ($orderarray as $index) {
1559  $idmatch = null;
1560  if (preg_match("/id_(\\d+)/", $index, $idmatch)) {
1561  $randomid = $idmatch[1];
1562  foreach ($this->getOrderingElementList() as $answeridx => $answer) {
1563  if ($answer->getRandomIdentifier() == $randomid) {
1564  $solutionSubmit[$answeridx] = $ordervalue;
1565  $ordervalue++;
1566  }
1567  }
1568  }
1569  }
1570  }
1571  } elseif ($this->getOrderingType() == OQ_NESTED_TERMS || $this->getOrderingType() == OQ_NESTED_PICTURES) {
1572  $index = 0;
1573  foreach ($formSubmissionDataStructure['content'] as $randomId => $content) {
1574  $indentation = $formSubmissionDataStructure['indentation'];
1575 
1576  $value1 = $index++;
1577  $value2 = implode(':', array($randomId, $indentation));
1578 
1579  $solutionSubmit[$value1] = $value2;
1580  }
1581  } else {
1582  foreach ($formSubmissionDataStructure as $key => $value) {
1583  $matches = null;
1584  if (preg_match("/^order_(\d+)/", $key, $matches)) {
1585  if (!(preg_match("/initial_value_\d+/", $value))) {
1586  if (strlen($value)) {
1587  foreach ($this->getOrderingElementList() as $answeridx => $answer) {
1588  if ($answer->getRandomIdentifier() == $matches[1]) {
1589  $solutionSubmit[$answeridx] = $value;
1590  }
1591  }
1592  }
1593  }
1594  }
1595  }
1596  }
1597 
1598  return $solutionSubmit;
1599  }
1600 
1605  {
1606  require_once 'Modules/TestQuestionPool/classes/forms/class.ilAssOrderingFormValuesObjectsConverter.php';
1607  $converter = new ilAssOrderingFormValuesObjectsConverter();
1608  $converter->setPostVar(self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR);
1609 
1610  return $converter;
1611  }
1612 
1617  {
1618  $formDataConverter = $this->buildOrderingElementFormDataConverter();
1620 
1621  $formDataConverter->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
1622  $formDataConverter->setImageUrlPath($this->getImagePathWeb());
1623  $formDataConverter->setImageFsPath($this->getImagePath());
1624 
1625  if ($this->getThumbSize() && $this->getThumbPrefix()) {
1626  $formDataConverter->setThumbnailPrefix($this->getThumbPrefix());
1627  }
1628  return $formDataConverter;
1629  }
1630 
1635  {
1636  $formDataConverter = $this->buildOrderingElementFormDataConverter();
1638  return $formDataConverter;
1639  }
1640 
1645  {
1646  $formDataConverter = $this->buildOrderingElementFormDataConverter();
1648 
1649  if ($this->getOrderingType() == OQ_NESTED_PICTURES) {
1650  $formDataConverter->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
1651  $formDataConverter->setImageUrlPath($this->getImagePathWeb());
1652  $formDataConverter->setThumbnailPrefix($this->getThumbPrefix());
1653  }
1654 
1655  return $formDataConverter;
1656  }
1657 }
duplicateImages($src_question_id, $src_object_id, $dest_question_id, $dest_object_id)
static makeDirParents($a_dir)
Create a new directory and all parent directories.
initOrderingElementAuthoringProperties(ilFormPropertyGUI $formField)
fetchSolutionListFromFormSubmissionData($userSolutionPost)
getId()
Gets the id of the assQuestion object.
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
getSolutionOrderingElementListForTestOutput(ilAssNestedOrderingElementsInputGUI $inputGUI, $lastPost, $activeId, $pass)
Class iQuestionCondition.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
$data
Definition: storeScorm.php:23
buildHashedImageFilename($plain_image_filename, $unique=false)
calculateReachedPointsForSolution(ilAssOrderingElementList $solutionOrderingElementList)
$result
$mobs
Definition: imgupload.php:54
getSolutionOrderingElementList($indexedSolutionValues)
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
getPoints()
Returns the maximum available points for the question.
repository for assOrderingQuestion (the answer elements within, at least...)
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
fetchSolutionSubmit($formSubmissionDataStructure)
Abstract basic class which is to be extended by the concrete assessment question type classes...
isComplete()
Returns true, if a ordering question is complete for use.
Class ChatMainBarProvider .
const OQ_NESTED_TERMS
initOrderingElementFormFieldLabels(ilFormPropertyGUI $formField)
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $ordering_type=self::OQ_TERMS)
assOrderingQuestion constructor
ensureNonNegativePoints($points)
getQuestionType()
Returns the question type of the question.
getOrderElements()
Returns the answers array.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
setId($id=-1)
Sets the id of the assQuestion object.
copyObject($target_questionpool_id, $title="")
Copies an assOrderingQuestion object.
static getDir($a_dir, $a_rec=false, $a_sub_dir="")
get directory
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
{}
getImagePathWeb()
Returns the web image path for web accessable images of a question.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
static buildInstance(int $question_id, array $elements=[])
setOrderingElementList(ilAssOrderingElementList $list)
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
savePreviewData(ilAssQuestionPreviewSession $previewSession)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getAnswer($index=0)
Returns the ordering element from the given position.
getOperators($expression)
Get all available operations for a specific question.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
setNrOfTries($a_nr_of_tries)
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
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...
getObjId()
Get the object id of the container object.
isImageReplaced(ilAssOrderingElement $newElement, ilAssOrderingElement $oldElement)
getSolutionValuePairBrandedOrderingElementBySolutionIdentifier($value1, $value2)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
Base Exception for all Exceptions relating to Modules/Test.
fetchIndexedValuesFromValuePairs(array $valuePairs)
$index
Definition: metadata.php:128
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{}
setInfo($a_info)
Set Information Text.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assOrderingQuestion.
validateSolutionSubmit()
Checks the data to be saved for consistency.
setAuthor($author="")
Sets the authors name of the assQuestion object.
getAuthor()
Gets 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.
getExpressionTypes()
Get all available expression types for a specific question.
const OQ_PICTURES
Ordering question constants.
Class ilUserQuestionResult.
getAnswerTableName()
Returns the name of the answer table in the database.
log($active_id, $langVar)
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
deleteAnswer($randomIdentifier)
Deletes an answer with a given index.
setTitle($a_title)
Set Title.
Interface ilObjAnswerScoringAdjustable.
global $DIC
Definition: goto.php:24
toJSON()
Returns a JSON representation of the question.
saveToDb($original_id="")
Saves a assOrderingQuestion object to a database.
getQuestion()
Gets the question string of the question object.
static convertImage( $a_from, $a_to, $a_target_format="", $a_geometry="", $a_background_color="")
convert image
getOrderingElementListForSolutionOutput($forceCorrectSolution, $activeId, $passIndex, $getUseIntermediateSolution=false)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
$filename
Definition: buildRTE.php:89
getTestOutputSolutions($activeId, $pass)
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
getSolutionValuePairBrandedOrderingElementByRandomIdentifier($value1, $value2)
const OQ_TERMS
storeImageFile(string $upload_file, string $upload_name)
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
setQuestion($question="")
Sets the question string of the question object.
This class represents a property in a property form.
Interface ilObjQuestionScoringAdjustable.
removeCurrentSolution($active_id, $pass, $authorized=true)
__construct(Container $dic, ilPlugin $plugin)
const OQ_NESTED_PICTURES
global $ilDB
setOriginalId($original_id)
Class for ordering questions.
setOrderingType($ordering_type=self::OQ_TERMS)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getTitle()
Gets the title string of the assQuestion object.
buildTestPresentationConfig()
Get the test question configuration.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
copyImages($question_id, $source_questionpool)
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.
loadFromDb($question_id)
Loads a assOrderingQuestion object from a database.
$_POST["username"]
ensureValidIdentifiers(ilAssOrderingElement $element)
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
$i
Definition: metadata.php:24
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
getAnswerCount()
Returns the number of answers.