ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 ) {
93 parent::__construct($title, $comment, $author, $owner, $question);
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->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
275 } catch (ilTestQuestionPoolException $e) {
276 }
277 }
278
279 $termids = array();
280 $result = $ilDB->queryF(
281 "SELECT * FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id ASC",
282 array('integer'),
283 array($question_id)
284 );
285 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
286 $this->terms = array();
287 if ($result->numRows() > 0) {
288 while ($data = $ilDB->fetchAssoc($result)) {
289 $term = new assAnswerMatchingTerm($data['term'], $data['picture'], $data['ident']);
290 array_push($this->terms, $term);
291 $termids[$data['term_id']] = $term;
292 }
293 }
294
295 $definitionids = array();
296 $result = $ilDB->queryF(
297 "SELECT * FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id ASC",
298 array('integer'),
299 array($question_id)
300 );
301 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
302 $this->definitions = array();
303 if ($result->numRows() > 0) {
304 while ($data = $ilDB->fetchAssoc($result)) {
305 $definition = new assAnswerMatchingDefinition($data['definition'], $data['picture'], $data['ident']);
306 array_push($this->definitions, $definition);
307 $definitionids[$data['def_id']] = $definition;
308 }
309 }
310
311 $this->matchingpairs = array();
312 $result = $ilDB->queryF(
313 "SELECT * FROM qpl_a_matching WHERE question_fi = %s ORDER BY answer_id",
314 array('integer'),
315 array($question_id)
316 );
317 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
318 if ($result->numRows() > 0) {
319 while ($data = $ilDB->fetchAssoc($result)) {
320 array_push($this->matchingpairs, new assAnswerMatchingPair($termids[$data['term_fi']], $definitionids[$data['definition_fi']], $data['points']));
321 }
322 }
323 parent::loadFromDb($question_id);
324 }
325
326
330 public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
331 {
332 if ($this->id <= 0) {
333 // The question has not been saved. It cannot be duplicated
334 return;
335 }
336 // duplicate the question in database
337 $this_id = $this->getId();
338 $thisObjId = $this->getObjId();
339
340 $clone = $this;
341 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
343 $clone->id = -1;
344
345 if ((int) $testObjId > 0) {
346 $clone->setObjId($testObjId);
347 }
348
349 if ($title) {
350 $clone->setTitle($title);
351 }
352 if ($author) {
353 $clone->setAuthor($author);
354 }
355 if ($owner) {
356 $clone->setOwner($owner);
357 }
358 if ($for_test) {
359 $clone->saveToDb($original_id);
360 } else {
361 $clone->saveToDb();
362 }
363
364 // copy question page content
365 $clone->copyPageOfQuestion($this_id);
366 // copy XHTML media objects
367 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
368 // duplicate the image
369 $clone->duplicateImages($this_id, $thisObjId, $clone->getId(), $testObjId);
370
371 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
372
373 return $clone->id;
374 }
375
379 public function copyObject($target_questionpool_id, $title = "")
380 {
381 if ($this->id <= 0) {
382 // The question has not been saved. It cannot be duplicated
383 return;
384 }
385 // duplicate the question in database
386 $clone = $this;
387 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
389 $clone->id = -1;
390 $source_questionpool_id = $this->getObjId();
391 $clone->setObjId($target_questionpool_id);
392 if ($title) {
393 $clone->setTitle($title);
394 }
395 $clone->saveToDb();
396 // copy question page content
397 $clone->copyPageOfQuestion($original_id);
398 // copy XHTML media objects
399 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
400 // duplicate the image
401 $clone->copyImages($original_id, $source_questionpool_id);
402
403 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
404
405 return $clone->id;
406 }
407
408 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
409 {
410 if ($this->id <= 0) {
411 // The question has not been saved. It cannot be duplicated
412 return;
413 }
414
415 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
416
417 $sourceQuestionId = $this->id;
418 $sourceParentId = $this->getObjId();
419
420 // duplicate the question in database
421 $clone = $this;
422 $clone->id = -1;
423
424 $clone->setObjId($targetParentId);
425
426 if ($targetQuestionTitle) {
427 $clone->setTitle($targetQuestionTitle);
428 }
429
430 $clone->saveToDb();
431 // copy question page content
432 $clone->copyPageOfQuestion($sourceQuestionId);
433 // copy XHTML media objects
434 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
435 // duplicate the image
436 $clone->copyImages($sourceQuestionId, $sourceParentId);
437
438 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
439
440 return $clone->id;
441 }
442
443 public function duplicateImages($question_id, $objectId = null)
444 {
445 global $DIC;
446 $ilLog = $DIC['ilLog'];
447 $imagepath = $this->getImagePath();
448 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
449
450 if ((int) $objectId > 0) {
451 $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
452 }
453
454 foreach ($this->terms as $term) {
455 if (strlen($term->picture)) {
456 $filename = $term->picture;
457 if (!file_exists($imagepath)) {
458 ilUtil::makeDirParents($imagepath);
459 }
460 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
461 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
462 }
463 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
464 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
465 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
466 }
467 }
468 }
469 }
470 foreach ($this->definitions as $definition) {
471 if (strlen($definition->picture)) {
472 $filename = $definition->picture;
473 if (!file_exists($imagepath)) {
474 ilUtil::makeDirParents($imagepath);
475 }
476 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
477 $ilLog->write("matching question image could not be duplicated: $imagepath_original$filename");
478 }
479 if (@file_exists($imagepath_original . $this->getThumbPrefix() . $filename)) {
480 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
481 $ilLog->write("matching question image thumbnail could not be duplicated: $imagepath_original" . $this->getThumbPrefix() . $filename);
482 }
483 }
484 }
485 }
486 }
487
488 public function copyImages($question_id, $source_questionpool)
489 {
490 global $DIC;
491 $ilLog = $DIC['ilLog'];
492
493 $imagepath = $this->getImagePath();
494 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
495 $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
496 foreach ($this->terms as $term) {
497 if (strlen($term->picture)) {
498 if (!file_exists($imagepath)) {
499 ilUtil::makeDirParents($imagepath);
500 }
501 $filename = $term->picture;
502 if (!@copy($imagepath_original . $filename, $imagepath . $filename)) {
503 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
504 }
505 if (!@copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename)) {
506 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
507 }
508 }
509 }
510 foreach ($this->definitions as $definition) {
511 if (strlen($definition->picture)) {
512 $filename = $definition->picture;
513 if (!file_exists($imagepath)) {
514 ilUtil::makeDirParents($imagepath);
515 }
516
517 if (assQuestion::isFileAvailable($imagepath_original . $filename)) {
518 copy($imagepath_original . $filename, $imagepath . $filename);
519 } else {
520 $ilLog->write("matching question image could not be copied: $imagepath_original$filename");
521 }
522
523 if (assQuestion::isFileAvailable($imagepath_original . $this->getThumbPrefix() . $filename)) {
524 copy($imagepath_original . $this->getThumbPrefix() . $filename, $imagepath . $this->getThumbPrefix() . $filename);
525 } else {
526 $ilLog->write("matching question image thumbnail could not be copied: $imagepath_original" . $this->getThumbPrefix() . $filename);
527 }
528 }
529 }
530 }
531
542 public function insertMatchingPair($position, $term = null, $definition = null, $points = 0.0)
543 {
544 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php";
545 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
546 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
547 if (is_null($term)) {
548 $term = new assAnswerMatchingTerm();
549 }
550 if (is_null($definition)) {
551 $definition = new assAnswerMatchingDefinition();
552 }
553 $pair = new assAnswerMatchingPair($term, $definition, $points);
554 if ($position < count($this->matchingpairs)) {
555 $part1 = array_slice($this->matchingpairs, 0, $position);
556 $part2 = array_slice($this->matchingpairs, $position);
557 $this->matchingpairs = array_merge($part1, array($pair), $part2);
558 } else {
559 array_push($this->matchingpairs, $pair);
560 }
561 }
562
574 public function addMatchingPair($term = null, $definition = null, $points = 0.0)
575 {
576 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingPair.php';
577 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php';
578 require_once './Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php';
579 if (is_null($term)) {
580 $term = new assAnswerMatchingTerm();
581 }
582 if (is_null($definition)) {
583 $definition = new assAnswerMatchingDefinition();
584 }
585 $pair = new assAnswerMatchingPair($term, $definition, $points);
586 array_push($this->matchingpairs, $pair);
587 }
588
592 public function getTermWithIdentifier($a_identifier)
593 {
594 foreach ($this->terms as $term) {
595 if ($term->identifier == $a_identifier) {
596 return $term;
597 }
598 }
599 return null;
600 }
601
605 public function getDefinitionWithIdentifier($a_identifier)
606 {
607 foreach ($this->definitions as $definition) {
608 if ($definition->identifier == $a_identifier) {
609 return $definition;
610 }
611 }
612 return null;
613 }
614
623 public function getMatchingPair($index = 0)
624 {
625 if ($index < 0) {
626 return null;
627 }
628 if (count($this->matchingpairs) < 1) {
629 return null;
630 }
631 if ($index >= count($this->matchingpairs)) {
632 return null;
633 }
634 return $this->matchingpairs[$index];
635 }
636
644 public function deleteMatchingPair($index = 0)
645 {
646 if ($index < 0) {
647 return;
648 }
649 if (count($this->matchingpairs) < 1) {
650 return;
651 }
652 if ($index >= count($this->matchingpairs)) {
653 return;
654 }
655 unset($this->matchingpairs[$index]);
656 $this->matchingpairs = array_values($this->matchingpairs);
657 }
658
663 public function flushMatchingPairs()
664 {
665 $this->matchingpairs = array();
666 }
667
674 public function getMatchingPairCount()
675 {
676 return count($this->matchingpairs);
677 }
678
685 public function getTerms()
686 {
687 return $this->terms;
688 }
689
696 public function getDefinitions()
697 {
698 return $this->definitions;
699 }
700
707 public function getTermCount()
708 {
709 return count($this->terms);
710 }
711
718 public function getDefinitionCount()
719 {
720 return count($this->definitions);
721 }
722
729 public function addTerm($term)
730 {
731 array_push($this->terms, $term);
732 }
733
740 public function addDefinition($definition)
741 {
742 array_push($this->definitions, $definition);
743 }
744
751 public function insertTerm($position, $term = null)
752 {
753 if (is_null($term)) {
754 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingTerm.php";
755 $term = new assAnswerMatchingTerm();
756 }
757 if ($position < count($this->terms)) {
758 $part1 = array_slice($this->terms, 0, $position);
759 $part2 = array_slice($this->terms, $position);
760 $this->terms = array_merge($part1, array($term), $part2);
761 } else {
762 array_push($this->terms, $term);
763 }
764 }
765
772 public function insertDefinition($position, $definition = null)
773 {
774 if (is_null($definition)) {
775 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatchingDefinition.php";
776 $definition = new assAnswerMatchingDefinition();
777 }
778 if ($position < count($this->definitions)) {
779 $part1 = array_slice($this->definitions, 0, $position);
780 $part2 = array_slice($this->definitions, $position);
781 $this->definitions = array_merge($part1, array($definition), $part2);
782 } else {
783 array_push($this->definitions, $definition);
784 }
785 }
786
791 public function flushTerms()
792 {
793 $this->terms = array();
794 }
795
800 public function flushDefinitions()
801 {
802 $this->definitions = array();
803 }
804
811 public function deleteTerm($position)
812 {
813 unset($this->terms[$position]);
814 $this->terms = array_values($this->terms);
815 }
816
823 public function deleteDefinition($position)
824 {
825 unset($this->definitions[$position]);
826 $this->definitions = array_values($this->definitions);
827 }
828
836 public function setTerm($term, $index)
837 {
838 $this->terms[$index] = $term;
839 }
840
851 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
852 {
853 if ($returndetails) {
854 throw new ilTestException('return details not implemented for ' . __METHOD__);
855 }
856
857 global $DIC;
858 $ilDB = $DIC['ilDB'];
859
860 $found_values = array();
861 if (is_null($pass)) {
862 $pass = $this->getSolutionMaxPass($active_id);
863 }
864 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
865 while ($data = $ilDB->fetchAssoc($result)) {
866 if (strcmp($data["value1"], "") != 0) {
867 if (!isset($found_values[$data['value2']])) {
868 $found_values[$data['value2']] = array();
869 }
870
871 $found_values[$data['value2']][] = $data['value1'];
872 }
873 }
874
875 $points = $this->calculateReachedPointsForSolution($found_values);
876
877 return $points;
878 }
879
883 public function getMaximumPoints()
884 {
885 $points = 0;
886
887 foreach ($this->getMaximumScoringMatchingPairs() as $pair) {
888 $points += $pair->points;
889 }
890
891 return $points;
892 }
893
895 {
896 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
897 return $this->getPositiveScoredMatchingPairs();
898 } elseif ($this->getMatchingMode() == self::MATCHING_MODE_1_ON_1) {
900 }
901
902 return array();
903 }
904
906 {
907 $matchingPairs = array();
908
909 foreach ($this->matchingpairs as $pair) {
910 if ($pair->points <= 0) {
911 continue;
912 }
913
914 $matchingPairs[] = $pair;
915 }
916
917 return $matchingPairs;
918 }
919
921 {
922 $matchingPairsByDefinition = array();
923
924 foreach ($this->matchingpairs as $pair) {
925 if ($pair->points <= 0) {
926 continue;
927 }
928
929 $defId = $pair->definition->identifier;
930
931 if (!isset($matchingPairsByDefinition[$defId])) {
932 $matchingPairsByDefinition[$defId] = $pair;
933 } elseif ($pair->points > $matchingPairsByDefinition[$defId]->points) {
934 $matchingPairsByDefinition[$defId] = $pair;
935 }
936 }
937
938 return $matchingPairsByDefinition;
939 }
940
945 public function fetchIndexedValuesFromValuePairs(array $valuePairs)
946 {
947 $indexedValues = array();
948
949 foreach ($valuePairs as $valuePair) {
950 if (!isset($indexedValues[$valuePair['value2']])) {
951 $indexedValues[$valuePair['value2']] = array();
952 }
953
954 $indexedValues[$valuePair['value2']][] = $valuePair['value1'];
955 }
956
957 return $indexedValues;
958 }
959
969 {
970 $extension = "";
971 if (preg_match("/.*\\.(\\w+)$/", $filename, $matches)) {
972 $extension = $matches[1];
973 }
974 return md5($filename) . "." . $extension;
975 }
976
977 public function removeTermImage($index)
978 {
979 $term = $this->terms[$index];
980 if (is_object($term)) {
981 $this->deleteImagefile($term->picture);
982 $term->picture = null;
983 }
984 }
985
987 {
988 $definition = $this->definitions[$index];
989 if (is_object($definition)) {
990 $this->deleteImagefile($definition->picture);
991 $definition->picture = null;
992 }
993 }
994
995
1003 {
1004 $deletename = $filename;
1005 $result = @unlink($this->getImagePath() . $deletename);
1006 $result = $result & @unlink($this->getImagePath() . $this->getThumbPrefix() . $deletename);
1007 return $result;
1008 }
1009
1018 public function setImageFile($image_tempfilename, $image_filename, $previous_filename = '')
1019 {
1020 $result = true;
1021 if (strlen($image_tempfilename)) {
1022 $image_filename = str_replace(" ", "_", $image_filename);
1023 $imagepath = $this->getImagePath();
1024 if (!file_exists($imagepath)) {
1025 ilUtil::makeDirParents($imagepath);
1026 }
1027 $savename = $image_filename;
1028 if (!ilUtil::moveUploadedFile($image_tempfilename, $savename, $imagepath . $savename)) {
1029 $result = false;
1030 } else {
1031 // create thumbnail file
1032 $thumbpath = $imagepath . $this->getThumbPrefix() . $savename;
1033 ilUtil::convertImage($imagepath . $savename, $thumbpath, "JPEG", $this->getThumbGeometry());
1034 }
1035 if ($result && (strcmp($image_filename, $previous_filename) != 0) && (strlen($previous_filename))) {
1036 $this->deleteImagefile($previous_filename);
1037 }
1038 }
1039 return $result;
1040 }
1041
1043 {
1044 $postData = $_POST['matching'][$this->getId()];
1045
1046 $matchings = array();
1047
1048 foreach ($this->getDefinitions() as $definition) {
1049 if (isset($postData[$definition->identifier])) {
1050 foreach ($this->getTerms() as $term) {
1051 if (isset($postData[$definition->identifier][$term->identifier])) {
1052 if (!is_array($postData[$definition->identifier])) {
1053 $postData[$definition->identifier] = array();
1054 }
1055
1056 $matchings[$definition->identifier][] = $term->identifier;
1057 }
1058 }
1059 }
1060 }
1061
1062 return $matchings;
1063 }
1064
1065 private function checkSubmittedMatchings($submittedMatchings)
1066 {
1067 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1068 return true;
1069 }
1070
1071 $handledTerms = array();
1072
1073 foreach ($submittedMatchings as $definition => $terms) {
1074 if (count($terms) > 1) {
1075 ilUtil::sendFailure($this->lng->txt("multiple_matching_values_selected"), true);
1076 return false;
1077 }
1078
1079 foreach ($terms as $i => $term) {
1080 if (isset($handledTerms[$term])) {
1081 ilUtil::sendFailure($this->lng->txt("duplicate_matching_values_selected"), true);
1082 return false;
1083 }
1084
1085 $handledTerms[$term] = $term;
1086 }
1087 }
1088
1089 return true;
1090 }
1091
1100 public function saveWorkingData($active_id, $pass = null, $authorized = true)
1101 {
1102 global $DIC;
1103 $ilDB = $DIC['ilDB'];
1104
1105 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1106 $submittedMatchingsValid = $this->checkSubmittedMatchings($submittedMatchings);
1107
1108 $matchingsExist = false;
1109
1110 if ($submittedMatchingsValid) {
1111 if (is_null($pass)) {
1112 include_once "./Modules/Test/classes/class.ilObjTest.php";
1113 $pass = ilObjTest::_getPass($active_id);
1114 }
1115
1116 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$matchingsExist, $submittedMatchings, $active_id, $pass, $authorized) {
1117 $this->removeCurrentSolution($active_id, $pass, $authorized);
1118
1119 foreach ($submittedMatchings as $definition => $terms) {
1120 foreach ($terms as $i => $term) {
1121 $this->saveCurrentSolution($active_id, $pass, $term, $definition, $authorized);
1122 $matchingsExist = true;
1123 }
1124 }
1125 });
1126
1127 $saveWorkingDataResult = true;
1128 } else {
1129 $saveWorkingDataResult = false;
1130 }
1131
1132 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1134 if ($matchingsExist) {
1135 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1136 } else {
1137 assQuestion::logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
1138 }
1139 }
1140
1141 return $saveWorkingDataResult;
1142 }
1143
1144 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
1145 {
1146 $submittedMatchings = $this->fetchSubmittedMatchingsFromPost();
1147
1148 if ($this->checkSubmittedMatchings($submittedMatchings)) {
1149 $previewSession->setParticipantsSolution($submittedMatchings);
1150 }
1151 }
1152
1153 public function getRandomId()
1154 {
1155 mt_srand((double) microtime() * 1000000);
1156 $random_number = mt_rand(1, 100000);
1157 $found = false;
1158 while ($found) {
1159 $found = false;
1160 foreach ($this->matchingpairs as $key => $pair) {
1161 if (($pair->term->identifier == $random_number) || ($pair->definition->identifier == $random_number)) {
1162 $found = true;
1163 $random_number++;
1164 }
1165 }
1166 }
1167 return $random_number;
1168 }
1169
1176 public function setShuffle($shuffle = true)
1177 {
1178 switch ($shuffle) {
1179 case 0:
1180 case 1:
1181 case 2:
1182 case 3:
1183 $this->shuffle = $shuffle;
1184 break;
1185 default:
1186 $this->shuffle = 1;
1187 break;
1188 }
1189 }
1190
1196 public function getQuestionType()
1197 {
1198 return "assMatchingQuestion";
1199 }
1200
1206 public function getAdditionalTableName()
1207 {
1208 return "qpl_qst_matching";
1209 }
1210
1216 public function getAnswerTableName()
1217 {
1218 return array("qpl_a_matching", "qpl_a_mterm");
1219 }
1220
1226 {
1227 return parent::getRTETextWithMediaObjects();
1228 }
1229
1233 public function &getMatchingPairs()
1234 {
1235 return $this->matchingpairs;
1236 }
1237
1241 public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
1242 {
1243 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1244
1245 $solutions = $this->getSolutionValues($active_id, $pass);
1246
1247 $imagepath = $this->getImagePath();
1248 $i = 1;
1249 foreach ($solutions as $solution) {
1250 $matches_written = false;
1251 foreach ($this->getMatchingPairs() as $idx => $pair) {
1252 if (!$matches_written) {
1253 $worksheet->setCell($startrow + $i, 1, $this->lng->txt("matches"));
1254 }
1255 $matches_written = true;
1256 if ($pair->definition->identifier == $solution["value2"]) {
1257 if (strlen($pair->definition->text)) {
1258 $worksheet->setCell($startrow + $i, 0, $pair->definition->text);
1259 } else {
1260 $worksheet->setCell($startrow + $i, 0, $pair->definition->picture);
1261 }
1262 }
1263 if ($pair->term->identifier == $solution["value1"]) {
1264 if (strlen($pair->term->text)) {
1265 $worksheet->setCell($startrow + $i, 2, $pair->term->text);
1266 } else {
1267 $worksheet->setCell($startrow + $i, 2, $pair->term->picture);
1268 }
1269 }
1270 }
1271 $i++;
1272 }
1273
1274 return $startrow + $i + 1;
1275 }
1276
1282 public function getThumbGeometry()
1283 {
1284 return $this->thumb_geometry;
1285 }
1286
1292 public function getThumbSize()
1293 {
1294 return $this->getThumbGeometry();
1295 }
1296
1302 public function setThumbGeometry($a_geometry)
1303 {
1304 $this->thumb_geometry = ($a_geometry < 1) ? 100 : $a_geometry;
1305 }
1306
1310 public function rebuildThumbnails()
1311 {
1312 foreach ($this->terms as $term) {
1313 if (strlen($term->picture)) {
1314 $this->generateThumbForFile($this->getImagePath(), $term->picture);
1315 }
1316 }
1317 foreach ($this->definitions as $definition) {
1318 if (strlen($definition->picture)) {
1319 $this->generateThumbForFile($this->getImagePath(), $definition->picture);
1320 }
1321 }
1322 }
1323
1324 public function getThumbPrefix()
1325 {
1326 return "thumb.";
1327 }
1328
1329 protected function generateThumbForFile($path, $file)
1330 {
1331 $filename = $path . $file;
1332 if (@file_exists($filename)) {
1333 $thumbpath = $path . $this->getThumbPrefix() . $file;
1334 $path_info = @pathinfo($filename);
1335 $ext = "";
1336 switch (strtoupper($path_info['extension'])) {
1337 case 'PNG':
1338 $ext = 'PNG';
1339 break;
1340 case 'GIF':
1341 $ext = 'GIF';
1342 break;
1343 default:
1344 $ext = 'JPEG';
1345 break;
1346 }
1347 ilUtil::convertImage($filename, $thumbpath, $ext, $this->getThumbGeometry());
1348 }
1349 }
1350
1355 public function toJSON()
1356 {
1357 $result = array();
1358
1359 $result['id'] = (int) $this->getId();
1360 $result['type'] = (string) $this->getQuestionType();
1361 $result['title'] = (string) $this->getTitle();
1362 $result['question'] = $this->formatSAQuestion($this->getQuestion());
1363 $result['nr_of_tries'] = (int) $this->getNrOfTries();
1364 $result['matching_mode'] = $this->getMatchingMode();
1365 $result['shuffle'] = true;
1366 $result['feedback'] = array(
1367 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
1368 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
1369 );
1370
1371 require_once 'Services/Randomization/classes/class.ilArrayElementShuffler.php';
1372 $this->setShuffler(new ilArrayElementShuffler());
1373 $seed = $this->getShuffler()->getSeed();
1374
1375 $terms = array();
1376 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'terms'));
1377 foreach ($this->getShuffler()->shuffle($this->getTerms()) as $term) {
1378 $terms[] = array(
1379 "text" => $this->formatSAQuestion($term->text),
1380 "id" => (int) $this->getId() . $term->identifier
1381 );
1382 }
1383 $result['terms'] = $terms;
1384
1385 // alex 9.9.2010 as a fix for bug 6513 I added the question id
1386 // to the "def_id" in the array. The $pair->definition->identifier is not
1387 // unique, since it gets it value from the morder table field
1388 // this value is not changed, when a question is copied.
1389 // thus copying the same question on a page results in problems
1390 // when the second one (the copy) is answered.
1391
1392 $definitions = array();
1393 $this->getShuffler()->setSeed($this->getShuffler()->buildSeedFromString($seed . 'definitions'));
1394 foreach ($this->getShuffler()->shuffle($this->getDefinitions()) as $def) {
1395 $definitions[] = array(
1396 "text" => $this->formatSAQuestion((string) $def->text),
1397 "id" => (int) $this->getId() . $def->identifier
1398 );
1399 }
1400 $result['definitions'] = $definitions;
1401
1402 // #10353
1403 $matchings = array();
1404 foreach ($this->getMatchingPairs() as $pair) {
1405 // fau: fixLmMatchingPoints - ignore matching pairs with 0 or negative points
1406 if ($pair->points <= 0) {
1407 continue;
1408 }
1409 // fau.
1410
1411 $pid = $pair->definition->identifier;
1412 if ($this->getMatchingMode() == self::MATCHING_MODE_N_ON_N) {
1413 $pid .= '::' . $pair->term->identifier;
1414 }
1415
1416 if (!isset($matchings[$pid]) || $matchings[$pid]["points"] < $pair->points) {
1417 $matchings[$pid] = array(
1418 "term_id" => (int) $this->getId() . $pair->term->identifier,
1419 "def_id" => (int) $this->getId() . $pair->definition->identifier,
1420 "points" => (int) $pair->points
1421 );
1422 }
1423 }
1424
1425 $result['matchingPairs'] = array_values($matchings);
1426
1427 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1428 $result['mobs'] = $mobs;
1429
1430 global $DIC;
1431 $lng = $DIC['lng'];
1432 $lng->loadLanguageModule('assessment');
1433 $result['reset_button_label'] = $lng->txt("reset_terms");
1434
1435 return json_encode($result);
1436 }
1437
1439 {
1440 return true;
1441 }
1442
1443 public function supportsNonJsOutput()
1444 {
1445 return false;
1446 }
1447
1449 {
1450 $this->matchingMode = $matchingMode;
1451 }
1452
1453 public function getMatchingMode()
1454 {
1455 return $this->matchingMode;
1456 }
1457
1462 protected function calculateReachedPointsForSolution($found_values)
1463 {
1464 $points = 0;
1465 foreach ($found_values as $definition => $terms) {
1466 foreach ($terms as $term) {
1467 foreach ($this->matchingpairs as $pair) {
1468 if ($pair->definition->identifier == $definition && $pair->term->identifier == $term) {
1469 $points += $pair->points;
1470 }
1471 }
1472 }
1473 }
1474 return $points;
1475 }
1476
1485 public function getOperators($expression)
1486 {
1487 require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1489 }
1490
1495 public function getExpressionTypes()
1496 {
1497 return array(
1502 );
1503 }
1512 public function getUserQuestionResult($active_id, $pass)
1513 {
1515 global $DIC;
1516 $ilDB = $DIC['ilDB'];
1517 $result = new ilUserQuestionResult($this, $active_id, $pass);
1518
1519 $data = $ilDB->queryF(
1520 "SELECT ident FROM qpl_a_mdef WHERE question_fi = %s ORDER BY def_id",
1521 array("integer"),
1522 array($this->getId())
1523 );
1524
1525 $definitions = array();
1526 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1527 $row = $ilDB->fetchAssoc($data);
1528 $definitions[$row["ident"]] = $index;
1529 }
1530
1531 $data = $ilDB->queryF(
1532 "SELECT ident FROM qpl_a_mterm WHERE question_fi = %s ORDER BY term_id",
1533 array("integer"),
1534 array($this->getId())
1535 );
1536
1537 $terms = array();
1538 for ($index = 1; $index <= $ilDB->numRows($data); ++$index) {
1539 $row = $ilDB->fetchAssoc($data);
1540 $terms[$row["ident"]] = $index;
1541 }
1542
1543 $maxStep = $this->lookupMaxStep($active_id, $pass);
1544
1545 if ($maxStep !== null) {
1546 $data = $ilDB->queryF(
1547 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1548 array("integer", "integer", "integer","integer"),
1549 array($active_id, $pass, $this->getId(), $maxStep)
1550 );
1551 } else {
1552 $data = $ilDB->queryF(
1553 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1554 array("integer", "integer", "integer"),
1555 array($active_id, $pass, $this->getId())
1556 );
1557 }
1558
1559 while ($row = $ilDB->fetchAssoc($data)) {
1560 if ($row["value1"] > 0) {
1561 $result->addKeyValue($definitions[$row["value2"]], $terms[$row["value1"]]);
1562 }
1563 }
1564
1565 $points = $this->calculateReachedPoints($active_id, $pass);
1566 $max_points = $this->getMaximumPoints();
1567
1568 $result->setReachedPercentage(($points / $max_points) * 100);
1569
1570 return $result;
1571 }
1572
1581 public function getAvailableAnswerOptions($index = null)
1582 {
1583 if ($index !== null) {
1584 return $this->getMatchingPair($index);
1585 } else {
1586 return $this->getMatchingPairs();
1587 }
1588 }
1589
1593 protected function afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
1594 {
1595 parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1596
1597 $origImagePath = $this->buildImagePath($origQuestionId, $origParentObjId);
1598 $dupImagePath = $this->buildImagePath($dupQuestionId, $dupParentObjId);
1599
1600 ilUtil::delDir($origImagePath);
1601 if (is_dir($dupImagePath)) {
1602 ilUtil::makeDirParents($origImagePath);
1603 ilUtil::rCopy($dupImagePath, $origImagePath);
1604 }
1605 }
1606}
$result
$path
Definition: aliased.php:25
$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)
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 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.
$def
Definition: croninfo.php:21
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
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:60
$row
if($session===NULL) $postData
$query
global $DIC
Definition: saml.php:7
global $ilDB
$mobs
$data
Definition: bench.php:6