ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.assMatchingQuestion.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
25{
43
49 protected $terms;
50
51 protected $definitions;
57 public $thumb_geometry = 100;
58
65
66 const MATCHING_MODE_1_ON_1 = '1:1';
67 const MATCHING_MODE_N_ON_N = 'n:n';
68
70
85 public function __construct(
86 $title = "",
87 $comment = "",
88 $author = "",
89 $owner = -1,
90 $question = "",
92 ) {
94 $this->matchingpairs = array();
95 $this->matching_type = $matching_type;
96 $this->terms = array();
97 $this->definitions = array();
98 }
99
105 public function isComplete()
106 {
107 if (strlen($this->title)
108 && $this->author
109 && $this->question
110 && count($this->matchingpairs)
111 && $this->getMaximumPoints() > 0
112 ) {
113 return true;
114 }
115 return false;
116 }
117
124 public function saveToDb($original_id = "")
125 {
126 global $DIC;
127 $ilDB = $DIC['ilDB'];
128
132
133
134 parent::saveToDb($original_id);
135 }
136
138 {
139 global $DIC;
140 $ilDB = $DIC['ilDB'];
141 // delete old terms
142 $ilDB->manipulateF(
143 "DELETE FROM qpl_a_mterm WHERE question_fi = %s",
144 array( 'integer' ),
145 array( $this->getId() )
146 );
147
148 // delete old definitions
149 $ilDB->manipulateF(
150 "DELETE FROM qpl_a_mdef WHERE question_fi = %s",
151 array( 'integer' ),
152 array( $this->getId() )
153 );
154
155 $termids = array();
156 // write terms
157 foreach ($this->terms as $key => $term) {
158 $next_id = $ilDB->nextId('qpl_a_mterm');
159 $ilDB->insert('qpl_a_mterm', array(
160 'term_id' => array('integer', $next_id),
161 'question_fi' => array('integer', $this->getId()),
162 'picture' => array('text', $term->picture),
163 'term' => array('text', $term->text),
164 'ident' => array('integer', $term->identifier)
165 ));
166 $termids[$term->identifier] = $next_id;
167 }
168
169 $definitionids = array();
170 // write definitions
171 foreach ($this->definitions as $key => $definition) {
172 $next_id = $ilDB->nextId('qpl_a_mdef');
173 $ilDB->insert('qpl_a_mdef', array(
174 'def_id' => array('integer', $next_id),
175 'question_fi' => array('integer', $this->getId()),
176 'picture' => array('text', $definition->picture),
177 'definition' => array('text', $definition->text),
178 'ident' => array('integer', $definition->identifier)
179 ));
180 $definitionids[$definition->identifier] = $next_id;
181 }
182
183 $ilDB->manipulateF(
184 "DELETE FROM qpl_a_matching WHERE question_fi = %s",
185 array( 'integer' ),
186 array( $this->getId() )
187 );
189 foreach ($matchingpairs as $key => $pair) {
190 $next_id = $ilDB->nextId('qpl_a_matching');
191 $ilDB->manipulateF(
192 "INSERT INTO qpl_a_matching (answer_id, question_fi, points, term_fi, definition_fi) VALUES (%s, %s, %s, %s, %s)",
193 array( 'integer', 'integer', 'float', 'integer', 'integer' ),
194 array(
195 $next_id,
196 $this->getId(),
197 $pair->points,
198 $termids[$pair->term->identifier],
199 $definitionids[$pair->definition->identifier]
200 )
201 );
202 }
203
204 $this->rebuildThumbnails();
205 }
206
208 {
209 global $DIC;
210 $ilDB = $DIC['ilDB'];
211
212 // save additional data
213
214 $ilDB->manipulateF(
215 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
216 array( "integer" ),
217 array( $this->getId() )
218 );
219
220 $ilDB->insert($this->getAdditionalTableName(), array(
221 'question_fi' => array('integer', $this->getId()),
222 'shuffle' => array('text', $this->shuffle),
223 'matching_type' => array('text', $this->matching_type),
224 'thumb_geometry' => array('integer', $this->getThumbGeometry()),
225 'matching_mode' => array('text', $this->getMatchingMode())
226 ));
227 }
228
235 public function loadFromDb($question_id)
236 {
237 global $DIC;
238 $ilDB = $DIC['ilDB'];
239
240 $query = "
241 SELECT qpl_questions.*,
242 {$this->getAdditionalTableName()}.*
243 FROM qpl_questions
244 LEFT JOIN {$this->getAdditionalTableName()}
245 ON {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id
246 WHERE qpl_questions.question_id = %s
247 ";
248
249 $result = $ilDB->queryF(
250 $query,
251 array('integer'),
252 array($question_id)
253 );
254
255 if ($result->numRows() == 1) {
256 $data = $ilDB->fetchAssoc($result);
257 $this->setId($question_id);
258 $this->setObjId($data["obj_fi"]);
259 $this->setTitle($data["title"]);
260 $this->setComment($data["description"]);
261 $this->setOriginalId($data["original_id"]);
262 $this->setNrOfTries($data['nr_of_tries']);
263 $this->setAuthor($data["author"]);
264 $this->setPoints($data["points"]);
265 $this->setOwner($data["owner"]);
266 include_once("./Services/RTE/classes/class.ilRTE.php");
267 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
268 $this->setThumbGeometry($data["thumb_geometry"]);
269 $this->setShuffle($data["shuffle"]);
270 $this->setMatchingMode($data['matching_mode'] === null ? self::MATCHING_MODE_1_ON_1 : $data['matching_mode']);
271 $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
272
273 try {
274 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
277 }
278
279 try {
280 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
282 }
283 }
284
285 $termids = array();
286 $result = $ilDB->queryF(
287 "SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
288 array('integer'),
289 array($question_id)
290 );
291 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
292 $this->terms = array();
293 if ($result->numRows() > 0) {
294 while ($data = $ilDB->fetchAssoc($result)) {
295 $term = new assAnswerMatchingTerm($data['term'], $data['picture'], $data['ident']);
296 array_push($this->terms, $term);
297 $termids[$data['term_id']] = $term;
298 }
299 }
300
301 $definitionids = array();
302 $result = $ilDB->queryF(
303 "SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
304 array('integer'),
305 array($question_id)
306 );
307 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
308 $this->definitions = array();
309 if ($result->numRows() > 0) {
310 while ($data = $ilDB->fetchAssoc($result)) {
311 $definition = new assAnswerMatchingDefinition($data['definition'], $data['picture'], $data['ident']);
312 array_push($this->definitions, $definition);
313 $definitionids[$data['def_id']] = $definition;
314 }
315 }
316
317 $this->matchingpairs = array();
318 $result = $ilDB->queryF(
319 "SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
320 array('integer'),
321 array($question_id)
322 );
323 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
324 if ($result->numRows() > 0) {
325 while ($data = $ilDB->fetchAssoc($result)) {
326 array_push($this->matchingpairs, new assAnswerMatchingPair($termids[$data['term_fi']], $definitionids[$data['definition_fi']], $data['points']));
327 }
328 }
329 parent::loadFromDb($question_id);
330 }
331
332
336 public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
337 {
338 if ($this->id <= 0) {
339 // The question has not been saved. It cannot be duplicated
340 return;
341 }
342 // duplicate the question in database
343 $this_id = $this->getId();
344 $thisObjId = $this->getObjId();
345
346 $clone = $this;
347 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
349 $clone->id = -1;
350
351 if ((int) $testObjId > 0) {
352 $clone->setObjId($testObjId);
353 }
354
355 if ($title) {
356 $clone->setTitle($title);
357 }
358 if ($author) {
359 $clone->setAuthor($author);
360 }
361 if ($owner) {
362 $clone->setOwner($owner);
363 }
364 if ($for_test) {
365 $clone->saveToDb($original_id);
366 } else {
367 $clone->saveToDb();
368 }
369
370 // copy question page content
371 $clone->copyPageOfQuestion($this_id);
372 // copy XHTML media objects
373 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
374 // duplicate the image
375 $clone->duplicateImages($this_id, $thisObjId, $clone->getId(), $testObjId);
376
377 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
378
379 return $clone->id;
380 }
381
385 public function copyObject($target_questionpool_id, $title = "")
386 {
387 if ($this->id <= 0) {
388 // The question has not been saved. It cannot be duplicated
389 return;
390 }
391 // duplicate the question in database
392 $clone = $this;
393 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
395 $clone->id = -1;
396 $source_questionpool_id = $this->getObjId();
397 $clone->setObjId($target_questionpool_id);
398 if ($title) {
399 $clone->setTitle($title);
400 }
401 $clone->saveToDb();
402 // copy question page content
403 $clone->copyPageOfQuestion($original_id);
404 // copy XHTML media objects
405 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
406 // duplicate the image
407 $clone->copyImages($original_id, $source_questionpool_id);
408
409 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
410
411 return $clone->id;
412 }
413
414 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
415 {
416 if ($this->id <= 0) {
417 // The question has not been saved. It cannot be duplicated
418 return;
419 }
420
421 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
422
423 $sourceQuestionId = $this->id;
424 $sourceParentId = $this->getObjId();
425
426 // duplicate the question in database
427 $clone = $this;
428 $clone->id = -1;
429
430 $clone->setObjId($targetParentId);
431
432 if ($targetQuestionTitle) {
433 $clone->setTitle($targetQuestionTitle);
434 }
435
436 $clone->saveToDb();
437 // copy question page content
438 $clone->copyPageOfQuestion($sourceQuestionId);
439 // copy XHTML media objects
440 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
441 // duplicate the image
442 $clone->copyImages($sourceQuestionId, $sourceParentId);
443
444 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
445
446 return $clone->id;
447 }
448
449 public function duplicateImages($question_id, $objectId = null)
450 {
451 global $DIC;
452 $ilLog = $DIC['ilLog'];
453 $imagepath = $this->getImagePath();
454 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
455
456 if ((int) $objectId > 0) {
457 $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
458 }
459
460 foreach ($this->terms as $term) {
461 if (strlen($term->picture)) {
462 $filename = $term->picture;
463 if (!file_exists($imagepath)) {
464 ilUtil::makeDirParents($imagepath);
465 }
466 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
467 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
468 }
469 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
470 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
471 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
472 }
473 }
474 }
475 }
476 foreach ($this->definitions as $definition) {
477 if (strlen($definition->picture)) {
478 $filename = $definition->picture;
479 if (!file_exists($imagepath)) {
480 ilUtil::makeDirParents($imagepath);
481 }
482 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
483 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
484 }
485 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
486 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
487 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
488 }
489 }
490 }
491 }
492 }
493
494 public function copyImages($question_id, $source_questionpool)
495 {
496 global $DIC;
497 $ilLog = $DIC['ilLog'];
498
499 $imagepath = $this->getImagePath();
500 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
501 $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
502 foreach ($this->terms as $term) {
503 if (strlen($term->picture)) {
504 if (!file_exists($imagepath)) {
505 ilUtil::makeDirParents($imagepath);
506 }
507 $filename = $term->picture;
508 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
509 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
510 }
511 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
512 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
513 }
514 }
515 }
516 foreach ($this->definitions as $definition) {
517 if (strlen($definition->picture)) {
518 $filename = $definition->picture;
519 if (!file_exists($imagepath)) {
520 ilUtil::makeDirParents($imagepath);
521 }
522
523 if (assQuestion::isFileAvailable($imagepath_original . $filename)) {
524 copy($imagepath_original . $filename, $imagepath . $filename);
525 } else {
526 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
527 }
528
529 if (assQuestion::isFileAvailable($imagepath_original . $this->getThumbPrefix() . $filename)) {
530 copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename);
531 } else {
532 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
533 }
534 }
535 }
536 }
537
548 public function insertMatchingPair($position, $term = null, $definition = null, $points = 0.0)
549 {
550 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
551 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
552 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
553 if (is_null($term)) {
554 $term = new assAnswerMatchingTerm();
555 }
556 if (is_null($definition)) {
557 $definition = new assAnswerMatchingDefinition();
558 }
559 $pair = new assAnswerMatchingPair($term, $definition, $points);
560 if ($position < count($this->matchingpairs)) {
561 $part1 = array_slice($this->matchingpairs, 0, $position);
562 $part2 = array_slice($this->matchingpairs, $position);
563 $this->matchingpairs = array_merge($part1, array($pair), $part2);
564 } else {
565 array_push($this->matchingpairs, $pair);
566 }
567 }
568
580 public function addMatchingPair($term = null, $definition = null, $points = 0.0)
581 {
582 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php';
583 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php';
584 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php';
585 if (is_null($term)) {
586 $term = new assAnswerMatchingTerm();
587 }
588 if (is_null($definition)) {
589 $definition = new assAnswerMatchingDefinition();
590 }
591 $pair = new assAnswerMatchingPair($term, $definition, $points);
592 array_push($this->matchingpairs, $pair);
593 }
594
598 public function getTermWithIdentifier($a_identifier)
599 {
600 foreach ($this->terms as $term) {
601 if ($term->identifier == $a_identifier) {
602 return $term;
603 }
604 }
605 return null;
606 }
607
611 public function getDefinitionWithIdentifier($a_identifier)
612 {
613 foreach ($this->definitions as $definition) {
614 if ($definition->identifier == $a_identifier) {
615 return $definition;
616 }
617 }
618 return null;
619 }
620
629 public function getMatchingPair($index = 0)
630 {
631 if ($index < 0) {
632 return null;
633 }
634 if (count($this->matchingpairs) < 1) {
635 return null;
636 }
637 if ($index >= count($this->matchingpairs)) {
638 return null;
639 }
640 return $this->matchingpairs[$index];
641 }
642
650 public function deleteMatchingPair($index = 0)
651 {
652 if ($index < 0) {
653 return;
654 }
655 if (count($this->matchingpairs) < 1) {
656 return;
657 }
658 if ($index >= count($this->matchingpairs)) {
659 return;
660 }
661 unset($this->matchingpairs[$index]);
662 $this->matchingpairs = array_values($this->matchingpairs);
663 }
664
669 public function flushMatchingPairs()
670 {
671 $this->matchingpairs = array();
672 }
673
680 public function getMatchingPairCount()
681 {
682 return count($this->matchingpairs);
683 }
684
691 public function getTerms()
692 {
693 return $this->terms;
694 }
695
702 public function getDefinitions()
703 {
704 return $this->definitions;
705 }
706
713 public function getTermCount()
714 {
715 return count($this->terms);
716 }
717
724 public function getDefinitionCount()
725 {
726 return count($this->definitions);
727 }
728
735 public function addTerm($term)
736 {
737 array_push($this->terms, $term);
738 }
739
746 public function addDefinition($definition)
747 {
748 array_push($this->definitions, $definition);
749 }
750
757 public function insertTerm($position, $term = null)
758 {
759 if (is_null($term)) {
760 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
761 $term = new assAnswerMatchingTerm();
762 }
763 if ($position < count($this->terms)) {
764 $part1 = array_slice($this->terms, 0, $position);
765 $part2 = array_slice($this->terms, $position);
766 $this->terms = array_merge($part1, array($term), $part2);
767 } else {
768 array_push($this->terms, $term);
769 }
770 }
771
778 public function insertDefinition($position, $definition = null)
779 {
780 if (is_null($definition)) {
781 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
782 $definition = new assAnswerMatchingDefinition();
783 }
784 if ($position < count($this->definitions)) {
785 $part1 = array_slice($this->definitions, 0, $position);
786 $part2 = array_slice($this->definitions, $position);
787 $this->definitions = array_merge($part1, array($definition), $part2);
788 } else {
789 array_push($this->definitions, $definition);
790 }
791 }
792
797 public function flushTerms()
798 {
799 $this->terms = array();
800 }
801
806 public function flushDefinitions()
807 {
808 $this->definitions = array();
809 }
810
817 public function deleteTerm($position)
818 {
819 unset($this->terms[$position]);
820 $this->terms = array_values($this->terms);
821 }
822
829 public function deleteDefinition($position)
830 {
831 unset($this->definitions[$position]);
832 $this->definitions = array_values($this->definitions);
833 }
834
842 public function setTerm($term, $index)
843 {
844 $this->terms[$index] = $term;
845 }
846
857 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
858 {
859 if ($returndetails) {
860 throw new ilTestException('return details not implemented for ' . __METHOD__);
861 }
862
863 global $DIC;
864 $ilDB = $DIC['ilDB'];
865
866 $found_values = array();
867 if (is_null($pass)) {
868 $pass = $this->getSolutionMaxPass($active_id);
869 }
870 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
871 while ($data = $ilDB->fetchAssoc($result)) {
872 if (strcmp($data["value1"], "") != 0) {
873 if (!isset($found_values[$data['value2']])) {
874 $found_values[$data['value2']] = array();
875 }
876
877 $found_values[$data['value2']][] = $data['value1'];
878 }
879 }
880
881 $points = $this->calculateReachedPointsForSolution($found_values);
882
883 return $points;
884 }
885
889 public function getMaximumPoints()
890 {
891 $points = 0;
892
893 foreach ($this->getMaximumScoringMatchingPairs() as $pair) {
894 $points += $pair->points;
895 }
896
897 return $points;
898 }
899
901 {
902 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
903 return $this->getPositiveScoredMatchingPairs();
904 } elseif ($this->getMatchingMode() == self::MATCHING_MODE_1_ON_1) {
906 }
907
908 return array();
909 }
910
912 {
913 $matchingPairs = array();
914
915 foreach ($this->matchingpairs as $pair) {
916 if ($pair->points <= 0) {
917 continue;
918 }
919
920 $matchingPairs[] = $pair;
921 }
922
923 return $matchingPairs;
924 }
925
927 {
928 $matchingPairsByDefinition = array();
929
930 foreach ($this->matchingpairs as $pair) {
931 if ($pair->points <= 0) {
932 continue;
933 }
934
935 $defId = $pair->definition->identifier;
936
937 if (!isset($matchingPairsByDefinition[$defId])) {
938 $matchingPairsByDefinition[$defId] = $pair;
939 } elseif ($pair->points > $matchingPairsByDefinition[$defId]->points) {
940 $matchingPairsByDefinition[$defId] = $pair;
941 }
942 }
943
944 return $matchingPairsByDefinition;
945 }
946
951 public function fetchIndexedValuesFromValuePairs(array $valuePairs)
952 {
953 $indexedValues = array();
954
955 foreach ($valuePairs as $valuePair) {
956 if (!isset($indexedValues[$valuePair['value2']])) {
957 $indexedValues[$valuePair['value2']] = array();
958 }
959
960 $indexedValues[$valuePair['value2']][] = $valuePair['value1'];
961 }
962
963 return $indexedValues;
964 }
965
975 {
976 $extension = "";
977 if (preg_match("/.*\\.(\\w+)$/", $filename, $matches)) {
978 $extension = $matches[1];
979 }
980 return md5($filename) . "." . $extension;
981 }
982
983 public function removeTermImage($index)
984 {
985 $term = $this->terms[$index];
986 if (is_object($term)) {
987 $this->deleteImagefile($term->picture);
988 $term->picture = null;
989 }
990 }
991
993 {
994 $definition = $this->definitions[$index];
995 if (is_object($definition)) {
996 $this->deleteImagefile($definition->picture);
997 $definition->picture = null;
998 }
999 }
1000
1001
1009 {
1010 $deletename = $filename;
1011 $result = @unlink($this->getImagePath() . $deletename);
1012 $result = $result & @unlink($this->getImagePath() . $this->getThumbPrefix() . $deletename);
1013 return $result;
1014 }
1015
1024 public function setImageFile($image_tempfilename, $image_filename, $previous_filename = '')
1025 {
1026 $result = true;
1027 if (strlen($image_tempfilename)) {
1028 $image_filename = str_replace(" ", "_", $image_filename);
1029 $imagepath = $this->getImagePath();
1030 if (!file_exists($imagepath)) {
1031 ilUtil::makeDirParents($imagepath);
1032 }
1033 $savename = $image_filename;
1034 if (!ilUtil::moveUploadedFile($image_tempfilename, $savename, $imagepath . $savename)) {
1035 $result = false;
1036 } else {
1037 // create thumbnail file
1038 $thumbpath = $imagepath . $this->getThumbPrefix() . $savename;
1039 ilUtil::convertImage($imagepath . $savename, $thumbpath, "JPEG", $this->getThumbGeometry());
1040 }
1041 if ($result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename))) {
1042 $this->deleteImagefile($previous_filename);
1043 }
1044 }
1045 return $result;
1046 }
1047
1049 {
1050 $postData = $_POST['matching'][$this->getId()];
1051
1052 $matchings = array();
1053
1054 foreach ($this->getDefinitions() as $definition) {
1055 if (isset($postData[$definition->identifier])) {
1056 foreach ($this->getTerms() as $term) {
1057 if (isset($postData[$definition->identifier][$term->identifier])) {
1058 if (!is_array($postData[$definition->identifier])) {
1059 $postData[$definition->identifier] = array();
1060 }
1061
1062 $matchings[$definition->identifier][] = $term->identifier;
1063 }
1064 }
1065 }
1066 }
1067
1068 return $matchings;
1069 }
1070
1071 private function checkSubmittedMatchings($submittedMatchings)
1072 {
1073 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1074 return true;
1075 }
1076
1077 $handledTerms = array();
1078
1079 foreach ($submittedMatchings as $definition => $terms) {
1080 if (count($terms) > 1) {
1081 ilUtil::sendFailure($this->lng->txt("multiple_matching_values_selected"), true);
1082 return false;
1083 }
1084
1085 foreach ($terms as $i => $term) {
1086 if (isset($handledTerms[$term])) {
1087 ilUtil::sendFailure($this->lng->txt("duplicate_matching_values_selected"), true);
1088 return false;
1089 }
1090
1091 $handledTerms[$term] = $term;
1092 }
1093 }
1094
1095 return true;
1096 }
1097
1106 public function saveWorkingData($active_id, $pass = null, $authorized = true)
1107 {
1108 global $DIC;
1109 $ilDB = $DIC['ilDB'];
1110
1111 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1112 $submittedMatchingsValid = $this->checkSubmittedMatchings($submittedMatchings);
1113
1114 $matchingsExist = false;
1115
1116 if ($submittedMatchingsValid) {
1117 if (is_null($pass)) {
1118 include_once "./Modules/Test/classes/class.ilObjTest.php";
1119 $pass = ilObjTest::_getPass($active_id);
1120 }
1121
1122 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$matchingsExist, $submittedMatchings, $active_id, $pass, $authorized) {
1123 $this->removeCurrentSolution($active_id, $pass, $authorized);
1124
1125 foreach ($submittedMatchings as $definition => $terms) {
1126 foreach ($terms as $i => $term) {
1127 $this->saveCurrentSolution($active_id, $pass, $term, $definition, $authorized);
1128 $matchingsExist = true;
1129 }
1130 }
1131 });
1132
1133 $saveWorkingDataResult = true;
1134 } else {
1135 $saveWorkingDataResult = false;
1136 }
1137
1138 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1140 if ($matchingsExist) {
1141 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1142 } else {
1143 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1144 }
1145 }
1146
1147 return $saveWorkingDataResult;
1148 }
1149
1150 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
1151 {
1152 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1153
1154 if ($this->checkSubmittedMatchings($submittedMatchings)) {
1155 $previewSession->setParticipantsSolution($submittedMatchings);
1156 }
1157 }
1158
1159 public function getRandomId()
1160 {
1161 mt_srand((double) microtime() * 1000000);
1162 $random_number = mt_rand(1, 100000);
1163 $found = false;
1164 while ($found) {
1165 $found = false;
1166 foreach ($this->matchingpairs as $key => $pair) {
1167 if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number)) {
1168 $found = true;
1169 $random_number++;
1170 }
1171 }
1172 }
1173 return $random_number;
1174 }
1175
1182 public function setShuffle($shuffle = true)
1183 {
1184 switch ($shuffle) {
1185 case 0:
1186 case 1:
1187 case 2:
1188 case 3:
1189 $this->shuffle = $shuffle;
1190 break;
1191 default:
1192 $this->shuffle = 1;
1193 break;
1194 }
1195 }
1196
1202 public function getQuestionType()
1203 {
1204 return "assMatchingQuestion";
1205 }
1206
1212 public function getAdditionalTableName()
1213 {
1214 return "qpl_qst_matching";
1215 }
1216
1222 public function getAnswerTableName()
1223 {
1224 return array("qpl_a_matching", "qpl_a_mterm");
1225 }
1226
1232 {
1233 return parent::getRTETextWithMediaObjects();
1234 }
1235
1239 public function &getMatchingPairs()
1240 {
1241 return $this->matchingpairs;
1242 }
1243
1247 public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
1248 {
1249 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1250
1251 $solutions = $this->getSolutionValues($active_id, $pass);
1252
1253 $imagepath = $this->getImagePath();
1254 $i = 1;
1255 foreach ($solutions as $solution) {
1256 $matches_written = false;
1257 foreach ($this->getMatchingPairs() as $idx => $pair) {
1258 if (!$matches_written) {
1259 $worksheet->setCell($startrow + $i, 1, $this->lng->txt("matches"));
1260 }
1261 $matches_written = true;
1262 if ($pair->definition->identifier == $solution["value2"]) {
1263 if (strlen($pair->definition->text)) {
1264 $worksheet->setCell($startrow + $i, 0, $pair->definition->text);
1265 } else {
1266 $worksheet->setCell($startrow + $i, 0, $pair->definition->picture);
1267 }
1268 }
1269 if ($pair->term->identifier == $solution["value1"]) {
1270 if (strlen($pair->term->text)) {
1271 $worksheet->setCell($startrow + $i, 2, $pair->term->text);
1272 } else {
1273 $worksheet->setCell($startrow + $i, 2, $pair->term->picture);
1274 }
1275 }
1276 }
1277 $i++;
1278 }
1279
1280 return $startrow + $i + 1;
1281 }
1282
1288 public function getThumbGeometry()
1289 {
1290 return $this->thumb_geometry;
1291 }
1292
1298 public function getThumbSize()
1299 {
1300 return $this->getThumbGeometry();
1301 }
1302
1308 public function setThumbGeometry($a_geometry)
1309 {
1310 $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1311 }
1312
1316 public function rebuildThumbnails()
1317 {
1318 foreach ($this->terms as $term) {
1319 if (strlen($term->picture)) {
1320 $this->generateThumbForFile($this->getImagePath(), $term->picture);
1321 }
1322 }
1323 foreach ($this->definitions as $definition) {
1324 if (strlen($definition->picture)) {
1325 $this->generateThumbForFile($this->getImagePath(), $definition->picture);
1326 }
1327 }
1328 }
1329
1330 public function getThumbPrefix()
1331 {
1332 return "thumb.";
1333 }
1334
1335 protected function generateThumbForFile($path, $file)
1336 {
1337 $filename = $path . $file;
1338 if (@file_exists($filename)) {
1339 $thumbpath = $path . $this->getThumbPrefix() . $file;
1340 $path_info = @pathinfo($filename);
1341 $ext = "";
1342 switch (strtoupper($path_info['extension'])) {
1343 case 'PNG':
1344 $ext = 'PNG';
1345 break;
1346 case 'GIF':
1347 $ext = 'GIF';
1348 break;
1349 default:
1350 $ext = 'JPEG';
1351 break;
1352 }
1353 ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1354 }
1355 }
1356
1361 public function toJSON()
1362 {
1363 $result = array();
1364
1365 $result['id'] = (int) $this->getId();
1366 $result['type'] = (string) $this->getQuestionType();
1367 $result['title'] = (string) $this->getTitle();
1368 $result['question'] = $this->formatSAQuestion($this->getQuestion());
1369 $result['nr_of_tries'] = (int) $this->getNrOfTries();
1370 $result['matching_mode'] = $this->getMatchingMode();
1371 $result['shuffle'] = true;
1372 $result['feedback'] = array(
1373 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1374 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1375 );
1376
1377 require_once 'Services/Randomization/classes/class.ilArrayElementShuffler.php';
1378 $this->setShuffler(new ilArrayElementShuffler());
1379 $seed = $this->getShuffler()->getSeed();
1380
1381 $terms = array();
1382 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'terms'));
1383 foreach ($this->getShuffler()->shuffle($this->getTerms()) as $term) {
1384 $terms[] = array(
1385 "text" => $this->formatSAQuestion($term->text),
1386 "id" => (int) $this->getId() . $term->identifier
1387 );
1388 }
1389 $result['terms'] = $terms;
1390
1391 // alex 9.9.2010 as a fix for bug 6513 I added the question id
1392 // to the "def_id" in the array. The $pair->definition->identifier is not
1393 // unique, since it gets it value from the morder table field
1394 // this value is not changed, when a question is copied.
1395 // thus copying the same question on a page results in problems
1396 // when the second one (the copy) is answered.
1397
1398 $definitions = array();
1399 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'definitions'));
1400 foreach ($this->getShuffler()->shuffle($this->getDefinitions()) as $def) {
1401 $definitions[] = array(
1402 "text" => $this->formatSAQuestion((string) $def->text),
1403 "id" => (int) $this->getId() . $def->identifier
1404 );
1405 }
1406 $result['definitions'] = $definitions;
1407
1408 // #10353
1409 $matchings = array();
1410 foreach ($this->getMatchingPairs() as $pair) {
1411 // fau: fixLmMatchingPoints - ignore matching pairs with 0 or negative points
1412 if ($pair->points <= 0) {
1413 continue;
1414 }
1415 // fau.
1416
1417 $pid = $pair->definition->identifier;
1418 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1419 $pid .= '::' . $pair->term->identifier;
1420 }
1421
1422 if (!isset($matchings[$pid]) || $matchings[$pid]["points"] < $pair->points) {
1423 $matchings[$pid] = array(
1424 "term_id" => (int) $this->getId() . $pair->term->identifier,
1425 "def_id" => (int) $this->getId() . $pair->definition->identifier,
1426 "points" => (int) $pair->points
1427 );
1428 }
1429 }
1430
1431 $result['matchingPairs'] = array_values($matchings);
1432
1433 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1434 $result['mobs'] = $mobs;
1435
1436 global $DIC;
1437 $lng = $DIC['lng'];
1438 $lng->loadLanguageModule('assessment');
1439 $result['reset_button_label'] = $lng->txt("reset_terms");
1440
1441 return json_encode($result);
1442 }
1443
1445 {
1446 return true;
1447 }
1448
1449 public function supportsNonJsOutput()
1450 {
1451 return false;
1452 }
1453
1455 {
1456 $this->matchingMode = $matchingMode;
1457 }
1458
1459 public function getMatchingMode()
1460 {
1461 return $this->matchingMode;
1462 }
1463
1468 protected function calculateReachedPointsForSolution($found_values)
1469 {
1470 $points = 0;
1471 foreach ($found_values as $definition => $terms) {
1472 foreach ($terms as $term) {
1473 foreach ($this->matchingpairs as $pair) {
1474 if ($pair->definition->identifier == $definition && $pair->term->identifier == $term) {
1475 $points += $pair->points;
1476 }
1477 }
1478 }
1479 }
1480 return $points;
1481 }
1482
1491 public function getOperators($expression)
1492 {
1493 require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1495 }
1496
1501 public function getExpressionTypes()
1502 {
1503 return array(
1508 );
1509 }
1518 public function getUserQuestionResult($active_id, $pass)
1519 {
1521 global $DIC;
1522 $ilDB = $DIC['ilDB'];
1523 $result = new ilUserQuestionResult($this, $active_id, $pass);
1524
1525 $data = $ilDB->queryF(
1526 "SELECT ident FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id",
1527 array("integer"),
1528 array($this->getId())
1529 );
1530
1531 $definitions = array();
1532 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1533 $row = $ilDB->fetchAssoc($data);
1534 $definitions[$row["ident"]] = $index;
1535 }
1536
1537 $data = $ilDB->queryF(
1538 "SELECT ident FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id",
1539 array("integer"),
1540 array($this->getId())
1541 );
1542
1543 $terms = array();
1544 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1545 $row = $ilDB->fetchAssoc($data);
1546 $terms[$row["ident"]] = $index;
1547 }
1548
1549 $maxStep = $this->lookupMaxStep($active_id, $pass);
1550
1551 if ($maxStep !== null) {
1552 $data = $ilDB->queryF(
1553 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1554 array("integer", "integer", "integer","integer"),
1555 array($active_id, $pass, $this->getId(), $maxStep)
1556 );
1557 } else {
1558 $data = $ilDB->queryF(
1559 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1560 array("integer", "integer", "integer"),
1561 array($active_id, $pass, $this->getId())
1562 );
1563 }
1564
1565 while ($row = $ilDB->fetchAssoc($data)) {
1566 if ($row["value1"] > 0) {
1567 $result->addKeyValue($definitions[$row["value2"]], $terms[$row["value1"]]);
1568 }
1569 }
1570
1571 $points = $this->calculateReachedPoints($active_id, $pass);
1572 $max_points = $this->getMaximumPoints();
1573
1574 $result->setReachedPercentage(($points / $max_points) * 100);
1575
1576 return $result;
1577 }
1578
1587 public function getAvailableAnswerOptions($index = null)
1588 {
1589 if ($index !== null) {
1590 return $this->getMatchingPair($index);
1591 } else {
1592 return $this->getMatchingPairs();
1593 }
1594 }
1595
1599 protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1600 {
1601 parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1602
1603 $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1604 $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1605
1606 ilUtil::delDir($origImagePath);
1607 if (is_dir($dupImagePath)) {
1608 ilUtil::makeDirParents($origImagePath);
1609 ilUtil::rCopy($dupImagePath, $origImagePath);
1610 }
1611 }
1612}
$result
$filename
Definition: buildRTE.php:89
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Class for matching question definitions.
Class for matching question pairs.
Class for matching question terms.
Class for matching questions.
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
setThumbGeometry($a_geometry)
Set the thumbnail geometry.
deleteDefinition($position)
Deletes a definition.
getEncryptedFilename($filename)
Returns the encrypted save filename of a matching picture Images are saved with an encrypted filename...
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $matching_type=MT_TERMS_DEFINITIONS)
assMatchingQuestion constructor
getMatchingPairCount()
Returns the number of matching pairs.
calculateReachedPointsForSolution($found_values)
addDefinition($definition)
Adds a definition.
getMaximumPoints()
Calculates and Returns the maximum points, a learner can reach answering the question.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
copyObject($target_questionpool_id, $title="")
Copies an assMatchingQuestion.
toJSON()
Returns a JSON representation of the question TODO.
getOperators($expression)
Get all available operations for a specific question.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
getDefinitionCount()
Returns the number of definitions.
getDefinitions()
Returns the definitions of the matching question.
getMatchingPair($index=0)
Returns a matching pair with a given index.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assMatchingQuestion.
getQuestionType()
Returns the question type of the question.
isComplete()
Returns true, if a matching question is complete for use.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
insertDefinition($position, $definition=null)
Inserts a definition.
& getMatchingPairs()
Returns the matchingpairs array.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
rebuildThumbnails()
Rebuild the thumbnail images with a new thumbnail size.
duplicateImages($question_id, $objectId=null)
getTermCount()
Returns the number of terms.
getThumbGeometry()
Get the thumbnail geometry.
deleteTerm($position)
Deletes a term.
checkSubmittedMatchings($submittedMatchings)
getTerms()
Returns the terms of the matching question.
addMatchingPair($term=null, $definition=null, $points=0.0)
Adds an matching pair for an matching choice question.
flushDefinitions()
Deletes all definitions.
fetchIndexedValuesFromValuePairs(array $valuePairs)
loadFromDb($question_id)
Loads a assMatchingQuestion object from a database.
getAnswerTableName()
Returns the name of the answer table in the database.
getDefinitionWithIdentifier($a_identifier)
Returns a definition with a given identifier.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
flushTerms()
Deletes all terms.
copyImages($question_id, $source_questionpool)
flushMatchingPairs()
Deletes all matching pairs.
saveToDb($original_id="")
Saves a assMatchingQuestion object to a database.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
setImageFile($image_tempfilename, $image_filename, $previous_filename='')
Sets the image file and uploads the image to the object's image directory.
setShuffle($shuffle=true)
Sets the shuffle flag.
getThumbSize()
Get the thumbnail geometry.
getTermWithIdentifier($a_identifier)
Returns a term with a given identifier.
setTerm($term, $index)
Sets a specific term.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
{}
getExpressionTypes()
Get all available expression types for a specific question.
deleteImagefile($filename)
Deletes an imagefile from the system if the file is deleted manually.
deleteMatchingPair($index=0)
Deletes a matching pair with a given index.
insertMatchingPair($position, $term=null, $definition=null, $points=0.0)
Inserts a matching pair for an matching choice question.
insertTerm($position, $term=null)
Inserts a term.
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
Abstract basic class which is to be extended by the concrete assessment question type classes.
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass.
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="")
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.
buildImagePath($questionId, $parentObjectId)
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
removeCurrentSolution($active_id, $pass, $authorized=true)
setAuthor($author="")
Sets the authors name of the assQuestion object.
static isFileAvailable($file)
setShuffler(ilArrayElementShuffler $shuffler)
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.
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.
static _getLogLanguage()
retrieve the log language for assessment logging
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
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 rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static makeDirParents($a_dir)
Create a new directory and all parent directories.
const MT_TERMS_DEFINITIONS
Class iQuestionCondition.
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
Interface ilObjAnswerScoringAdjustable.
Interface ilObjQuestionScoringAdjustable.
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$query
global $ilDB
$data
Definition: storeScorm.php:23
$mobs
$DIC
Definition: xapitoken.php:46