ILIAS  release_7 Revision v7.30-3-g800a261c036
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
4require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
10
11require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssOrderingElementList.php';
12
14
30{
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;
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 }
139 }
140
141
149 public function saveToDb($original_id = "")
150 {
151 if ($original_id == '') {
152 $this->saveQuestionDataToDb();
153 } else {
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']);
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 {
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
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())) {
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
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
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
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
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}
$result
$filename
Definition: buildRTE.php:89
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
repository for assOrderingQuestion (the answer elements within, at least...)
Class for ordering questions.
getOrderElements()
Returns the answers array.
getOperators($expression)
Get all available operations for a specific question.
getSolutionValuePairBrandedOrderingElementBySolutionIdentifier($value1, $value2)
getAnswer($index=0)
Returns the ordering element from the given position.
getExpressionTypes()
Get all available expression types for a specific question.
getQuestionType()
Returns the question type of the question.
copyImages($question_id, $source_questionpool)
initOrderingElementAuthoringProperties(ilFormPropertyGUI $formField)
getAnswerTableName()
Returns the name of the answer table in the database.
getSolutionOrderingElementList($indexedSolutionValues)
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
toJSON()
Returns a JSON representation of the question.
setOrderingType($ordering_type=self::OQ_TERMS)
fetchSolutionListFromFormSubmissionData($userSolutionPost)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
isImageReplaced(ilAssOrderingElement $newElement, ilAssOrderingElement $oldElement)
isComplete()
Returns true, if a ordering question is complete for use.
saveToDb($original_id="")
Saves a assOrderingQuestion object to a database.
buildTestPresentationConfig()
Get the test question configuration.
fetchSolutionSubmit($formSubmissionDataStructure)
getOrderingElementListForSolutionOutput($forceCorrectSolution, $activeId, $passIndex, $getUseIntermediateSolution=false)
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
savePreviewData(ilAssQuestionPreviewSession $previewSession)
storeImageFile(string $upload_file, string $upload_name)
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $ordering_type=self::OQ_TERMS)
assOrderingQuestion constructor
initOrderingElementFormFieldLabels(ilFormPropertyGUI $formField)
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assOrderingQuestion.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getAdditionalTableName()
Returns the name of the additional question data table in the database.
getSolutionValuePairBrandedOrderingElementByRandomIdentifier($value1, $value2)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
loadFromDb($question_id)
Loads a assOrderingQuestion object from a database.
setOrderingElementList(ilAssOrderingElementList $list)
duplicateImages($src_question_id, $src_object_id, $dest_question_id, $dest_object_id)
getSolutionOrderingElementListForTestOutput(ilAssNestedOrderingElementsInputGUI $inputGUI, $lastPost, $activeId, $pass)
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
{}
deleteAnswer($randomIdentifier)
Deletes an answer with a given index.
validateSolutionSubmit()
Checks the data to be saved for consistency.
calculateReachedPointsForSolution(ilAssOrderingElementList $solutionOrderingElementList)
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
copyObject($target_questionpool_id, $title="")
Copies an assOrderingQuestion object.
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
getAnswerCount()
Returns the number of answers.
Abstract basic class which is to be extended by the concrete assessment question type classes.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
setId($id=-1)
Sets the id of the assQuestion object.
setOriginalId($original_id)
setObjId($obj_id=0)
Set the object id of the container object.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
saveQuestionDataToDb($original_id="")
log($active_id, $langVar)
getId()
Gets the id of the assQuestion object.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
getObjId()
Get the object id of the container object.
setTitle($title="")
Sets the title string of the assQuestion object.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second.
fetchIndexedValuesFromValuePairs(array $valuePairs)
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
removeCurrentSolution($active_id, $pass, $authorized=true)
buildHashedImageFilename($plain_image_filename, $unique=false)
setAuthor($author="")
Sets the authors name of the assQuestion object.
getPoints()
Returns the maximum available points for the question.
getTestOutputSolutions($activeId, $pass)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getTitle()
Gets the title string of the assQuestion object.
setPoints($a_points)
Sets the maximum available points for the question.
setComment($comment="")
Sets the comment string of the assQuestion object.
getAuthor()
Gets the authors name of the assQuestion object.
setNrOfTries($a_nr_of_tries)
getQuestion()
Gets the question string of the question object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
setQuestion($question="")
Sets the question string of the question object.
getImagePathWeb()
Returns the web image path for web accessable images of a question.
ensureNonNegativePoints($points)
static buildInstance(int $question_id, array $elements=[])
ensureValidIdentifiers(ilAssOrderingElement $element)
This class represents a property in a property form.
setTitle($a_title)
Set Title.
setInfo($a_info)
Set Information Text.
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
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...
Base Exception for all Exceptions relating to Modules/Test.
Class ilUserQuestionResult.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static convertImage( $a_from, $a_to, $a_target_format="", $a_geometry="", $a_background_color="")
convert image
static getDir($a_dir, $a_rec=false, $a_sub_dir="")
get directory
static makeDirParents($a_dir)
Create a new directory and all parent directories.
global $DIC
Definition: goto.php:24
$mobs
Definition: imgupload.php:54
const OQ_NESTED_PICTURES
const OQ_TERMS
const OQ_NESTED_TERMS
const OQ_PICTURES
Ordering question constants.
Class iQuestionCondition.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
Interface ilObjAnswerScoringAdjustable.
Interface ilObjQuestionScoringAdjustable.
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Class ChatMainBarProvider \MainMenu\Provider.
global $ilDB
$data
Definition: storeScorm.php:23