ILIAS  release_7 Revision v7.30-3-g800a261c036
class.assMatchingQuestion.php
Go to the documentation of this file.
1<?php
18require_once './Modules/Test/classes/inc.AssessmentConstants.php';
19require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
20require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
21require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
22require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
23
38{
56
62 protected $terms;
63
64 protected $definitions;
70 public $thumb_geometry = 100;
71
78
79 const MATCHING_MODE_1_ON_1 = '1:1';
80 const MATCHING_MODE_N_ON_N = 'n:n';
81
83
98 public function __construct(
99 $title = "",
100 $comment = "",
101 $author = "",
102 $owner = -1,
103 $question = "",
105 ) {
107 $this->matchingpairs = array();
108 $this->matching_type = $matching_type;
109 $this->terms = array();
110 $this->definitions = array();
111 }
112
118 public function isComplete()
119 {
120 if (strlen($this->title)
121 && $this->author
122 && $this->question
123 && count($this->matchingpairs)
124 && $this->getMaximumPoints() > 0
125 ) {
126 return true;
127 }
128 return false;
129 }
130
137 public function saveToDb($original_id = "")
138 {
139 global $DIC;
140 $ilDB = $DIC['ilDB'];
141
145
146
147 parent::saveToDb($original_id);
148 }
149
151 {
152 global $DIC;
153 $ilDB = $DIC['ilDB'];
154 // delete old terms
155 $ilDB->manipulateF(
156 "DELETE FROM qpl_a_mterm WHERE question_fi = %s",
157 array( 'integer' ),
158 array( $this->getId() )
159 );
160
161 // delete old definitions
162 $ilDB->manipulateF(
163 "DELETE FROM qpl_a_mdef WHERE question_fi = %s",
164 array( 'integer' ),
165 array( $this->getId() )
166 );
167
168 $termids = array();
169 // write terms
170 foreach ($this->terms as $key => $term) {
171 $next_id = $ilDB->nextId('qpl_a_mterm');
172 $ilDB->insert('qpl_a_mterm', array(
173 'term_id' => array('integer', $next_id),
174 'question_fi' => array('integer', $this->getId()),
175 'picture' => array('text', $term->picture),
176 'term' => array('text', $term->text),
177 'ident' => array('integer', $term->identifier)
178 ));
179 $termids[$term->identifier] = $next_id;
180 }
181
182 $definitionids = array();
183 // write definitions
184 foreach ($this->definitions as $key => $definition) {
185 $next_id = $ilDB->nextId('qpl_a_mdef');
186 $ilDB->insert('qpl_a_mdef', array(
187 'def_id' => array('integer', $next_id),
188 'question_fi' => array('integer', $this->getId()),
189 'picture' => array('text', $definition->picture),
190 'definition' => array('text', $definition->text),
191 'ident' => array('integer', $definition->identifier)
192 ));
193 $definitionids[$definition->identifier] = $next_id;
194 }
195
196 $ilDB->manipulateF(
197 "DELETE FROM qpl_a_matching WHERE question_fi = %s",
198 array( 'integer' ),
199 array( $this->getId() )
200 );
202 foreach ($matchingpairs as $key => $pair) {
203 $next_id = $ilDB->nextId('qpl_a_matching');
204 $ilDB->manipulateF(
205 "INSERT INTO qpl_a_matching (answer_id, question_fi, points, term_fi, definition_fi) VALUES (%s, %s, %s, %s, %s)",
206 array( 'integer', 'integer', 'float', 'integer', 'integer' ),
207 array(
208 $next_id,
209 $this->getId(),
210 $pair->points,
211 $termids[$pair->term->identifier],
212 $definitionids[$pair->definition->identifier]
213 )
214 );
215 }
216
217 $this->rebuildThumbnails();
218 }
219
221 {
222 global $DIC;
223 $ilDB = $DIC['ilDB'];
224
225 // save additional data
226
227 $ilDB->manipulateF(
228 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
229 array( "integer" ),
230 array( $this->getId() )
231 );
232
233 $ilDB->insert($this->getAdditionalTableName(), array(
234 'question_fi' => array('integer', $this->getId()),
235 'shuffle' => array('text', $this->shuffle),
236 'matching_type' => array('text', $this->matching_type),
237 'thumb_geometry' => array('integer', $this->getThumbGeometry()),
238 'matching_mode' => array('text', $this->getMatchingMode())
239 ));
240 }
241
248 public function loadFromDb($question_id)
249 {
250 global $DIC;
251 $ilDB = $DIC['ilDB'];
252
253 $query = "
254 SELECT qpl_questions.*,
255 {$this->getAdditionalTableName()}.*
256 FROM qpl_questions
257 LEFT JOIN {$this->getAdditionalTableName()}
258 ON {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id
259 WHERE qpl_questions.question_id = %s
260 ";
261
262 $result = $ilDB->queryF(
263 $query,
264 array('integer'),
265 array($question_id)
266 );
267
268 if ($result->numRows() == 1) {
269 $data = $ilDB->fetchAssoc($result);
270 $this->setId($question_id);
271 $this->setObjId($data["obj_fi"]);
272 $this->setTitle($data["title"]);
273 $this->setComment($data["description"]);
274 $this->setOriginalId($data["original_id"]);
275 $this->setNrOfTries($data['nr_of_tries']);
276 $this->setAuthor($data["author"]);
277 $this->setPoints($data["points"]);
278 $this->setOwner($data["owner"]);
279 include_once("./Services/RTE/classes/class.ilRTE.php");
280 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
281 $this->setThumbGeometry($data["thumb_geometry"]);
282 $this->setShuffle($data["shuffle"]);
283 $this->setMatchingMode($data['matching_mode'] === null ? self::MATCHING_MODE_1_ON_1 : $data['matching_mode']);
284 $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
285
286 try {
287 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
290 }
291
292 try {
293 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
295 }
296 }
297
298 $termids = array();
299 $result = $ilDB->queryF(
300 "SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
301 array('integer'),
302 array($question_id)
303 );
304 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
305 $this->terms = array();
306 if ($result->numRows() > 0) {
307 while ($data = $ilDB->fetchAssoc($result)) {
308 $term = new assAnswerMatchingTerm($data['term'], $data['picture'], $data['ident']);
309 array_push($this->terms, $term);
310 $termids[$data['term_id']] = $term;
311 }
312 }
313
314 $definitionids = array();
315 $result = $ilDB->queryF(
316 "SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
317 array('integer'),
318 array($question_id)
319 );
320 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
321 $this->definitions = array();
322 if ($result->numRows() > 0) {
323 while ($data = $ilDB->fetchAssoc($result)) {
324 $definition = new assAnswerMatchingDefinition($data['definition'], $data['picture'], $data['ident']);
325 array_push($this->definitions, $definition);
326 $definitionids[$data['def_id']] = $definition;
327 }
328 }
329
330 $this->matchingpairs = array();
331 $result = $ilDB->queryF(
332 "SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
333 array('integer'),
334 array($question_id)
335 );
336 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
337 if ($result->numRows() > 0) {
338 while ($data = $ilDB->fetchAssoc($result)) {
339 array_push($this->matchingpairs, new assAnswerMatchingPair($termids[$data['term_fi']], $definitionids[$data['definition_fi']], $data['points']));
340 }
341 }
342 parent::loadFromDb($question_id);
343 }
344
345
349 public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
350 {
351 if ($this->id <= 0) {
352 // The question has not been saved. It cannot be duplicated
353 return;
354 }
355 // duplicate the question in database
356 $this_id = $this->getId();
357 $thisObjId = $this->getObjId();
358
359 $clone = $this;
360 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
362 $clone->id = -1;
363
364 if ((int) $testObjId > 0) {
365 $clone->setObjId($testObjId);
366 }
367
368 if ($title) {
369 $clone->setTitle($title);
370 }
371 if ($author) {
372 $clone->setAuthor($author);
373 }
374 if ($owner) {
375 $clone->setOwner($owner);
376 }
377 if ($for_test) {
378 $clone->saveToDb($original_id);
379 } else {
380 $clone->saveToDb();
381 }
382
383 // copy question page content
384 $clone->copyPageOfQuestion($this_id);
385 // copy XHTML media objects
386 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
387 // duplicate the image
388 $clone->duplicateImages($this_id, $thisObjId, $clone->getId(), $testObjId);
389
390 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
391
392 return $clone->id;
393 }
394
398 public function copyObject($target_questionpool_id, $title = "")
399 {
400 if ($this->id <= 0) {
401 // The question has not been saved. It cannot be duplicated
402 return;
403 }
404 // duplicate the question in database
405 $clone = $this;
406 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
408 $clone->id = -1;
409 $source_questionpool_id = $this->getObjId();
410 $clone->setObjId($target_questionpool_id);
411 if ($title) {
412 $clone->setTitle($title);
413 }
414 $clone->saveToDb();
415 // copy question page content
416 $clone->copyPageOfQuestion($original_id);
417 // copy XHTML media objects
418 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
419 // duplicate the image
420 $clone->copyImages($original_id, $source_questionpool_id);
421
422 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
423
424 return $clone->id;
425 }
426
427 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
428 {
429 if ($this->id <= 0) {
430 // The question has not been saved. It cannot be duplicated
431 return;
432 }
433
434 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
435
436 $sourceQuestionId = $this->id;
437 $sourceParentId = $this->getObjId();
438
439 // duplicate the question in database
440 $clone = $this;
441 $clone->id = -1;
442
443 $clone->setObjId($targetParentId);
444
445 if ($targetQuestionTitle) {
446 $clone->setTitle($targetQuestionTitle);
447 }
448
449 $clone->saveToDb();
450 // copy question page content
451 $clone->copyPageOfQuestion($sourceQuestionId);
452 // copy XHTML media objects
453 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
454 // duplicate the image
455 $clone->copyImages($sourceQuestionId, $sourceParentId);
456
457 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
458
459 return $clone->id;
460 }
461
462 public function duplicateImages($question_id, $objectId = null)
463 {
464 global $DIC;
465 $ilLog = $DIC['ilLog'];
466 $imagepath = $this->getImagePath();
467 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
468
469 if ((int) $objectId > 0) {
470 $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
471 }
472
473 foreach ($this->terms as $term) {
474 if (strlen($term->picture)) {
475 $filename = $term->picture;
476 if (!file_exists($imagepath)) {
477 ilUtil::makeDirParents($imagepath);
478 }
479 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
480 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
481 }
482 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
483 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
484 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
485 }
486 }
487 }
488 }
489 foreach ($this->definitions as $definition) {
490 if (strlen($definition->picture)) {
491 $filename = $definition->picture;
492 if (!file_exists($imagepath)) {
493 ilUtil::makeDirParents($imagepath);
494 }
495 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
496 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
497 }
498 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
499 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
500 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
501 }
502 }
503 }
504 }
505 }
506
507 public function copyImages($question_id, $source_questionpool)
508 {
509 global $DIC;
510 $ilLog = $DIC['ilLog'];
511
512 $imagepath = $this->getImagePath();
513 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
514 $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
515 foreach ($this->terms as $term) {
516 if (strlen($term->picture)) {
517 if (!file_exists($imagepath)) {
518 ilUtil::makeDirParents($imagepath);
519 }
520 $filename = $term->picture;
521 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
522 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
523 }
524 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
525 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
526 }
527 }
528 }
529 foreach ($this->definitions as $definition) {
530 if (strlen($definition->picture)) {
531 $filename = $definition->picture;
532 if (!file_exists($imagepath)) {
533 ilUtil::makeDirParents($imagepath);
534 }
535
536 if (assQuestion::isFileAvailable($imagepath_original . $filename)) {
537 copy($imagepath_original . $filename, $imagepath . $filename);
538 } else {
539 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
540 }
541
542 if (assQuestion::isFileAvailable($imagepath_original . $this->getThumbPrefix() . $filename)) {
543 copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename);
544 } else {
545 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
546 }
547 }
548 }
549 }
550
561 public function insertMatchingPair($position, $term = null, $definition = null, $points = 0.0)
562 {
563 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
564 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
565 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
566 if (is_null($term)) {
567 $term = new assAnswerMatchingTerm();
568 }
569 if (is_null($definition)) {
570 $definition = new assAnswerMatchingDefinition();
571 }
572 $pair = new assAnswerMatchingPair($term, $definition, $points);
573 if ($position < count($this->matchingpairs)) {
574 $part1 = array_slice($this->matchingpairs, 0, $position);
575 $part2 = array_slice($this->matchingpairs, $position);
576 $this->matchingpairs = array_merge($part1, array($pair), $part2);
577 } else {
578 array_push($this->matchingpairs, $pair);
579 }
580 }
581
593 public function addMatchingPair($term = null, $definition = null, $points = 0.0)
594 {
595 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php';
596 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php';
597 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php';
598 if (is_null($term)) {
599 $term = new assAnswerMatchingTerm();
600 }
601 if (is_null($definition)) {
602 $definition = new assAnswerMatchingDefinition();
603 }
604 $pair = new assAnswerMatchingPair($term, $definition, $points);
605 array_push($this->matchingpairs, $pair);
606 }
607
611 public function getTermWithIdentifier($a_identifier)
612 {
613 foreach ($this->terms as $term) {
614 if ($term->identifier == $a_identifier) {
615 return $term;
616 }
617 }
618 return null;
619 }
620
624 public function getDefinitionWithIdentifier($a_identifier)
625 {
626 foreach ($this->definitions as $definition) {
627 if ($definition->identifier == $a_identifier) {
628 return $definition;
629 }
630 }
631 return null;
632 }
633
642 public function getMatchingPair($index = 0)
643 {
644 if ($index < 0) {
645 return null;
646 }
647 if (count($this->matchingpairs) < 1) {
648 return null;
649 }
650 if ($index >= count($this->matchingpairs)) {
651 return null;
652 }
653 return $this->matchingpairs[$index];
654 }
655
663 public function deleteMatchingPair($index = 0)
664 {
665 if ($index < 0) {
666 return;
667 }
668 if (count($this->matchingpairs) < 1) {
669 return;
670 }
671 if ($index >= count($this->matchingpairs)) {
672 return;
673 }
674 unset($this->matchingpairs[$index]);
675 $this->matchingpairs = array_values($this->matchingpairs);
676 }
677
682 public function flushMatchingPairs()
683 {
684 $this->matchingpairs = array();
685 }
686
693 public function getMatchingPairCount()
694 {
695 return count($this->matchingpairs);
696 }
697
704 public function getTerms()
705 {
706 return $this->terms;
707 }
708
715 public function getDefinitions()
716 {
717 return $this->definitions;
718 }
719
726 public function getTermCount()
727 {
728 return count($this->terms);
729 }
730
737 public function getDefinitionCount()
738 {
739 return count($this->definitions);
740 }
741
748 public function addTerm($term)
749 {
750 array_push($this->terms, $term);
751 }
752
759 public function addDefinition($definition)
760 {
761 array_push($this->definitions, $definition);
762 }
763
770 public function insertTerm($position, $term = null)
771 {
772 if (is_null($term)) {
773 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
774 $term = new assAnswerMatchingTerm();
775 }
776 if ($position < count($this->terms)) {
777 $part1 = array_slice($this->terms, 0, $position);
778 $part2 = array_slice($this->terms, $position);
779 $this->terms = array_merge($part1, array($term), $part2);
780 } else {
781 array_push($this->terms, $term);
782 }
783 }
784
791 public function insertDefinition($position, $definition = null)
792 {
793 if (is_null($definition)) {
794 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
795 $definition = new assAnswerMatchingDefinition();
796 }
797 if ($position < count($this->definitions)) {
798 $part1 = array_slice($this->definitions, 0, $position);
799 $part2 = array_slice($this->definitions, $position);
800 $this->definitions = array_merge($part1, array($definition), $part2);
801 } else {
802 array_push($this->definitions, $definition);
803 }
804 }
805
810 public function flushTerms()
811 {
812 $this->terms = array();
813 }
814
819 public function flushDefinitions()
820 {
821 $this->definitions = array();
822 }
823
830 public function deleteTerm($position)
831 {
832 unset($this->terms[$position]);
833 $this->terms = array_values($this->terms);
834 }
835
842 public function deleteDefinition($position)
843 {
844 unset($this->definitions[$position]);
845 $this->definitions = array_values($this->definitions);
846 }
847
855 public function setTerm($term, $index)
856 {
857 $this->terms[$index] = $term;
858 }
859
870 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
871 {
872 if ($returndetails) {
873 throw new ilTestException('return details not implemented for ' . __METHOD__);
874 }
875
876 global $DIC;
877 $ilDB = $DIC['ilDB'];
878
879 $found_values = array();
880 if (is_null($pass)) {
881 $pass = $this->getSolutionMaxPass($active_id);
882 }
883 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
884 while ($data = $ilDB->fetchAssoc($result)) {
885 if (strcmp($data["value1"], "") != 0) {
886 if (!isset($found_values[$data['value2']])) {
887 $found_values[$data['value2']] = array();
888 }
889
890 $found_values[$data['value2']][] = $data['value1'];
891 }
892 }
893
894 $points = $this->calculateReachedPointsForSolution($found_values);
895
896 return $points;
897 }
898
902 public function getMaximumPoints()
903 {
904 $points = 0;
905
906 foreach ($this->getMaximumScoringMatchingPairs() as $pair) {
907 $points += $pair->points;
908 }
909
910 return $points;
911 }
912
914 {
915 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
916 return $this->getPositiveScoredMatchingPairs();
917 } elseif ($this->getMatchingMode() == self::MATCHING_MODE_1_ON_1) {
919 }
920
921 return array();
922 }
923
925 {
926 $matchingPairs = array();
927
928 foreach ($this->matchingpairs as $pair) {
929 if ($pair->points <= 0) {
930 continue;
931 }
932
933 $matchingPairs[] = $pair;
934 }
935
936 return $matchingPairs;
937 }
938
940 {
941 $matchingPairsByDefinition = array();
942
943 foreach ($this->matchingpairs as $pair) {
944 if ($pair->points <= 0) {
945 continue;
946 }
947
948 $defId = $pair->definition->identifier;
949
950 if (!isset($matchingPairsByDefinition[$defId])) {
951 $matchingPairsByDefinition[$defId] = $pair;
952 } elseif ($pair->points > $matchingPairsByDefinition[$defId]->points) {
953 $matchingPairsByDefinition[$defId] = $pair;
954 }
955 }
956
957 return $matchingPairsByDefinition;
958 }
959
964 public function fetchIndexedValuesFromValuePairs(array $valuePairs)
965 {
966 $indexedValues = array();
967
968 foreach ($valuePairs as $valuePair) {
969 if (!isset($indexedValues[$valuePair['value2']])) {
970 $indexedValues[$valuePair['value2']] = array();
971 }
972
973 $indexedValues[$valuePair['value2']][] = $valuePair['value1'];
974 }
975
976 return $indexedValues;
977 }
978
988 {
989 $extension = "";
990 if (preg_match("/.*\\.(\\w+)$/", $filename, $matches)) {
991 $extension = $matches[1];
992 }
993 return md5($filename) . "." . $extension;
994 }
995
996 public function removeTermImage($index)
997 {
998 $term = $this->terms[$index];
999 if (is_object($term)) {
1000 $this->deleteImagefile($term->picture);
1001 $term->picture = null;
1002 }
1003 }
1004
1006 {
1007 $definition = $this->definitions[$index];
1008 if (is_object($definition)) {
1009 $this->deleteImagefile($definition->picture);
1010 $definition->picture = null;
1011 }
1012 }
1013
1014
1022 {
1023 $deletename = $filename;
1024 $result = @unlink($this->getImagePath() . $deletename);
1025 $result = $result & @unlink($this->getImagePath() . $this->getThumbPrefix() . $deletename);
1026 return $result;
1027 }
1028
1037 public function setImageFile($image_tempfilename, $image_filename, $previous_filename = '')
1038 {
1039 $result = true;
1040 if (strlen($image_tempfilename)) {
1041 $image_filename = str_replace(" ", "_", $image_filename);
1042 $imagepath = $this->getImagePath();
1043 if (!file_exists($imagepath)) {
1044 ilUtil::makeDirParents($imagepath);
1045 }
1046 $savename = $image_filename;
1047 if (!ilUtil::moveUploadedFile($image_tempfilename, $savename, $imagepath . $savename)) {
1048 $result = false;
1049 } else {
1050 // create thumbnail file
1051 $thumbpath = $imagepath . $this->getThumbPrefix() . $savename;
1052 ilUtil::convertImage($imagepath . $savename, $thumbpath, "JPEG", $this->getThumbGeometry());
1053 }
1054 if ($result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename))) {
1055 $this->deleteImagefile($previous_filename);
1056 }
1057 }
1058 return $result;
1059 }
1060
1062 {
1063 $postData = $_POST['matching'][$this->getId()];
1064
1065 $matchings = array();
1066
1067 foreach ($this->getDefinitions() as $definition) {
1068 if (isset($postData[$definition->identifier])) {
1069 foreach ($this->getTerms() as $term) {
1070 if (isset($postData[$definition->identifier][$term->identifier])) {
1071 if (!is_array($postData[$definition->identifier])) {
1072 $postData[$definition->identifier] = array();
1073 }
1074
1075 $matchings[$definition->identifier][] = $term->identifier;
1076 }
1077 }
1078 }
1079 }
1080
1081 return $matchings;
1082 }
1083
1084 private function checkSubmittedMatchings($submittedMatchings)
1085 {
1086 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1087 return true;
1088 }
1089
1090 $handledTerms = array();
1091
1092 foreach ($submittedMatchings as $definition => $terms) {
1093 if (count($terms) > 1) {
1094 ilUtil::sendFailure($this->lng->txt("multiple_matching_values_selected"), true);
1095 return false;
1096 }
1097
1098 foreach ($terms as $i => $term) {
1099 if (isset($handledTerms[$term])) {
1100 ilUtil::sendFailure($this->lng->txt("duplicate_matching_values_selected"), true);
1101 return false;
1102 }
1103
1104 $handledTerms[$term] = $term;
1105 }
1106 }
1107
1108 return true;
1109 }
1110
1119 public function saveWorkingData($active_id, $pass = null, $authorized = true)
1120 {
1121 global $DIC;
1122 $ilDB = $DIC['ilDB'];
1123
1124 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1125 $submittedMatchingsValid = $this->checkSubmittedMatchings($submittedMatchings);
1126
1127 $matchingsExist = false;
1128
1129 if ($submittedMatchingsValid) {
1130 if (is_null($pass)) {
1131 include_once "./Modules/Test/classes/class.ilObjTest.php";
1132 $pass = ilObjTest::_getPass($active_id);
1133 }
1134
1135 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$matchingsExist, $submittedMatchings, $active_id, $pass, $authorized) {
1136 $this->removeCurrentSolution($active_id, $pass, $authorized);
1137
1138 foreach ($submittedMatchings as $definition => $terms) {
1139 foreach ($terms as $i => $term) {
1140 $this->saveCurrentSolution($active_id, $pass, $term, $definition, $authorized);
1141 $matchingsExist = true;
1142 }
1143 }
1144 });
1145
1146 $saveWorkingDataResult = true;
1147 } else {
1148 $saveWorkingDataResult = false;
1149 }
1150
1151 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1153 if ($matchingsExist) {
1154 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1155 } else {
1156 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1157 }
1158 }
1159
1160 return $saveWorkingDataResult;
1161 }
1162
1163 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
1164 {
1165 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1166
1167 if ($this->checkSubmittedMatchings($submittedMatchings)) {
1168 $previewSession->setParticipantsSolution($submittedMatchings);
1169 }
1170 }
1171
1172 public function getRandomId()
1173 {
1174 mt_srand((double) microtime() * 1000000);
1175 $random_number = mt_rand(1, 100000);
1176 $found = false;
1177 while ($found) {
1178 $found = false;
1179 foreach ($this->matchingpairs as $key => $pair) {
1180 if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number)) {
1181 $found = true;
1182 $random_number++;
1183 }
1184 }
1185 }
1186 return $random_number;
1187 }
1188
1195 public function setShuffle($shuffle = true)
1196 {
1197 switch ($shuffle) {
1198 case 0:
1199 case 1:
1200 case 2:
1201 case 3:
1202 $this->shuffle = $shuffle;
1203 break;
1204 default:
1205 $this->shuffle = 1;
1206 break;
1207 }
1208 }
1209
1215 public function getQuestionType()
1216 {
1217 return "assMatchingQuestion";
1218 }
1219
1225 public function getAdditionalTableName()
1226 {
1227 return "qpl_qst_matching";
1228 }
1229
1235 public function getAnswerTableName()
1236 {
1237 return array("qpl_a_matching", "qpl_a_mterm");
1238 }
1239
1245 {
1246 return parent::getRTETextWithMediaObjects();
1247 }
1248
1252 public function &getMatchingPairs()
1253 {
1254 return $this->matchingpairs;
1255 }
1256
1260 public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
1261 {
1262 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1263
1264 $solutions = $this->getSolutionValues($active_id, $pass);
1265
1266 $imagepath = $this->getImagePath();
1267 $i = 1;
1268 foreach ($solutions as $solution) {
1269 $matches_written = false;
1270 foreach ($this->getMatchingPairs() as $idx => $pair) {
1271 if (!$matches_written) {
1272 $worksheet->setCell($startrow + $i, 1, $this->lng->txt("matches"));
1273 }
1274 $matches_written = true;
1275 if ($pair->definition->identifier == $solution["value2"]) {
1276 if (strlen($pair->definition->text)) {
1277 $worksheet->setCell($startrow + $i, 0, $pair->definition->text);
1278 } else {
1279 $worksheet->setCell($startrow + $i, 0, $pair->definition->picture);
1280 }
1281 }
1282 if ($pair->term->identifier == $solution["value1"]) {
1283 if (strlen($pair->term->text)) {
1284 $worksheet->setCell($startrow + $i, 2, $pair->term->text);
1285 } else {
1286 $worksheet->setCell($startrow + $i, 2, $pair->term->picture);
1287 }
1288 }
1289 }
1290 $i++;
1291 }
1292
1293 return $startrow + $i + 1;
1294 }
1295
1301 public function getThumbGeometry()
1302 {
1303 return $this->thumb_geometry;
1304 }
1305
1311 public function getThumbSize()
1312 {
1313 return $this->getThumbGeometry();
1314 }
1315
1321 public function setThumbGeometry($a_geometry)
1322 {
1323 $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1324 }
1325
1329 public function rebuildThumbnails()
1330 {
1331 foreach ($this->terms as $term) {
1332 if (strlen($term->picture)) {
1333 $this->generateThumbForFile($this->getImagePath(), $term->picture);
1334 }
1335 }
1336 foreach ($this->definitions as $definition) {
1337 if (strlen($definition->picture)) {
1338 $this->generateThumbForFile($this->getImagePath(), $definition->picture);
1339 }
1340 }
1341 }
1342
1343 public function getThumbPrefix()
1344 {
1345 return "thumb.";
1346 }
1347
1348 protected function generateThumbForFile($path, $file)
1349 {
1350 $filename = $path . $file;
1351 if (@file_exists($filename)) {
1352 $thumbpath = $path . $this->getThumbPrefix() . $file;
1353 $path_info = @pathinfo($filename);
1354 $ext = "";
1355 switch (strtoupper($path_info['extension'])) {
1356 case 'PNG':
1357 $ext = 'PNG';
1358 break;
1359 case 'GIF':
1360 $ext = 'GIF';
1361 break;
1362 default:
1363 $ext = 'JPEG';
1364 break;
1365 }
1366 ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1367 }
1368 }
1369
1374 public function toJSON()
1375 {
1376 $result = array();
1377
1378 $result['id'] = (int) $this->getId();
1379 $result['type'] = (string) $this->getQuestionType();
1380 $result['title'] = (string) $this->getTitle();
1381 $result['question'] = $this->formatSAQuestion($this->getQuestion());
1382 $result['nr_of_tries'] = (int) $this->getNrOfTries();
1383 $result['matching_mode'] = $this->getMatchingMode();
1384 $result['shuffle'] = true;
1385 $result['feedback'] = array(
1386 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1387 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1388 );
1389
1390 require_once 'Services/Randomization/classes/class.ilArrayElementShuffler.php';
1391 $this->setShuffler(new ilArrayElementShuffler());
1392 $seed = $this->getShuffler()->getSeed();
1393
1394 $terms = array();
1395 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'terms'));
1396 foreach ($this->getShuffler()->shuffle($this->getTerms()) as $term) {
1397 $terms[] = array(
1398 "text" => $this->formatSAQuestion($term->text),
1399 "id" => (int) $this->getId() . $term->identifier
1400 );
1401 }
1402 $result['terms'] = $terms;
1403
1404 // alex 9.9.2010 as a fix for bug 6513 I added the question id
1405 // to the "def_id" in the array. The $pair->definition->identifier is not
1406 // unique, since it gets it value from the morder table field
1407 // this value is not changed, when a question is copied.
1408 // thus copying the same question on a page results in problems
1409 // when the second one (the copy) is answered.
1410
1411 $definitions = array();
1412 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'definitions'));
1413 foreach ($this->getShuffler()->shuffle($this->getDefinitions()) as $def) {
1414 $definitions[] = array(
1415 "text" => $this->formatSAQuestion((string) $def->text),
1416 "id" => (int) $this->getId() . $def->identifier
1417 );
1418 }
1419 $result['definitions'] = $definitions;
1420
1421 // #10353
1422 $matchings = array();
1423 foreach ($this->getMatchingPairs() as $pair) {
1424 // fau: fixLmMatchingPoints - ignore matching pairs with 0 or negative points
1425 if ($pair->points <= 0) {
1426 continue;
1427 }
1428 // fau.
1429
1430 $pid = $pair->definition->identifier;
1431 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1432 $pid .= '::' . $pair->term->identifier;
1433 }
1434
1435 if (!isset($matchings[$pid]) || $matchings[$pid]["points"] < $pair->points) {
1436 $matchings[$pid] = array(
1437 "term_id" => (int) $this->getId() . $pair->term->identifier,
1438 "def_id" => (int) $this->getId() . $pair->definition->identifier,
1439 "points" => (int) $pair->points
1440 );
1441 }
1442 }
1443
1444 $result['matchingPairs'] = array_values($matchings);
1445
1446 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1447 $result['mobs'] = $mobs;
1448
1449 global $DIC;
1450 $lng = $DIC['lng'];
1451 $lng->loadLanguageModule('assessment');
1452 $result['reset_button_label'] = $lng->txt("reset_terms");
1453
1454 return json_encode($result);
1455 }
1456
1458 {
1459 return true;
1460 }
1461
1462 public function supportsNonJsOutput()
1463 {
1464 return false;
1465 }
1466
1468 {
1469 $this->matchingMode = $matchingMode;
1470 }
1471
1472 public function getMatchingMode()
1473 {
1474 return $this->matchingMode;
1475 }
1476
1481 protected function calculateReachedPointsForSolution($found_values)
1482 {
1483 $points = 0;
1484 foreach ($found_values as $definition => $terms) {
1485 foreach ($terms as $term) {
1486 foreach ($this->matchingpairs as $pair) {
1487 if ($pair->definition->identifier == $definition && $pair->term->identifier == $term) {
1488 $points += $pair->points;
1489 }
1490 }
1491 }
1492 }
1493 return $points;
1494 }
1495
1504 public function getOperators($expression)
1505 {
1506 require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1508 }
1509
1514 public function getExpressionTypes()
1515 {
1516 return array(
1521 );
1522 }
1531 public function getUserQuestionResult($active_id, $pass)
1532 {
1534 global $DIC;
1535 $ilDB = $DIC['ilDB'];
1536 $result = new ilUserQuestionResult($this, $active_id, $pass);
1537
1538 $data = $ilDB->queryF(
1539 "SELECT ident FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id",
1540 array("integer"),
1541 array($this->getId())
1542 );
1543
1544 $definitions = array();
1545 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1546 $row = $ilDB->fetchAssoc($data);
1547 $definitions[$row["ident"]] = $index;
1548 }
1549
1550 $data = $ilDB->queryF(
1551 "SELECT ident FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id",
1552 array("integer"),
1553 array($this->getId())
1554 );
1555
1556 $terms = array();
1557 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1558 $row = $ilDB->fetchAssoc($data);
1559 $terms[$row["ident"]] = $index;
1560 }
1561
1562 $maxStep = $this->lookupMaxStep($active_id, $pass);
1563
1564 if ($maxStep !== null) {
1565 $data = $ilDB->queryF(
1566 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1567 array("integer", "integer", "integer","integer"),
1568 array($active_id, $pass, $this->getId(), $maxStep)
1569 );
1570 } else {
1571 $data = $ilDB->queryF(
1572 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1573 array("integer", "integer", "integer"),
1574 array($active_id, $pass, $this->getId())
1575 );
1576 }
1577
1578 while ($row = $ilDB->fetchAssoc($data)) {
1579 if ($row["value1"] > 0) {
1580 $result->addKeyValue($definitions[$row["value2"]], $terms[$row["value1"]]);
1581 }
1582 }
1583
1584 $points = $this->calculateReachedPoints($active_id, $pass);
1585 $max_points = $this->getMaximumPoints();
1586
1587 $result->setReachedPercentage(($points / $max_points) * 100);
1588
1589 return $result;
1590 }
1591
1600 public function getAvailableAnswerOptions($index = null)
1601 {
1602 if ($index !== null) {
1603 return $this->getMatchingPair($index);
1604 } else {
1605 return $this->getMatchingPairs();
1606 }
1607 }
1608
1612 protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1613 {
1614 parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1615
1616 $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1617 $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1618
1619 ilUtil::delDir($origImagePath);
1620 if (is_dir($dupImagePath)) {
1621 ilUtil::makeDirParents($origImagePath);
1622 ilUtil::rCopy($dupImagePath, $origImagePath);
1623 }
1624 }
1625}
$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.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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.
global $DIC
Definition: goto.php:24
$mobs
Definition: imgupload.php:54
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