ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
class.ilObjTest.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 'Services/Object/classes/class.ilObject.php';
5require_once 'Modules/Test/classes/inc.AssessmentConstants.php';
6require_once 'Modules/Test/interfaces/interface.ilMarkSchemaAware.php';
7require_once 'Modules/Test/interfaces/interface.ilEctsGradesEnabled.php';
8
20{
22
23 #region Properties
24
28 const QUESTION_SET_TYPE_FIXED = 'FIXED_QUEST_SET';
29
33 const QUESTION_SET_TYPE_RANDOM = 'RANDOM_QUEST_SET';
34
38 const QUESTION_SET_TYPE_DYNAMIC = 'DYNAMIC_QUEST_SET';
39
44
49
54
61
65 private $skillServiceEnabled = false;
66
70 private $resultFilterTaxIds = array();
71
79 protected $_kiosk;
80
87
94
102
109
116
121
128 protected $introduction;
129
136
145
156
165
172
182
189
197
205
215
222
229
236
241
247 protected $starting_time;
248
253
259 protected $ending_time;
260
265 protected $ects_output = FALSE;
266
271 protected $ects_fx = NULL;
272
277 protected $ects_grades = array();
278
279
287
294
301
309
316
323
330
335
341 protected $password;
342
347
353 protected $allowedUsers;
354
361
368
375
382
389
396
403
410
417
424
431
437 private $_showinfo;
438
444 private $_forcejs = TRUE;
445
452
454
455 protected $mailnottype;
456
458
459 protected $poolUsage;
460
462
468 private $online = null;
469
474
481
487 private $obligationsEnabled = null;
488
490
492
494
495 protected $autosave;
496
497 protected $autosave_ival;
498
505 private $passDeletionAllowed = null;
506
512 private $participantDataExist = null;
513
516
519
522
525
529 private $redirection_mode = 0;
530
534 private $redirection_url = NULL;
535
538
541
544
547
550
555
560
565
570
571 #endregion
572
581 public function __construct($a_id = 0,$a_call_by_reference = true)
582 {
583 global $ilUser, $lng;
584 $this->type = "tst";
585
586 $lng->loadLanguageModule("assessment");
587 // Defaults:
588 include_once "./Modules/Test/classes/class.assMarkSchema.php";
589 $this->mark_schema = new ASS_MarkSchema();
590 $this->mark_schema->createSimpleSchema(
591 $lng->txt("failed_short"),
592 $lng->txt("failed_official"),
593 0,
594 0,
595 $lng->txt("passed_short"),
596 $lng->txt("passed_official"),
597 50,
598 1
599 );
600
601 $this->test_id = -1;
602 $this->author = $ilUser->fullname;
603 $this->introductionEnabled = false;
604 $this->introduction = "";
605 $this->questions = array();
606 $this->sequence_settings = TEST_FIXED_SEQUENCE;
607 $this->score_reporting = REPORT_AFTER_TEST;
608 $this->instant_verification = 0;
609 $this->answer_feedback_points = 0;
610 $this->reporting_date = "";
611 $this->nr_of_tries = 0;
612 $this->_kiosk = 0;
613 $this->use_previous_answers = 1;
614 $this->title_output = 0;
615 $this->starting_time = "";
616 $this->ending_time = "";
617 $this->processing_time = "";
618 $this->enable_processing_time = "0";
619 $this->reset_processing_time = 0;
620 $this->ects_output = FALSE;
621 $this->ects_fx = NULL;
622 $this->shuffle_questions = FALSE;
623 $this->mailnottype = 0;
624 $this->exportsettings = 0;
625 $this->show_summary = 8;
626 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
627 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
628 $this->score_cutting = SCORE_CUT_QUESTION;
629 $this->pass_scoring = SCORE_LAST_PASS;
630 $this->answer_feedback = 0;
631 $this->password = "";
632 $this->certificate_visibility = 0;
633 $this->allowedUsers = "";
634 $this->_showfinalstatement = FALSE;
635 $this->_finalstatement = "";
636 $this->_showinfo = TRUE;
637 $this->_forcejs = TRUE;
638 $this->_customStyle = "";
639 $this->allowedUsersTimeGap = "";
640 $this->anonymity = 0;
641 $this->show_cancel = 0;
642 $this->show_marker = 0;
643 $this->fixed_participants = 0;
644 $this->setShowPassDetails(TRUE);
645 $this->setShowSolutionDetails(TRUE);
646 $this->setShowSolutionAnswersOnly(FALSE);
647 $this->setShowSolutionSignature(FALSE);
648 $this->testSession = FALSE;
649 $this->testSequence = FALSE;
650 $this->mailnotification = 0;
651 $this->poolUsage = 1;
652
653 $this->ects_grades = array(
654 'A' => 90,
655 'B' => 65,
656 'C' => 35,
657 'D' => 10,
658 'E' => 0
659 );
660
661 $this->autosave = FALSE;
662 $this->autosave_ival = 30000;
663
664 $this->enable_examview = false;
665 $this->show_examview_html = false;
666 $this->show_examview_pdf = false;
667 $this->enable_archiving = false;
668
669 $this->express_mode = false;
670 $this->template_id = '';
671 $this->redirection_mode = 0;
672 $this->redirection_url = NULL;
673 $this->show_exam_id_in_test_pass_enabled = false;
674 $this->show_exam_id_in_test_results_enabled = false;
675 $this->sign_submission = false;
676 $this->char_selector_availability = 0;
677 $this->char_selector_definition = null;
678
679 $this->showGradingStatusEnabled = true;
680 $this->showGradingMarkEnabled = true;
681
682 $this->instantFeedbackAnswerFixationEnabled = false;
683
684 $this->testFinalBroken = false;
685
686 $this->ilObject($a_id, $a_call_by_reference);
687 }
688
692 function create($a_upload = false)
693 {
694 parent::create();
695
696 // meta data will be created by
697 // import parser
698 if (!$a_upload)
699 {
700 $this->createMetaData();
701 }
702 }
703
710 function update()
711 {
712 if (!parent::update())
713 {
714 return false;
715 }
716
717 // put here object specific stuff
718
719 return true;
720 }
721
727 function read($a_force_db = false)
728 {
729 parent::read($a_force_db);
730 $this->loadFromDb();
731 }
732
733
740 function delete()
741 {
742 // always call parent delete function first!!
743 if (!parent::delete())
744 {
745 return false;
746 }
747
748 // delet meta data
749 $this->deleteMetaData();
750
751 //put here your module specific stuff
752 $this->deleteTest();
753
754 return true;
755 }
756
762 function deleteTest()
763 {
764 global $tree, $ilDB, $ilPluginAdmin;
765
766 // first of all remove all test editings, because the delete statements used for this
767 // contain a subquery for active ids, that are deleted in the next steps
768 $this->removeAllTestEditings();
769
770 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
771 array('integer'),
772 array($this->getTestId())
773 );
774 $active_array = array();
775 while ($row = $ilDB->fetchAssoc($result))
776 {
777 array_push($active_array, $row["active_id"]);
778 }
779
780 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
781 array('integer'),
782 array($this->getTestId())
783 );
784
785 if (count($active_array))
786 {
787 foreach ($active_array as $active_id)
788 {
789 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_times WHERE active_fi = %s",
790 array('integer'),
791 array($active_id)
792 );
793
794 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
795 array('integer'),
796 array($active_id)
797 );
798 }
799 }
800
801 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_mark WHERE test_fi = %s",
802 array('integer'),
803 array($this->getTestId())
804 );
805
806 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_tests WHERE test_id = %s",
807 array('integer'),
808 array($this->getTestId())
809 );
810
811 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
812 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
813 $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
814
815 // delete export files
816 include_once "./Services/Utilities/classes/class.ilUtil.php";
817 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
818 $directory = $tst_data_dir."/tst_".$this->getId();
819 if (is_dir($directory))
820 {
821 include_once "./Services/Utilities/classes/class.ilUtil.php";
822 ilUtil::delDir($directory);
823 }
824 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
825 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
826 // remaining usages are not in text anymore -> delete them
827 // and media objects (note: delete method of ilObjMediaObject
828 // checks whether object is used in another context; if yes,
829 // the object is not deleted!)
830 foreach($mobs as $mob)
831 {
832 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
834 {
835 $mob_obj =& new ilObjMediaObject($mob);
836 $mob_obj->delete();
837 }
838 }
839 }
840
841
855 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
856 {
857 global $tree;
858
859 switch ($a_event)
860 {
861 case "link":
862
863 //var_dump("<pre>",$a_params,"</pre>");
864 //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
865 //exit;
866 break;
867
868 case "cut":
869
870 //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
871 //exit;
872 break;
873
874 case "copy":
875
876 //var_dump("<pre>",$a_params,"</pre>");
877 //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
878 //exit;
879 break;
880
881 case "paste":
882
883 //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
884 //exit;
885 break;
886
887 case "new":
888
889 //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
890 //exit;
891 break;
892 }
893
894 // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
895 if ($a_node_id==$_GET["ref_id"])
896 {
897 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
898 $parent_type = $parent_obj->getType();
899 if ($parent_type == $this->getType())
900 {
901 $a_node_id = (int) $tree->getParentId($a_node_id);
902 }
903 }
904
905 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
906 }
907
914 {
915 include_once "./Services/Utilities/classes/class.ilUtil.php";
916 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
917 ilUtil::makeDir($tst_data_dir);
918 if (!is_writable($tst_data_dir))
919 {
920 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
921 .") not writeable.",$this->ilias->error_obj->MESSAGE);
922 }
923
924 // create learning module directory (data_dir/lm_data/lm_<id>)
925 $tst_dir = $tst_data_dir."/tst_".$this->getId();
926 ilUtil::makeDir($tst_dir);
927 if (!@is_dir($tst_dir))
928 {
929 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
930 }
931 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
932 $export_dir = $tst_dir."/export";
933 ilUtil::makeDir($export_dir);
934 if (!@is_dir($export_dir))
935 {
936 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
937 }
938 }
939
946 {
947 include_once "./Services/Utilities/classes/class.ilUtil.php";
948 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
949 return $export_dir;
950 }
951
958 function getExportFiles($dir)
959 {
960 // quit if import dir not available
961 if(!@is_dir($dir) || !is_writeable($dir))
962 {
963 return array();
964 }
965
966 $files = array();
967 foreach(new DirectoryIterator($dir) as $file)
968 {
972 if($file->isDir())
973 {
974 continue;
975 }
976
977 $files[] = $file->getBasename();
978 }
979
980 sort($files);
981
982 return $files;
983 }
984
988 function _setImportDirectory($a_import_dir = null)
989 {
990 if (strlen($a_import_dir))
991 {
992 $_SESSION["tst_import_dir"] = $a_import_dir;
993 }
994 else
995 {
996 unset($_SESSION["tst_import_dir"]);
997 }
998 }
999
1007 {
1008 if (strlen($_SESSION["tst_import_dir"]))
1009 {
1010 return $_SESSION["tst_import_dir"];
1011 }
1012 return null;
1013 }
1014
1016 {
1018 }
1019
1026 {
1027 global $ilias;
1028 include_once "./Services/Utilities/classes/class.ilUtil.php";
1029 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
1030 ilUtil::makeDir($tst_data_dir);
1031
1032 if (!is_writable($tst_data_dir))
1033 {
1034 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
1035 .") not writeable.",$this->ilias->error_obj->FATAL);
1036 }
1037
1038 // create test directory (data_dir/tst_data/tst_import)
1039 $tst_dir = $tst_data_dir."/tst_import";
1040 ilUtil::makeDir($tst_dir);
1041 if (!@is_dir($tst_dir))
1042 {
1043 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
1044 }
1045 return $tst_dir;
1046 }
1047
1055 {
1056 global $ilDB;
1057
1058 $result = $ilDB->queryF("SELECT DISTINCT(qpl_qst_type.type_tag) foundtypes FROM qpl_questions, tst_test_result, qpl_qst_type, tst_active WHERE tst_test_result.question_fi = qpl_questions.question_id AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND tst_test_result.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
1059 array('integer'),
1060 array($this->getTestId())
1061 );
1062 $hasSC = false;
1063 while ($row = $ilDB->fetchAssoc($result))
1064 {
1065 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1066 {
1067 $hasSC = true;
1068 }
1069 }
1070 return $hasSC;
1071 }
1072
1080 {
1081 global $ilDB;
1082
1083 $result = $ilDB->queryF("SELECT DISTINCT(qpl_qst_type.type_tag) foundtypes FROM qpl_questions, tst_test_result, qpl_qst_type, tst_active WHERE tst_test_result.question_fi = qpl_questions.question_id AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND tst_test_result.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
1084 array('integer'),
1085 array($this->getTestId())
1086 );
1087 if ($result->numRows() == 1)
1088 {
1089 $row = $ilDB->fetchAssoc($result);
1090 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1091 {
1092 return TRUE;
1093 }
1094 else
1095 {
1096 return false;
1097 }
1098 }
1099 return FALSE;
1100 }
1101
1109 {
1110 global $ilDB;
1111
1112 if (!$this->hasSingleChoiceQuestions()) return false;
1113
1114 $result = $ilDB->queryF("
1115 SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1116 FROM qpl_questions,
1117 qpl_qst_sc,
1118 tst_test_result,
1119 qpl_qst_type,
1120 tst_active
1121 WHERE tst_test_result.question_fi = qpl_questions.question_id
1122 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1123 AND tst_test_result.active_fi = tst_active.active_id
1124 AND qpl_questions.question_id = qpl_qst_sc.question_fi
1125 AND tst_active.test_fi = %s
1126 AND qpl_qst_type.type_tag = %s
1127 ",
1128 array('integer', 'text'),
1129 array($this->getTestId(), 'assSingleChoice')
1130 );
1131 if ($result->numRows() == 1)
1132 {
1133 $row = $ilDB->fetchAssoc($result);
1134 return ($row['foundshuffles'] == 0);
1135 }
1136 return FALSE;
1137 }
1138
1145 final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1146 {
1147 if( !count($this->mark_schema->mark_steps) )
1148 {
1149 return false;
1150 }
1151
1152 if( !$testQuestionSetConfig->isQuestionSetConfigured() )
1153 {
1154 return false;
1155 }
1156
1157 return true;
1158 }
1159
1166 function _isComplete($obj_id)
1167 {
1168 global $tree, $ilDB, $ilPluginAdmin;
1169
1170 $test = new ilObjTest($obj_id, false);
1171 $test->loadFromDb();
1172
1173 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1174 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1175
1176 return $test->isComplete( $testQuestionSetConfigFactory->getQuestionSetConfig() );
1177 }
1178
1182 public function saveECTSStatus()
1183 {
1187 global $ilDB;
1188
1189 if($this->getTestId() > 0)
1190 {
1191 $this->setECTSFX(preg_replace('/,/', '.', $this->getECTSFX()));
1192 if(!preg_match('/\d+/', $this->getECTSFX()))
1193 {
1194 $this->setECTSFX(NULL);
1195 }
1196
1197 $grades = $this->getECTSGrades();
1198 $ilDB->manipulateF(
1199 "UPDATE tst_tests
1200 SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s
1201 WHERE test_id = %s",
1202 array('text', 'float', 'float', 'float', 'float', 'float', 'float', 'integer'),
1203 array(
1204 (int)$this->getECTSOutput(),
1205 $grades['A'], $grades['B'], $grades['C'], $grades['D'], $grades['E'],
1206 $this->getECTSFX(),
1207 $this->getTestId()
1208 )
1209 );
1210 }
1211 }
1212
1217 public function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1218 {
1219 global $ilDB;
1220
1221 $complete = 0;
1222 if($this->isComplete($testQuestionSetConfig))
1223 {
1224 $complete = 1;
1225 }
1226 if($this->getTestId() > 0)
1227 {
1228 $ilDB->manipulateF(
1229 "UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1230 array('text', 'integer'),
1231 array($complete, $this->test_id)
1232 );
1233 }
1234 }
1235
1242 {
1243 $result = array();
1244 array_push($result, $this->getIntroduction());
1245 array_push($result, $this->getFinalStatement());
1246 return $result;
1247 }
1248
1255 {
1256 include_once("./Services/RTE/classes/class.ilRTE.php");
1257 $completecontent = "";
1258 foreach ($this->getAllRTEContent() as $content)
1259 {
1260 $completecontent .= $content;
1261 }
1262 ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
1263 $this->getId());
1264 }
1265
1271 public function saveToDb($properties_only = FALSE)
1272 {
1273 global $tree, $ilDB, $ilPluginAdmin;
1274
1275 // moved online_status to ilObjectActivation (see below)
1276
1277 // cleanup RTE images
1278 $this->cleanupMediaobjectUsage();
1279
1280 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1281 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1282 $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1283
1284 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1285 if ($this->test_id == -1)
1286 {
1287 // Create new dataset
1288 $next_id = $ilDB->nextId('tst_tests');
1289
1290 $ilDB->insert('tst_tests', array(
1291 'test_id' => array('integer', $next_id),
1292 'obj_fi' => array('integer', $this->getId()),
1293 'author' => array('text', $this->getAuthor()),
1294 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1295 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1296 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1297 'showinfo' => array('integer', $this->getShowInfo()),
1298 'forcejs' => array('integer', $this->getForceJS()),
1299 'customstyle' => array('text', $this->getCustomStyle()),
1300 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1301 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1302 'score_reporting' => array('integer', $this->getScoreReporting()),
1303 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1304 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1305 'answer_feedback' => array('text', $this->getAnswerFeedback()),
1306 'anonymity' => array('text', $this->getAnonymity()),
1307 'show_cancel' => array('text', $this->getShowCancel()),
1308 'show_marker' => array('integer', $this->getShowMarker()),
1309 'fixed_participants' => array('text', $this->getFixedParticipants()),
1310 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1311 'kiosk' => array('integer', $this->getKiosk()),
1312 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1313 'title_output' => array('text', $this->getTitleOutput()),
1314 'processing_time' => array('text', $this->getProcessingTime()),
1315 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1316 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1317 'reporting_date' => array('text', $this->getReportingDate()),
1318 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1319 'starting_time' => array('text', $this->getStartingTime()),
1320 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1321 'ending_time' => array('text', $this->getEndingTime()),
1322 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1323 'ects_output' => array('text', $this->getECTSOutput()),
1324 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1325 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1326 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1327 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1328 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1329 'ects_fx' => array('float', $this->getECTSFX()),
1330 'count_system' => array('text', $this->getCountSystem()),
1331 'mc_scoring' => array('text', $this->getMCScoring()),
1332 'score_cutting' => array('text', $this->getScoreCutting()),
1333 'pass_scoring' => array('text', $this->getPassScoring()),
1334 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1335 'results_presentation' => array('integer', $this->getResultsPresentation()),
1336 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1337 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1338 'password' => array('text', $this->getPassword()),
1339 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1340 'allowedusers' => array('integer', $this->getAllowedUsers()),
1341 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1342 'mailnottype' => array('integer', $this->getMailNotificationType()),
1343 'exportsettings' => array('integer', $this->getExportSettings()),
1344 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1345 'mailnotification' => array('integer', $this->getMailNotification()),
1346 'created' => array('integer', time()),
1347 'tstamp' => array('integer', time()),
1348 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1349 'template_id' => array('integer', $this->getTemplate()),
1350 'pool_usage' => array('integer', $this->getPoolUsage()),
1351 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1352 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1353 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1354 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1355 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1356 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1357 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1358 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1359 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1360 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1361 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1362 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1363 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1364 'online_status' => array('integer', (int)$this->isOnline()),
1365 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1366 'autosave' => array('integer', (int)$this->getAutosave()),
1367 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1368 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1369 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1370 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1371 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1372 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1373 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1374 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1375 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1376 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1377 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1378 'question_set_type' => array('text', $this->getQuestionSetType()),
1379 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1380 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1381 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1382 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1383 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1384 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1385 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1386 'broken' => array('integer', (int)$this->isTestFinalBroken())
1387 ));
1388
1389 $this->test_id = $next_id;
1390
1392 {
1393 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1394 }
1395 }
1396 else
1397 {
1398 // Modify existing dataset
1399 $oldrow = array();
1401 {
1402 $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1403 array('integer'),
1404 array($this->test_id)
1405 );
1406 if ($result->numRows() == 1)
1407 {
1408 $oldrow = $ilDB->fetchAssoc($result);
1409 }
1410 }
1411
1412 $ilDB->update('tst_tests',
1413 array(
1414 'author' => array('text', $this->getAuthor()),
1415 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1416 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1417 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1418 'showinfo' => array('integer', $this->getShowInfo()),
1419 'forcejs' => array('integer', $this->getForceJS()),
1420 'customstyle' => array('text', $this->getCustomStyle()),
1421 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1422 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1423 'score_reporting' => array('integer', $this->getScoreReporting()),
1424 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1425 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1426 'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1427 'anonymity' => array('text', $this->getAnonymity()),
1428 'show_cancel' => array('text', $this->getShowCancel()),
1429 'show_marker' => array('integer', $this->getShowMarker()),
1430 'fixed_participants' => array('text', $this->getFixedParticipants()),
1431 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1432 'kiosk' => array('integer', $this->getKiosk()),
1433 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1434 'title_output' => array('text', $this->getTitleOutput()),
1435 'processing_time' => array('text', $this->getProcessingTime()),
1436 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1437 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1438 'reporting_date' => array('text', $this->getReportingDate()),
1439 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1440 'starting_time' => array('text', $this->getStartingTime()),
1441 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1442 'ending_time' => array('text', $this->getEndingTime()),
1443 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1444 'ects_output' => array('text', $this->getECTSOutput()),
1445 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1446 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1447 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1448 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1449 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1450 'ects_fx' => array('float', $this->getECTSFX()),
1451 'count_system' => array('text', $this->getCountSystem()),
1452 'mc_scoring' => array('text', $this->getMCScoring()),
1453 'score_cutting' => array('text', $this->getScoreCutting()),
1454 'pass_scoring' => array('text', $this->getPassScoring()),
1455 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1456 'results_presentation' => array('integer', $this->getResultsPresentation()),
1457 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1458 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1459 'password' => array('text', $this->getPassword()),
1460 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1461 'allowedusers' => array('integer', $this->getAllowedUsers()),
1462 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1463 'mailnottype' => array('integer', $this->getMailNotificationType()),
1464 'exportsettings' => array('integer', $this->getExportSettings()),
1465 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1466 'mailnotification' => array('integer', $this->getMailNotification()),
1467 'tstamp' => array('integer', time()),
1468 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1469 'template_id' => array('integer', $this->getTemplate()),
1470 'pool_usage' => array('integer', $this->getPoolUsage()),
1471 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1472 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1473 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1474 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1475 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1476 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1477 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1478 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1479 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1480 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1481 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1482 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1483 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1484 'online_status' => array('integer', (int)$this->isOnline()),
1485 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1486 'autosave' => array('integer', (int)$this->getAutosave()),
1487 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1488 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1489 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1490 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1491 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1492 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1493 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1494 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1495 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1496 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1497 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1498 'question_set_type' => array('text', $this->getQuestionSetType()),
1499 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1500 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1501 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1502 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1503 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1504 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1505 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1506 'broken' => array('integer', (int)$this->isTestFinalBroken())
1507 ),
1508 array(
1509 'test_id' => array('integer', (int)$this->getTestId())
1510 )
1511 );
1512
1513 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1515 {
1516 $logresult = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1517 array('integer'),
1518 array($this->getTestId())
1519 );
1520 $newrow = array();
1521 if ($logresult->numRows() == 1)
1522 {
1523 $newrow = $ilDB->fetchAssoc($logresult);
1524 }
1525 $changed_fields = array();
1526 foreach ($oldrow as $key => $value)
1527 {
1528 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
1529 {
1530 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
1531 }
1532 }
1533 $changes = join($changed_fields, ", ");
1534 if (count($changed_fields) > 0)
1535 {
1536 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
1537 }
1538 }
1539 if ($this->evalTotalPersons() > 0)
1540 {
1541 // reset the finished status of participants if the nr of test passes did change
1542 if ($this->getNrOfTries() > 0)
1543 {
1544 // set all unfinished tests with nr of passes >= allowed passes finished
1545 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = %s",
1546 array('integer', 'integer', 'integer'),
1547 array($this->getTestId(), $this->getNrOfTries(), 0)
1548 );
1549 while ($row = $ilDB->fetchAssoc($aresult))
1550 {
1551 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1552 array('integer', 'timestamp', 'integer'),
1553 array(1, date('Y-m-d H:i:s'), $row["active_id"])
1554 );
1555 }
1556
1557 // set all finished tests with nr of passes < allowed passes not finished
1558 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = %s",
1559 array('integer', 'integer', 'integer'),
1560 array($this->getTestId(), $this->getNrOfTries()-1, 1)
1561 );
1562 while ($row = $ilDB->fetchAssoc($aresult))
1563 {
1564 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1565 array('integer', 'timestamp', 'integer'),
1566 array(0, NULL, $row["active_id"])
1567 );
1568 }
1569 }
1570 else
1571 {
1572 // set all finished tests with nr of passes >= allowed passes not finished
1573 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = %s",
1574 array('integer', 'integer'),
1575 array($this->getTestId(), 1)
1576 );
1577 while ($row = $ilDB->fetchAssoc($aresult))
1578 {
1579 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1580 array('integer', 'timestamp', 'integer'),
1581 array(0, NULL, $row["active_id"])
1582 );
1583 }
1584 }
1585 }
1586 }
1587
1588 // moved activation to ilObjectActivation
1589 if($this->ref_id)
1590 {
1591 include_once "./Services/Object/classes/class.ilObjectActivation.php";
1592 ilObjectActivation::getItem($this->ref_id);
1593
1594 $item = new ilObjectActivation;
1595 if(!$this->isActivationLimited())
1596 {
1598 }
1599 else
1600 {
1601 $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1602 $item->setTimingStart($this->getActivationStartingTime());
1603 $item->setTimingEnd($this->getActivationEndingTime());
1604 $item->toggleVisible($this->getActivationVisibility());
1605 }
1606
1607 $item->update($this->ref_id);
1608 }
1609
1610 if (!$properties_only)
1611 {
1612 if (PEAR::isError($result))
1613 {
1614 global $ilias;
1615 $ilias->raiseError($result->getMessage());
1616 }
1617 else
1618 {
1619 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
1620 {
1621 $this->saveQuestionsToDb();
1622 }
1623 $this->mark_schema->saveToDb($this->test_id);
1624 }
1625 }
1626 }
1627
1635 {
1636 global $ilDB;
1637
1638 $oldquestions = array();
1639 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1641 {
1642 $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1643 array('integer'),
1644 array($this->getTestId())
1645 );
1646 if ($result->numRows() > 0)
1647 {
1648 while ($row = $ilDB->fetchAssoc($result))
1649 {
1650 array_push($oldquestions, $row["question_fi"]);
1651 }
1652 }
1653 }
1654 // workaround for lost obligations
1655 // this method is called if a question is removed
1656 $currentQuestionsObligationsQuery = 'SELECT question_fi, obligatory FROM tst_test_question WHERE test_fi = %s';
1657 $rset = $ilDB->queryF($currentQuestionsObligationsQuery, array('integer'), array($this->getTestId()));
1658 while ($row = $ilDB->fetchAssoc($rset)) {
1659 $obligatoryQuestionState[$row['question_fi']] = $row['obligatory'];
1660 }
1661 // delete existing category relations
1662 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_question WHERE test_fi = %s",
1663 array('integer'),
1664 array($this->getTestId())
1665 );
1666 // create new category relations
1667 foreach ($this->questions as $key => $value)
1668 {
1669 // workaround for import witout obligations information
1670 if( !isset($obligatoryQuestionState[$value]) || is_null($obligatoryQuestionState[$value]) )
1671 {
1672 $obligatoryQuestionState[$value] = 0;
1673 }
1674
1675 // insert question
1676 $next_id = $ilDB->nextId('tst_test_question');
1677 $ilDB->insert('tst_test_question', array(
1678 'test_question_id' => array('integer', $next_id),
1679 'test_fi' => array('integer', $this->getTestId()),
1680 'question_fi' => array('integer', $value),
1681 'sequence' => array('integer', $key),
1682 'obligatory' => array('integer', $obligatoryQuestionState[$value]),
1683 'tstamp' => array('integer', time())
1684 ));
1685 }
1686 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1688 {
1689 $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1690 array('integer'),
1691 array($this->getTestId())
1692 );
1693 $newquestions = array();
1694 if ($result->numRows() > 0)
1695 {
1696 while ($row = $ilDB->fetchAssoc($result))
1697 {
1698 array_push($newquestions, $row["question_fi"]);
1699 }
1700 }
1701 foreach ($oldquestions as $index => $question_id)
1702 {
1703 if (strcmp($newquestions[$index], $question_id) != 0)
1704 {
1705 $pos = array_search($question_id, $newquestions);
1706 if ($pos === FALSE)
1707 {
1708 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
1709 }
1710 else
1711 {
1712 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
1713 }
1714 }
1715 }
1716 foreach ($newquestions as $index => $question_id)
1717 {
1718 if (array_search($question_id, $oldquestions) === FALSE)
1719 {
1720 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
1721 }
1722 }
1723 }
1724 }
1725
1731 protected function isNewRandomTest()
1732 {
1733 global $ilDB;
1734 $result = $ilDB->queryF('SELECT copy_id FROM tst_rnd_cpy WHERE tst_fi = %s',
1735 array('integer'),
1736 array($this->getTestId())
1737 );
1738 return $result->numRows() > 0;
1739 }
1740
1753 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
1754 {
1755 global $rbacsystem;
1756 global $ilDB;
1757
1758 // retrieve object id instead of ref id if necessary
1759 if (($questionpool != 0) && (!$use_obj_id)) $questionpool = ilObject::_lookupObjId($questionpool);
1760
1761 // get original ids of all existing questions in the test
1762 $result = $ilDB->queryF("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND qpl_questions.tstamp > 0 AND tst_test_question.test_fi = %s",
1763 array("integer"),
1764 array($this->getTestId())
1765 );
1766 $original_ids = array();
1767 $paramtypes = array();
1768 $paramvalues = array();
1769 while ($row = $ilDB->fetchAssoc($result))
1770 {
1771 array_push($original_ids, $row['original_id']);
1772 }
1773
1774 $available = "";
1775 // get a list of all available questionpools
1776 if (($questionpool == 0) && (!is_array($qpls)))
1777 {
1778 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1779 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE, "read", ilObject::_lookupOwner($this->getId())));
1780 if (count($available_pools))
1781 {
1782 $available = " AND " . $ilDB->in('obj_fi', $available_pools, false, 'integer');
1783 }
1784 else
1785 {
1786 return array();
1787 }
1788 }
1789
1790 $constraint_qpls = "";
1791 $result_array = array();
1792 if ($questionpool == 0)
1793 {
1794 if (is_array($qpls))
1795 {
1796 if (count($qpls) > 0)
1797 {
1798 $constraint_qpls = " AND " . $ilDB->in('obj_fi', $qpls, false, 'integer');
1799 }
1800 }
1801 }
1802
1803 $original_clause = "";
1804 if (count($original_ids))
1805 {
1806 $original_clause = " AND " . $ilDB->in('question_id', $original_ids, true, 'integer');
1807 }
1808
1809 if ($questionpool == 0)
1810 {
1811 $result = $ilDB->queryF("SELECT question_id FROM qpl_questions WHERE original_id IS NULL $available $constraint_qpls AND owner > %s AND complete = %s $original_clause",
1812 array('integer', 'text'),
1813 array(0, "1")
1814 );
1815 }
1816 else
1817 {
1818 $result = $ilDB->queryF("SELECT question_id FROM qpl_questions WHERE original_id IS NULL AND obj_fi = %s AND owner > %s AND complete = %s $original_clause",
1819 array('integer','integer', 'text'),
1820 array($questionpool, 0, "1")
1821 );
1822 }
1823 $found_ids = array();
1824 while ($row = $ilDB->fetchAssoc($result))
1825 {
1826 array_push($found_ids, $row['question_id']);
1827 }
1828 $nr_of_questions = ($nr_of_questions > count($found_ids)) ? count($found_ids) : $nr_of_questions;
1829 if ($nr_of_questions == 0) return array();
1830 $rand_keys = array_rand($found_ids, $nr_of_questions);
1831 $result = array();
1832 if (is_array($rand_keys))
1833 {
1834 foreach ($rand_keys as $key)
1835 {
1836 $result[$found_ids[$key]] = $found_ids[$key];
1837 }
1838 }
1839 else
1840 {
1841 $result[$found_ids[$rand_keys]] = $found_ids[$rand_keys];
1842 }
1843 return $result;
1844 }
1845
1853 function getNrOfResultsForPass($active_id, $pass)
1854 {
1855 global $ilDB;
1856
1857 $result = $ilDB->queryF("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
1858 array('integer','integer'),
1859 array($active_id, $pass)
1860 );
1861 return $result->numRows();
1862 }
1863
1874 function hasRandomQuestionsForPass($active_id, $pass)
1875 {
1876 global $ilDB;
1877 $result = $ilDB->queryF("SELECT test_random_question_id FROM tst_test_rnd_qst WHERE active_fi = %s AND pass = %s",
1878 array('integer','integer'),
1879 array($active_id, $pass)
1880 );
1881 return ($result->numRows() > 0) ? true : false;
1882 }
1883
1887 public function loadFromDb()
1888 {
1889 global $ilDB;
1890
1891 $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE obj_fi = %s",
1892 array('integer'),
1893 array($this->getId())
1894 );
1895 if ($result->numRows() == 1)
1896 {
1897 $data = $ilDB->fetchObject($result);
1898 $this->setTestId($data->test_id);
1899 if (strlen($this->getAuthor()) == 0)
1900 {
1901 $this->saveAuthorToMetadata($data->author);
1902 }
1903 $this->setAuthor($data->author);
1904 include_once("./Services/RTE/classes/class.ilRTE.php");
1905 $this->setIntroductionEnabled($data->intro_enabled);
1907 $this->setShowInfo($data->showinfo);
1909 $this->setForceJS($data->forcejs);
1910 $this->setCustomStyle($data->customstyle);
1911 $this->setShowFinalStatement($data->showfinalstatement);
1912 $this->setSequenceSettings($data->sequence_settings);
1913 $this->setScoreReporting($data->score_reporting);
1914 $this->setInstantFeedbackSolution($data->instant_verification);
1915 $this->setAnswerFeedbackPoints($data->answer_feedback_points);
1916 $this->setAnswerFeedback($data->answer_feedback);
1917 $this->setAnonymity($data->anonymity);
1918 $this->setShowCancel($data->show_cancel);
1919 $this->setShowMarker($data->show_marker);
1920 $this->setFixedParticipants($data->fixed_participants);
1921 $this->setNrOfTries($data->nr_of_tries);
1922 $this->setKiosk($data->kiosk);
1923 $this->setUsePreviousAnswers($data->use_previous_answers);
1924 $this->setRedirectionMode($data->redirection_mode);
1925 $this->setRedirectionUrl($data->redirection_url);
1926 $this->setTitleOutput($data->title_output);
1927 $this->setProcessingTime($data->processing_time);
1928 $this->setEnableProcessingTime($data->enable_processing_time);
1929 $this->setResetProcessingTime($data->reset_processing_time);
1930 $this->setReportingDate($data->reporting_date);
1931 $this->setShuffleQuestions($data->shuffle_questions);
1932 $this->setResultsPresentation($data->results_presentation);
1933 $this->setStartingTimeEnabled($data->starting_time_enabled);
1934 $this->setStartingTime($data->starting_time);
1935 $this->setEndingTimeEnabled($data->ending_time_enabled);
1936 $this->setEndingTime($data->ending_time);
1937 $this->setListOfQuestionsSettings($data->show_summary);
1938 $this->setECTSOutput($data->ects_output);
1939 $this->setECTSGrades(
1940 array(
1941 "A" => $data->ects_a,
1942 "B" => $data->ects_b,
1943 "C" => $data->ects_c,
1944 "D" => $data->ects_d,
1945 "E" => $data->ects_e
1946 )
1947 );
1948 $this->setECTSFX($data->ects_fx);
1949 $this->mark_schema->flush();
1950 $this->mark_schema->loadFromDb($this->getTestId());
1951 $this->setCountSystem($data->count_system);
1952 $this->setMCScoring($data->mc_scoring);
1953 $this->setMailNotification($data->mailnotification);
1954 $this->setMailNotificationType($data->mailnottype);
1955 $this->setExportSettings($data->exportsettings);
1956 $this->setScoreCutting($data->score_cutting);
1957 $this->setPasswordEnabled($data->password_enabled);
1958 $this->setPassword($data->password);
1959 $this->setLimitUsersEnabled($data->limit_users_enabled);
1960 $this->setAllowedUsers($data->allowedusers);
1961 $this->setAllowedUsersTimeGap($data->alloweduserstimegap);
1962 $this->setPassScoring($data->pass_scoring);
1963 $this->setObligationsEnabled($data->obligations_enabled);
1964 $this->setOfferingQuestionHintsEnabled($data->offer_question_hints);
1965 $this->setCertificateVisibility($data->certificate_visibility);
1966 $this->setEnabledViewMode($data->enabled_view_mode);
1967 $this->setTemplate($data->template_id);
1968 $this->setPoolUsage($data->pool_usage);
1969 $this->setPrintBestSolutionWithResult((bool) $data->print_bs_with_res);
1970 $this->setHighscoreEnabled((bool) $data->highscore_enabled);
1971 $this->setHighscoreAnon((bool) $data->highscore_anon);
1972 $this->setHighscoreAchievedTS((bool) $data->highscore_achieved_ts);
1973 $this->setHighscoreScore((bool) $data->highscore_score);
1974 $this->setHighscorePercentage((bool) $data->highscore_percentage);
1975 $this->setHighscoreHints((bool) $data->highscore_hints);
1976 $this->setHighscoreWTime((bool) $data->highscore_wtime);
1977 $this->setHighscoreOwnTable((bool) $data->highscore_own_table);
1978 $this->setHighscoreTopTable((bool) $data->highscore_top_table);
1979 $this->setHighscoreTopNum((int) $data->highscore_top_num);
1980 $this->setOnline((bool) $data->online_status);
1981 $this->setSpecificAnswerFeedback((int) $data->specific_feedback);
1982 $this->setAutosave((bool)$data->autosave);
1983 $this->setAutosaveIval((int)$data->autosave_ival);
1984 $this->setPassDeletionAllowed($data->pass_deletion_allowed);
1985 $this->setEnableExamview((bool)$data->enable_examview);
1986 $this->setShowExamviewHtml((bool)$data->show_examview_html);
1987 $this->setShowExamviewPdf((bool)$data->show_examview_pdf);
1988 $this->setEnableArchiving((bool)$data->enable_archiving);
1989 $this->setShowExamIdInTestPassEnabled( (bool)$data->examid_in_test_pass);
1990 $this->setShowExamIdInTestResultsEnabled( (bool)$data->examid_in_test_res);
1991 $this->setSignSubmission( (bool)$data->sign_submission );
1992 $this->setQuestionSetType($data->question_set_type);
1993 $this->setCharSelectorAvailability((int)$data->char_selector_availability);
1994 $this->setCharSelectorDefinition($data->char_selector_definition);
1995 $this->setSkillServiceEnabled((bool)$data->skill_service);
1996 $this->setResultFilterTaxIds(strlen($data->result_tax_filters) ? unserialize($data->result_tax_filters) : array());
1997 $this->setShowGradingStatusEnabled((bool)$data->show_grading_status);
1998 $this->setShowGradingMarkEnabled((bool)$data->show_grading_mark);
1999 $this->setInstantFeedbackAnswerFixationEnabled((bool)$data->inst_fb_answer_fixation);
2000 $this->setTestFinalBroken((bool)$data->broken);
2001 $this->loadQuestions();
2002 }
2003
2004 // moved activation to ilObjectActivation
2005 if($this->ref_id)
2006 {
2007 include_once "./Services/Object/classes/class.ilObjectActivation.php";
2008 $activation = ilObjectActivation::getItem($this->ref_id);
2009 switch($activation["timing_type"])
2010 {
2012 $this->setActivationLimited(true);
2013 $this->setActivationStartingTime($activation["timing_start"]);
2014 $this->setActivationEndingTime($activation["timing_end"]);
2015 $this->setActivationVisibility($activation["visible"]);
2016 break;
2017
2018 default:
2019 $this->setActivationLimited(false);
2020 break;
2021 }
2022 }
2023 }
2024
2031function loadQuestions($active_id = "", $pass = NULL)
2032{
2033 global $ilUser;
2034 global $ilDB;
2035
2036 $this->questions = array();
2037 if (strcmp($active_id, "") == 0)
2038 {
2039 $active_id = $this->getActiveIdOfUser($ilUser->getId());
2040 }
2041 if ($this->isRandomTest())
2042 {
2043 if (is_null($pass))
2044 {
2045 $pass = $this->_getPass($active_id);
2046 }
2047 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.* FROM tst_test_rnd_qst, qpl_questions WHERE tst_test_rnd_qst.active_fi = %s AND qpl_questions.question_id = tst_test_rnd_qst.question_fi AND tst_test_rnd_qst.pass = %s ORDER BY sequence",
2048 array('integer', 'integer'),
2049 array($active_id, $pass)
2050 );
2051 // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
2052 // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
2053 // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
2054 // no questions are present for a newer pass.
2055 if ($result->numRows() == 0)
2056 {
2057 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.* FROM tst_test_rnd_qst, qpl_questions WHERE tst_test_rnd_qst.active_fi = %s AND qpl_questions.question_id = tst_test_rnd_qst.question_fi AND tst_test_rnd_qst.pass = 0 ORDER BY sequence",
2058 array('integer'),
2059 array($active_id)
2060 );
2061 }
2062 }
2063 else
2064 {
2065 $result = $ilDB->queryF("SELECT tst_test_question.* FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND qpl_questions.question_id = tst_test_question.question_fi ORDER BY sequence",
2066 array('integer'),
2067 array($this->test_id)
2068 );
2069 }
2070 $index = 1;
2071 while ($data = $ilDB->fetchAssoc($result))
2072 {
2073 $this->questions[$index++] = $data["question_fi"];
2074 }
2075}
2076
2080 public function isIntroductionEnabled()
2081 {
2083 }
2084
2089 {
2090 $this->introductionEnabled = $introductionEnabled;
2091 }
2092
2099 public function getIntroduction()
2100 {
2101 return (strlen($this->introduction)) ? $this->introduction : NULL;
2102 }
2103
2111 public function setIntroduction($introduction = "")
2112 {
2113 $this->introduction = $introduction;
2114 }
2115
2116
2124 public function setFinalStatement($a_statement = "")
2125 {
2126 $this->_finalstatement = $a_statement;
2127 }
2128
2136 public function setShowInfo($a_info = 1)
2137 {
2138 $this->_showinfo = ($a_info) ? 1 : 0;
2139 }
2140
2148 public function setForceJS($a_js = 1)
2149 {
2150 $this->_forcejs = ($a_js) ? 1 : 0;
2151 }
2152
2160 public function setCustomStyle($a_customStyle = NULL)
2161 {
2162 $this->_customStyle = $a_customStyle;
2163 }
2164
2172 public function getCustomStyle()
2173 {
2174 return (strlen($this->_customStyle)) ? $this->_customStyle : NULL;
2175 }
2176
2184 public function getCustomStyles()
2185 {
2186 $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2187 $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2188 $customstyles = array();
2189 if (is_dir($css_path))
2190 {
2191 $results = array();
2192 include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2194 if (is_array($results["file"]))
2195 {
2196 foreach ($results["file"] as $filename)
2197 {
2198 if (strpos($filename, ".css"))
2199 {
2200 array_push($customstyles, $filename);
2201 }
2202 }
2203 }
2204 }
2205 return $customstyles;
2206 }
2207
2215 public function getTestStyleLocation($mode = "output")
2216 {
2217 if (strlen($this->getCustomStyle()))
2218 {
2219 $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2220 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2221 if (file_exists($custom))
2222 {
2223 $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2224 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2225 return $custom;
2226 }
2227 else
2228 {
2229 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2230 }
2231 }
2232 else
2233 {
2234 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2235 }
2236 }
2237
2245 public function setShowFinalStatement($show = 0)
2246 {
2247 $this->_showfinalstatement = ($show) ? 1 : 0;
2248 }
2249
2256 public function getFinalStatement()
2257 {
2258 return (strlen($this->_finalstatement)) ? $this->_finalstatement : NULL;
2259 }
2260
2268 public function getShowInfo()
2269 {
2270 return ($this->_showinfo) ? 1 : 0;
2271 }
2272
2280 public function getForceJS()
2281 {
2282 return ($this->_forcejs) ? 1 : 0;
2283 }
2284
2292 public function getShowFinalStatement()
2293 {
2294 return ($this->_showfinalstatement) ? 1 : 0;
2295 }
2296
2304 function getTestId()
2305 {
2306 return $this->test_id;
2307 }
2308
2312 public function getECTSOutput()
2313 {
2314 return ($this->ects_output) ? 1 : 0;
2315 }
2316
2320 public function setECTSOutput($a_ects_output)
2321 {
2322 $this->ects_output = $a_ects_output ? 1 : 0;
2323 }
2324
2328 public function getECTSFX()
2329 {
2330 return (strlen($this->ects_fx)) ? $this->ects_fx : NULL;
2331 }
2332
2336 public function setECTSFX($a_ects_fx)
2337 {
2338 $this->ects_fx = $a_ects_fx;
2339 }
2340
2344 public function getECTSGrades()
2345 {
2346 return $this->ects_grades;
2347 }
2348
2352 public function setECTSGrades(array $a_ects_grades)
2353 {
2354 $this->ects_grades = $a_ects_grades;
2355 }
2356
2362 public function getSequenceSettings()
2363 {
2364 return ($this->sequence_settings) ? $this->sequence_settings : 0;
2365 }
2366
2373 {
2374 $this->sequence_settings = $sequence_settings;
2375 }
2376
2380 public function isPostponingEnabled()
2381 {
2382 return (bool)$this->getSequenceSettings();
2383 }
2384
2388 public function setPostponingEnabled($postponingEnabled)
2389 {
2390 $this->setSequenceSettings((int)$postponingEnabled);
2391 }
2392
2401 {
2402 $this->score_reporting = $score_reporting;
2403 }
2404
2412 function setInstantFeedbackSolution($instant_feedback = 0)
2413 {
2414 switch ($instant_feedback)
2415 {
2416 case 1:
2417 $this->instant_verification = 1;
2418 break;
2419 default:
2420 $this->instant_verification = 0;
2421 break;
2422 }
2423 }
2424
2433{
2434 switch ($answer_feedback)
2435 {
2436 case 1:
2437 $this->answer_feedback = 1;
2438 break;
2439 default:
2440 $this->answer_feedback = 0;
2441 break;
2442 }
2443}
2444
2451function setGenericAnswerFeedback($generic_answer_feedback = 0)
2452{
2453 switch ($generic_answer_feedback)
2454 {
2455 case 1:
2456 $this->answer_feedback = 1;
2457 break;
2458 default:
2459 $this->answer_feedback = 0;
2460 break;
2461 }
2462}
2463
2472 {
2474 {
2475 case 1:
2476 $this->answer_feedback_points = 1;
2477 break;
2478 default:
2479 $this->answer_feedback_points = 0;
2480 break;
2481 }
2482 }
2483
2489 {
2490 if(!$reporting_date)
2491 {
2492 $this->reporting_date = '';
2493 $this->setECTSOutput(false);
2494 }
2495 else
2496 {
2497 $this->reporting_date = $reporting_date;
2498 }
2499 }
2500
2505
2514 {
2515 return ($this->score_reporting) ? $this->score_reporting : 0;
2516 }
2517
2518 public function isScoreReportingEnabled()
2519 {
2520 return $this->getScoreReporting() > 0 && $this->getScoreReporting() < 4;
2521 }
2522
2531 {
2532 return ($this->instant_verification) ? $this->instant_verification : 0;
2533 }
2534
2543 public function getAnswerFeedback()
2544 {
2545 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2546 }
2547
2557 {
2558 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2559 }
2560
2569{
2570 return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2571}
2572
2581 {
2582 return ($this->count_system) ? $this->count_system : 0;
2583 }
2584
2592 function _getCountSystem($active_id)
2593 {
2594 global $ilDB;
2595 $result = $ilDB->queryF("SELECT tst_tests.count_system FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
2596 array('integer'),
2597 array($active_id)
2598 );
2599 if ($result->numRows())
2600 {
2601 $row = $ilDB->fetchAssoc($result);
2602 return $row["count_system"];
2603 }
2604 return FALSE;
2605 }
2606
2614 function getMCScoring()
2615 {
2616 return ($this->mc_scoring) ? $this->mc_scoring : 0;
2617 }
2618
2627 {
2628 return ($this->score_cutting) ? $this->score_cutting : 0;
2629 }
2630
2639 {
2640 return ($this->pass_scoring) ? $this->pass_scoring : 0;
2641 }
2642
2650 function _getPassScoring($active_id)
2651 {
2652 global $ilDB;
2653 $result = $ilDB->queryF("SELECT tst_tests.pass_scoring FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
2654 array('integer'),
2655 array($active_id)
2656 );
2657 if ($result->numRows())
2658 {
2659 $row = $ilDB->fetchAssoc($result);
2660 return $row["pass_scoring"];
2661 }
2662 return 0;
2663 }
2664
2672 function _getMCScoring($active_id)
2673 {
2674 global $ilDB;
2675 $result = $ilDB->queryF("SELECT tst_tests.mc_scoring FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
2676 array('integer'),
2677 array($active_id)
2678 );
2679 if ($result->numRows())
2680 {
2681 $row = $ilDB->fetchAssoc($result);
2682 return $row["mc_scoring"];
2683 }
2684 return FALSE;
2685 }
2686
2694 function _getScoreCutting($active_id)
2695 {
2696 global $ilDB;
2697 $result = $ilDB->queryF("SELECT tst_tests.score_cutting FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
2698 array('integer'),
2699 array($active_id)
2700 );
2701 if ($result->numRows())
2702 {
2703 $row = $ilDB->fetchAssoc($result);
2704 return $row["score_cutting"];
2705 }
2706 return FALSE;
2707 }
2708
2717 {
2718 return (strlen($this->reporting_date)) ? $this->reporting_date : NULL;
2719 }
2720
2728 function getNrOfTries()
2729 {
2730 return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2731 }
2732
2740 function getKiosk()
2741 {
2742 return ($this->_kiosk) ? $this->_kiosk : 0;
2743 }
2744
2745
2753 function setKiosk($kiosk = 0)
2754 {
2755 $this->_kiosk = $kiosk;
2756 }
2757
2765 function getKioskMode()
2766 {
2767 if (($this->_kiosk & 1) > 0)
2768 {
2769 return TRUE;
2770 }
2771 else
2772 {
2773 return FALSE;
2774 }
2775 }
2776
2784 public function setKioskMode($a_kiosk = FALSE)
2785 {
2786 if ($a_kiosk)
2787 {
2788 $this->_kiosk = $this->_kiosk | 1;
2789 }
2790 else
2791 {
2792 if ($this->getKioskMode())
2793 {
2794 $this->_kiosk = $this->_kiosk ^ 1;
2795 }
2796 }
2797 }
2798
2806 public function getShowKioskModeTitle()
2807 {
2808 if (($this->_kiosk & 2) > 0)
2809 {
2810 return TRUE;
2811 }
2812 else
2813 {
2814 return FALSE;
2815 }
2816 }
2817
2824 public function setShowKioskModeTitle($a_title = FALSE)
2825 {
2826 if ($a_title)
2827 {
2828 $this->_kiosk = $this->_kiosk | 2;
2829 }
2830 else
2831 {
2832 if ($this->getShowKioskModeTitle())
2833 {
2834 $this->_kiosk = $this->_kiosk ^ 2;
2835 }
2836 }
2837 }
2838
2847 {
2848 if (($this->_kiosk & 4) > 0)
2849 {
2850 return TRUE;
2851 }
2852 else
2853 {
2854 return FALSE;
2855 }
2856 }
2857
2864 public function setShowKioskModeParticipant($a_participant = FALSE)
2865 {
2866 if ($a_participant)
2867 {
2868 $this->_kiosk = $this->_kiosk | 4;
2869 }
2870 else
2871 {
2872 if ($this->getShowKioskModeParticipant())
2873 {
2874 $this->_kiosk = $this->_kiosk ^ 4;
2875 }
2876 }
2877 }
2878
2887 {
2888 return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2889 }
2890
2899 {
2900 return ($this->title_output) ? $this->title_output : 0;
2901 }
2902
2911 function _getTitleOutput($active_id)
2912 {
2913 global $ilDB;
2914
2915 $result = $ilDB->queryF("SELECT tst_tests.title_output FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
2916 array('integer'),
2917 array($active_id)
2918 );
2919 if ($result->numRows())
2920 {
2921 $row = $ilDB->fetchAssoc($result);
2922 return $row["title_output"];
2923 }
2924 return 0;
2925 }
2926
2936 function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2937 {
2938 global $ilDB;
2939 global $ilUser;
2940
2942
2943 $result = $ilDB->queryF("SELECT tst_tests.use_previous_answers FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
2944 array("integer"),
2945 array($active_id)
2946 );
2947 if ($result->numRows())
2948 {
2949 $row = $ilDB->fetchAssoc($result);
2950 $use_previous_answers = $row["use_previous_answers"];
2951 }
2952
2953 if ($use_previous_answers == 1)
2954 {
2955 if ($user_active_user_setting)
2956 {
2957 $res = $ilUser->getPref("tst_use_previous_answers");
2958 if ($res !== FALSE)
2959 {
2961 }
2962 }
2963 }
2964 return $use_previous_answers;
2965 }
2966
2975 {
2976 return (strlen($this->processing_time)) ? $this->processing_time : NULL;
2977 }
2978
2986 {
2987 if (strlen($this->processing_time))
2988 {
2989 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
2990 {
2991 if ((int)$matches[1]+(int)$matches[2]+(int)$matches[3] == 0)
2992 {
2993 return $this->getEstimatedWorkingTime();
2994 }
2995 else
2996 {
2997 return array(
2998 'hh' => $matches[1],
2999 'mm' => $matches[2],
3000 'ss' => $matches[3],
3001 );
3002 }
3003 }
3004 }
3005 return $this->getEstimatedWorkingTime();
3006 }
3007
3009 {
3010 if (strlen($this->processing_time))
3011 {
3012 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
3013 {
3014 return ($matches[1] * 60) + $matches[2];
3015 }
3016 }
3017
3019 }
3020
3028 function getProcessingTimeInSeconds($active_id = "")
3029 {
3030 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
3031 {
3032 $extratime = $this->getExtraTime($active_id) * 60;
3033 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
3034 }
3035 else
3036 {
3037 return 0;
3038 }
3039 }
3040
3049 {
3050 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
3051 {
3052 $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
3053 $now = time();
3054 return $ending - $now;
3055 }
3056 else
3057 {
3058 return 0;
3059 }
3060 }
3061
3070 {
3071 return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
3072 }
3073
3082 {
3083 return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
3084 }
3085
3089 public function isStartingTimeEnabled()
3090 {
3092 }
3093
3098 {
3099 $this->starting_time_enabled = $starting_time_enabled;
3100 }
3101
3109 public function getStartingTime()
3110 {
3111 return (strlen($this->starting_time)) ? $this->starting_time : NULL;
3112 }
3113
3121 public function setStartingTime($starting_time = NULL)
3122 {
3123 $this->starting_time = $starting_time;
3124 }
3125
3129 public function isEndingTimeEnabled()
3130 {
3132 }
3133
3138 {
3139 $this->ending_time_enabled = $ending_time_enabled;
3140 }
3141
3149 public function getEndingTime()
3150 {
3151 return (strlen($this->ending_time)) ? $this->ending_time : NULL;
3152 }
3153
3161 public function setEndingTime($ending_time = NULL)
3162 {
3163 $this->ending_time = $ending_time;
3164 }
3165
3174 {
3175 $this->nr_of_tries = $nr_of_tries;
3176 }
3177
3186 {
3188 {
3189 $this->use_previous_answers = 1;
3190 }
3191 else
3192 {
3193 $this->use_previous_answers = 0;
3194 }
3195 }
3196
3198 {
3199 $this->redirection_mode = $redirection_mode;
3200 }
3202 {
3204 }
3206 {
3207 $this->redirection_url = $redirection_url;
3208 }
3210 {
3212 }
3213
3222 {
3223 switch ($title_output)
3224 {
3225 case 1:
3226 $this->title_output = 1;
3227 break;
3228 case 2:
3229 $this->title_output = 2;
3230 break;
3231 default:
3232 $this->title_output = 0;
3233 break;
3234 }
3235 }
3236
3245 {
3246 $this->processing_time = $processing_time;
3247 }
3248
3249 public function setProcessingTimeByMinutes($minutes)
3250 {
3251 $this->processing_time = sprintf("%02d:%02d:00", floor($minutes/60), $minutes%60);
3252 }
3253
3261 function setEnableProcessingTime($enable = 0)
3262 {
3263 if ($enable) {
3264 $this->enable_processing_time = "1";
3265 } else {
3266 $this->enable_processing_time = "0";
3267 }
3268 }
3269
3277 function setResetProcessingTime($reset = 0)
3278 {
3279 if ($reset)
3280 {
3281 $this->reset_processing_time = 1;
3282 }
3283 else
3284 {
3285 $this->reset_processing_time = 0;
3286 }
3287 }
3288
3296 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3297 {
3298 $this->count_system = $a_count_system;
3299 }
3300
3304 public function isPasswordEnabled()
3305 {
3307 }
3308
3313 {
3314 $this->passwordEnabled = $passwordEnabled;
3315 }
3316
3324 public function getPassword()
3325 {
3326 return (strlen($this->password)) ? $this->password : NULL;
3327 }
3328
3336 public function setPassword($a_password = NULL)
3337 {
3338 $this->password = $a_password;
3339 }
3340
3348 function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3349 {
3350 $this->score_cutting = $a_score_cutting;
3351 }
3352
3361 {
3362 $this->mc_scoring = $a_mc_scoring;
3363 }
3364
3372 function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3373 {
3374 switch ($a_pass_scoring)
3375 {
3376 case SCORE_BEST_PASS:
3377 $this->pass_scoring = SCORE_BEST_PASS;
3378 break;
3379 default:
3380 $this->pass_scoring = SCORE_LAST_PASS;
3381 break;
3382 }
3383 }
3384
3392 function removeQuestion($question_id)
3393 {
3394 $question =& ilObjTest::_instanciateQuestion($question_id);
3395 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3397 {
3398 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3399 }
3400 $question->delete($question_id);
3401 $this->removeAllTestEditings($question_id);
3402 $this->loadQuestions();
3403 $this->saveQuestionsToDb();
3404 }
3405
3413 public function removeAllTestEditings($question_id = "")
3414 {
3415 global $ilDB;
3416
3417 // remove the question from tst_solutions
3418 if ($question_id)
3419 {
3420 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_solutions.question_fi = %s",
3421 array('integer','integer'),
3422 array($this->getTestId(), $question_id)
3423 );
3424 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_qst_solved.question_fi = %s",
3425 array('integer','integer'),
3426 array($this->getTestId(), $question_id)
3427 );
3428 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_test_result.question_fi = %s",
3429 array('integer','integer'),
3430 array($this->getTestId(), $question_id)
3431 );
3432 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3433 array('integer'),
3434 array($this->getTestId())
3435 );
3436
3437 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3439 }
3440 else
3441 {
3442 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3443 array('integer'),
3444 array($this->getTestId())
3445 );
3446 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3447 array('integer'),
3448 array($this->getTestId())
3449 );
3450 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3451 array('integer'),
3452 array($this->getTestId())
3453 );
3454 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3455 array('integer'),
3456 array($this->getTestId())
3457 );
3458
3459 $query = "SELECT active_id FROM tst_active WHERE test_fi = %s";
3460 $res = $ilDB->queryF($query, array('integer'), array($this->getTestId()));
3461 $activeIds = array();
3462 while( $row = $ilDB->fetchAssoc($res) )
3463 {
3464 $activeIds[] = $row['active_id'];
3465 }
3466
3467 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3469
3470 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3472 {
3473 $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
3474 }
3475 }
3476
3477 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE tst_sequence.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3478 array('integer'),
3479 array($this->getTestId())
3480 );
3481
3482 if ($this->isRandomTest())
3483 {
3484 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE tst_test_rnd_qst.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3485 array('integer'),
3486 array($this->getTestId())
3487 );
3488 }
3489
3490 // remove test_active entries, because test has changed
3491 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3492 array('integer'),
3493 array($this->getTestId())
3494 );
3495
3496 // remove saved user passwords
3497 $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE keyword = %s",
3498 array('text'),
3499 array("tst_password_".$this->getTestId())
3500 );
3501
3502 // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3503 // remove file uploads
3504 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId()))
3505 {
3506 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId());
3507 }
3508 }
3509
3510 public function removeTestResults(ilTestParticipantData $participantData)
3511 {
3512 if( count($participantData->getAnonymousActiveIds()) )
3513 {
3514 $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3515 }
3516
3517 if( count($participantData->getUserIds()) )
3518 {
3519 /* @var ilTestLP $testLP */
3520 require_once 'Services/Object/classes/class.ilObjectLP.php';
3521 $testLP = ilObjectLP::getInstance($this->getId());
3522 $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3523 }
3524
3525 if( count($participantData->getActiveIds()) )
3526 {
3527 $this->removeTestActives($participantData->getActiveIds());
3528 }
3529 }
3530
3531 public function removeTestResultsByUserIds($userIds)
3532 {
3533 global $ilDB, $lng;
3534
3535 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3536 $participantData = new ilTestParticipantData($ilDB, $lng);
3537 $participantData->setUserIds($userIds);
3538 $participantData->load($this->getTestId());
3539
3540 $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3541 $ilDB->manipulateF("DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3542 array('text'), array("tst_password_".$this->getTestId())
3543 );
3544
3545 if( count($participantData->getActiveIds()) )
3546 {
3547 $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3548 }
3549 }
3550
3551 public function removeTestResultsByActiveIds($activeIds)
3552 {
3553 global $ilDB;
3554
3555 $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3556
3557 $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3558 $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3559 $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3560 $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3561 $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3562 $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3563
3564 if( $this->isRandomTest() )
3565 {
3566 $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3567 }
3568 elseif( $this->isDynamicTest() )
3569 {
3570 $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3571 $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3572 $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3573 $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3574 }
3575
3576 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3577
3578 foreach ($activeIds as $active_id)
3579 {
3580 // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3581 // remove file uploads
3582 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3583 {
3584 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3585 }
3586
3588 {
3589 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3590 }
3591 }
3592
3593 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3595 }
3596
3597 public function removeTestActives($activeIds)
3598 {
3599 global $ilDB;
3600
3601 $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3602 $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3603 }
3604
3605 function removeTestResultsForUser($user_id)
3606 {
3607 global $ilDB;
3608
3609 $active_id = $this->getActiveIdOfUser($user_id);
3610
3611 // remove the question from tst_solutions
3612 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s",
3613 array('integer'),
3614 array($active_id)
3615 );
3616 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s",
3617 array('integer'),
3618 array($active_id)
3619 );
3620 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE active_fi = %s",
3621 array('integer'),
3622 array($active_id)
3623 );
3624 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE active_fi = %s",
3625 array('integer'),
3626 array($active_id)
3627 );
3628
3629 if ($this->isRandomTest())
3630 {
3631 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE active_fi = %s",
3632 array('integer'),
3633 array($active_id)
3634 );
3635 }
3636
3637 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3639 {
3640 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3641 }
3642
3643 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
3644 array('integer'),
3645 array($active_id)
3646 );
3647
3648 // remove test_active entry
3649 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE active_id = %s",
3650 array('integer'),
3651 array($active_id)
3652 );
3653
3654 // remove saved user password
3655 if ($user_id > 0)
3656 {
3657 $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s",
3658 array('integer', 'text'),
3659 array($user_id, "tst_password_".$this->getTestId())
3660 );
3661 }
3662
3663 // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3664 // remove file uploads
3665 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3666 {
3667 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3668 }
3669
3670 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3672 }
3673
3681 function questionMoveUp($question_id)
3682 {
3683 global $ilDB;
3684
3685 // Move a question up in sequence
3686 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3687 array('integer', 'integer'),
3688 array($this->getTestId(), $question_id)
3689 );
3690 $data = $ilDB->fetchObject($result);
3691 if ($data->sequence > 1)
3692 {
3693 // OK, it's not the top question, so move it up
3694 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3695 array('integer','integer'),
3696 array($this->getTestId(), $data->sequence - 1)
3697 );
3698 $data_previous = $ilDB->fetchObject($result);
3699 // change previous dataset
3700 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3701 array('integer','integer'),
3702 array($data->sequence, $data_previous->test_question_id)
3703 );
3704 // move actual dataset up
3705 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3706 array('integer','integer'),
3707 array($data->sequence - 1, $data->test_question_id)
3708 );
3709 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3711 {
3712 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3713 }
3714 }
3715 $this->loadQuestions();
3716 }
3717
3725 function questionMoveDown($question_id)
3726 {
3727 global $ilDB;
3728
3729 // Move a question down in sequence
3730 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3731 array('integer','integer'),
3732 array($this->getTestId(), $question_id)
3733 );
3734 $data = $ilDB->fetchObject($result);
3735 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3736 array('integer','integer'),
3737 array($this->getTestId(), $data->sequence + 1)
3738 );
3739 if ($result->numRows() == 1)
3740 {
3741 // OK, it's not the last question, so move it down
3742 $data_next = $ilDB->fetchObject($result);
3743 // change next dataset
3744 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3745 array('integer','integer'),
3746 array($data->sequence, $data_next->test_question_id)
3747 );
3748 // move actual dataset down
3749 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3750 array('integer','integer'),
3751 array($data->sequence + 1, $data->test_question_id)
3752 );
3753 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3755 {
3756 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3757 }
3758 }
3759 $this->loadQuestions();
3760 }
3761
3769 function duplicateQuestionForTest($question_id)
3770 {
3771 global $ilUser;
3772 $question =& ilObjTest::_instanciateQuestion($question_id);
3773 $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3774
3775 return $duplicate_id;
3776 }
3777
3786 public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3787 {
3788 global $ilDB;
3789#var_dump($question_id);
3790 if ($linkOnly)
3791 {
3792 $duplicate_id = $question_id;
3793 }
3794 else
3795 {
3796 $duplicate_id = $this->duplicateQuestionForTest($question_id);
3797 }
3798
3799 // get maximum sequence index in test
3800 $result = $ilDB->queryF("SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3801 array('integer'),
3802 array($this->getTestId())
3803 );
3804 $sequence = 1;
3805
3806 if ($result->numRows() == 1)
3807 {
3808 $data = $ilDB->fetchObject($result);
3809 $sequence = $data->seq + 1;
3810 }
3811
3812 $next_id = $ilDB->nextId('tst_test_question');
3813 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3814 array('integer', 'integer','integer','integer','integer'),
3815 array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3816 );
3817 if ($affectedRows == 1)
3818 {
3819 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3821 {
3822 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3823 }
3824 }
3825 // remove test_active entries, because test has changed
3826 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3827 array('integer'),
3828 array($this->getTestId())
3829 );
3830 $this->loadQuestions();
3831 $this->saveCompleteStatus($testQuestionSetConfig);
3832 return $duplicate_id;
3833 }
3834
3843 {
3844 $titles = array();
3845 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3846 {
3847 global $ilDB;
3848 $result = $ilDB->queryF("SELECT qpl_questions.title FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY tst_test_question.sequence",
3849 array('integer'),
3850 array($this->getTestId())
3851 );
3852 while ($row = $ilDB->fetchAssoc($result))
3853 {
3854 array_push($titles, $row["title"]);
3855 }
3856 }
3857 return $titles;
3858 }
3859
3868 {
3869 $titles = array();
3870 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3871 {
3872 global $ilDB;
3873 $result = $ilDB->queryF("SELECT qpl_questions.title, qpl_questions.question_id FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY tst_test_question.sequence",
3874 array('integer'),
3875 array($this->getTestId())
3876 );
3877 while ($row = $ilDB->fetchAssoc($result))
3878 {
3879 $titles[$row['question_id']] = $row["title"];
3880 }
3881 }
3882 return $titles;
3883 }
3884
3894 {
3895 if ($this->getTitleOutput() == 2)
3896 {
3897 return $this->lng->txt("ass_question");
3898 }
3899 else
3900 {
3901 return $title;
3902 }
3903 }
3904
3913 function getQuestionDataset($question_id)
3914 {
3915 global $ilDB;
3916
3917 $result = $ilDB->queryF("SELECT qpl_questions.*, qpl_qst_type.type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
3918 array('integer'),
3919 array($question_id)
3920 );
3921 $row = $ilDB->fetchObject($result);
3922 return $row;
3923 }
3924
3931 function &getExistingQuestions($pass = NULL)
3932 {
3933 global $ilUser;
3934 global $ilDB;
3935
3936 $existing_questions = array();
3937 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3938 if ($this->isRandomTest())
3939 {
3940 if (is_null($pass)) $pass = 0;
3941 $result = $ilDB->queryF("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_rnd_qst WHERE tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.question_fi = qpl_questions.question_id AND tst_test_rnd_qst.pass = %s",
3942 array('integer','integer'),
3943 array($active_id, $pass)
3944 );
3945 }
3946 else
3947 {
3948 $result = $ilDB->queryF("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id",
3949 array('integer'),
3950 array($this->getTestId())
3951 );
3952 }
3953 while ($data = $ilDB->fetchObject($result))
3954 {
3955 if( $data->original_id === null )
3956 {
3957 continue;
3958 }
3959
3960 array_push($existing_questions, $data->original_id);
3961 }
3962 return $existing_questions;
3963 }
3964
3972 function getQuestionType($question_id)
3973 {
3974 global $ilDB;
3975
3976 if ($question_id < 1) return -1;
3977 $result = $ilDB->queryF("SELECT type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
3978 array('integer'),
3979 array($question_id)
3980 );
3981 if ($result->numRows() == 1)
3982 {
3983 $data = $ilDB->fetchObject($result);
3984 return $data->type_tag;
3985 }
3986 else
3987 {
3988 return "";
3989 }
3990 }
3991
3998 function startWorkingTime($active_id, $pass)
3999 {
4000 global $ilDB;
4001
4002 $next_id = $ilDB->nextId('tst_times');
4003 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
4004 array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
4005 array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
4006 );
4007 return $next_id;
4008 }
4009
4016 function updateWorkingTime($times_id)
4017 {
4018 global $ilDB;
4019
4020 $affectedRows = $ilDB->manipulateF("UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
4021 array('timestamp', 'integer', 'integer'),
4022 array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
4023 );
4024 }
4025
4032 function &getWorkedQuestions($active_id, $pass = NULL)
4033 {
4034 global $ilUser;
4035 global $ilDB;
4036
4037 if (is_null($pass))
4038 {
4039 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
4040 array('integer','integer'),
4041 array($active_id, 0)
4042 );
4043 }
4044 else
4045 {
4046 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
4047 array('integer','integer'),
4048 array($active_id, $pass)
4049 );
4050 }
4051 $result_array = array();
4052 while ($row = $ilDB->fetchAssoc($result))
4053 {
4054 array_push($result_array, $row["question_fi"]);
4055 }
4056 return $result_array;
4057 }
4058
4067 function isTestFinishedToViewResults($active_id, $currentpass)
4068 {
4069 $num = $this->getPassFinishDate($active_id, $currentpass);
4070 return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
4071 }
4072
4079 function &getAllQuestions($pass = NULL)
4080 {
4081 global $ilUser;
4082 global $ilDB;
4083
4084 $result_array = array();
4085 if ($this->isRandomTest())
4086 {
4087 $active_id = $this->getActiveIdOfUser($ilUser->getId());
4088 $this->loadQuestions($active_id, $pass);
4089 if (count($this->questions) == 0) return $result_array;
4090 if (is_null($pass))
4091 {
4092 $pass = $this->_getPass($active_id);
4093 }
4094 $result = $ilDB->queryF("SELECT qpl_questions.* FROM qpl_questions, tst_test_rnd_qst WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s AND " . $ilDB->in('qpl_questions.question_id', $this->questions, false, 'integer'),
4095 array('integer','integer'),
4096 array($active_id, $pass)
4097 );
4098 }
4099 else
4100 {
4101 if (count($this->questions) == 0) return $result_array;
4102 $result = $ilDB->query("SELECT qpl_questions.* FROM qpl_questions, tst_test_question WHERE tst_test_question.question_fi = qpl_questions.question_id AND " . $ilDB->in('qpl_questions.question_id', $this->questions, false, 'integer'));
4103 }
4104 while ($row = $ilDB->fetchAssoc($result))
4105 {
4106 $result_array[$row["question_id"]] = $row;
4107 }
4108 return $result_array;
4109 }
4110
4119 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
4120 {
4121 global $ilDB;
4122 global $ilUser;
4123
4124 if (!$user_id) $user_id = $ilUser->getId();
4125 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
4126 {
4127 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4128 array('integer','integer','text'),
4129 array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
4130 );
4131 }
4132 else if (strlen($anonymous_id))
4133 {
4134 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4135 array('integer','integer','text'),
4136 array($user_id, $this->test_id, $anonymous_id)
4137 );
4138 }
4139 else
4140 {
4141 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
4142 {
4143 return NULL;
4144 }
4145 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4146 array('integer','integer'),
4147 array($user_id, $this->test_id)
4148 );
4149 }
4150 if ($result->numRows())
4151 {
4152 $row = $ilDB->fetchAssoc($result);
4153 return $row["active_id"];
4154 }
4155 else
4156 {
4157 return 0;
4158 }
4159 }
4160
4169 function _getActiveIdOfUser($user_id = "", $test_id = "")
4170 {
4171 global $ilDB;
4172 global $ilUser;
4173
4174 if (!$user_id) {
4175 $user_id = $ilUser->id;
4176 }
4177 if (!$test_id)
4178 {
4179 return "";
4180 }
4181 $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4182 array('integer', 'integer'),
4183 array($user_id, $test_id)
4184 );
4185 if ($result->numRows())
4186 {
4187 $row = $ilDB->fetchAssoc($result);
4188 return $row["active_id"];
4189 }
4190 else
4191 {
4192 return "";
4193 }
4194 }
4195
4202 function pcArrayShuffle($array)
4203 {
4204 $keys = array_keys($array);
4205 shuffle($keys);
4206 $result = array();
4207 foreach ($keys as $key)
4208 {
4209 $result[$key] = $array[$key];
4210 }
4211 return $result;
4212 }
4213
4221 function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE)
4222 {
4223 global $tree, $ilDB, $lng, $ilPluginAdmin;
4224
4225 $results = $this->getResultsForActiveId($active_id);
4226
4227 if( is_null($pass) )
4228 {
4229 $pass = $results['pass'];
4230 }
4231
4232 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
4233 $testSessionFactory = new ilTestSessionFactory($this);
4234 $testSession = $testSessionFactory->getSession($active_id);
4235
4236 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4237 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
4238 $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $pass);
4239
4240 if( $this->isDynamicTest() )
4241 {
4242 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4243 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
4244 $dynamicQuestionSetConfig->loadFromDb();
4245
4246 $testSequence->loadFromDb($dynamicQuestionSetConfig);
4247 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4248
4249 $sequence = $testSequence->getUserSequenceQuestions();
4250 }
4251 else
4252 {
4253 $testSequence->loadFromDb();
4254 $testSequence->loadQuestions();
4255
4256 if( $ordered_sequence )
4257 {
4258 $sequence = $testSequence->getOrderedSequenceQuestions();
4259 }
4260 else
4261 {
4262 $sequence = $testSequence->getUserSequenceQuestions();
4263 }
4264 }
4265
4266 $arrResults = array();
4267
4268 $query = "
4269 SELECT tst_test_result.question_fi,
4270 tst_test_result.points reached,
4271 tst_test_result.hint_count requested_hints,
4272 tst_test_result.hint_points hint_points,
4273 tst_test_result.answered answered
4274
4275 FROM tst_test_result
4276
4277 LEFT JOIN tst_solutions
4278 ON tst_solutions.active_fi = tst_test_result.active_fi
4279 AND tst_solutions.question_fi = tst_test_result.question_fi
4280
4281 WHERE tst_test_result.active_fi = %s
4282 AND tst_test_result.pass = %s
4283 ";
4284
4285 $solutionresult = $ilDB->queryF(
4286 $query, array('integer', 'integer'), array($active_id, $pass)
4287 );
4288
4289 while( $row = $ilDB->fetchAssoc($solutionresult) )
4290 {
4291 $arrResults[ $row['question_fi'] ] = $row;
4292 }
4293
4294 $numWorkedThrough = count($arrResults);
4295
4296 require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4297
4298 $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4299
4300 $query = "
4301 SELECT qpl_questions.*,
4302 qpl_qst_type.type_tag,
4303 qpl_sol_sug.question_fi has_sug_sol
4304
4305 FROM qpl_qst_type,
4306 qpl_questions
4307
4308 LEFT JOIN qpl_sol_sug
4309 ON qpl_sol_sug.question_fi = qpl_questions.question_id
4310
4311 WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4312 AND $IN_question_ids
4313 ";
4314
4315 $result = $ilDB->query($query);
4316
4317 $unordered = array();
4318
4319 $key = 1;
4320
4321 $obligationsAnswered = true;
4322
4323 while( $row = $ilDB->fetchAssoc($result) )
4324 {
4325 $percentvalue = (
4326 $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4327 );
4328
4329 if( $percentvalue < 0 ) $percentvalue = 0.0;
4330
4331 $data = array(
4332 "nr" => "$key",
4333 "title" => ilUtil::prepareFormOutput($row['title']),
4334 "max" => round($row['points'], 2),
4335 "reached" => round($arrResults[$row['question_id']]['reached'],2),
4336 'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4337 'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4338 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4339 "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4340 "type" => $row["type_tag"],
4341 "qid" => $row['question_id'],
4342 "original_id" => $row["original_id"],
4343 "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4344 'answered' => $arrResults[$row['question_id']]['answered']
4345 );
4346
4347 if( !$arrResults[ $row['question_id'] ]['answered'] )
4348 {
4349 $obligationsAnswered = false;
4350 }
4351
4352 $unordered[ $row['question_id'] ] = $data;
4353
4354 $key++;
4355 }
4356
4357 $pass_max = 0;
4358 $pass_reached = 0;
4359 $pass_requested_hints = 0;
4360 $pass_hint_points = 0;
4361 $key = 1;
4362
4363 $found = array();
4364
4365 foreach( $sequence as $qid )
4366 {
4367 // building pass point sums based on prepared data
4368 // for question that exists in users qst sequence
4369 $pass_max += round($unordered[$qid]['max'], 2);
4370 $pass_reached += round($unordered[$qid]['reached'], 2);
4371 $pass_requested_hints += $unordered[$qid]['requested_hints'];
4372 $pass_hint_points += $unordered[$qid]['hint_points'];
4373
4374 // pickup prepared data for question
4375 // that exists in users qst sequence
4376 $unordered[$qid]['nr'] = $key;
4377 array_push($found, $unordered[$qid]);
4378
4379 // increment key counter
4380 $key++;
4381 }
4382
4383 $unordered = null;
4384
4385 if( $this->getScoreCutting() == 1 )
4386 {
4387 if( $results['reached_points'] < 0 )
4388 {
4389 $results['reached_points'] = 0;
4390 }
4391
4392 if( $pass_reached < 0 ) $pass_reached = 0;
4393 }
4394
4395 $found['pass']['total_max_points'] = $pass_max;
4396 $found['pass']['total_reached_points'] = $pass_reached;
4397 $found['pass']['total_requested_hints'] = $pass_requested_hints;
4398 $found['pass']['total_hint_points'] = $pass_hint_points;
4399 $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4400 $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4401 $found['pass']['num_workedthrough'] = $numWorkedThrough;
4402
4403 $found["test"]["total_max_points"] = $results['max_points'];
4404 $found["test"]["total_reached_points"] = $results['reached_points'];
4405 $found["test"]["total_requested_hints"] = $results['hint_count'];
4406 $found["test"]["total_hint_points"] = $results['hint_points'];
4407 $found["test"]["result_pass"] = $results['pass'];
4408 $found['test']['obligations_answered'] = $results['obligations_answered'];
4409
4410 if( (!$total_reached_points) or (!$total_max_points) )
4411 {
4412 $percentage = 0.0;
4413 }
4414 else
4415 {
4416 $percentage = ($total_reached_points / $total_max_points) * 100.0;
4417
4418 if( $percentage < 0 ) $percentage = 0.0;
4419 }
4420
4421 $found["test"]["passed"] = $results['passed'];
4422
4423 return $found;
4424 }
4425
4433 {
4434 global $ilDB;
4435
4436 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4437 array('integer'),
4438 array($this->getTestId())
4439 );
4440 $row = $ilDB->fetchAssoc($result);
4441 return $row["total"];
4442 }
4443
4450 function getCompleteWorkingTime($user_id)
4451 {
4452 global $ilDB;
4453
4454 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.user_fi = %s",
4455 array('integer','integer'),
4456 array($this->getTestId(), $user_id)
4457 );
4458 $time = 0;
4459 while ($row = $ilDB->fetchAssoc($result))
4460 {
4461 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4462 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4463 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4464 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4465 $time += ($epoch_2 - $epoch_1);
4466 }
4467 return $time;
4468 }
4469
4477 {
4478 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4479 }
4480
4489 {
4490 global $ilDB;
4491
4492 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.active_fi, tst_times.started",
4493 array('integer'),
4494 array($test_id)
4495 );
4496 $time = 0;
4497 $times = array();
4498 while ($row = $ilDB->fetchAssoc($result))
4499 {
4500 if (!array_key_exists($row["active_fi"], $times))
4501 {
4502 $times[$row["active_fi"]] = 0;
4503 }
4504 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4505 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4506 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4507 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4508 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4509 }
4510 return $times;
4511 }
4512
4520 {
4521 global $ilDB;
4522
4523 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.active_id = %s ORDER BY tst_times.active_fi, tst_times.started",
4524 array('integer','integer'),
4525 array($this->getTestId(), $active_id)
4526 );
4527 $time = 0;
4528 while ($row = $ilDB->fetchAssoc($result))
4529 {
4530 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4531 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4532 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4533 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4534 $time += ($epoch_2 - $epoch_1);
4535 }
4536 return $time;
4537 }
4538
4546 {
4547 global $ilDB;
4548
4549 $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4550 array('integer','integer'),
4551 array($active_id, $pass)
4552 );
4553 $time = 0;
4554 while ($row = $ilDB->fetchAssoc($result))
4555 {
4556 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4557 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4558 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4559 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4560 $time += ($epoch_2 - $epoch_1);
4561 }
4562 return $time;
4563 }
4564
4572 function getVisitTimeOfParticipant($active_id)
4573 {
4574 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4575 }
4576
4586 {
4587 global $ilDB;
4588
4589 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.active_id = %s ORDER BY tst_times.started",
4590 array('integer','integer'),
4591 array($test_id, $active_id)
4592 );
4593 $firstvisit = 0;
4594 $lastvisit = 0;
4595 while ($row = $ilDB->fetchAssoc($result))
4596 {
4597 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4598 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4599 if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
4600 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4601 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4602 if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
4603 }
4604 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4605 }
4606
4613 function &evalStatistical($active_id)
4614 {
4615 global $ilDB;
4616// global $ilBench;
4617 $pass = ilObjTest::_getResultPass($active_id);
4618 $test_result =& $this->getTestResult($active_id, $pass);
4619 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
4620 array('integer'),
4621 array($active_id)
4622 );
4623 $times = array();
4624 $first_visit = 0;
4625 $last_visit = 0;
4626 while ($row = $ilDB->fetchObject($result))
4627 {
4628 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4629 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4630 if (!$first_visit) {
4631 $first_visit = $epoch_1;
4632 }
4633 if ($epoch_1 < $first_visit) {
4634 $first_visit = $epoch_1;
4635 }
4636 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4637 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4638 if (!$last_visit) {
4639 $last_visit = $epoch_2;
4640 }
4641 if ($epoch_2 > $last_visit) {
4642 $last_visit = $epoch_2;
4643 }
4644 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4645 }
4646 $max_time = 0;
4647 foreach ($times as $key => $value) {
4648 $max_time += $value;
4649 }
4650 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
4651 {
4652 $percentage = 0.0;
4653 }
4654 else
4655 {
4656 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4657 if ($percentage < 0) $percentage = 0.0;
4658 }
4659 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4660 $first_date = getdate($first_visit);
4661 $last_date = getdate($last_visit);
4662 $qworkedthrough = 0;
4663 foreach ($test_result as $key => $value)
4664 {
4665 if (preg_match("/\d+/", $key))
4666 {
4667 $qworkedthrough += $value["workedthrough"];
4668 }
4669 }
4670 if (!$qworkedthrough)
4671 {
4672 $atimeofwork = 0;
4673 }
4674 else
4675 {
4676 $atimeofwork = $max_time / $qworkedthrough;
4677 }
4678
4679 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4680
4681 $result_mark = "";
4682 $passed = "";
4683
4684 if ($mark_obj)
4685 {
4686 $result_mark = $mark_obj->getShortName();
4687
4688 if( $mark_obj->getPassed() && $obligationsAnswered )
4689 {
4690 $passed = 1;
4691 }
4692 else
4693 {
4694 $passed = 0;
4695 }
4696 }
4697 $percent_worked_through = 0;
4698 if (count($this->questions))
4699 {
4700 $percent_worked_through = $qworkedthrough / count($this->questions);
4701 }
4702 $result_array = array(
4703 "qworkedthrough" => $qworkedthrough,
4704 "qmax" => count($this->questions),
4705 "pworkedthrough" => $percent_worked_through,
4706 "timeofwork" => $max_time,
4707 "atimeofwork" => $atimeofwork,
4708 "firstvisit" => $first_date,
4709 "lastvisit" => $last_date,
4710 "resultspoints" => $test_result["test"]["total_reached_points"],
4711 "maxpoints" => $test_result["test"]["total_max_points"],
4712 "resultsmarks" => $result_mark,
4713 "passed" => $passed,
4714 "distancemedian" => "0"
4715 );
4716 foreach ($test_result as $key => $value)
4717 {
4718 if (preg_match("/\d+/", $key))
4719 {
4720 $result_array[$key] = $value;
4721 }
4722 }
4723 return $result_array;
4724 }
4725
4734 {
4735 $totalpoints_array = array();
4736 $all_users =& $this->evalTotalParticipantsArray();
4737 foreach ($all_users as $active_id => $user_name)
4738 {
4739 $test_result =& $this->getTestResult($active_id);
4740 $reached = $test_result["test"]["total_reached_points"];
4741 $total = $test_result["test"]["total_max_points"];
4742 $percentage = $total != 0 ? $reached/$total : 0;
4743 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4744
4745 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4746
4747 if ($mark)
4748 {
4749 if( $mark->getPassed() && $obligationsAnswered )
4750 {
4751 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4752 }
4753 }
4754 }
4755 return $totalpoints_array;
4756 }
4757
4763 public function &getParticipants()
4764 {
4765 global $ilDB;
4766 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname ASC",
4767 array('integer'),
4768 array($this->getTestId())
4769 );
4770 $persons_array = array();
4771 while ($row = $ilDB->fetchAssoc($result))
4772 {
4773 $name = $this->lng->txt("anonymous");
4774 $fullname = $this->lng->txt("anonymous");
4775 $login = "";
4776 if (!$this->getAnonymity())
4777 {
4778 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4779 {
4780 $name = $this->lng->txt("deleted_user");
4781 $fullname = $this->lng->txt("deleted_user");
4782 $login = $this->lng->txt("unknown");
4783 }
4784 else
4785 {
4786 $login = $row["login"];
4787 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4788 {
4789 $name = $this->lng->txt("anonymous");
4790 $fullname = $this->lng->txt("anonymous");
4791 }
4792 else
4793 {
4794 $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4795 $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4796 }
4797 }
4798 }
4799 $persons_array[$row["active_id"]] = array(
4800 "name" => $name,
4801 "fullname" => $fullname,
4802 "login" => $login
4803 );
4804 }
4805 return $persons_array;
4806 }
4807
4814 function &evalTotalPersonsArray($name_sort_order = "asc")
4815 {
4816 global $ilDB;
4817 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
4818 array('integer'),
4819 array($this->getTestId())
4820 );
4821 $persons_array = array();
4822 while ($row = $ilDB->fetchAssoc($result))
4823 {
4824 if ($this->getAnonymity())
4825 {
4826 $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
4827 }
4828 else
4829 {
4830 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4831 {
4832 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4833 }
4834 else
4835 {
4836 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4837 {
4838 $persons_array[$row["active_id"]] = $row["lastname"];
4839 }
4840 else
4841 {
4842 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4843 }
4844 }
4845 }
4846 }
4847 return $persons_array;
4848 }
4849
4856 function &evalTotalParticipantsArray($name_sort_order = "asc")
4857 {
4858 global $ilDB;
4859 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_data.login, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
4860 array('integer'),
4861 array($this->getTestId())
4862 );
4863 $persons_array = array();
4864 while ($row = $ilDB->fetchAssoc($result))
4865 {
4866 if ($this->getAnonymity())
4867 {
4868 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
4869 }
4870 else
4871 {
4872 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4873 {
4874 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4875 }
4876 else
4877 {
4878 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4879 {
4880 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4881 }
4882 else
4883 {
4884 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4885 }
4886 }
4887 }
4888 }
4889 return $persons_array;
4890 }
4891
4899 {
4900 global $ilDB;
4901
4902 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4903 array('integer', 'integer'),
4904 array($this->getTestId(), 1)
4905 );
4906 $row = $ilDB->fetchAssoc($result);
4907 return $row["total"];
4908 }
4909
4916 function &getQuestionsOfTest($active_id)
4917 {
4918 global $ilDB;
4919 if ($this->isRandomTest())
4920 {
4921 $ilDB->setLimit($this->getQuestionCount(), 0);
4922 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4923 "tst_test_rnd_qst.pass, qpl_questions.points " .
4924 "FROM tst_test_rnd_qst, qpl_questions " .
4925 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4926 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4927 array('integer'),
4928 array($active_id)
4929 );
4930 }
4931 else
4932 {
4933 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4934 "qpl_questions.points " .
4935 "FROM tst_test_question, tst_active, qpl_questions " .
4936 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4937 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4938 array('integer'),
4939 array($active_id)
4940 );
4941 }
4942 $qtest = array();
4943 if ($result->numRows())
4944 {
4945 while ($row = $ilDB->fetchAssoc($result))
4946 {
4947 array_push($qtest, $row);
4948 }
4949 }
4950 return $qtest;
4951 }
4952
4959 function &getQuestionsOfPass($active_id, $pass)
4960 {
4961 global $ilDB;
4962 if ($this->isRandomTest())
4963 {
4964 $ilDB->setLimit($this->getQuestionCount(), 0);
4965 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4966 "qpl_questions.points " .
4967 "FROM tst_test_rnd_qst, qpl_questions " .
4968 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4969 "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4970 "ORDER BY tst_test_rnd_qst.sequence",
4971 array('integer', 'integer'),
4972 array($active_id, $pass)
4973 );
4974 }
4975 else
4976 {
4977 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4978 "qpl_questions.points " .
4979 "FROM tst_test_question, tst_active, qpl_questions " .
4980 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4981 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4982 array('integer'),
4983 array($active_id)
4984 );
4985 }
4986 $qpass = array();
4987 if ($result->numRows())
4988 {
4989 while ($row = $ilDB->fetchAssoc($result))
4990 {
4991 array_push($qpass, $row);
4992 }
4993 }
4994 return $qpass;
4995 }
4996
4997 function getUnfilteredEvaluationData()
4998 {
5000 global $DIC;
5001
5002 $ilDB = $DIC->database();
5003
5004 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5005 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5006 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5007
5008 $data = new ilTestEvaluationData($this);
5009
5010 $query = "
5011 SELECT tst_test_result.*,
5012 qpl_questions.original_id,
5013 qpl_questions.title questiontitle,
5014 qpl_questions.points maxpoints
5015
5016 FROM tst_test_result, qpl_questions, tst_active
5017
5018 WHERE tst_active.active_id = tst_test_result.active_fi
5019 AND qpl_questions.question_id = tst_test_result.question_fi
5020 AND tst_active.test_fi = %s
5021
5022 ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
5023 ";
5024
5025 $result = $ilDB->queryF(
5026 $query, array('integer'), array($this->getTestId())
5027 );
5028
5029 $pass = NULL;
5030 $checked = array();
5031 $datasets = 0;
5032 $questionData = [];
5033
5034 while( $row = $ilDB->fetchAssoc($result) )
5035 {
5036 $participantObject = $data->getParticipant($row["active_fi"]);
5037
5038 if( !($participantObject instanceof ilTestEvaluationUserData) )
5039 {
5040 continue;
5041 }
5042
5043 $passObject = $participantObject->getPass($row["pass"]);
5044
5045 if( !($passObject instanceof ilTestEvaluationPassData) )
5046 {
5047 continue;
5048 }
5049
5050 $passObject->addAnsweredQuestion(
5051 $row["question_fi"], $row["maxpoints"], $row["points"], $row['answered'], null, $row['manual']
5052 );
5053 }
5054
5055 foreach( array_keys($data->getParticipants()) as $active_id )
5056 {
5057 if( $this->isRandomTest() )
5058 {
5059 for( $testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++ )
5060 {
5061 $ilDB->setLimit($this->getQuestionCount(), 0);
5062 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id, " .
5063 "tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title " .
5064 "FROM tst_test_rnd_qst, qpl_questions " .
5065 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
5066 "AND tst_test_rnd_qst.pass = %s " .
5067 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
5068 array('integer','integer'),
5069 array($testpass, $active_id)
5070 );
5071 if ($result->numRows())
5072 {
5073 while ($row = $ilDB->fetchAssoc($result))
5074 {
5075 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
5076 $data->getParticipant($active_id)->addQuestion($row["original_id"], $row["question_fi"], $row["points"], $row["sequence"], $tpass);
5077 $data->addQuestionTitle($row["question_fi"], $row["title"]);
5078 }
5079 }
5080 }
5081 }
5082 else if($this->isDynamicTest())
5083 {
5084 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
5085 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
5086 require_once 'Modules/Test/classes/class.ilTestDynamicQuestionSetFilterSelection.php';
5087
5088 $lastPass = $data->getParticipant($active_id)->getLastPass();
5089 for($testpass = 0; $testpass <= $lastPass; $testpass++)
5090 {
5091 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
5092 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig(
5093 $DIC->repositoryTree(), $DIC->database(), $DIC['ilPluginAdmin'], $this
5094 );
5095 $dynamicQuestionSetConfig->loadFromDb();
5096
5097 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
5098 $testSequenceFactory = new ilTestSequenceFactory($DIC->database(), $DIC->language(), $DIC['ilPluginAdmin'], $this);
5099 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $testpass);
5100
5101 $testSequence->loadFromDb($dynamicQuestionSetConfig);
5102 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
5103
5104 $sequence = (array)$testSequence->getUserSequenceQuestions();
5105
5106 $questionsIdsToRequest = array_diff(array_values($sequence), array_values($questionData));
5107 if(count($questionsIdsToRequest) > 0)
5108 {
5109 $questionIdsCondition = ' ' . $DIC->database()->in('question_id', array_values($questionsIdsToRequest), false, 'integer') . ' ';
5110
5111 $res = $DIC->database()->queryF("
5112 SELECT *
5113 FROM qpl_questions
5114 WHERE {$questionIdsCondition}",
5115 array('integer'),
5116 array($active_id)
5117 );
5118 while($row = $DIC->database()->fetchAssoc($res))
5119 {
5120 $questionData[$row['question_id']] = $row;
5121 $data->addQuestionTitle($row['question_id'], $row['title']);
5122 }
5123 }
5124
5125 foreach($sequence as $questionId)
5126 {
5127 if(!isset($questionData[$questionId]))
5128 {
5129 continue;
5130 }
5131
5132 $row = $questionData[$questionId];
5133
5134 $data->getParticipant(
5135 $active_id)->addQuestion($row['original_id'], $row['question_id'], $row['points'],
5136 NULL, $testpass
5137 );
5138 }
5139 }
5140 }
5141 else
5142 {
5143 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
5144 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
5145 "FROM tst_test_question, tst_active, qpl_questions " .
5146 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
5147 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
5148 array('integer'),
5149 array($active_id)
5150 );
5151 if ($result->numRows())
5152 {
5153 $questionsbysequence = array();
5154
5155 while ($row = $ilDB->fetchAssoc($result))
5156 {
5157 $questionsbysequence[$row["sequence"]] = $row;
5158 }
5159
5160 $seqresult = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s",
5161 array('integer'),
5162 array($active_id)
5163 );
5164
5165 while ($seqrow = $ilDB->fetchAssoc($seqresult))
5166 {
5167 $questionsequence = unserialize($seqrow["sequence"]);
5168 foreach ($questionsequence as $sidx => $seq)
5169 {
5170 $data->getParticipant($active_id)->addQuestion($questionsbysequence[$seq]["original_id"], $questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
5171 $data->addQuestionTitle($questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["title"]);
5172 }
5173 }
5174 }
5175 }
5176 }
5177
5178 if($this->getECTSOutput())
5179 {
5180 $passed_array =& $this->getTotalPointsPassedArray();
5181 }
5182
5183 foreach( array_keys($data->getParticipants()) as $active_id )
5184 {
5185 $tstUserData = $data->getParticipant($active_id);
5186
5187 $percentage = $tstUserData->getReachedPointsInPercent();
5188
5189 $obligationsAnswered = $tstUserData->areObligationsAnswered();
5190
5191 $mark = $this->mark_schema->getMatchingMark($percentage);
5192
5193 if (is_object($mark))
5194 {
5195 $tstUserData->setMark($mark->getShortName());
5196 $tstUserData->setMarkOfficial($mark->getOfficialName());
5197
5198 $tstUserData->setPassed(
5199 $mark->getPassed() && $tstUserData->areObligationsAnswered()
5200 );
5201 }
5202
5203 if($this->getECTSOutput())
5204 {
5205 $ects_mark = $this->getECTSGrade(
5206 $passed_array, $tstUserData->getReached(), $tstUserData->getMaxPoints()
5207 );
5208
5209 $tstUserData->setECTSMark($ects_mark);
5210 }
5211
5212 $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
5213
5214 $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
5215 $tstUserData->setLastVisit($visitingTime["lastvisit"]);
5216 }
5217
5218 return $data;
5219 }
5220
5222 {
5223 global $ilDB;
5224
5226
5227 switch( $questionSetType )
5228 {
5230
5231 $res = $ilDB->queryF("
5232 SELECT COUNT(qpl_questions.question_id) qcount,
5233 SUM(qpl_questions.points) qsum
5234 FROM tst_active
5235 INNER JOIN tst_tests
5236 ON tst_tests.test_id = tst_active.test_fi
5237 INNER JOIN tst_dyn_quest_set_cfg
5238 ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
5239 INNER JOIN qpl_questions
5240 ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
5241 AND qpl_questions.original_id IS NULL
5242 AND qpl_questions.complete = %s
5243 WHERE tst_active.active_id = %s
5244 ",
5245 array('integer', 'integer'),
5246 array(1, $active_id)
5247 );
5248
5249 break;
5250
5252
5253 $res = $ilDB->queryF("
5254 SELECT tst_test_rnd_qst.pass,
5255 COUNT(tst_test_rnd_qst.question_fi) qcount,
5256 SUM(qpl_questions.points) qsum
5257
5258 FROM tst_test_rnd_qst,
5259 qpl_questions
5260
5261 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
5262 AND tst_test_rnd_qst.active_fi = %s
5263 AND pass = %s
5264
5265 GROUP BY tst_test_rnd_qst.active_fi,
5266 tst_test_rnd_qst.pass
5267 ",
5268 array('integer', 'integer'),
5269 array($active_id, $pass)
5270 );
5271
5272 break;
5273
5275
5276 $res = $ilDB->queryF("
5277 SELECT COUNT(tst_test_question.question_fi) qcount,
5278 SUM(qpl_questions.points) qsum
5279
5280 FROM tst_test_question,
5281 qpl_questions,
5282 tst_active
5283
5284 WHERE tst_test_question.question_fi = qpl_questions.question_id
5285 AND tst_test_question.test_fi = tst_active.test_fi
5286 AND tst_active.active_id = %s
5287
5288 GROUP BY tst_test_question.test_fi
5289 ",
5290 array('integer'),
5291 array($active_id)
5292 );
5293
5294 break;
5295
5296 default:
5297
5298 throw new ilTestException("not supported question set type: $questionSetType");
5299 }
5300
5301 $row = $ilDB->fetchAssoc($res);
5302
5303 if( is_array($row) )
5304 {
5305 return array("count" => $row["qcount"], "points" => $row["qsum"]);
5306 }
5307
5308 return array("count" => 0, "points" => 0);
5309 }
5310
5311 function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
5312 {
5313 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5314 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5315 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5316 $data = $this->getUnfilteredEvaluationData();
5317 if ($withStatistics)
5318 {
5319 $data->calculateStatistics();
5320 }
5321 $data->setFilter($filterby, $filtertext);
5322 return $data;
5323 }
5324
5332 {
5333 return $this->_evalResultsOverview($this->getTestId());
5334 }
5335
5342 function &_evalResultsOverview($test_id)
5343 {
5344 global $ilDB;
5345
5346 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5347 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5348 "qpl_questions.points maxpoints " .
5349 "FROM tst_test_result, qpl_questions, tst_active " .
5350 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5351 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5352 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5353 "AND tst_active.test_fi = %s " .
5354 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5355 array('integer'),
5356 array($test_id)
5357 );
5358 $overview = array();
5359 while ($row = $ilDB->fetchAssoc($result))
5360 {
5361 if (!array_key_exists($row["active_fi"], $overview))
5362 {
5363 $overview[$row["active_fi"]] = array();
5364 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5365 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5366 $overview[$row["active_fi"]]["title"] = $row["title"];
5367 $overview[$row["active_fi"]]["login"] = $row["login"];
5368 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5369 $overview[$row["active_fi"]]["started"] = $row["started"];
5370 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5371 }
5372 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5373 {
5374 $overview[$row["active_fi"]][$row["pass"]] = array();
5375 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5376 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5377 }
5378 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5379 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5380 }
5381 return $overview;
5382 }
5383
5392 {
5393 global $ilDB;
5394
5395 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5396 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5397 "qpl_questions.points maxpoints " .
5398 "FROM tst_test_result, qpl_questions, tst_active " .
5399 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5400 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5401 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5402 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5403 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5404 array('integer', 'integer'),
5405 array($this->getTestId(), $active_id)
5406 );
5407 $overview = array();
5408 while ($row = $ilDB->fetchAssoc($result))
5409 {
5410 if (!array_key_exists($row["active_fi"], $overview))
5411 {
5412 $overview[$row["active_fi"]] = array();
5413 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5414 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5415 $overview[$row["active_fi"]]["title"] = $row["title"];
5416 $overview[$row["active_fi"]]["login"] = $row["login"];
5417 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5418 $overview[$row["active_fi"]]["started"] = $row["started"];
5419 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5420 }
5421 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5422 {
5423 $overview[$row["active_fi"]][$row["pass"]] = array();
5424 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5425 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5426 }
5427 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5428 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5429 }
5430 return $overview;
5431 }
5432
5444 function buildName($user_id, $firstname, $lastname, $title)
5445 {
5446 $name = "";
5447 if (strlen($firstname.$lastname.$title) == 0)
5448 {
5449 $name = $this->lng->txt("deleted_user");
5450 }
5451 else
5452 {
5453 if ($user_id == ANONYMOUS_USER_ID)
5454 {
5455 $name = $lastname;
5456 }
5457 else
5458 {
5459 $name = trim($lastname . ", " . $firstname . " " . $title);
5460 }
5461 if ($this->getAnonymity())
5462 {
5463 $name = $this->lng->txt("anonymous");
5464 }
5465 }
5466 return $name;
5467 }
5468
5481 function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5482 {
5483 global $lng;
5484 $name = "";
5485 if (strlen($firstname.$lastname.$title) == 0)
5486 {
5487 $name = $lng->txt("deleted_user");
5488 }
5489 else
5490 {
5491 if ($user_id == ANONYMOUS_USER_ID)
5492 {
5493 $name = $lastname;
5494 }
5495 else
5496 {
5497 $name = trim($lastname . ", " . $firstname . " " . $title);
5498 }
5499 if ($is_anonymous)
5500 {
5501 $name = $lng->txt("anonymous");
5502 }
5503 }
5504 return $name;
5505 }
5506
5514 {
5515 global $ilDB;
5516
5517 $result = $ilDB->queryF("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
5518 array('integer'),
5519 array($this->getTestId())
5520 );
5521 $times = array();
5522 while ($row = $ilDB->fetchObject($result))
5523 {
5524 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5525 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5526 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5527 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5528 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5529 }
5530 $max_time = 0;
5531 $counter = 0;
5532 foreach ($times as $key => $value)
5533 {
5534 $max_time += $value;
5535 $counter++;
5536 }
5537 if ($counter)
5538 {
5539 $average_time = round($max_time / $counter);
5540 }
5541 else
5542 {
5543 $average_time = 0;
5544 }
5545 return $average_time;
5546 }
5547
5554 function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
5555 {
5556 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5557 return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5558 }
5559
5567 {
5568 $time_in_seconds = 0;
5569 foreach ($this->questions as $question_id)
5570 {
5571 $question =& ilObjTest::_instanciateQuestion($question_id);
5572 $est_time = $question->getEstimatedWorkingTime();
5573 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5574 }
5575 $hours = (int)($time_in_seconds / 3600) ;
5576 $time_in_seconds = $time_in_seconds - ($hours * 3600);
5577 $minutes = (int)($time_in_seconds / 60);
5578 $time_in_seconds = $time_in_seconds - ($minutes * 60);
5579 $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5580 return $result;
5581 }
5582
5589 function getImagePath()
5590 {
5591 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5592 }
5593
5601 {
5602 include_once "./Services/Utilities/classes/class.ilUtil.php";
5603 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5605 }
5606
5615 function &createQuestionGUI($question_type, $question_id = -1)
5616 {
5617 if ((!$question_type) and ($question_id > 0))
5618 {
5619 $question_type = $this->getQuestionType($question_id);
5620 }
5621
5622 if (!strlen($question_type)) return null;
5623
5624 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5625 assQuestion::_includeClass($question_type, 1);
5626
5627 $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5628 $question = new $question_type_gui();
5629
5630 $question->object->setObligationsToBeConsidered( $this->areObligationsEnabled() );
5631
5632 if ($question_id > 0)
5633 {
5634 $question->object->loadFromDb($question_id);
5635
5636 global $ilCtrl, $ilDB, $ilUser, $lng;
5637
5638 $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5639 $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5640
5641 $assSettings = new ilSetting('assessment');
5642 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5643 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5644 $processLockerFactory->setQuestionId($question->object->getId());
5645 $processLockerFactory->setUserId($ilUser->getId());
5646 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5647 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5648 $question->object->setProcessLocker($processLockerFactory->getLocker());
5649 }
5650
5651 return $question;
5652 }
5653
5663 function &_instanciateQuestion($question_id)
5664 {
5665 if (strcmp($question_id, "") != 0)
5666 {
5667 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5668 return assQuestion::_instanciateQuestion($question_id);
5669 }
5670 }
5671
5680 function moveQuestions($move_questions, $target_index, $insert_mode)
5681 {
5682 $this->questions = array_values($this->questions);
5683 $array_pos = array_search($target_index, $this->questions);
5684 if ($insert_mode == 0)
5685 {
5686 $part1 = array_slice($this->questions, 0, $array_pos);
5687 $part2 = array_slice($this->questions, $array_pos);
5688 }
5689 else if ($insert_mode == 1)
5690 {
5691 $part1 = array_slice($this->questions, 0, $array_pos + 1);
5692 $part2 = array_slice($this->questions, $array_pos + 1);
5693 }
5694 foreach ($move_questions as $question_id)
5695 {
5696 if (!(array_search($question_id, $part1) === FALSE))
5697 {
5698 unset($part1[array_search($question_id, $part1)]);
5699 }
5700 if (!(array_search($question_id, $part2) === FALSE))
5701 {
5702 unset($part2[array_search($question_id, $part2)]);
5703 }
5704 }
5705 $part1 = array_values($part1);
5706 $part2 = array_values($part2);
5707 $new_array = array_values(array_merge($part1, $move_questions, $part2));
5708 $this->questions = array();
5709 $counter = 1;
5710 foreach ($new_array as $question_id)
5711 {
5712 $this->questions[$counter] = $question_id;
5713 $counter++;
5714 }
5715 $this->saveQuestionsToDb();
5716 }
5717
5718
5727 {
5728 if( $this->isStartingTimeEnabled() && $this->getStartingTime() )
5729 {
5730 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
5731 {
5732 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5733 $now = mktime();
5734 if ($now < $epoch_time)
5735 {
5736 // starting time not reached
5737 return false;
5738 }
5739 }
5740 }
5741 return true;
5742 }
5743
5752 {
5753 if( $this->isEndingTimeEnabled() && $this->getEndingTime() )
5754 {
5755 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
5756 {
5757 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5758 $now = mktime();
5759 if ($now > $epoch_time)
5760 {
5761 // ending time reached
5762 return true;
5763 }
5764 }
5765 }
5766 return false;
5767 }
5768
5774 function getAvailableQuestions($arrFilter, $completeonly = 0)
5775 {
5776 global $ilUser;
5777 global $ilDB;
5778
5779 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5780 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
5781 $available = "";
5782 if (count($available_pools))
5783 {
5784 $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5785 }
5786 else
5787 {
5788 return array();
5789 }
5790 if ($completeonly)
5791 {
5792 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5793 }
5794
5795 $where = "";
5796 if (is_array($arrFilter))
5797 {
5798 if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
5799 {
5800 $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5801 }
5802 if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
5803 {
5804 $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5805 }
5806 if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
5807 {
5808 $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5809 }
5810 if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
5811 {
5812 $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5813 }
5814 if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl']))
5815 {
5816 $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5817 }
5818 }
5819
5820 $original_ids =& $this->getExistingQuestions();
5821 $original_clause = " qpl_questions.original_id IS NULL";
5822 if (count($original_ids))
5823 {
5824 $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5825 }
5826
5827 $query_result = $ilDB->query(
5828 "SELECT qpl_questions.*, qpl_questions.tstamp, qpl_qst_type.type_tag, qpl_qst_type.plugin, object_data.title qpl " .
5829 "FROM qpl_questions, qpl_qst_type, object_data WHERE $original_clause $available AND " .
5830 "object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.tstamp > 0 AND " .
5831 "qpl_questions.question_type_fi = qpl_qst_type.question_type_id$where");
5832 $rows = array();
5833 $types = $this->getQuestionTypeTranslations();
5834 if ($query_result->numRows())
5835 {
5836 while ($row = $ilDB->fetchAssoc($query_result))
5837 {
5838 $row['ttype'] = $types[$row['type_tag']];
5839 if ($row["plugin"])
5840 {
5841 if ($this->isPluginActive($row["type_tag"]))
5842 {
5843 array_push($rows, $row);
5844 }
5845 }
5846 else
5847 {
5848 array_push($rows, $row);
5849 }
5850 }
5851 }
5852 return $rows;
5853 }
5854
5856 {
5857 global $ilDB;
5858 global $lng;
5859 global $ilLog;
5860 global $ilPluginAdmin;
5861
5862 $lng->loadLanguageModule("assessment");
5863 $result = $ilDB->query("SELECT * FROM qpl_qst_type");
5864 $types = array();
5865 while ($row = $ilDB->fetchAssoc($result))
5866 {
5867 if ($row["plugin"] == 0)
5868 {
5869 $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
5870 }
5871 else
5872 {
5873 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
5874 foreach ($pl_names as $pl_name)
5875 {
5876 $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
5877 if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0)
5878 {
5879 $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
5880 }
5881 }
5882 }
5883 }
5884 ksort($types);
5885 return $types;
5886 }
5887
5892 public function fromXML(ilQTIAssessment $assessment)
5893 {
5894 unset($_SESSION["import_mob_xhtml"]);
5895
5896 $this->setDescription($assessment->getComment());
5897 $this->setTitle($assessment->getTitle());
5898
5899 $this->setIntroductionEnabled(false);
5900 foreach ($assessment->objectives as $objectives)
5901 {
5902 foreach ($objectives->materials as $material)
5903 {
5904 $intro = $this->QTIMaterialToString($material);
5905 $this->setIntroduction($intro);
5906 $this->setIntroductionEnabled(strlen($intro) > 0);
5907 }
5908 }
5909
5910 if(
5911 $assessment->getPresentationMaterial() &&
5912 $assessment->getPresentationMaterial()->getFlowMat(0) &&
5913 $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5914 )
5915 {
5916 $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5917 }
5918
5919 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
5920 {
5921 switch ($assessmentcontrol->getSolutionswitch())
5922 {
5923 case "Yes":
5925 break;
5926 default:
5928 break;
5929 }
5930 }
5931
5932 $this->setStartingTimeEnabled(false);
5933 $this->setEndingTimeEnabled(false);
5934 $this->setPasswordEnabled(false);
5935 $this->setLimitUsersEnabled(false);
5936
5937 foreach ($assessment->qtimetadata as $metadata)
5938 {
5939 switch ($metadata["label"])
5940 {
5941 case "test_type":
5942 // for old tests with a test type
5943 $type = $metadata["entry"];
5944 switch ($type)
5945 {
5946 case 1:
5947 // assessment
5948 $this->setAnonymity(1);
5949 break;
5950 case 2:
5951 // self assessment
5952 break;
5953 case 4:
5954 // online exam
5955 $this->setFixedParticipants(1);
5957 $this->setShowSolutionPrintview(1);
5958 break;
5959 case 5:
5960 // varying random test
5961 break;
5962 }
5963 break;
5964 case "sequence_settings":
5965 $this->setSequenceSettings($metadata["entry"]);
5966 break;
5967 case "solution_details":
5968 $this->setShowSolutionDetails((int)$metadata["entry"]);
5969 break;
5970 case "print_bs_with_res":
5971 $this->setPrintBestSolutionWithResult((int)$metadata["entry"]);
5972 break;
5973 case "author":
5974 $this->setAuthor($metadata["entry"]);
5975 break;
5976 case "nr_of_tries":
5977 $this->setNrOfTries($metadata["entry"]);
5978 break;
5979 case "kiosk":
5980 $this->setKiosk($metadata["entry"]);
5981 break;
5982 case "showfinalstatement":
5983 $this->setShowFinalStatement($metadata["entry"]);
5984 break;
5985 case "showinfo":
5986 $this->setShowInfo($metadata["entry"]);
5987 break;
5988 case "forcejs":
5989 $this->setForceJS($metadata["entry"]);
5990 break;
5991 case "customstyle":
5992 $this->setCustomStyle($metadata["entry"]);
5993 break;
5994
5995 case "highscore_enabled":
5996 $this->setHighscoreEnabled($metadata["entry"]);
5997 break;
5998
5999 case "highscore_anon":
6000 $this->setHighscoreAnon($metadata["entry"]);
6001 break;
6002
6003 case "highscore_achieved_ts":
6004 $this->setHighscoreAchievedTS($metadata["entry"]);
6005 break;
6006
6007 case "highscore_score":
6008 $this->setHighscoreScore($metadata["entry"]);
6009 break;
6010
6011 case "highscore_percentage":
6012 $this->setHighscorePercentage($metadata["entry"]);
6013 break;
6014
6015 case "highscore_hints":
6016 $this->setHighscoreHints($metadata["entry"]);
6017 break;
6018
6019 case "highscore_wtime":
6020 $this->setHighscoreWTime($metadata["entry"]);
6021 break;
6022
6023 case "highscore_own_table":
6024 $this->setHighscoreOwnTable($metadata["entry"]);
6025 break;
6026
6027 case "highscore_top_table":
6028 $this->setHighscoreTopTable($metadata["entry"]);
6029 break;
6030
6031 case "highscore_top_num":
6032 $this->setHighscoreTopNum($metadata["entry"]);
6033 break;
6034
6035 case "hide_previous_results":
6036 if ($metadata["entry"] == 0)
6037 {
6038 $this->setUsePreviousAnswers(1);
6039 }
6040 else
6041 {
6042 $this->setUsePreviousAnswers(0);
6043 }
6044 break;
6045 case "use_previous_answers":
6046 $this->setUsePreviousAnswers($metadata["entry"]);
6047 break;
6048 case "answer_feedback":
6049 $this->setAnswerFeedback($metadata["entry"]);
6050 break;
6051 case "hide_title_points":
6052 $this->setTitleOutput($metadata["entry"]);
6053 break;
6054 case "title_output":
6055 $this->setTitleOutput($metadata["entry"]);
6056 break;
6057 case "question_set_type":
6058 $this->setQuestionSetType($metadata["entry"]);
6059 break;
6060 case "random_test":
6061 if( $metadata["entry"] )
6062 {
6063 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
6064 }
6065 else
6066 {
6067 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
6068 }
6069 break;
6070 case "results_presentation":
6071 $this->setResultsPresentation($metadata["entry"]);
6072 break;
6073 case "reset_processing_time":
6074 $this->setResetProcessingTime($metadata["entry"]);
6075 break;
6076 case "instant_verification":
6077 $this->setInstantFeedbackSolution($metadata["entry"]);
6078 break;
6079 case "answer_feedback_points":
6080 $this->setAnswerFeedbackPoints($metadata["entry"]);
6081 break;
6082 case "anonymity":
6083 $this->setAnonymity($metadata["entry"]);
6084 break;
6085 case "show_cancel":
6086 $this->setShowCancel($metadata["entry"]);
6087 break;
6088 case "show_marker":
6089 $this->setShowMarker($metadata["entry"]);
6090 break;
6091 case "fixed_participants":
6092 $this->setFixedParticipants($metadata["entry"]);
6093 break;
6094 case "score_reporting":
6095 $this->setScoreReporting($metadata["entry"]);
6096 break;
6097 case "shuffle_questions":
6098 $this->setShuffleQuestions($metadata["entry"]);
6099 break;
6100 case "count_system":
6101 $this->setCountSystem($metadata["entry"]);
6102 break;
6103 case "mc_scoring":
6104 $this->setMCScoring($metadata["entry"]);
6105 break;
6106 case "mailnotification":
6107 $this->setMailNotification($metadata["entry"]);
6108 break;
6109 case "mailnottype":
6110 $this->setMailNotificationType($metadata["entry"]);
6111 break;
6112 case "exportsettings":
6113 $this->setExportSettings($metadata['entry']);
6114 break;
6115 case "score_cutting":
6116 $this->setScoreCutting($metadata["entry"]);
6117 break;
6118 case "password":
6119 $this->setPassword($metadata["entry"]);
6120 $this->setPasswordEnabled(strlen($metadata["entry"]) > 0);
6121 break;
6122 case "allowedUsers":
6123 $this->setAllowedUsers($metadata["entry"]);
6124 $this->setLimitUsersEnabled((int)$metadata["entry"] > 0);
6125 break;
6126 case "allowedUsersTimeGap":
6127 $this->setAllowedUsersTimeGap($metadata["entry"]);
6128 break;
6129 case "pass_scoring":
6130 $this->setPassScoring($metadata["entry"]);
6131 break;
6132 case "show_summary":
6133 $this->setListOfQuestionsSettings($metadata["entry"]);
6134 break;
6135 case "reporting_date":
6136 $iso8601period = $metadata["entry"];
6137 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6138 {
6139 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6140 }
6141 break;
6142 case 'enable_processing_time':
6143 $this->setEnableProcessingTime($metadata['entry']);
6144 break;
6145 case "processing_time":
6146 $this->setProcessingTime($metadata['entry']);
6147 break;
6148 case "starting_time":
6149 $iso8601period = $metadata["entry"];
6150 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6151 {
6152 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6153 $this->setStartingTimeEnabled(true);
6154 }
6155 break;
6156 case "ending_time":
6157 $iso8601period = $metadata["entry"];
6158 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6159 {
6160 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6161 $this->setEndingTimeEnabled(true);
6162 }
6163 break;
6164 case "enable_examview":
6165 $this->setEnableExamview($metadata["entry"]);
6166 break;
6167 case 'show_examview_html':
6168 $this->setShowExamviewHtml($metadata['entry']);
6169 break;
6170 case 'show_examview_pdf':
6171 $this->setShowExamviewPdf($metadata['entry']);
6172 break;
6173 case 'redirection_mode':
6174 $this->setRedirectionMode($metadata['entry']);
6175 break;
6176 case 'redirection_url':
6177 $this->setRedirectionUrl($metadata['entry']);
6178 break;
6179 case 'examid_in_kiosk':
6180 case 'examid_in_test_pass':
6181 $this->setShowExamIdInTestPassEnabled($metadata['entry']);
6182 break;
6183 case 'show_exam_id':
6184 case 'examid_in_test_res':
6185 $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
6186 break;
6187 case 'enable_archiving':
6188 $this->setEnableArchiving($metadata['entry']);
6189 break;
6190 case 'sign_submission':
6191 $this->setSignSubmission($metadata['entry']);
6192 break;
6193 case 'char_selector_availability':
6194 $this->setCharSelectorAvailability($metadata['entry']);
6195 break;
6196 case 'char_selector_definition':
6197 $this->setCharSelectorDefinition($metadata['entry']);
6198 break;
6199 case 'skill_service':
6200 $this->setSkillServiceEnabled((bool)$metadata['entry']);
6201 break;
6202 case 'result_tax_filters':
6203 $this->setResultFilterTaxIds(strlen($metadata['entry']) ? unserialize($metadata['entry']) : array());
6204 break;
6205 case 'show_grading_status':
6206 $this->setShowGradingStatusEnabled((bool)$metadata['entry']);
6207 break;
6208 case 'show_grading_mark':
6209 $this->setShowGradingMarkEnabled((bool)$metadata['entry']);
6210 break;
6211 case 'activation_limited':
6212 $this->setActivationLimited($metadata['entry']);
6213 break;
6214 case 'activation_start_time':
6215 $this->setActivationStartingTime($metadata['entry']);
6216 break;
6217 case 'activation_end_time':
6218 $this->setActivationEndingTime($metadata['entry']);
6219 break;
6220 case 'activation_visibility':
6221 $this->setActivationVisibility($metadata['entry']);
6222 break;
6223 case 'autosave':
6224 $this->setAutosave($metadata['entry']);
6225 break;
6226 case 'autosave_ival':
6227 $this->setAutosaveIval($metadata['entry']);
6228 break;
6229 case 'offer_question_hints':
6230 $this->setOfferingQuestionHintsEnabled($metadata['entry']);
6231 break;
6232 case 'instant_feedback_specific':
6233 $this->setSpecificAnswerFeedback($metadata['entry']);
6234 break;
6235 case 'instant_feedback_answer_fixation':
6236 $this->setInstantFeedbackAnswerFixationEnabled($metadata['entry']);
6237 break;
6238 case 'obligations_enabled':
6239 $this->setObligationsEnabled($metadata['entry']);
6240 break;
6241 }
6242 if (preg_match("/mark_step_\d+/", $metadata["label"]))
6243 {
6244 $xmlmark = $metadata["entry"];
6245 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
6246 $mark_short = $matches[1];
6247 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
6248 $mark_official = $matches[1];
6249 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
6250 $mark_percentage = $matches[1];
6251 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
6252 $mark_passed = $matches[1];
6253 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
6254 }
6255 }
6256 // handle the import of media objects in XHTML code
6257 if (is_array($_SESSION["import_mob_xhtml"]))
6258 {
6259 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6260 include_once "./Services/RTE/classes/class.ilRTE.php";
6261 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
6262 foreach ($_SESSION["import_mob_xhtml"] as $mob)
6263 {
6264 $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
6265 if (file_exists($importfile))
6266 {
6267 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
6268 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
6269 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
6270 $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
6271 }
6272 else
6273 {
6274 global $ilLog;
6275 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
6276 }
6277 }
6278 $this->saveToDb();
6279 }
6280 }
6281
6287 public function toXML()
6288 {
6289 include_once("./Services/Xml/classes/class.ilXmlWriter.php");
6290 $a_xml_writer = new ilXmlWriter;
6291 // set xml header
6292 $a_xml_writer->xmlHeader();
6293 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
6294 $a_xml_writer->xmlStartTag("questestinterop");
6295
6296 $attrs = array(
6297 "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
6298 "title" => $this->getTitle()
6299 );
6300 $a_xml_writer->xmlStartTag("assessment", $attrs);
6301 // add qti comment
6302 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
6303
6304 // add qti duration
6305 if ($this->enable_processing_time)
6306 {
6307 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
6308 $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
6309 }
6310
6311 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
6312 $a_xml_writer->xmlStartTag("qtimetadata");
6313 $a_xml_writer->xmlStartTag("qtimetadatafield");
6314 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
6315 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
6316 $a_xml_writer->xmlEndTag("qtimetadatafield");
6317
6318 // anonymity
6319 $a_xml_writer->xmlStartTag("qtimetadatafield");
6320 $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
6321 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
6322 $a_xml_writer->xmlEndTag("qtimetadatafield");
6323
6324 // question set type (fixed, random, dynamic, ...)
6325 $a_xml_writer->xmlStartTag("qtimetadatafield");
6326 $a_xml_writer->xmlElement("fieldlabel", NULL, "question_set_type");
6327 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getQuestionSetType());
6328 $a_xml_writer->xmlEndTag("qtimetadatafield");
6329
6330 // sequence settings
6331 $a_xml_writer->xmlStartTag("qtimetadatafield");
6332 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
6333 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
6334 $a_xml_writer->xmlEndTag("qtimetadatafield");
6335
6336 // author
6337 $a_xml_writer->xmlStartTag("qtimetadatafield");
6338 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
6339 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
6340 $a_xml_writer->xmlEndTag("qtimetadatafield");
6341
6342 // reset processing time
6343 $a_xml_writer->xmlStartTag("qtimetadatafield");
6344 $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
6345 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
6346 $a_xml_writer->xmlEndTag("qtimetadatafield");
6347
6348 // count system
6349 $a_xml_writer->xmlStartTag("qtimetadatafield");
6350 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
6351 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
6352 $a_xml_writer->xmlEndTag("qtimetadatafield");
6353
6354 // multiple choice scoring
6355 $a_xml_writer->xmlStartTag("qtimetadatafield");
6356 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
6357 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
6358 $a_xml_writer->xmlEndTag("qtimetadatafield");
6359
6360 // multiple choice scoring
6361 $a_xml_writer->xmlStartTag("qtimetadatafield");
6362 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
6363 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
6364 $a_xml_writer->xmlEndTag("qtimetadatafield");
6365
6366 // multiple choice scoring
6367 $a_xml_writer->xmlStartTag("qtimetadatafield");
6368 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
6369 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
6370 $a_xml_writer->xmlEndTag("qtimetadatafield");
6371
6372 // allowed users
6373 $a_xml_writer->xmlStartTag("qtimetadatafield");
6374 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
6375 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
6376 $a_xml_writer->xmlEndTag("qtimetadatafield");
6377
6378 // allowed users time gap
6379 $a_xml_writer->xmlStartTag("qtimetadatafield");
6380 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
6381 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
6382 $a_xml_writer->xmlEndTag("qtimetadatafield");
6383
6384 // pass scoring
6385 $a_xml_writer->xmlStartTag("qtimetadatafield");
6386 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
6387 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
6388 $a_xml_writer->xmlEndTag("qtimetadatafield");
6389
6390 // score reporting date
6391 if ($this->getReportingDate())
6392 {
6393 $a_xml_writer->xmlStartTag("qtimetadatafield");
6394 $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
6395 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6396 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6397 $a_xml_writer->xmlEndTag("qtimetadatafield");
6398 }
6399 // number of tries
6400 $a_xml_writer->xmlStartTag("qtimetadatafield");
6401 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
6402 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
6403 $a_xml_writer->xmlEndTag("qtimetadatafield");
6404
6405 // kiosk
6406 $a_xml_writer->xmlStartTag("qtimetadatafield");
6407 $a_xml_writer->xmlElement("fieldlabel", NULL, "kiosk");
6408 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getKiosk()));
6409 $a_xml_writer->xmlEndTag("qtimetadatafield");
6410
6411
6412 //redirection_mode
6413 $a_xml_writer->xmlStartTag('qtimetadatafield');
6414 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_mode");
6415 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionMode());
6416 $a_xml_writer->xmlEndTag("qtimetadatafield");
6417
6418 //redirection_url
6419 $a_xml_writer->xmlStartTag('qtimetadatafield');
6420 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_url");
6421 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionUrl());
6422 $a_xml_writer->xmlEndTag("qtimetadatafield");
6423
6424 // use previous answers
6425 $a_xml_writer->xmlStartTag("qtimetadatafield");
6426 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
6427 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
6428 $a_xml_writer->xmlEndTag("qtimetadatafield");
6429
6430 // hide title points
6431 $a_xml_writer->xmlStartTag("qtimetadatafield");
6432 $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
6433 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
6434 $a_xml_writer->xmlEndTag("qtimetadatafield");
6435
6436 // results presentation
6437 $a_xml_writer->xmlStartTag("qtimetadatafield");
6438 $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
6439 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
6440 $a_xml_writer->xmlEndTag("qtimetadatafield");
6441
6442 // examid in test pass
6443 $a_xml_writer->xmlStartTag("qtimetadatafield");
6444 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_pass");
6445 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6446 $a_xml_writer->xmlEndTag("qtimetadatafield");
6447
6448 // examid in kiosk
6449 $a_xml_writer->xmlStartTag("qtimetadatafield");
6450 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_res");
6451 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6452 $a_xml_writer->xmlEndTag("qtimetadatafield");
6453
6454 // solution details
6455 $a_xml_writer->xmlStartTag("qtimetadatafield");
6456 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
6457 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
6458 $a_xml_writer->xmlEndTag("qtimetadatafield");
6459
6460 // solution details
6461 $a_xml_writer->xmlStartTag("qtimetadatafield");
6462 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
6463 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
6464 $a_xml_writer->xmlEndTag("qtimetadatafield");
6465
6466 $a_xml_writer->xmlStartTag("qtimetadatafield");
6467 $a_xml_writer->xmlElement("fieldlabel", NULL, "solution_details");
6468 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails());
6469 $a_xml_writer->xmlEndTag("qtimetadatafield");
6470 $a_xml_writer->xmlStartTag("qtimetadatafield");
6471 $a_xml_writer->xmlElement("fieldlabel", NULL, "print_bs_with_res");
6472 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails() ? (int)$this->isBestSolutionPrintedWithResult() : 0);
6473 $a_xml_writer->xmlEndTag("qtimetadatafield");
6474
6475 // solution details
6476 $a_xml_writer->xmlStartTag("qtimetadatafield");
6477 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
6478 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
6479 $a_xml_writer->xmlEndTag("qtimetadatafield");
6480
6481 // answer specific feedback
6482 $a_xml_writer->xmlStartTag("qtimetadatafield");
6483 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
6484 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
6485 $a_xml_writer->xmlEndTag("qtimetadatafield");
6486
6487 // answer specific feedback of reached points
6488 $a_xml_writer->xmlStartTag("qtimetadatafield");
6489 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
6490 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
6491 $a_xml_writer->xmlEndTag("qtimetadatafield");
6492
6493 // highscore
6494 $highscore_metadata = array(
6495 'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6496 'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6497 'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6498 'highscore_score' => array('value' => $this->getHighscoreScore()),
6499 'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6500 'highscore_hints' => array('value' => $this->getHighscoreHints()),
6501 'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6502 'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6503 'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6504 'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6505 );
6506 foreach($highscore_metadata as $label => $data)
6507 {
6508 $a_xml_writer->xmlStartTag("qtimetadatafield");
6509 $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
6510 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $data['value']));
6511 $a_xml_writer->xmlEndTag("qtimetadatafield");
6512 }
6513
6514 // show cancel
6515 $a_xml_writer->xmlStartTag("qtimetadatafield");
6516 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
6517 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
6518 $a_xml_writer->xmlEndTag("qtimetadatafield");
6519
6520 // show marker
6521 $a_xml_writer->xmlStartTag("qtimetadatafield");
6522 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
6523 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
6524 $a_xml_writer->xmlEndTag("qtimetadatafield");
6525
6526 // fixed participants
6527 $a_xml_writer->xmlStartTag("qtimetadatafield");
6528 $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
6529 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
6530 $a_xml_writer->xmlEndTag("qtimetadatafield");
6531
6532 // show final statement
6533 $a_xml_writer->xmlStartTag("qtimetadatafield");
6534 $a_xml_writer->xmlElement("fieldlabel", NULL, "showfinalstatement");
6535 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6536 $a_xml_writer->xmlEndTag("qtimetadatafield");
6537
6538 // show introduction only
6539 $a_xml_writer->xmlStartTag("qtimetadatafield");
6540 $a_xml_writer->xmlElement("fieldlabel", NULL, "showinfo");
6541 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6542 $a_xml_writer->xmlEndTag("qtimetadatafield");
6543
6544 // mail notification
6545 $a_xml_writer->xmlStartTag("qtimetadatafield");
6546 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnotification");
6547 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotification());
6548 $a_xml_writer->xmlEndTag("qtimetadatafield");
6549
6550 // mail notification type
6551 $a_xml_writer->xmlStartTag("qtimetadatafield");
6552 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnottype");
6553 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotificationType());
6554 $a_xml_writer->xmlEndTag("qtimetadatafield");
6555
6556 // export settings
6557 $a_xml_writer->xmlStartTag("qtimetadatafield");
6558 $a_xml_writer->xmlElement("fieldlabel", NULL, "exportsettings");
6559 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getExportSettings());
6560 $a_xml_writer->xmlEndTag("qtimetadatafield");
6561
6562 // force JavaScript
6563 $a_xml_writer->xmlStartTag("qtimetadatafield");
6564 $a_xml_writer->xmlElement("fieldlabel", NULL, "forcejs");
6565 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6566 $a_xml_writer->xmlEndTag("qtimetadatafield");
6567
6568 // custom style
6569 $a_xml_writer->xmlStartTag("qtimetadatafield");
6570 $a_xml_writer->xmlElement("fieldlabel", NULL, "customstyle");
6571 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCustomStyle());
6572 $a_xml_writer->xmlEndTag("qtimetadatafield");
6573
6574 // shuffle questions
6575 $a_xml_writer->xmlStartTag("qtimetadatafield");
6576 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
6577 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
6578 $a_xml_writer->xmlEndTag("qtimetadatafield");
6579
6580 // processing time
6581 $a_xml_writer->xmlStartTag("qtimetadatafield");
6582 $a_xml_writer->xmlElement("fieldlabel", NULL, "processing_time");
6583 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getProcessingTime());
6584 $a_xml_writer->xmlEndTag("qtimetadatafield");
6585
6586 // enable_examview
6587 $a_xml_writer->xmlStartTag("qtimetadatafield");
6588 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_examview");
6589 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableExamview());
6590 $a_xml_writer->xmlEndTag("qtimetadatafield");
6591
6592 // show_examview_html
6593 $a_xml_writer->xmlStartTag("qtimetadatafield");
6594 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_html");
6595 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewHtml());
6596 $a_xml_writer->xmlEndTag("qtimetadatafield");
6597
6598 // show_examview_pdf
6599 $a_xml_writer->xmlStartTag("qtimetadatafield");
6600 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_pdf");
6601 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewPdf());
6602 $a_xml_writer->xmlEndTag("qtimetadatafield");
6603
6604 // enable_archiving
6605 $a_xml_writer->xmlStartTag("qtimetadatafield");
6606 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_archiving");
6607 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableArchiving());
6608 $a_xml_writer->xmlEndTag("qtimetadatafield");
6609
6610 // sign_submission
6611 $a_xml_writer->xmlStartTag("qtimetadatafield");
6612 $a_xml_writer->xmlElement("fieldlabel", NULL, "sign_submission");
6613 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSignSubmission());
6614 $a_xml_writer->xmlEndTag("qtimetadatafield");
6615
6616 // char_selector_availability
6617 $a_xml_writer->xmlStartTag("qtimetadatafield");
6618 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_availability");
6619 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getCharSelectorAvailability()));
6620 $a_xml_writer->xmlEndTag("qtimetadatafield");
6621
6622 // char_selector_definition
6623 $a_xml_writer->xmlStartTag("qtimetadatafield");
6624 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_definition");
6625 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCharSelectorDefinition());
6626 $a_xml_writer->xmlEndTag("qtimetadatafield");
6627
6628 // skill_service
6629 $a_xml_writer->xmlStartTag("qtimetadatafield");
6630 $a_xml_writer->xmlElement("fieldlabel", NULL, "skill_service");
6631 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isSkillServiceEnabled());
6632 $a_xml_writer->xmlEndTag("qtimetadatafield");
6633
6634 // result_tax_filters
6635 $a_xml_writer->xmlStartTag("qtimetadatafield");
6636 $a_xml_writer->xmlElement("fieldlabel", NULL, "result_tax_filters");
6637 $a_xml_writer->xmlElement("fieldentry", NULL, serialize((array)$this->getResultFilterTaxIds()));
6638 $a_xml_writer->xmlEndTag("qtimetadatafield");
6639
6640 // show_grading_status
6641 $a_xml_writer->xmlStartTag("qtimetadatafield");
6642 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_status");
6643 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingStatusEnabled());
6644 $a_xml_writer->xmlEndTag("qtimetadatafield");
6645
6646 // show_grading_mark
6647 $a_xml_writer->xmlStartTag("qtimetadatafield");
6648 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_mark");
6649 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingMarkEnabled());
6650 $a_xml_writer->xmlEndTag("qtimetadatafield");
6651
6652
6653 // starting time
6654 if ($this->getStartingTime())
6655 {
6656 $a_xml_writer->xmlStartTag("qtimetadatafield");
6657 $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
6658 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
6659 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6660 $a_xml_writer->xmlEndTag("qtimetadatafield");
6661 }
6662 // ending time
6663 if ($this->getEndingTime())
6664 {
6665 $a_xml_writer->xmlStartTag("qtimetadatafield");
6666 $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
6667 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
6668 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6669 $a_xml_writer->xmlEndTag("qtimetadatafield");
6670 }
6671
6672
6673 //activation_limited
6674 $a_xml_writer->xmlStartTag("qtimetadatafield");
6675 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_limited");
6676 $a_xml_writer->xmlElement("fieldentry", NULL,(int)$this->isActivationLimited());
6677 $a_xml_writer->xmlEndTag("qtimetadatafield");
6678
6679 //activation_start_time
6680 $a_xml_writer->xmlStartTag("qtimetadatafield");
6681 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_start_time");
6682 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationStartingTime());
6683 $a_xml_writer->xmlEndTag("qtimetadatafield");
6684
6685 //activation_end_time
6686 $a_xml_writer->xmlStartTag("qtimetadatafield");
6687 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_end_time");
6688 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationEndingTime());
6689 $a_xml_writer->xmlEndTag("qtimetadatafield");
6690
6691 //activation_visibility
6692 $a_xml_writer->xmlStartTag("qtimetadatafield");
6693 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_visibility");
6694 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationVisibility());
6695 $a_xml_writer->xmlEndTag("qtimetadatafield");
6696
6697 // autosave
6698 $a_xml_writer->xmlStartTag("qtimetadatafield");
6699 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave");
6700 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosave());
6701 $a_xml_writer->xmlEndTag("qtimetadatafield");
6702
6703 // autosave_ival
6704 $a_xml_writer->xmlStartTag("qtimetadatafield");
6705 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave_ival");
6706 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosaveIval());
6707 $a_xml_writer->xmlEndTag("qtimetadatafield");
6708
6709 //offer_question_hints
6710 $a_xml_writer->xmlStartTag("qtimetadatafield");
6711 $a_xml_writer->xmlElement("fieldlabel", NULL, "offer_question_hints");
6712 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isOfferingQuestionHintsEnabled());
6713 $a_xml_writer->xmlEndTag("qtimetadatafield");
6714
6715 //instant_feedback_specific
6716 $a_xml_writer->xmlStartTag("qtimetadatafield");
6717 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_specific");
6718 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSpecificAnswerFeedback());
6719 $a_xml_writer->xmlEndTag("qtimetadatafield");
6720
6721 //instant_feedback_answer_fixation
6722 $a_xml_writer->xmlStartTag("qtimetadatafield");
6723 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6724 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6725 $a_xml_writer->xmlEndTag("qtimetadatafield");
6726
6727 //obligations_enabled
6728 $a_xml_writer->xmlStartTag("qtimetadatafield");
6729 $a_xml_writer->xmlElement("fieldlabel", NULL, "obligations_enabled");
6730 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->areObligationsEnabled());
6731 $a_xml_writer->xmlEndTag("qtimetadatafield");
6732
6733 //enable_processing_time
6734 $a_xml_writer->xmlStartTag("qtimetadatafield");
6735 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_processing_time");
6736 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableProcessingTime());
6737 $a_xml_writer->xmlEndTag("qtimetadatafield");
6738
6739 foreach ($this->mark_schema->mark_steps as $index => $mark)
6740 {
6741 // mark steps
6742 $a_xml_writer->xmlStartTag("qtimetadatafield");
6743 $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
6744 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf(
6745 "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6746 $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()
6747 ));
6748 $a_xml_writer->xmlEndTag("qtimetadatafield");
6749 }
6750 $a_xml_writer->xmlEndTag("qtimetadata");
6751
6752 // add qti objectives
6753 $a_xml_writer->xmlStartTag("objectives");
6754 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6755 $a_xml_writer->xmlEndTag("objectives");
6756
6757 // add qti assessmentcontrol
6758 if ($this->getInstantFeedbackSolution() == 1)
6759 {
6760 $attrs = array(
6761 "solutionswitch" => "Yes"
6762 );
6763 }
6764 else
6765 {
6766 $attrs = NULL;
6767 }
6768 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
6769
6770 if (strlen($this->getFinalStatement()))
6771 {
6772 // add qti presentation_material
6773 $a_xml_writer->xmlStartTag("presentation_material");
6774 $a_xml_writer->xmlStartTag("flow_mat");
6775 $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6776 $a_xml_writer->xmlEndTag("flow_mat");
6777 $a_xml_writer->xmlEndTag("presentation_material");
6778 }
6779
6780 $attrs = array(
6781 "ident" => "1"
6782 );
6783 $a_xml_writer->xmlElement("section", $attrs, NULL);
6784 $a_xml_writer->xmlEndTag("assessment");
6785 $a_xml_writer->xmlEndTag("questestinterop");
6786
6787 $xml = $a_xml_writer->xmlDumpMem(FALSE);
6788
6789 foreach ($this->questions as $question_id)
6790 {
6791 $question =& ilObjTest::_instanciateQuestion($question_id);
6792 $qti_question = $question->toXML(false);
6793 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
6794 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
6795 if (strpos($xml, "</section>") !== false)
6796 {
6797 $xml = str_replace("</section>", "$qti_question</section>", $xml);
6798 }
6799 else
6800 {
6801 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
6802 }
6803 }
6804 return $xml;
6805 }
6806
6813 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6814 {
6815 global $ilBench;
6816
6817 $this->mob_ids = array();
6818 $this->file_ids = array();
6819
6820 $attrs = array();
6821 $attrs["Type"] = "Test";
6822 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
6823
6824 // MetaData
6825 $this->exportXMLMetaData($a_xml_writer);
6826
6827 // PageObjects
6828 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
6829 $ilBench->start("ContentObjectExport", "exportPageObjects");
6830 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6831 $ilBench->stop("ContentObjectExport", "exportPageObjects");
6832 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
6833
6834 // MediaObjects
6835 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
6836 $ilBench->start("ContentObjectExport", "exportMediaObjects");
6837 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6838 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6839 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
6840
6841 // FileItems
6842 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
6843 $ilBench->start("ContentObjectExport", "exportFileItems");
6844 $this->exportFileItems($a_target_dir, $expLog);
6845 $ilBench->stop("ContentObjectExport", "exportFileItems");
6846 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
6847
6848 $a_xml_writer->xmlEndTag("ContentObject");
6849 }
6850
6857 function exportXMLMetaData(&$a_xml_writer)
6858 {
6859 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6860 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6861 $md2xml->setExportMode(true);
6862 $md2xml->startExport();
6863 $a_xml_writer->appendXML($md2xml->getXML());
6864 }
6865
6871 function modifyExportIdentifier($a_tag, $a_param, $a_value)
6872 {
6873 if ($a_tag == "Identifier" && $a_param == "Entry")
6874 {
6875 include_once "./Services/Utilities/classes/class.ilUtil.php";
6876 $a_value = ilUtil::insertInstIntoID($a_value);
6877 }
6878
6879 return $a_value;
6880 }
6881
6882
6889 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6890 {
6891 global $ilBench;
6892
6893 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6894
6895 foreach ($this->questions as $question_id)
6896 {
6897 $ilBench->start("ContentObjectExport", "exportPageObject");
6898 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
6899
6900 $attrs = array();
6901 $a_xml_writer->xmlStartTag("PageObject", $attrs);
6902
6903
6904 // export xml to writer object
6905 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6906 include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6907 $page_object = new ilAssQuestionPage($question_id);
6908 $page_object->buildDom();
6909 $page_object->insertInstIntoIDs($a_inst);
6910 $mob_ids = $page_object->collectMediaObjects(false);
6911 require_once 'Services/COPage/classes/class.ilPCFileList.php';
6912 $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6913 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6914 $xml = str_replace("&","&amp;", $xml);
6915 $a_xml_writer->appendXML($xml);
6916 $page_object->freeDom();
6917 unset ($page_object);
6918
6919 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6920
6921 // collect media objects
6922 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6923 //$mob_ids = $page_obj->getMediaObjectIDs();
6924 foreach($mob_ids as $mob_id)
6925 {
6926 $this->mob_ids[$mob_id] = $mob_id;
6927 }
6928 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6929
6930 // collect all file items
6931 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6932 //$file_ids = $page_obj->getFileItemIds();
6933 foreach($file_ids as $file_id)
6934 {
6935 $this->file_ids[$file_id] = $file_id;
6936 }
6937 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6938
6939 $a_xml_writer->xmlEndTag("PageObject");
6940 //unset($page_obj);
6941
6942 $ilBench->stop("ContentObjectExport", "exportPageObject");
6943
6944
6945 }
6946 }
6947
6954 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6955 {
6956 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6957
6958 foreach ($this->mob_ids as $mob_id)
6959 {
6960 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
6961 if (ilObjMediaObject::_exists($mob_id))
6962 {
6963 $media_obj = new ilObjMediaObject($mob_id);
6964 $media_obj->exportXML($a_xml_writer, $a_inst);
6965 $media_obj->exportFiles($a_target_dir);
6966 unset($media_obj);
6967 }
6968 }
6969 }
6970
6975 function exportFileItems($a_target_dir, &$expLog)
6976 {
6977 include_once "./Modules/File/classes/class.ilObjFile.php";
6978
6979 foreach ($this->file_ids as $file_id)
6980 {
6981 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
6982 $file_obj = new ilObjFile($file_id, false);
6983 $file_obj->export($a_target_dir);
6984 unset($file_obj);
6985 }
6986 }
6987
6993 {
6994 if (!is_array($this->import_mapping))
6995 {
6996 return array();
6997 }
6998 else
6999 {
7000 return $this->import_mapping;
7001 }
7002 }
7003
7007 public function canEditEctsGrades()
7008 {
7009 return $this->getReportingDate();
7010 }
7011
7015 public function getECTSGrade($passed_array, $reached_points, $max_points)
7016 {
7017 return self::_getECTSGrade($passed_array, $reached_points, $max_points, $this->ects_grades["A"], $this->ects_grades["B"], $this->ects_grades["C"], $this->ects_grades["D"], $this->ects_grades["E"], $this->ects_fx);
7018 }
7019
7023 public static function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
7024 {
7025 include_once "./Modules/Test/classes/class.ilStatistics.php";
7026 // calculate the median
7027 $passed_statistics = new ilStatistics();
7028 $passed_statistics->setData($points_passed);
7029 $ects_percentiles = array
7030 (
7031 "A" => $passed_statistics->quantile($a),
7032 "B" => $passed_statistics->quantile($b),
7033 "C" => $passed_statistics->quantile($c),
7034 "D" => $passed_statistics->quantile($d),
7035 "E" => $passed_statistics->quantile($e)
7036 );
7037 if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
7038 {
7039 return "A";
7040 }
7041 else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
7042 {
7043 return "B";
7044 }
7045 else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
7046 {
7047 return "C";
7048 }
7049 else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
7050 {
7051 return "D";
7052 }
7053 else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
7054 {
7055 return "E";
7056 }
7057 else if (strcmp($fx, "") != 0)
7058 {
7059 if ($max_points > 0)
7060 {
7061 $percentage = ($reached_points / $max_points) * 100.0;
7062 if ($percentage < 0) $percentage = 0.0;
7063 }
7064 else
7065 {
7066 $percentage = 0.0;
7067 }
7068 if ($percentage >= $fx)
7069 {
7070 return "FX";
7071 }
7072 else
7073 {
7074 return "F";
7075 }
7076 }
7077 else
7078 {
7079 return "F";
7080 }
7081 }
7082
7086 public function checkMarks()
7087 {
7088 return $this->mark_schema->checkMarks();
7089 }
7090
7094 public function getMarkSchema()
7095 {
7096 return $this->mark_schema;
7097 }
7098
7102 public function getMarkSchemaForeignId()
7103 {
7104 return $this->getTestId();
7105 }
7106
7109 public function onMarkSchemaSaved()
7110 {
7116 global $ilDB, $ilPluginAdmin, $tree;
7117
7118 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7119 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7120 $this->saveCompleteStatus($testQuestionSetConfigFactory->getQuestionSetConfig());
7121
7122 if( $this->participantDataExist() )
7123 {
7124 $this->recalculateScores(true);
7125 }
7126 }
7127
7131 public function canEditMarks()
7132 {
7133 $total = $this->evalTotalPersons();
7134 if($total > 0)
7135 {
7136 if($this->getReportingDate())
7137 {
7138 if(preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
7139 {
7140 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
7141 $now = mktime();
7142 if($now < $epoch_time)
7143 {
7144 return true;
7145 }
7146 }
7147 }
7148 return false;
7149 }
7150 else
7151 {
7152 return true;
7153 }
7154 }
7155
7163 function setAuthor($author = "")
7164 {
7165 $this->author = $author;
7166 }
7167
7177 function saveAuthorToMetadata($a_author = "")
7178 {
7179 $md =& new ilMD($this->getId(), 0, $this->getType());
7180 $md_life =& $md->getLifecycle();
7181 if (!$md_life)
7182 {
7183 if (strlen($a_author) == 0)
7184 {
7185 global $ilUser;
7186 $a_author = $ilUser->getFullname();
7187 }
7188
7189 $md_life =& $md->addLifecycle();
7190 $md_life->save();
7191 $con =& $md_life->addContribute();
7192 $con->setRole("Author");
7193 $con->save();
7194 $ent =& $con->addEntity();
7195 $ent->setEntity($a_author);
7196 $ent->save();
7197 }
7198 }
7199
7206 {
7207 parent::createMetaData();
7208 $this->saveAuthorToMetadata();
7209 }
7210
7218 function getAuthor()
7219 {
7220 $author = array();
7221 include_once "./Services/MetaData/classes/class.ilMD.php";
7222 $md =& new ilMD($this->getId(), 0, $this->getType());
7223 $md_life =& $md->getLifecycle();
7224 if ($md_life)
7225 {
7226 $ids =& $md_life->getContributeIds();
7227 foreach ($ids as $id)
7228 {
7229 $md_cont =& $md_life->getContribute($id);
7230 if (strcmp($md_cont->getRole(), "Author") == 0)
7231 {
7232 $entids =& $md_cont->getEntityIds();
7233 foreach ($entids as $entid)
7234 {
7235 $md_ent =& $md_cont->getEntity($entid);
7236 array_push($author, $md_ent->getEntity());
7237 }
7238 }
7239 }
7240 }
7241 return join($author, ",");
7242 }
7243
7251 function _lookupAuthor($obj_id)
7252 {
7253 $author = array();
7254 include_once "./Services/MetaData/classes/class.ilMD.php";
7255 $md =& new ilMD($obj_id, 0, "tst");
7256 $md_life =& $md->getLifecycle();
7257 if ($md_life)
7258 {
7259 $ids =& $md_life->getContributeIds();
7260 foreach ($ids as $id)
7261 {
7262 $md_cont =& $md_life->getContribute($id);
7263 if (strcmp($md_cont->getRole(), "Author") == 0)
7264 {
7265 $entids =& $md_cont->getEntityIds();
7266 foreach ($entids as $entid)
7267 {
7268 $md_ent =& $md_cont->getEntity($entid);
7269 array_push($author, $md_ent->getEntity());
7270 }
7271 }
7272 }
7273 }
7274 return join($author, ",");
7275 }
7276
7283 function &_getAvailableTests($use_object_id = FALSE)
7284 {
7285 global $ilUser;
7286 global $ilDB;
7287
7288 $result_array = array();
7289 $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
7290 if (count($tests))
7291 {
7292 $titles = ilObject::_prepareCloneSelection($tests, "tst");
7293 foreach ($tests as $ref_id)
7294 {
7295 if ($use_object_id)
7296 {
7298 $result_array[$obj_id] = $titles[$ref_id];
7299 }
7300 else
7301 {
7302 $result_array[$ref_id] = $titles[$ref_id];
7303 }
7304 }
7305 }
7306 return $result_array;
7307 }
7308
7317 public function cloneObject($a_target_id,$a_copy_id = 0)
7318 {
7319 global $ilLog, $tree, $ilDB, $ilPluginAdmin;
7320
7321 $this->loadFromDb();
7322
7323 // Copy settings
7325 $newObj = parent::cloneObject($a_target_id,$a_copy_id);
7326 $this->cloneMetaData($newObj);
7327
7328 //copy online status if object is not the root copy object
7329 $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
7330
7331 if(!$cp_options->isRootNode($this->getRefId()))
7332 {
7333 $newObj->setOnline($this->isOnline());
7334 }
7335
7336 $newObj->setAnonymity($this->getAnonymity());
7337 $newObj->setAnswerFeedback($this->getAnswerFeedback());
7338 $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
7339 $newObj->setAuthor($this->getAuthor());
7340 $newObj->setLimitUsersEnabled($this->isLimitUsersEnabled());
7341 $newObj->setAllowedUsers($this->getAllowedUsers());
7342 $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
7343 $newObj->setCountSystem($this->getCountSystem());
7344 $newObj->setECTSFX($this->getECTSFX());
7345 $newObj->setECTSGrades($this->getECTSGrades());
7346 $newObj->setECTSOutput($this->getECTSOutput());
7347 $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
7348 $newObj->setEndingTimeEnabled($this->isEndingTimeEnabled());
7349 $newObj->setEndingTime($this->getEndingTime());
7350 $newObj->setFixedParticipants($this->getFixedParticipants());
7351 $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
7352 $newObj->setIntroductionEnabled($this->isIntroductionEnabled());
7353 $newObj->setIntroduction($this->getIntroduction());
7354 $newObj->setFinalStatement($this->getFinalStatement());
7355 $newObj->setShowInfo($this->getShowInfo());
7356 $newObj->setForceJS($this->getForceJS());
7357 $newObj->setCustomStyle($this->getCustomStyle());
7358 $newObj->setKiosk($this->getKiosk());
7359 $newObj->setShowFinalStatement($this->getShowFinalStatement());
7360 $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
7361 $newObj->setMCScoring($this->getMCScoring());
7362 $newObj->setMailNotification($this->getMailNotification());
7363 $newObj->setMailNotificationType($this->getMailNotificationType());
7364 $newObj->setNrOfTries($this->getNrOfTries());
7365 $newObj->setPassScoring($this->getPassScoring());
7366 $newObj->setPasswordEnabled($this->isPasswordEnabled());
7367 $newObj->setPassword($this->getPassword());
7368 $newObj->setProcessingTime($this->getProcessingTime());
7369 $newObj->setQuestionSetType($this->getQuestionSetType());
7370 $newObj->setReportingDate($this->getReportingDate());
7371 $newObj->setResetProcessingTime($this->getResetProcessingTime());
7372 $newObj->setResultsPresentation($this->getResultsPresentation());
7373 $newObj->setScoreCutting($this->getScoreCutting());
7374 $newObj->setScoreReporting($this->getScoreReporting());
7375 $newObj->setSequenceSettings($this->getSequenceSettings());
7376 $newObj->setShowCancel($this->getShowCancel());
7377 $newObj->setShowMarker($this->getShowMarker());
7378 $newObj->setShuffleQuestions($this->getShuffleQuestions());
7379 $newObj->setStartingTimeEnabled($this->isStartingTimeEnabled());
7380 $newObj->setStartingTime($this->getStartingTime());
7381 $newObj->setTitleOutput($this->getTitleOutput());
7382 $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
7383 $newObj->setRedirectionMode($this->getRedirectionMode());
7384 $newObj->setRedirectionUrl($this->getRedirectionUrl());
7385 $newObj->setCertificateVisibility($this->getCertificateVisibility());
7386 $newObj->mark_schema = clone $this->mark_schema;
7387 $newObj->setEnabledViewMode($this->getEnabledViewMode());
7388 $newObj->setTemplate($this->getTemplate());
7389 $newObj->setPoolUsage($this->getPoolUsage());
7390 $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
7391 $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
7392 $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
7393 $newObj->setEnableExamView($this->getEnableExamview());
7394 $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7395 $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7396 $newObj->setEnableArchiving($this->getEnableArchiving());
7397 $newObj->setSignSubmission($this->getSignSubmission());
7398 $newObj->setCharSelectorAvailability((int)$this->getCharSelectorAvailability());
7399 $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7400 $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
7401 $newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
7402 $newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
7403 $newObj->saveToDb();
7404
7405 // clone certificate
7406 include_once "./Services/Certificate/classes/class.ilCertificate.php";
7407 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7408 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7409 $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7410 $cert->cloneCertificate($newcert);
7411
7412 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7413 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7414 $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7415
7416 $newObj->saveToDb();
7417 $newObj->updateMetaData();// #14467
7418
7419 include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
7420 $obj_settings = new ilLPObjSettings($this->getId());
7421 $obj_settings->cloneSettings($newObj->getId());
7422
7423 return $newObj;
7424 }
7425
7433 {
7434 $num = 0;
7435
7436 if( $this->isRandomTest() )
7437 {
7438 global $tree, $ilDB, $ilPluginAdmin;
7439
7440 $questionSetConfig = new ilTestRandomQuestionSetConfig(
7441 $tree, $ilDB, $ilPluginAdmin, $this
7442 );
7443
7444 $questionSetConfig->loadFromDb();
7445
7446 if( $questionSetConfig->isQuestionAmountConfigurationModePerPool() )
7447 {
7448 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7449 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7450 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7451
7452 $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList(
7454 );
7455
7456 $sourcePoolDefinitionList->loadDefinitions();
7457
7458 $num = $sourcePoolDefinitionList->getQuestionAmount();
7459 }
7460 else
7461 {
7462 $num = $questionSetConfig->getQuestionAmountPerTest();
7463 }
7464 }
7465 else
7466 {
7467 $num = count($this->questions);
7468 }
7469
7470 return $num;
7471 }
7472
7480 function logAction($logtext = "", $question_id = "")
7481 {
7482 global $ilUser;
7483
7484 $original_id = "";
7485 if (strcmp($question_id, "") != 0)
7486 {
7487 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7488 $original_id = assQuestion::_getOriginalId($question_id);
7489 }
7490 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7491 ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
7492 }
7493
7502 {
7503 global $ilDB;
7504 $object_id = FALSE;
7505 $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7506 array('integer'),
7507 array($test_id)
7508 );
7509 if ($result->numRows())
7510 {
7511 $row = $ilDB->fetchAssoc($result);
7512 $object_id = $row["obj_fi"];
7513 }
7514 return $object_id;
7515 }
7516
7524 function _getObjectIDFromActiveID($active_id)
7525 {
7526 global $ilDB;
7527 $object_id = FALSE;
7528 $result = $ilDB->queryF("SELECT tst_tests.obj_fi FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
7529 array('integer'),
7530 array($active_id)
7531 );
7532 if ($result->numRows())
7533 {
7534 $row = $ilDB->fetchAssoc($result);
7535 $object_id = $row["obj_fi"];
7536 }
7537 return $object_id;
7538 }
7539
7547 function _getTestIDFromObjectID($object_id)
7548 {
7549 global $ilDB;
7550 $test_id = FALSE;
7551 $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7552 array('integer'),
7553 array($object_id)
7554 );
7555 if ($result->numRows())
7556 {
7557 $row = $ilDB->fetchAssoc($result);
7558 $test_id = $row["test_id"];
7559 }
7560 return $test_id;
7561 }
7562
7571 function getTextAnswer($active_id, $question_id, $pass = NULL)
7572 {
7573 global $ilDB;
7574
7575 $res = "";
7576 if (($active_id) && ($question_id))
7577 {
7578 if (is_null($pass))
7579 {
7580 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7581 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7582 }
7583 $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7584 array('integer', 'integer', 'integer'),
7585 array($active_id, $question_id, $pass)
7586 );
7587 if ($result->numRows() == 1)
7588 {
7589 $row = $ilDB->fetchAssoc($result);
7590 $res = $row["value1"];
7591 }
7592 }
7593 return $res;
7594 }
7595
7603 function getQuestiontext($question_id)
7604 {
7605 global $ilDB;
7606
7607 $res = "";
7608 if ($question_id)
7609 {
7610 $result = $ilDB->queryF("SELECT question_text FROM qpl_questions WHERE question_id = %s",
7611 array('integer'),
7612 array($question_id)
7613 );
7614 if ($result->numRows() == 1)
7615 {
7616 $row = $ilDB->fetchAssoc($result);
7617 $res = $row["question_text"];
7618 }
7619 }
7620 return $res;
7621 }
7622
7629 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7630 {
7631 global $ilDB;
7632
7633 $result_array = array();
7634
7635 if ($this->getAnonymity())
7636 {
7637 if (is_numeric($user_id))
7638 {
7639 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7640 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7641 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7642 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7643 "ORDER BY $order",
7644 array('text', 'text', 'text', 'integer', 'integer'),
7645 array("", $this->lng->txt("anonymous"), "", $this->getTestId(), $user_id)
7646 );
7647 }
7648 else
7649 {
7650 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7651 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7652 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7653 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7654 "ORDER BY $order",
7655 array('text', 'text', 'text', 'integer'),
7656 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7657 );
7658 }
7659 }
7660 else
7661 {
7662 if (is_numeric($user_id))
7663 {
7664 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7665 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7666 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7667 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7668 "ORDER BY $order",
7669 array('integer', 'integer'),
7670 array($this->getTestId(), $user_id)
7671 );
7672 }
7673 else
7674 {
7675 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7676 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7677 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7678 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7679 "ORDER BY $order",
7680 array('integer'),
7681 array($this->getTestId())
7682 );
7683 }
7684 }
7685 $result_array = array();
7686 while ($row = $ilDB->fetchAssoc($result))
7687 {
7688 $result_array[$row['usr_id']]= $row;
7689 }
7690 return $result_array;
7691 }
7692
7700 {
7701 global $ilDB;
7702
7703 if ($this->getAnonymity())
7704 {
7705 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi usr_id, %s login, %s lastname, %s firstname, tst_active.submitted test_finished, usr_data.matriculation, usr_data.active ".
7706 "FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
7707 array('text', 'text', 'text', 'integer'),
7708 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7709 );
7710 }
7711 else
7712 {
7713 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi usr_id, usr_data.login, usr_data.lastname, usr_data.firstname, tst_active.submitted test_finished, usr_data.matriculation, usr_data.active ".
7714 "FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
7715 array('integer'),
7716 array($this->getTestId())
7717 );
7718 }
7719 $data = array();
7720 while ($row = $ilDB->fetchAssoc($result))
7721 {
7722 $data[$row['active_id']] = $row;
7723 }
7724 foreach ($data as $index => $participant)
7725 {
7726 if (strlen(trim($participant["firstname"].$participant["lastname"])) == 0)
7727 {
7728 $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7729 }
7730 }
7731 return $data;
7732 }
7733
7734 public function getTestParticipantsForManualScoring($filter = NULL)
7735 {
7736 global $ilDB;
7737
7738 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7740 if (count($scoring) == 0) return array();
7741
7742 $participants =& $this->getTestParticipants();
7743 $filtered_participants = array();
7744 foreach ($participants as $active_id => $participant)
7745 {
7746 $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7747
7748 $queryString = "
7749 SELECT tst_test_result.manual
7750
7751 FROM tst_test_result
7752
7753 INNER JOIN qpl_questions
7754 ON tst_test_result.question_fi = qpl_questions.question_id
7755
7756 WHERE tst_test_result.active_fi = %s
7757 AND $qstType_IN_manScoreableQstTypes
7758 ";
7759
7760 $result = $ilDB->queryF(
7761 $queryString, array("integer"), array($active_id)
7762 );
7763
7764 $count = $result->numRows();
7765
7766 if ($count > 0)
7767 {
7768 switch ($filter)
7769 {
7770 case 1: // only active users
7771 if ($participant->active) $filtered_participants[$active_id] = $participant;
7772 break;
7773 case 2: // only inactive users
7774 if (!$participant->active) $filtered_participants[$active_id] = $participant;
7775 break;
7776 case 3: // all users
7777 $filtered_participants[$active_id] = $participant;
7778 break;
7779 case 4:
7780 // already scored participants
7781 //$found = 0;
7782 //while ($row = $ilDB->fetchAssoc($result))
7783 //{
7784 // if ($row["manual"]) $found++;
7785 //}
7786 //if ($found == $count)
7787 //{
7788 //$filtered_participants[$active_id] = $participant;
7789 //}
7790 //else
7791 //{
7792 $assessmentSetting = new ilSetting("assessment");
7793 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7794 if ($manscoring_done) $filtered_participants[$active_id] = $participant;
7795 //}
7796 break;
7797 case 5:
7798 // unscored participants
7799 //$found = 0;
7800 //while ($row = $ilDB->fetchAssoc($result))
7801 //{
7802 // if ($row["manual"]) $found++;
7803 //}
7804 //if ($found == 0)
7805 //{
7806 $assessmentSetting = new ilSetting("assessment");
7807 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7808 if (!$manscoring_done) $filtered_participants[$active_id] = $participant;
7809 //}
7810 break;
7811 case 6:
7812 // partially scored participants
7813 $found = 0;
7814 while ($row = $ilDB->fetchAssoc($result))
7815 {
7816 if ($row["manual"]) $found++;
7817 }
7818 if (($found > 0) && ($found < $count)) $filtered_participants[$active_id] = $participant;
7819 break;
7820 default:
7821 $filtered_participants[$active_id] = $participant;
7822 break;
7823 }
7824 }
7825 }
7826 return $filtered_participants;
7827 }
7828
7836 function &getUserData($ids)
7837 {
7838 global $ilDB;
7839
7840 if (!is_array($ids) || count($ids) ==0) return array();
7841
7842 if ($this->getAnonymity())
7843 {
7844 $result = $ilDB->queryF("SELECT usr_id, %s login, %s lastname, %s firstname, client_ip clientip FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login",
7845 array('text', 'text', 'text'),
7846 array("", $this->lng->txt("anonymous"), "")
7847 );
7848 }
7849 else
7850 {
7851 $result = $ilDB->query("SELECT usr_id, login, lastname, firstname, client_ip clientip FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login");
7852 }
7853
7854 $result_array = array();
7855 while ($row = $ilDB->fetchAssoc($result))
7856 {
7857 $result_array[$row["usr_id"]]= $row;
7858 }
7859 return $result_array;
7860 }
7861
7862 function &getGroupData($ids)
7863 {
7864 if (!is_array($ids) || count($ids) ==0) return array();
7865 $result = array();
7866 foreach ($ids as $ref_id)
7867 {
7869 $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7870 }
7871 return $result;
7872 }
7873
7874 function &getRoleData($ids)
7875 {
7876 if (!is_array($ids) || count($ids) ==0) return array();
7877 $result = array();
7878 foreach ($ids as $obj_id)
7879 {
7880 $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7881 }
7882 return $result;
7883 }
7884
7885
7892 function inviteGroup($group_id)
7893 {
7894 include_once "./Modules/Group/classes/class.ilObjGroup.php";
7895 $group = new ilObjGroup($group_id);
7896 $members = $group->getGroupMemberIds();
7897 include_once './Services/User/classes/class.ilObjUser.php';
7898 foreach ($members as $user_id)
7899 {
7900 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7901 }
7902 }
7903
7910 function inviteRole($role_id)
7911 {
7912 global $rbacreview;
7913 $members = $rbacreview->assignedUsers($role_id,"usr_id");
7914 include_once './Services/User/classes/class.ilObjUser.php';
7915 foreach ($members as $user_id)
7916 {
7917 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7918 }
7919 }
7920
7921
7922
7929 function disinviteUser($user_id)
7930 {
7931 global $ilDB;
7932
7933 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7934 array('integer', 'integer'),
7935 array($this->getTestId(), $user_id)
7936 );
7937 }
7938
7945 function inviteUser($user_id, $client_ip="")
7946 {
7947 global $ilDB;
7948
7949 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7950 array('integer', 'integer'),
7951 array($this->getTestId(), $user_id)
7952 );
7953 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7954 array('integer', 'integer', 'text', 'integer'),
7955 array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : NULL, time())
7956 );
7957 }
7958
7959
7960 function setClientIP($user_id, $client_ip)
7961 {
7962 global $ilDB;
7963
7964 $affectedRows = $ilDB->manipulateF("UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7965 array('text', 'integer', 'integer', 'integer'),
7966 array((strlen($client_ip)) ? $client_ip : NULL, time(), $this->getTestId(), $user_id)
7967 );
7968 }
7969
7975 function _getSolvedQuestions($active_id, $question_fi = null)
7976 {
7977 global $ilDB;
7978 if (is_numeric($question_fi))
7979 {
7980 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7981 array('integer', 'integer'),
7982 array($active_id, $question_fi)
7983 );
7984 }
7985 else
7986 {
7987 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7988 array('integer'),
7989 array($active_id)
7990 );
7991 }
7992 $result_array = array();
7993 while ($row = $ilDB->fetchAssoc($result))
7994 {
7995 $result_array[$row["question_fi"]]= $row;
7996 }
7997 return $result_array;
7998 }
7999
8000
8004 function setQuestionSetSolved($value, $question_id, $user_id)
8005 {
8006 global $ilDB;
8007
8008 $active_id = $this->getActiveIdOfUser($user_id);
8009 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
8010 array('integer', 'integer'),
8011 array($active_id, $question_id)
8012 );
8013 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
8014 array('integer', 'integer', 'integer'),
8015 array($value, $question_id, $active_id)
8016 );
8017 }
8018
8022 function isTestFinished($active_id)
8023 {
8024 global $ilDB;
8025
8026 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
8027 array('integer', 'integer'),
8028 array($active_id, 1)
8029 );
8030 return $result->numRows() == 1;
8031 }
8032
8036 function isActiveTestSubmitted($user_id = null)
8037 {
8038 global $ilUser;
8039 global $ilDB;
8040
8041 if (!is_numeric($user_id))
8042 $user_id = $ilUser->getId();
8043
8044 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
8045 array('integer', 'integer', 'integer'),
8046 array($this->getTestId(), $user_id, 1)
8047 );
8048 return $result->numRows() == 1;
8049 }
8050
8055 {
8056 return $this->getNrOfTries() != 0;
8057 }
8058
8059
8065 function isNrOfTriesReached($tries)
8066 {
8067 return $tries >= (int) $this->getNrOfTries();
8068 }
8069
8070
8079 function getAllTestResults($participants, $prepareForCSV = true)
8080 {
8081 $results = array();
8082 $row = array(
8083 "user_id" => $this->lng->txt("user_id"),
8084 "matriculation" => $this->lng->txt("matriculation"),
8085 "lastname" => $this->lng->txt("lastname"),
8086 "firstname" => $this->lng->txt("firstname"),
8087 "login" =>$this->lng->txt("login"),
8088 "reached_points" => $this->lng->txt("tst_reached_points"),
8089 "max_points" => $this->lng->txt("tst_maximum_points"),
8090 "percent_value" => $this->lng->txt("tst_percent_solved"),
8091 "mark" => $this->lng->txt("tst_mark"),
8092 "ects" => $this->lng->txt("ects_grade")
8093 );
8094 $results[] = $row;
8095 if (count($participants))
8096 {
8097 if($this->getECTSOutput())
8098 {
8099 $passed_array =& $this->getTotalPointsPassedArray();
8100 }
8101 foreach ($participants as $active_id => $user_rec)
8102 {
8103 $row = array();
8104 $reached_points = 0;
8105 $max_points = 0;
8106 foreach ($this->questions as $value)
8107 {
8108 $question =& ilObjTest::_instanciateQuestion($value);
8109 if (is_object($question))
8110 {
8111 $max_points += $question->getMaximumPoints();
8112 $reached_points += $question->getReachedPoints($active_id);
8113 }
8114 }
8115 if ($max_points > 0)
8116 {
8117 $percentvalue = $reached_points / $max_points;
8118 if ($percentvalue < 0) $percentvalue = 0.0;
8119 }
8120 else
8121 {
8122 $percentvalue = 0;
8123 }
8124 $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
8125 $passed = "";
8126 if ($mark_obj)
8127 {
8128 $mark = $mark_obj->getOfficialName();
8129 $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
8130 }
8131 if ($this->getAnonymity())
8132 {
8133 $user_rec['firstname'] = "";
8134 $user_rec['lastname'] = $this->lng->txt("anonymous");
8135 }
8136 $row = array(
8137 "user_id"=>$user_rec['usr_id'],
8138 "matriculation" => $user_rec['matriculation'],
8139 "lastname" => $user_rec['lastname'],
8140 "firstname" => $user_rec['firstname'],
8141 "login"=>$user_rec['login'],
8142 "reached_points" => $reached_points,
8143 "max_points" => $max_points,
8144 "percent_value" => $percentvalue,
8145 "mark" => $mark,
8146 "ects" => $ects_mark
8147 );
8148 $results[] = $prepareForCSV ? $this->processCSVRow ($row, true) : $row;
8149 }
8150 }
8151 return $results;
8152 }
8153
8164 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
8165 {
8166 $resultarray = array();
8167 foreach ($row as $rowindex => $entry)
8168 {
8169 $surround = FALSE;
8170 if ($quoteAll)
8171 {
8172 $surround = TRUE;
8173 }
8174 if (strpos($entry, "\"") !== FALSE)
8175 {
8176 $entry = str_replace("\"", "\"\"", $entry);
8177 $surround = TRUE;
8178 }
8179 if (strpos($entry, $separator) !== FALSE)
8180 {
8181 $surround = TRUE;
8182 }
8183 // replace all CR LF with LF (for Excel for Windows compatibility
8184 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
8185
8186 if ($surround)
8187 {
8188 $entry = "\"" . $entry . "\"";
8189 }
8190
8191 $resultarray[$rowindex] = $entry;
8192 }
8193 return $resultarray;
8194 }
8195
8204 function _getPass($active_id)
8205 {
8206 global $ilDB;
8207 $result = $ilDB->queryF("SELECT tries FROM tst_active WHERE active_id = %s",
8208 array('integer'),
8209 array($active_id)
8210 );
8211 if ($result->numRows())
8212 {
8213 $row = $ilDB->fetchAssoc($result);
8214 return $row["tries"];
8215 }
8216 else
8217 {
8218 return 0;
8219 }
8220 }
8221
8231 function _getMaxPass($active_id)
8232 {
8233 global $ilDB;
8234 $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
8235 array('integer'),
8236 array($active_id)
8237 );
8238 if ($result->numRows())
8239 {
8240 $row = $ilDB->fetchAssoc($result);
8241 $max = $row["maxpass"];
8242 }
8243 else
8244 {
8245 $max = NULL;
8246 }
8247 return $max;
8248 }
8249
8260 function _getBestPass($active_id)
8261 {
8262 global $ilDB;
8263
8264 $result = $ilDB->queryF("SELECT * FROM tst_pass_result WHERE active_fi = %s",
8265 array('integer'),
8266 array($active_id)
8267 );
8268 if ($result->numRows())
8269 {
8270 $bestrow = null;
8271 $bestfactor = 0;
8272 while ($row = $ilDB->fetchAssoc($result))
8273 {
8274 if($row["maxpoints"] > 0)
8275 {
8276 $factor = $row["points"] / $row["maxpoints"];
8277 }
8278 else
8279 {
8280 $factor = 0;
8281 }
8282
8283 if($factor > $bestfactor)
8284 {
8285 $bestrow = $row;
8286 $bestfactor = $factor;
8287 }
8288 }
8289 if (is_array($bestrow))
8290 {
8291 return $bestrow["pass"];
8292 }
8293 else
8294 {
8295 return 0;
8296 }
8297 }
8298 else
8299 {
8300 return 0;
8301 }
8302 }
8303
8312 function _getResultPass($active_id)
8313 {
8314 $counted_pass = NULL;
8316 {
8317 $counted_pass = ilObjTest::_getBestPass($active_id);
8318 }
8319 else
8320 {
8321 $counted_pass = ilObjTest::_getMaxPass($active_id);
8322 }
8323 return $counted_pass;
8324 }
8325
8335 function getAnsweredQuestionCount($active_id, $pass = NULL)
8336 {
8337 if( $this->isDynamicTest() )
8338 {
8339 global $tree, $ilDB, $lng, $ilPluginAdmin;
8340
8341 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
8342 $testSessionFactory = new ilTestSessionFactory($this);
8343 $testSession = $testSessionFactory->getSession($active_id);
8344
8345 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
8346 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
8347 $testSequence = $testSequenceFactory->getSequence($testSession);
8348
8349 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
8350 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
8351 $dynamicQuestionSetConfig->loadFromDb();
8352
8353 $testSequence->loadFromDb($dynamicQuestionSetConfig);
8354 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
8355
8356 return $testSequence->getTrackedQuestionCount();
8357 }
8358
8359 if ($this->isRandomTest())
8360 {
8361 $this->loadQuestions($active_id, $pass);
8362 }
8363 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
8364 $workedthrough = 0;
8365 foreach ($this->questions as $value)
8366 {
8367 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
8368 {
8369 $workedthrough += 1;
8370 }
8371 }
8372 return $workedthrough;
8373 }
8374
8384 function getPassFinishDate($active_id, $pass)
8385 {
8386 global $ilDB;
8387
8388 if (is_null($pass))
8389 {
8390 $pass = 0;
8391 }
8392
8393 $query = "
8394 SELECT tst_pass_result.tstamp pass_res_tstamp,
8395 tst_test_result.tstamp quest_res_tstamp
8396
8397 FROM tst_pass_result
8398
8399 LEFT JOIN tst_test_result
8400 ON tst_test_result.active_fi = tst_pass_result.active_fi
8401 AND tst_test_result.pass = tst_pass_result.pass
8402
8403 WHERE tst_pass_result.active_fi = %s
8404 AND tst_pass_result.pass = %s
8405
8406 ORDER BY tst_test_result.tstamp DESC
8407 ";
8408
8409 $result = $ilDB->queryF($query,
8410 array('integer', 'integer'),
8411 array($active_id, $pass)
8412 );
8413
8414 while( $row = $ilDB->fetchAssoc($result) )
8415 {
8416 if( $row['qres_tstamp'] )
8417 {
8418 return $row['quest_res_tstamp'];
8419 }
8420
8421 return $row['pass_res_tstamp'];
8422 }
8423
8424 return 0;
8425 }
8426
8435 function isExecutable($testSession, $user_id, $allowPassIncrease = FALSE)
8436 {
8437 $result = array(
8438 "executable" => true,
8439 "errormessage" => ""
8440 );
8441 if (!$this->startingTimeReached())
8442 {
8443 $result["executable"] = false;
8444 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getStartingTime(), IL_CAL_TIMESTAMP)));
8445 return $result;
8446 }
8447 if ($this->endingTimeReached())
8448 {
8449 $result["executable"] = false;
8450 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getEndingTime(), IL_CAL_TIMESTAMP)));
8451 return $result;
8452 }
8453
8454 $active_id = $this->getActiveIdOfUser($user_id);
8455
8456 if ($this->getEnableProcessingTime())
8457 {
8458 if ($active_id > 0)
8459 {
8460 $starting_time = $this->getStartingTimeOfUser($active_id);
8461 if ($starting_time !== FALSE)
8462 {
8463 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8464 {
8465 if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > ($this->_getPass($active_id)+1))))
8466 {
8467 // a test pass was quitted because the maximum processing time was reached, but the time
8468 // will be resetted for future passes, so if there are more passes allowed, the participant may
8469 // start the test again.
8470 // This code block is only called when $allowPassIncrease is TRUE which only happens when
8471 // the test info page is opened. Otherwise this will lead to unexpected results!
8472 $testSession->increasePass();
8473 $testSession->setLastSequence(0);
8474 $testSession->saveToDb();
8475 }
8476 else
8477 {
8478 $result["executable"] = false;
8479 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8480 }
8481 return $result;
8482 }
8483 }
8484 }
8485 }
8486
8487 if ($this->hasNrOfTriesRestriction() && ($active_id > 0))
8488 {
8489 require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8490 $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8491 $testPassesSelector->setActiveId($active_id);
8492 $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8493
8494 $closedPasses = $testPassesSelector->getClosedPasses();
8495
8496 if( count($closedPasses) >= $this->getNrOfTries() )
8497 {
8498 $result["executable"] = false;
8499 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8500 return $result;
8501 }
8502 }
8503
8504 return $result;
8505 }
8506
8514 {
8515 $result = true;
8516 if ($this->getScoreReporting() == 4) return false;
8517 if ($this->getReportingDate())
8518 {
8519 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8520 {
8521 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8522 $now = mktime();
8523 if ($now < $epoch_time)
8524 {
8525 $result = false;
8526 }
8527 }
8528 }
8529 return $result;
8530 }
8531
8533 {
8534 $active_id = $this->getActiveIdOfUser($user_id);
8535 if ($active_id > 0)
8536 {
8537 $starting_time = $this->getStartingTimeOfUser($active_id);
8538 }
8539 $notimeleft = FALSE;
8540 if ($starting_time !== FALSE)
8541 {
8542 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8543 {
8544 $notimeleft = TRUE;
8545 }
8546 }
8547 $result = TRUE;
8548 if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
8549 {
8550 $result = FALSE;
8551 }
8552 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
8553 $result = $result & $this->canViewResults();
8554 return $result;
8555 }
8556
8564 function getStartingTimeOfUser($active_id, $pass = null)
8565 {
8566 global $ilDB;
8567
8568 if ($active_id < 1) return FALSE;
8569 if($pass === null)
8570 {
8571 $pass = ($this->getResetProcessingTime()) ? $this->_getPass($active_id) : 0;
8572 }
8573 $result = $ilDB->queryF("SELECT tst_times.started FROM tst_times WHERE tst_times.active_fi = %s AND tst_times.pass = %s ORDER BY tst_times.started",
8574 array('integer', 'integer'),
8575 array($active_id, $pass)
8576 );
8577 if ($result->numRows())
8578 {
8579 $row = $ilDB->fetchAssoc($result);
8580 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
8581 {
8582 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8583 }
8584 else
8585 {
8586 return mktime();
8587 }
8588 }
8589 else
8590 {
8591 return mktime();
8592 }
8593 }
8594
8604 {
8605 if ($this->getEnableProcessingTime())
8606 {
8607 $processing_time = $this->getProcessingTimeInSeconds($active_id);
8608 $now = mktime();
8609 if ($now > ($starting_time + $processing_time))
8610 {
8611 return TRUE;
8612 }
8613 else
8614 {
8615 return FALSE;
8616 }
8617 }
8618 else
8619 {
8620 return FALSE;
8621 }
8622 }
8623
8625 {
8626 global $ilDB;
8627
8628 $query = "
8629 SELECT questions.*,
8630 questtypes.type_tag,
8631 tstquest.sequence,
8632 tstquest.obligatory,
8633 origquest.obj_fi orig_obj_fi
8634
8635 FROM qpl_questions questions
8636
8637 INNER JOIN qpl_qst_type questtypes
8638 ON questtypes.question_type_id = questions.question_type_fi
8639
8640 INNER JOIN tst_test_question tstquest
8641 ON tstquest.question_fi = questions.question_id
8642
8643 LEFT JOIN qpl_questions origquest
8644 ON origquest.question_id = questions.original_id
8645
8646 WHERE tstquest.test_fi = %s
8647
8648 ORDER BY tstquest.sequence
8649 ";
8650
8651 $query_result = $ilDB->queryF(
8652 $query, array('integer'), array($this->getTestId())
8653 );
8654
8655 $questions = array();
8656
8657 while ($row = $ilDB->fetchAssoc($query_result))
8658 {
8659 $question = $row;
8660
8661 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8662
8663 $questions[] = $question;
8664 }
8665
8666 return $questions;
8667 }
8668
8672 public function getPotentialRandomTestQuestions()
8673 {
8677 global $ilDB;
8678
8679 $query = "
8680 SELECT questions.*,
8681 questtypes.type_tag,
8682 origquest.obj_fi orig_obj_fi
8683
8684 FROM qpl_questions questions
8685
8686 INNER JOIN qpl_qst_type questtypes
8687 ON questtypes.question_type_id = questions.question_type_fi
8688
8689 INNER JOIN tst_rnd_cpy tstquest
8690 ON tstquest.qst_fi = questions.question_id
8691
8692 LEFT JOIN qpl_questions origquest
8693 ON origquest.question_id = questions.original_id
8694
8695 WHERE tstquest.tst_fi = %s
8696 ";
8697
8698 $query_result = $ilDB->queryF(
8699 $query, array('integer'), array($this->getTestId())
8700 );
8701
8702 $questions = array();
8703
8704 while ($row = $ilDB->fetchAssoc($query_result))
8705 {
8706 $question = $row;
8707
8708 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8709
8710 $questions[] = $question;
8711 }
8712
8713 return $questions;
8714 }
8715
8723 {
8724 return ($this->shuffle_questions) ? 1 : 0;
8725 }
8726
8733 function setShuffleQuestions($a_shuffle)
8734 {
8735 $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8736 }
8737
8751 {
8752 return ($this->show_summary) ? $this->show_summary : 0;
8753 }
8754
8767 function setListOfQuestionsSettings($a_value = 0)
8768 {
8769 $this->show_summary = $a_value;
8770 }
8771
8779 {
8780 if (($this->show_summary & 1) > 0)
8781 {
8782 return TRUE;
8783 }
8784 else
8785 {
8786 return FALSE;
8787 }
8788 }
8789
8796 function setListOfQuestions($a_value = TRUE)
8797 {
8798 if ($a_value)
8799 {
8800 $this->show_summary = 1;
8801 }
8802 else
8803 {
8804 $this->show_summary = 0;
8805 }
8806 }
8807
8815 {
8816 if (($this->show_summary & 2) > 0)
8817 {
8818 return TRUE;
8819 }
8820 else
8821 {
8822 return FALSE;
8823 }
8824 }
8825
8832 function setListOfQuestionsStart($a_value = TRUE)
8833 {
8834 if ($a_value && $this->getListOfQuestions())
8835 {
8836 $this->show_summary = $this->show_summary | 2;
8837 }
8838 if (!$a_value && $this->getListOfQuestions())
8839 {
8840 if ($this->getListOfQuestionsStart())
8841 {
8842 $this->show_summary = $this->show_summary ^ 2;
8843 }
8844 }
8845 }
8846
8854 {
8855 if (($this->show_summary & 4) > 0)
8856 {
8857 return TRUE;
8858 }
8859 else
8860 {
8861 return FALSE;
8862 }
8863 }
8864
8871 function setListOfQuestionsEnd($a_value = TRUE)
8872 {
8873 if ($a_value && $this->getListOfQuestions())
8874 {
8875 $this->show_summary = $this->show_summary | 4;
8876 }
8877 if (!$a_value && $this->getListOfQuestions())
8878 {
8879 if ($this->getListOfQuestionsEnd())
8880 {
8881 $this->show_summary = $this->show_summary ^ 4;
8882 }
8883 }
8884 }
8885
8893 {
8894 if (($this->show_summary & 8) > 0)
8895 {
8896 return TRUE;
8897 }
8898 else
8899 {
8900 return FALSE;
8901 }
8902 }
8903
8910 function setListOfQuestionsDescription($a_value = TRUE)
8911 {
8912 if ($a_value && $this->getListOfQuestions())
8913 {
8914 $this->show_summary = $this->show_summary | 8;
8915 }
8916 if (!$a_value && $this->getListOfQuestions())
8917 {
8918 if ($this->getListOfQuestionsDescription())
8919 {
8920 $this->show_summary = $this->show_summary ^ 8;
8921 }
8922 }
8923 }
8924
8932 {
8933 return ($this->results_presentation) ? $this->results_presentation : 0;
8934 }
8935
8943 {
8944 if (($this->results_presentation & 1) > 0)
8945 {
8946 return TRUE;
8947 }
8948 else
8949 {
8950 return FALSE;
8951 }
8952 }
8953
8961 {
8962 if (($this->results_presentation & 2) > 0)
8963 {
8964 return TRUE;
8965 }
8966 else
8967 {
8968 return FALSE;
8969 }
8970 }
8971
8979 {
8980 if (($this->results_presentation & 4) > 0)
8981 {
8982 return TRUE;
8983 }
8984 else
8985 {
8986 return FALSE;
8987 }
8988 }
8989
8997 {
8998 if (($this->results_presentation & 8) > 0)
8999 {
9000 return TRUE;
9001 }
9002 else
9003 {
9004 return FALSE;
9005 }
9006 }
9007
9015 {
9016 if (($this->results_presentation & 16) > 0)
9017 {
9018 return TRUE;
9019 }
9020 else
9021 {
9022 return FALSE;
9023 }
9024 }
9025
9033 {
9034 if (($this->results_presentation & 32) > 0)
9035 {
9036 return TRUE;
9037 }
9038 else
9039 {
9040 return FALSE;
9041 }
9042 }
9043
9049 {
9050 if (($this->results_presentation & 64) > 0)
9051 {
9052 return TRUE;
9053 }
9054 else
9055 {
9056 return FALSE;
9057 }
9058 }
9059
9065 {
9066 if(($this->results_presentation & 128) > 0)
9067 {
9068 return TRUE;
9069 }
9070 else
9071 {
9072 return FALSE;
9073 }
9074 }
9075
9082 function setResultsPresentation($a_results_presentation = 3)
9083 {
9084 $this->results_presentation = $a_results_presentation;
9085 }
9086
9095 function setShowPassDetails($a_details = 1)
9096 {
9097 if ($a_details)
9098 {
9099 $this->results_presentation = $this->results_presentation | 1;
9100 }
9101 else
9102 {
9103 if ($this->getShowPassDetails())
9104 {
9105 $this->results_presentation = $this->results_presentation ^ 1;
9106 }
9107 }
9108 }
9109
9116 function setShowSolutionDetails($a_details = 1)
9117 {
9118 if ($a_details)
9119 {
9120 $this->results_presentation = $this->results_presentation | 2;
9121 }
9122 else
9123 {
9124 if ($this->getShowSolutionDetails())
9125 {
9126 $this->results_presentation = $this->results_presentation ^ 2;
9127 }
9128 }
9129 }
9130
9137 function canShowSolutionPrintview($user_id = NULL)
9138 {
9139 return $this->getShowSolutionPrintview();
9140 }
9141
9148 function setShowSolutionPrintview($a_printview = 1)
9149 {
9150 if ($a_printview)
9151 {
9152 $this->results_presentation = $this->results_presentation | 4;
9153 }
9154 else
9155 {
9156 if ($this->getShowSolutionPrintview())
9157 {
9158 $this->results_presentation = $this->results_presentation ^ 4;
9159 }
9160 }
9161 }
9162
9169 function setShowSolutionFeedback($a_feedback = TRUE)
9170 {
9171 if ($a_feedback)
9172 {
9173 $this->results_presentation = $this->results_presentation | 8;
9174 }
9175 else
9176 {
9177 if ($this->getShowSolutionFeedback())
9178 {
9179 $this->results_presentation = $this->results_presentation ^ 8;
9180 }
9181 }
9182 }
9183
9190 function setShowSolutionAnswersOnly($a_full = TRUE)
9191 {
9192 if ($a_full)
9193 {
9194 $this->results_presentation = $this->results_presentation | 16;
9195 }
9196 else
9197 {
9198 if ($this->getShowSolutionAnswersOnly())
9199 {
9200 $this->results_presentation = $this->results_presentation ^ 16;
9201 }
9202 }
9203 }
9204
9211 function setShowSolutionSignature($a_signature = FALSE)
9212 {
9213 if ($a_signature)
9214 {
9215 $this->results_presentation = $this->results_presentation | 32;
9216 }
9217 else
9218 {
9219 if ($this->getShowSolutionSignature())
9220 {
9221 $this->results_presentation = $this->results_presentation ^ 32;
9222 }
9223 }
9224 }
9225
9232 function setShowSolutionSuggested($a_solution = FALSE)
9233 {
9234 if ($a_solution)
9235 {
9236 $this->results_presentation = $this->results_presentation | 64;
9237 }
9238 else
9239 {
9240 if ($this->getShowSolutionSuggested())
9241 {
9242 $this->results_presentation = $this->results_presentation ^ 64;
9243 }
9244 }
9245 }
9246
9252 public function setShowSolutionListComparison($a_comparison = FALSE)
9253 {
9254 if($a_comparison)
9255 {
9256 $this->results_presentation = $this->results_presentation | 128;
9257 }
9258 else
9259 {
9261 {
9262 $this->results_presentation = $this->results_presentation ^ 128;
9263 }
9264 }
9265 }
9266
9270 public static function _getUserIdFromActiveId($active_id)
9271 {
9272 global $ilDB;
9273 $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
9274 array('integer'),
9275 array($active_id)
9276 );
9277 if ($result->numRows())
9278 {
9279 $row = $ilDB->fetchAssoc($result);
9280 return $row["user_fi"];
9281 }
9282 else
9283 {
9284 return -1;
9285 }
9286 }
9287
9291 public function isLimitUsersEnabled()
9292 {
9294 }
9295
9300 {
9301 $this->limitUsersEnabled = $limitUsersEnabled;
9302 }
9303
9304 public function getAllowedUsers()
9305 {
9306 return ($this->allowedUsers) ? $this->allowedUsers : 0;
9307 }
9308
9309 public function setAllowedUsers($a_allowed_users)
9310 {
9311 $this->allowedUsers = $a_allowed_users;
9312 }
9313
9314 public function getAllowedUsersTimeGap()
9315 {
9316 return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
9317 }
9318
9319 public function setAllowedUsersTimeGap($a_allowed_users_time_gap)
9320 {
9321 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
9322 }
9323
9325 {
9326 global $ilDB;
9327
9328 $nr_of_users = $this->getAllowedUsers();
9329 $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
9330 if (($nr_of_users > 0) && ($time_gap > 0))
9331 {
9332 $now = mktime();
9333 $time_border = $now - $time_gap;
9334 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
9335 $query = "
9336 SELECT DISTINCT tst_times.active_fi
9337 FROM tst_times
9338 INNER JOIN tst_active
9339 ON tst_times.active_fi = tst_active.active_id
9340 AND (
9341 tst_times.pass > tst_active.last_finished_pass OR tst_active.last_finished_pass IS NULL
9342 )
9343 WHERE tst_times.tstamp > %s
9344 AND tst_active.test_fi = %s
9345 ";
9346 $result = $ilDB->queryF($query, array('integer', 'integer'), array($time_border, $this->getTestId()));
9347 if ($result->numRows() >= $nr_of_users)
9348 {
9349 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
9351 {
9352 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
9353 }
9354 return FALSE;
9355 }
9356 else
9357 {
9358 return TRUE;
9359 }
9360 }
9361 return TRUE;
9362 }
9363
9364 function _getLastAccess($active_id)
9365 {
9366 global $ilDB;
9367
9368 $result = $ilDB->queryF("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
9369 array('integer'),
9370 array($active_id)
9371 );
9372 if ($result->numRows())
9373 {
9374 $row = $ilDB->fetchAssoc($result);
9375 return $row["finished"];
9376 }
9377 return "";
9378 }
9379
9387 function isHTML($a_text)
9388 {
9389 if (preg_match("/<[^>]*?>/", $a_text))
9390 {
9391 return TRUE;
9392 }
9393 else
9394 {
9395 return FALSE;
9396 }
9397 }
9398
9406 function QTIMaterialToString($a_material)
9407 {
9408 $result = "";
9409 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
9410 {
9411 $material = $a_material->getMaterial($i);
9412 if (strcmp($material["type"], "mattext") == 0)
9413 {
9414 $result .= $material["material"]->getContent();
9415 }
9416 if (strcmp($material["type"], "matimage") == 0)
9417 {
9418 $matimage = $material["material"];
9419 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
9420 {
9421 // import an mediaobject which was inserted using tiny mce
9422 if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
9423 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
9424 }
9425 }
9426 }
9427 global $ilLog;
9428 $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
9429 return $result;
9430 }
9431
9440 function addQTIMaterial(&$a_xml_writer, $a_material)
9441 {
9442 include_once "./Services/RTE/classes/class.ilRTE.php";
9443 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9444
9445 $a_xml_writer->xmlStartTag("material");
9446 $attrs = array(
9447 "texttype" => "text/plain"
9448 );
9449 if ($this->isHTML($a_material))
9450 {
9451 $attrs["texttype"] = "text/xhtml";
9452 }
9453 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9454
9455 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9456 foreach ($mobs as $mob)
9457 {
9458 $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9459 if (strpos($a_material, "mm_$mob") !== FALSE)
9460 {
9461 if (ilObjMediaObject::_exists($mob))
9462 {
9463 $mob_obj =& new ilObjMediaObject($mob);
9464 $imgattrs = array(
9465 "label" => $moblabel,
9466 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9467 );
9468 }
9469 $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
9470 }
9471 }
9472 $a_xml_writer->xmlEndTag("material");
9473 }
9474
9481 function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE, $omitNl2BrWhenTextArea = false)
9482 {
9483 include_once "./Services/Utilities/classes/class.ilUtil.php";
9484 return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output, $omitNl2BrWhenTextArea);
9485 }
9486
9493 function saveCertificateVisibility($a_value)
9494 {
9495 global $ilDB;
9496
9497 $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9498 array('text', 'integer', 'integer'),
9499 array($a_value, time(), $this->getTestId())
9500 );
9501 }
9502
9510 {
9511 return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9512 }
9513
9520 function setCertificateVisibility($a_value)
9521 {
9522 $this->certificate_visibility = $a_value;
9523 }
9524
9531 function getAnonymity()
9532 {
9533 return ($this->anonymity) ? 1 : 0;
9534 }
9535
9542 function setAnonymity($a_value = 0)
9543 {
9544 switch ($a_value)
9545 {
9546 case 1:
9547 $this->anonymity = 1;
9548 break;
9549 default:
9550 $this->anonymity = 0;
9551 break;
9552 }
9553 }
9554
9561 function getShowCancel()
9562 {
9563 return ($this->show_cancel) ? 1 : 0;
9564 }
9565
9572 function setShowCancel($a_value = 1)
9573 {
9574 switch ($a_value)
9575 {
9576 case 1:
9577 $this->show_cancel = 1;
9578 break;
9579 default:
9580 $this->show_cancel = 0;
9581 break;
9582 }
9583 }
9584
9591 function getShowMarker()
9592 {
9593 return ($this->show_marker) ? 1 : 0;
9594 }
9595
9602 function setShowMarker($a_value = 1)
9603 {
9604 switch ($a_value)
9605 {
9606 case 1:
9607 $this->show_marker = 1;
9608 break;
9609 default:
9610 $this->show_marker = 0;
9611 break;
9612 }
9613 }
9614
9622 {
9623 return ($this->fixed_participants) ? 1 : 0;
9624 }
9625
9632 function setFixedParticipants($a_value = 1)
9633 {
9634 switch ($a_value)
9635 {
9636 case 1:
9637 $this->fixed_participants = 1;
9638 break;
9639 default:
9640 $this->fixed_participants = 0;
9641 break;
9642 }
9643 }
9644
9652 function _lookupAnonymity($a_obj_id)
9653 {
9654 global $ilDB;
9655
9656 $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9657 array('integer'),
9658 array($a_obj_id)
9659 );
9660 while($row = $ilDB->fetchAssoc($result))
9661 {
9662 return $row['anonymity'];
9663 }
9664 return 0;
9665 }
9666
9673 public static function lookupQuestionSetTypeByActiveId($active_id)
9674 {
9675 global $ilDB;
9676
9677 $query = "
9678 SELECT tst_tests.question_set_type
9679 FROM tst_active
9680 INNER JOIN tst_tests
9681 ON tst_active.test_fi = tst_tests.test_id
9682 WHERE tst_active.active_id = %s
9683 ";
9684
9685 $res = $ilDB->queryF( $query, array('integer'), array($active_id) );
9686
9687 while($row = $ilDB->fetchAssoc($res))
9688 {
9689 return $row['question_set_type'];
9690 }
9691
9692 return null;
9693 }
9694
9704 {
9705 throw new Exception(__METHOD__.' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9706
9707 global $ilDB;
9708
9709 $result = $ilDB->queryF("SELECT tst_tests.random_test FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
9710 array('integer'),
9711 array($active_id)
9712 );
9713 while($row = $ilDB->fetchAssoc($result))
9714 {
9715 return $row['random_test'];
9716 }
9717 return 0;
9718 }
9719
9730 function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
9731 {
9732 if ($this->getAnonymity() && !$overwrite_anonymity)
9733 {
9734 return $this->lng->txt("anonymous") . $suffix;
9735 }
9736 else
9737 {
9738 include_once './Services/User/classes/class.ilObjUser.php';
9739 $uname = ilObjUser::_lookupName($user_id);
9740 if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
9741 if ($sorted_order)
9742 {
9743 return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9744 }
9745 else
9746 {
9747 return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9748 }
9749 }
9750 }
9751
9759 function getStartTestLabel($active_id)
9760 {
9761 if ($this->getNrOfTries() == 1)
9762 {
9763 return $this->lng->txt("tst_start_test");
9764 }
9765 $active_pass = $this->_getPass($active_id);
9766 $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9767 if ($res == 0)
9768 {
9769 if ($active_pass == 0)
9770 {
9771 return $this->lng->txt("tst_start_test");
9772 }
9773 else
9774 {
9775 return $this->lng->txt("tst_start_new_test_pass");
9776 }
9777 }
9778 else
9779 {
9780 return $this->lng->txt("tst_resume_test");
9781 }
9782 }
9783
9789 public function getAvailableDefaults()
9790 {
9795 global $ilDB, $ilUser;
9796
9797 $result = $ilDB->queryF(
9798 "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9799 array('integer'),
9800 array($ilUser->getId())
9801 );
9802 $defaults = array();
9803 while($row = $ilDB->fetchAssoc($result))
9804 {
9805 $defaults[$row["test_defaults_id"]] = $row;
9806 }
9807 return $defaults;
9808 }
9809
9817 function &getTestDefaults($test_defaults_id)
9818 {
9819 return self::_getTestDefaults($test_defaults_id);
9820 }
9821
9822 public static function _getTestDefaults($test_defaults_id)
9823 {
9824 global $ilDB;
9825
9826 $result = $ilDB->queryF("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9827 array('integer'),
9828 array($test_defaults_id)
9829 );
9830 if ($result->numRows() == 1)
9831 {
9832 $row = $ilDB->fetchAssoc($result);
9833 return $row;
9834 }
9835 else
9836 {
9837 return NULL;
9838 }
9839 }
9840
9847 function deleteDefaults($test_default_id)
9848 {
9849 global $ilDB;
9850 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9851 array('integer'),
9852 array($test_default_id)
9853 );
9854 }
9855
9862 function addDefaults($a_name)
9863 {
9864 global $ilDB;
9865 global $ilUser;
9866 $testsettings = array(
9867 "TitleOutput" => $this->getTitleOutput(),
9868 "PassScoring" => $this->getPassScoring(),
9869 "IntroEnabled" => $this->isIntroductionEnabled(),
9870 "Introduction" => $this->getIntroduction(),
9871 "FinalStatement" => $this->getFinalStatement(),
9872 "ShowInfo" => $this->getShowInfo(),
9873 "ForceJS" => $this->getForceJS(),
9874 "CustomStyle" => $this->getCustomStyle(),
9875 "ShowFinalStatement" => $this->getShowFinalStatement(),
9876 "SequenceSettings" => $this->getSequenceSettings(),
9877 "ScoreReporting" => $this->getScoreReporting(),
9878 "ScoreCutting" => $this->getScoreCutting(),
9879 'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9880 'PrintBsWithRes' => (int)$this->isBestSolutionPrintedWithResult(),
9881 "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9882 "AnswerFeedback" => $this->getAnswerFeedback(),
9883 "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9884 "ResultsPresentation" => $this->getResultsPresentation(),
9885 "Anonymity" => $this->getAnonymity(),
9886 "ShowCancel" => $this->getShowCancel(),
9887 "ShowMarker" => $this->getShowMarker(),
9888 "ReportingDate" => $this->getReportingDate(),
9889 "NrOfTries" => $this->getNrOfTries(),
9890 "Shuffle" => $this->getShuffleQuestions(),
9891 "Kiosk" => $this->getKiosk(),
9892 "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9893 "ProcessingTime" => $this->getProcessingTime(),
9894 "EnableProcessingTime" => $this->getEnableProcessingTime(),
9895 "ResetProcessingTime" => $this->getResetProcessingTime(),
9896 "StartingTimeEnabled" => $this->isStartingTimeEnabled(),
9897 "StartingTime" => $this->getStartingTime(),
9898 "EndingTimeEnabled" => $this->isEndingTimeEnabled(),
9899 "EndingTime" => $this->getEndingTime(),
9900 "ECTSOutput" => $this->getECTSOutput(),
9901 "ECTSFX" => $this->getECTSFX(),
9902 "ECTSGrades" => $this->getECTSGrades(),
9903 "questionSetType" => $this->getQuestionSetType(),
9904 "CountSystem" => $this->getCountSystem(),
9905 "MCScoring" => $this->getMCScoring(),
9906 "mailnotification" => $this->getMailNotification(),
9907 "mailnottype" => $this->getMailNotificationType(),
9908 "exportsettings" => $this->getExportSettings(),
9909 "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9910 'obligations_enabled' => (int)$this->areObligationsEnabled(),
9911 'offer_question_hints' => (int)$this->isOfferingQuestionHintsEnabled(),
9912 'pass_deletion_allowed' => (int)$this->isPassDeletionAllowed(),
9913 'enable_examview' => $this->getEnableExamview(),
9914 'show_examview_html' => $this->getShowExamviewHtml(),
9915 'show_examview_pdf' => $this->getShowExamviewPdf(),
9916 'char_selector_availability' => $this->getCharSelectorAvailability(),
9917 'char_selector_definition' => $this->getCharSelectorDefinition(),
9918 'skill_service' => (int)$this->isSkillServiceEnabled(),
9919 'result_tax_filters' => (array)$this->getResultFilterTaxIds(),
9920 'show_grading_status' => (int)$this->isShowGradingStatusEnabled(),
9921 'show_grading_mark' => (int)$this->isShowGradingMarkEnabled(),
9922
9923 'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
9924 'redirection_mode' => $this->getRedirectionMode(),
9925 'redirection_url' => $this->getRedirectionUrl(),
9926 'sign_submission' => $this->getSignSubmission(),
9927 'autosave' => (int)$this->getAutosave(),
9928 'autosave_ival' => (int)$this->getAutosaveIval(),
9929 'examid_in_test_pass' => (int)$this->isShowExamIdInTestPassEnabled(),
9930 'examid_in_test_res' => (int)$this->isShowExamIdInTestResultsEnabled(),
9931
9932 'enable_archiving' => (int)$this->getEnableArchiving(),
9933 'password_enabled' => (int)$this->isPasswordEnabled(),
9934 'password' => (string)$this->getPassword(),
9935 'fixed_participants' => $this->getFixedParticipants(),
9936 'limit_users_enabled' => $this->isLimitUsersEnabled(),
9937 'allowedusers' => $this->getAllowedUsers(),
9938 'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9939 'pool_usage' => $this->getPoolUsage(),
9940 'activation_limited' => $this->isActivationLimited(),
9941 'activation_start_time' => $this->getActivationStartingTime(),
9942 'activation_end_time' => $this->getActivationEndingTime(),
9943 'activation_visibility' => $this->getActivationVisibility(),
9944 'highscore_enabled' => $this->getHighscoreEnabled(),
9945 'highscore_anon' => $this->getHighscoreAnon(),
9946 'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9947 'highscore_score' => $this->getHighscoreScore(),
9948 'highscore_percentage' => $this->getHighscorePercentage(),
9949 'highscore_hints' => $this->getHighscoreHints(),
9950 'highscore_wtime' => $this->getHighscoreWTime(),
9951 'highscore_own_table' => $this->getHighscoreOwnTable(),
9952 'highscore_top_table' => $this->getHighscoreTopTable(),
9953 'highscore_top_num' => $this->getHighscoreTopNum(),
9954 'use_previous_answers' => (string)$this->getUsePreviousAnswers()
9955 );
9956
9957 $next_id = $ilDB->nextId('tst_test_defaults');
9958 $ilDB->insert(
9959 'tst_test_defaults',
9960 array(
9961 'test_defaults_id' => array('integer', $next_id),
9962 'name' => array('text', $a_name),
9963 'user_fi' => array('integer', $ilUser->getId()),
9964 'defaults' => array('clob', serialize($testsettings)),
9965 'marks' => array('clob', serialize($this->mark_schema)),
9966 'tstamp' => array('integer', time())
9967 )
9968 );
9969 }
9970
9978 public function applyDefaults($test_defaults)
9979 {
9980 $testsettings = unserialize($test_defaults["defaults"]);
9981 include_once "./Modules/Test/classes/class.assMarkSchema.php";
9982 $this->mark_schema = unserialize($test_defaults["marks"]);
9983
9984 $this->setTitleOutput($testsettings["TitleOutput"]);
9985 $this->setPassScoring($testsettings["PassScoring"]);
9986 $this->setIntroductionEnabled($testsettings["IntroEnabled"]);
9987 $this->setIntroduction($testsettings["Introduction"]);
9988 $this->setFinalStatement($testsettings["FinalStatement"]);
9989 $this->setShowInfo($testsettings["ShowInfo"]);
9990 $this->setForceJS($testsettings["ForceJS"]);
9991 $this->setCustomStyle($testsettings["CustomStyle"]);
9992 $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
9993 $this->setSequenceSettings($testsettings["SequenceSettings"]);
9994 $this->setScoreReporting($testsettings["ScoreReporting"]);
9995 $this->setScoreCutting($testsettings['ScoreCutting']);
9996 $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
9997 $this->setPrintBestSolutionWithResult((bool)$testsettings['PrintBsWithRes']);
9998 $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
9999 $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
10000 $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
10001 $this->setResultsPresentation($testsettings["ResultsPresentation"]);
10002 $this->setAnonymity($testsettings["Anonymity"]);
10003 $this->setShowCancel($testsettings["ShowCancel"]);
10004 $this->setShuffleQuestions($testsettings["Shuffle"]);
10005 $this->setShowMarker($testsettings["ShowMarker"]);
10006 $this->setReportingDate($testsettings["ReportingDate"]);
10007 $this->setNrOfTries($testsettings["NrOfTries"]);
10008 $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
10009 $this->setRedirectionMode($testsettings['redirection_mode']);
10010 $this->setRedirectionUrl($testsettings['redirection_url']);
10011 $this->setProcessingTime($testsettings["ProcessingTime"]);
10012 $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
10013 $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
10014 $this->setStartingTimeEnabled($testsettings["StartingTimeEnabled"]);
10015 $this->setStartingTime($testsettings["StartingTime"]);
10016 $this->setKiosk($testsettings["Kiosk"]);
10017 $this->setEndingTimeEnabled($testsettings["EndingTimeEnabled"]);
10018 $this->setEndingTime($testsettings["EndingTime"]);
10019 $this->setECTSOutput($testsettings["ECTSOutput"]);
10020 $this->setECTSFX($testsettings["ECTSFX"]);
10021 $this->setECTSGrades($testsettings["ECTSGrades"]);
10022 if( isset($testsettings["isRandomTest"]) )
10023 {
10024 if( $testsettings["isRandomTest"] )
10025 {
10026 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
10027 }
10028 else
10029 {
10030 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
10031 }
10032 }
10033 elseif( isset($testsettings["questionSetType"]) )
10034 {
10035 $this->setQuestionSetType($testsettings["questionSetType"]);
10036 }
10037 $this->setCountSystem($testsettings["CountSystem"]);
10038 $this->setMCScoring($testsettings["MCScoring"]);
10039 $this->setMailNotification($testsettings["mailnotification"]);
10040 $this->setMailNotificationType($testsettings["mailnottype"]);
10041 $this->setExportSettings($testsettings['exportsettings']);
10042 $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
10043 $this->setObligationsEnabled($testsettings["obligations_enabled"]);
10044 $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
10045 $this->setHighscoreEnabled($testsettings['highscore_enabled']);
10046 $this->setHighscoreAnon($testsettings['highscore_anon']);
10047 $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
10048 $this->setHighscoreScore($testsettings['highscore_score']);
10049 $this->setHighscorePercentage($testsettings['highscore_percentage']);
10050 $this->setHighscoreHints($testsettings['highscore_hints']);
10051 $this->setHighscoreWTime($testsettings['highscore_wtime']);
10052 $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
10053 $this->setHighscoreTopTable($testsettings['highscore_top_table']);
10054 $this->setHighscoreTopNum($testsettings['highscore_top_num']);
10055 $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
10056 if( isset($testsettings['examid_in_kiosk']) )
10057 {
10058 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
10059 }
10060 else
10061 {
10062 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
10063 }
10064 if( isset($testsettings['show_exam_id']) )
10065 {
10066 $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
10067 }
10068 else
10069 {
10070 $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
10071 }
10072 $this->setEnableExamview($testsettings['enable_examview']);
10073 $this->setShowExamviewHtml($testsettings['show_examview_html']);
10074 $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
10075 $this->setEnableArchiving($testsettings['enable_archiving']);
10076 $this->setSignSubmission($testsettings['sign_submission']);
10077 $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
10078 $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
10079 $this->setSkillServiceEnabled((bool)$testsettings['skill_service']);
10080 $this->setResultFilterTaxIds((array)$testsettings['result_tax_filters']);
10081 $this->setShowGradingStatusEnabled((bool)$testsettings['show_grading_status']);
10082 $this->setShowGradingMarkEnabled((bool)$testsettings['show_grading_mark']);
10083
10084 $this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
10085 $this->setRedirectionMode($testsettings['redirection_mode']);
10086 $this->setRedirectionUrl($testsettings['redirection_url']);
10087
10088 $this->setAutosave($testsettings['autosave']);
10089 $this->setAutosaveIval($testsettings['autosave_ival']);
10090 $this->setShowExamIdInTestResultsEnabled((int)$testsettings['examid_in_test_res']);
10091 $this->setPasswordEnabled($testsettings['password_enabled']);
10092 $this->setPassword($testsettings['password']);
10093 $this->setFixedParticipants($testsettings['fixed_participants'] );
10094 $this->setLimitUsersEnabled($testsettings['limit_users_enabled']);
10095 $this->setAllowedUsers($testsettings['allowedusers']);
10096 $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
10097 $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
10098 $this->setPoolUsage($testsettings['pool_usage']);
10099 $this->setActivationLimited($testsettings['activation_limited']);
10100 $this->setActivationStartingTime($testsettings['activation_start_time']);
10101 $this->setActivationEndingTime($testsettings['activation_end_time']);
10102 $this->setActivationVisibility($testsettings['activation_visibility']);
10103
10104 $this->saveToDb();
10105
10106 return true;
10107 }
10108
10116 function processPrintoutput2FO($print_output)
10117 {
10118 if (extension_loaded("tidy"))
10119 {
10120 $config = array(
10121 "indent" => false,
10122 "output-xml" => true,
10123 "numeric-entities" => true
10124 );
10125 $tidy = new tidy();
10126 $tidy->parseString($print_output, $config, 'utf8');
10127 $tidy->cleanRepair();
10128 $print_output = tidy_get_output($tidy);
10129 $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
10130 }
10131 else
10132 {
10133 $print_output = str_replace("&nbsp;", "&#160;", $print_output);
10134 $print_output = str_replace("&otimes;", "X", $print_output);
10135 }
10136 $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
10137
10138 // additional font support
10139 $xsl = str_replace(
10140 'font-family="Helvetica, unifont"',
10141 'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
10142 $xsl
10143 );
10144
10145 $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
10146 $xh = xslt_create();
10147 $params = array();
10148 $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
10149 xslt_error($xh);
10150 xslt_free($xh);
10151 return $output;
10152 }
10153
10160 public function deliverPDFfromHTML($content, $title = NULL)
10161 {
10162 $content = preg_replace("/href=\".*?\"/", "", $content);
10163 $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", TRUE, TRUE, "Modules/Test");
10164 $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
10165 $printbody->setVariable("ADM_CONTENT", $content);
10166 $printbody->setCurrentBlock("css_file");
10167 $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
10168 $printbody->parseCurrentBlock();
10169 $printbody->setCurrentBlock("css_file");
10170 $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
10171 $printbody->parseCurrentBlock();
10172 $printoutput = $printbody->get();
10173 $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
10174 $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
10175 if (extension_loaded("tidy"))
10176 {
10177 $config = array(
10178 "indent" => false,
10179 "output-xml" => true,
10180 "numeric-entities" => true
10181 );
10182 $tidy = new tidy();
10183 $tidy->parseString($html, $config, 'utf8');
10184 $tidy->cleanRepair();
10185 $html = tidy_get_output($tidy);
10186 $html = preg_replace("/^.*?(<html)/", "\\1", $html);
10187 }
10188 else
10189 {
10190 $html = str_replace("&nbsp;", "&#160;", $html);
10191 $html = str_replace("&otimes;", "X", $html);
10192 }
10193 $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
10194 $this->deliverPDFfromFO($this->processPrintoutput2FO($html), $title);
10195 }
10196
10203 public function deliverPDFfromFO($fo, $title = null)
10204 {
10205 global $ilLog;
10206
10207 include_once "./Services/Utilities/classes/class.ilUtil.php";
10208 $fo_file = ilUtil::ilTempnam() . ".fo";
10209 $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
10210
10211 include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
10212 try
10213 {
10214 $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
10215 $filename = (strlen($title)) ? $title : $this->getTitle();
10216 ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10217 return true;
10218 }
10219 catch(XML_RPC2_FaultException $e)
10220 {
10221 $ilLog->write(__METHOD__.': '.$e->getMessage());
10222 return false;
10223 }
10224 catch(Exception $e)
10225 {
10226 $ilLog->write(__METHOD__.': '.$e->getMessage());
10227 return false;
10228 }
10229
10230 /*
10231 include_once "./Services/Transformation/classes/class.ilFO2PDF.php";
10232 $fo2pdf = new ilFO2PDF();
10233 $fo2pdf->setFOString($fo);
10234 $result = $fo2pdf->send();
10235 $filename = (strlen($title)) ? $title : $this->getTitle();
10236 ilUtil::deliverData($result, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10237 */
10238 }
10239
10249 static function getManualFeedback($active_id, $question_id, $pass)
10250 {
10251 global $ilDB;
10252 $feedback = "";
10253 $result = $ilDB->queryF("SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10254 array('integer', 'integer', 'integer'),
10255 array($active_id, $question_id, $pass)
10256 );
10257 if ($result->numRows())
10258 {
10259 $row = $ilDB->fetchAssoc($result);
10260 include_once("./Services/RTE/classes/class.ilRTE.php");
10261 $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
10262 }
10263 return $feedback;
10264 }
10265
10276 function saveManualFeedback($active_id, $question_id, $pass, $feedback)
10277 {
10278 global $ilDB;
10279
10280 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10281 array('integer', 'integer', 'integer'),
10282 array($active_id, $question_id, $pass)
10283 );
10284
10285 if (strlen($feedback))
10286 {
10287 $next_id = $ilDB->nextId('tst_manual_fb');
10289 $result = $ilDB->insert('tst_manual_fb', array(
10290 'manual_feedback_id' => array( 'integer', $next_id ),
10291 'active_fi' => array( 'integer', $active_id ),
10292 'question_fi' => array( 'integer', $question_id ),
10293 'pass' => array( 'integer', $pass),
10294 'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0) ),
10295 'tstamp' => array( 'integer', time() ),
10296 )
10297 );
10298 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10300 {
10301 global $lng, $ilUser;
10302 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
10303 $username = ilObjTestAccess::_getParticipantData($active_id);
10304 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10305 $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
10306 }
10307 }
10308 if (PEAR::isError($result))
10309 {
10310 global $ilias;
10311 $ilias->raiseError($result->getMessage());
10312 }
10313 else
10314 {
10315 return TRUE;
10316 }
10317 }
10318
10327 {
10328 return TRUE;
10329
10330// global $ilUser;
10331// if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
10332// if ($this->getForceJS()) return TRUE;
10333// $assessmentSetting = new ilSetting("assessment");
10334// return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
10335 }
10336
10337 function &createTestSequence($active_id, $pass, $shuffle)
10338 {
10339 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10340 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10341 }
10342
10348 public function setTestId($a_id)
10349 {
10350 $this->test_id = $a_id;
10351 }
10352
10361 function getDetailedTestResults($participants)
10362 {
10363 $results = array();
10364 if (count($participants))
10365 {
10366 foreach ($participants as $active_id => $user_rec)
10367 {
10368 $row = array();
10369 $reached_points = 0;
10370 $max_points = 0;
10371 foreach ($this->questions as $value)
10372 {
10373 $question =& ilObjTest::_instanciateQuestion($value);
10374 if (is_object($question))
10375 {
10376 $max_points += $question->getMaximumPoints();
10377 $reached_points += $question->getReachedPoints($active_id);
10378 if ($max_points > 0)
10379 {
10380 $percentvalue = $reached_points / $max_points;
10381 if ($percentvalue < 0) $percentvalue = 0.0;
10382 }
10383 else
10384 {
10385 $percentvalue = 0;
10386 }
10387 if ($this->getAnonymity())
10388 {
10389 $user_rec['firstname'] = "";
10390 $user_rec['lastname'] = $this->lng->txt("anonymous");
10391 }
10392 $row = array(
10393 "user_id"=>$user_rec['usr_id'],
10394 "matriculation" => $user_rec['matriculation'],
10395 "lastname" => $user_rec['lastname'],
10396 "firstname" => $user_rec['firstname'],
10397 "login"=>$user_rec['login'],
10398 "question_id" => $question->getId(),
10399 "question_title" => $question->getTitle(),
10400 "reached_points" => $reached_points,
10401 "max_points" => $max_points
10402 );
10403 $results[] = $row;
10404 }
10405 }
10406 }
10407 }
10408 return $results;
10409 }
10410
10415 {
10416 global $ilDB;
10417
10418 $result = $ilDB->queryF("SELECT t.obj_fi obj_id FROM tst_test_question q, tst_tests t WHERE q.test_fi = t.test_id AND q.question_fi = %s",
10419 array('integer'),
10420 array($a_q_id)
10421 );
10422 $rec = $ilDB->fetchAssoc($result);
10423 return $rec["obj_id"];
10424 }
10425
10432 function isPluginActive($a_pname)
10433 {
10434 global $ilPluginAdmin;
10435 if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname))
10436 {
10437 return TRUE;
10438 }
10439 else
10440 {
10441 return FALSE;
10442 }
10443 }
10444
10445 public function getPassed($active_id)
10446 {
10447 global $ilDB;
10448
10449 $result = $ilDB->queryF("SELECT passed FROM tst_result_cache WHERE active_fi = %s",
10450 array('integer'),
10451 array($active_id)
10452 );
10453 if ($result->numRows())
10454 {
10455 $row = $ilDB->fetchAssoc($result);
10456 return $row['passed'];
10457 }
10458 else
10459 {
10460 $counted_pass = ilObjTest::_getResultPass($active_id);
10461 $result_array =& $this->getTestResult($active_id, $counted_pass);
10462 return $result_array["test"]["passed"];
10463 }
10464 }
10465
10471 function canShowCertificate($testSession, $user_id, $active_id)
10472 {
10473 if ($this->canShowTestResults($testSession, $user_id))
10474 {
10475 include_once "./Services/Certificate/classes/class.ilCertificate.php";
10476 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
10477 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
10478 if ($cert->isComplete())
10479 {
10480 $vis = $this->getCertificateVisibility();
10481 $showcert = FALSE;
10482 switch ($vis)
10483 {
10484 case 0:
10485 $showcert = TRUE;
10486 break;
10487 case 1:
10488 if ($this->getPassed($active_id))
10489 {
10490 $showcert = TRUE;
10491 }
10492 break;
10493 case 2:
10494 $showcert = FALSE;
10495 break;
10496 }
10497 if ($showcert)
10498 {
10499 return TRUE;
10500 }
10501 else
10502 {
10503 return FALSE;
10504 }
10505 }
10506 else
10507 {
10508 return FALSE;
10509 }
10510 }
10511 else
10512 {
10513 return FALSE;
10514 }
10515 }
10516
10520 public function getParticipantsForTestAndQuestion($test_id, $question_id)
10521 {
10523 global $ilDB;
10524
10525 $query = "
10526 SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10527 FROM tst_test_result, tst_active, qpl_questions
10528 WHERE tst_active.active_id = tst_test_result.active_fi
10529 AND tst_active.test_fi = %s
10530 AND tst_test_result.question_fi = qpl_questions.question_id
10531 AND tst_test_result.question_fi = %s";
10532
10533 $result = $ilDB->queryF($query,
10534 array('integer', 'integer'),
10535 array($test_id, $question_id)
10536 );
10537 $foundusers = array();
10539 while ($row = $ilDB->fetchAssoc($result))
10540 {
10541 if (!array_key_exists($row["active_fi"], $foundusers))
10542 {
10543 $foundusers[$row["active_fi"]] = array();
10544 }
10545 array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10546 }
10547 return $foundusers;
10548 }
10549
10556 {
10557 $data =& $this->getCompleteEvaluationData();
10558 $foundParticipants =& $data->getParticipants();
10559 $results = array("overview" => array(), "questions" => array());
10560 if (count($foundParticipants))
10561 {
10562 $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10563 $total_finished = $this->evalTotalFinished();
10564 $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10565 $average_time = $this->evalTotalStartedAverageTime();
10566 $diff_seconds = $average_time;
10567 $diff_hours = floor($diff_seconds/3600);
10568 $diff_seconds -= $diff_hours * 3600;
10569 $diff_minutes = floor($diff_seconds/60);
10570 $diff_seconds -= $diff_minutes * 60;
10571 $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10572 $total_passed = 0;
10573 $total_passed_reached = 0;
10574 $total_passed_max = 0;
10575 $total_passed_time = 0;
10576 foreach ($foundParticipants as $userdata)
10577 {
10578 if ($userdata->getPassed())
10579 {
10580 $total_passed++;
10581 $total_passed_reached += $userdata->getReached();
10582 $total_passed_max += $userdata->getMaxpoints();
10583 $total_passed_time += $userdata->getTimeOfWork();
10584 }
10585 }
10586 $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10587 $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10588 $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10589 $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10590 $results["overview"][$this->lng->txt("tst_eval_total_passed_average_points")] = sprintf("%2.2f", $average_passed_reached) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%2.2f", $average_passed_max);
10591 $average_time = $average_passed_time;
10592 $diff_seconds = $average_time;
10593 $diff_hours = floor($diff_seconds/3600);
10594 $diff_seconds -= $diff_hours * 3600;
10595 $diff_minutes = floor($diff_seconds/60);
10596 $diff_seconds -= $diff_minutes * 60;
10597 $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10598 }
10599
10600 foreach ($data->getQuestionTitles() as $question_id => $question_title)
10601 {
10602 $answered = 0;
10603 $reached = 0;
10604 $max = 0;
10605 foreach ($foundParticipants as $userdata)
10606 {
10607 for ($i = 0; $i <= $userdata->getLastPass(); $i++)
10608 {
10609 if (is_object($userdata->getPass($i)))
10610 {
10611 $question =& $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10612 if (is_array($question))
10613 {
10614 $answered++;
10615 $reached += $question["reached"];
10616 $max += $question["points"];
10617 }
10618 }
10619 }
10620 }
10621 $percent = $max ? $reached/$max * 100.0 : 0;
10622 $counter++;
10623 $results["questions"][$question_id] = array(
10624 $question_title,
10625 sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10626 sprintf("%.2f", $percent) . "%",
10627 $answered,
10628 sprintf("%.2f", $answered ? $reached / $answered : 0),
10629 sprintf("%.2f", $answered ? $max / $answered : 0),
10630 $percent / 100.0
10631 );
10632 }
10633 return $results;
10634 }
10635
10639 function getXMLZip()
10640 {
10641 include_once("./Modules/Test/classes/class.ilTestExport.php");
10642 $test_exp = new ilTestExport($this, "xml");
10643 return $test_exp->buildExportFile();
10644 }
10645
10649 public function getMailNotification()
10650 {
10652 }
10653
10659 public function setMailNotification($a_notification)
10660 {
10661 $this->mailnotification = $a_notification;
10662 }
10663
10664 public function sendSimpleNotification($active_id)
10665 {
10666 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10667
10668 $mail = new ilTestMailNotification();
10669 $owner_id = $this->getOwner();
10670 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10671 $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10672 }
10673
10680 {
10681 include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10682 include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10683 $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(), 'outEvaluation', $this->getAnonymity());
10684 return $table_gui->getSelectedColumns();
10685 }
10686
10687 public function sendAdvancedNotification($active_id)
10688 {
10689 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10690
10691 $mail = new ilTestMailNotification();
10692 $owner_id = $this->getOwner();
10693 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10694
10695 include_once "./Modules/Test/classes/class.ilTestExport.php";
10696 $exportObj = new ilTestExport($this, "results");
10697 $file = $exportObj->exportToExcel($deliver = FALSE, 'active_id', $active_id, $passedonly = FALSE);
10698 include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10699 $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10700 $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10701 $file_names[] = "result_" . $active_id . ".xls";
10702
10703 $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10704
10705 if(count($file_names))
10706 {
10707 $fd->unlinkFiles($file_names);
10708 unset($fd);
10709 @unlink($file);
10710 }
10711 }
10712
10713 function createRandomSolutions($number)
10714 {
10715 global $ilDB;
10716
10717 // 1. get a user
10718 $query = "SELECT usr_id FROM usr_data";
10719 $result = $ilDB->query($query);
10720 while ($data = $ilDB->fetchAssoc($result))
10721 {
10722 $activequery = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10723 $ilDB->quote($this->getTestId()),
10724 $ilDB->quote($data['usr_id'])
10725 );
10726 $activeresult = $ilDB->query($activequery);
10727 if ($activeresult->numRows() == 0)
10728 {
10729 $user_id = $data['usr_id'];
10730 if ($user_id != 13)
10731 {
10732 include_once "./Modules/Test/classes/class.ilTestSession.php";
10733 $testSession = FALSE;
10735 $testSession->setRefId($this->getRefId());
10736 $testSession->setTestId($this->getTestId());
10737 $testSession->setUserId($user_id);
10738 $testSession->saveToDb();
10739 $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10740 $nr_of_passes = rand(1, $passes);
10741 $active_id = $testSession->getActiveId();
10742 for ($pass = 0; $pass < $nr_of_passes; $pass++)
10743 {
10744 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10745 $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10746 if (!$testSequence->hasSequence())
10747 {
10748 $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10749 $testSequence->saveToDb();
10750 }
10751 for ($seq = 1; $seq <= count($this->questions); $seq++)
10752 {
10753 $question_id = $testSequence->getQuestionForSequence($seq);
10754 $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10755 $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10756 }
10757 if ($pass < $nr_of_passes - 1)
10758 {
10759 $testSession->increasePass();
10760 $testSession->setLastSequence(0);
10761 $testSession->saveToDb();
10762 }
10763 else
10764 {
10765 $testSession->setSubmitted(1);
10766 $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10767 $testSession->saveToDb();
10768 }
10769 }
10770 $number--;
10771 if ($number == 0) return;
10772 }
10773 }
10774 }
10775 }
10776
10777 public function getResultsForActiveId($active_id)
10778 {
10779 global $ilDB;
10780
10781 $query = "
10782 SELECT *
10783 FROM tst_result_cache
10784 WHERE active_fi = %s
10785 ";
10786
10787 $result = $ilDB->queryF(
10788 $query, array('integer'), array($active_id)
10789 );
10790
10791 if( !$result->numRows() )
10792 {
10793 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10794
10796
10797 $query = "
10798 SELECT *
10799 FROM tst_result_cache
10800 WHERE active_fi = %s
10801 ";
10802
10803 $result = $ilDB->queryF(
10804 $query, array('integer'), array($active_id)
10805 );
10806 }
10807
10808 $row = $ilDB->fetchAssoc($result);
10809
10810 return $row;
10811
10812 }
10813
10814 public function getMailNotificationType()
10815 {
10816 if ($this->mailnottype == 1)
10817 {
10818 return $this->mailnottype;
10819 }
10820 else
10821 {
10822 return 0;
10823 }
10824 }
10825
10826 public function setMailNotificationType($a_type)
10827 {
10828 if ($a_type == 1)
10829 {
10830 $this->mailnottype = 1;
10831 }
10832 else
10833 {
10834 $this->mailnottype = 0;
10835 }
10836 }
10837
10838 public function getExportSettings()
10839 {
10840 if ($this->exportsettings)
10841 {
10842 return $this->exportsettings;
10843 }
10844 else
10845 {
10846 return 0;
10847 }
10848 }
10849
10850 public function setExportSettings($a_settings)
10851 {
10852 if ($a_settings)
10853 {
10854 $this->exportsettings = $a_settings;
10855 }
10856 else
10857 {
10858 $this->exportsettings = 0;
10859 }
10860 }
10861
10863 {
10864 if (($this->exportsettings & 1) > 0)
10865 {
10866 return true;
10867 }
10868 else
10869 {
10870 return false;
10871 }
10872 }
10873
10874 public function setExportSettingsSingleChoiceShort($a_settings)
10875 {
10876 if ($a_settings)
10877 {
10878 $this->exportsettings = $this->exportsettings | 1;
10879 }
10880 else
10881 {
10883 {
10884 $this->exportsettings = $this->exportsettings ^ 1;
10885 }
10886 }
10887 }
10888
10889 public function getEnabledViewMode() {
10890 return $this->enabled_view_mode;
10891 }
10892
10893 public function setEnabledViewMode($mode) {
10894 $this->enabled_view_mode = $mode;
10895 }
10896
10898 $this->template_id = (int)$template_id;
10899 }
10900
10901 function getTemplate() {
10902 return $this->template_id;
10903 }
10904
10905 public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
10906 $new_array = array();
10907 $position = 1;
10908
10909 $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10910 $types = array('integer');
10911 $values = array($this->getTestId());
10912
10913 $new_question_id += 1;
10914
10915 global $ilDB;
10916 $inserted = false;
10917 $res = $ilDB->queryF($query, $types, $values);
10918 while($row = $ilDB->fetchAssoc($res)) {
10919
10920 $qid = $row['question_fi'];
10921
10922 if ($qid == $new_question_id) {
10923 continue;
10924 }
10925 else if ($qid == $previous_question_id) {
10926 $new_array[$position++] = $qid;
10927 $new_array[$position++] = $new_question_id;
10928 $inserted = true;
10929 }
10930 else {
10931 $new_array[$position++] = $qid;
10932 }
10933 }
10934
10935 $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10936 $update_types = array('integer', 'integer', 'integer');
10937
10938 foreach($new_array as $position => $qid) {
10939 $ilDB->manipulateF(
10940 $update_query,
10941 $update_types,
10942 $vals = array(
10943 $position,
10944 $this->getTestId(),
10945 $qid
10946 )
10947 );
10948 }
10949 }
10950
10952 {
10953 if (is_array($options))
10954 {
10955 $this->setGenericAnswerFeedback( in_array('instant_feedback_generic', $options) ? 1 : 0);
10956 $this->setSpecificAnswerFeedback( in_array('instant_feedback_specific', $options) ? 1 : 0);
10957 $this->setAnswerFeedbackPoints( in_array('instant_feedback_points', $options) ? 1 : 0);
10958 $this->setInstantFeedbackSolution( in_array('instant_feedback_solution', $options) ? 1 : 0);
10959 $this->setInstantFeedbackAnswerFixationEnabled( in_array('instant_feedback_answer_fixation', $options) ? true : false);
10960 }
10961 else
10962 {
10963 $this->setGenericAnswerFeedback(0);
10964 $this->setSpecificAnswerFeedback(0);
10965 $this->setAnswerFeedbackPoints(0);
10968 }
10969 }
10970
10972 $setter = array(
10973 'pass_details' => 'setShowPassDetails',
10974 'solution_details' => 'setShowSolutionDetails',
10975 'solution_printview' => 'setShowSolutionPrintview',
10976 'solution_feedback' => 'setShowSolutionFeedback',
10977 'solution_answers_only' => 'setShowSolutionAnswersOnly',
10978 'solution_signature' => 'setShowSolutionSignature',
10979 'solution_suggested' => 'setShowSolutionSuggested',
10980 );
10981 foreach($setter as $key => $setter) {
10982 if (in_array($key, $options)) {
10983 $this->$setter(1);
10984 }
10985 else {
10986 $this->$setter(0);
10987 }
10988 }
10989 }
10990
10991 public function getPoolUsage() {
10992 return (boolean) $this->poolUsage;
10993 }
10994
10995 public function setPoolUsage($usage) {
10996 $this->poolUsage = (boolean)$usage;
10997 }
10998
10999 public function setQuestionOrderAndObligations($orders, $obligations)
11000 {
11001 global $ilDB;
11002
11003 asort($orders);
11004
11005 $i = 0;
11006
11007 foreach($orders as $id => $position)
11008 {
11009 $i++;
11010
11011 $obligatory = (
11012 isset($obligations[$id]) && $obligations[$id] ? 1 : 0
11013 );
11014
11015 $query = "
11016 UPDATE tst_test_question
11017 SET sequence = %s,
11018 obligatory = %s
11019 WHERE question_fi = %s
11020 ";
11021
11022 $ilDB->manipulateF(
11023 $query, array('integer', 'integer', 'integer'), array($i, $obligatory, $id)
11024 );
11025 }
11026
11027 $this->loadQuestions();
11028 }
11029
11030 public function moveQuestionAfter($question_to_move, $question_before) {
11031 global $ilDB;
11032 //var_dump(func_get_args());
11033 if ($question_before) {
11034 $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
11035 $types = array('integer');
11036 $values = array($question_before);
11037 $rset = $ilDB->queryF($query, $types, $values);
11038 }
11039
11040 if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
11041 $row = array(
11042 'sequence' => 0,
11043 'test_fi' => $this->getTestId(),
11044 );
11045 }
11046
11047 $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
11048 $types = array('integer', 'integer');
11049 $values = array($row['sequence'], $row['test_fi']);
11050 $ilDB->manipulateF($update, $types, $values);
11051
11052 $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
11053 $types = array('integer', 'integer');
11054 $values = array($row['sequence'] + 1, $question_to_move);
11055 $ilDB->manipulateF($update, $types, $values);
11056
11057 }
11058
11060 {
11061 global $ilDB;
11062
11064
11065 $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
11066
11067 $query = "
11068 SELECT count(q1.question_id) cnt
11069
11070 FROM qpl_questions q1
11071
11072 INNER JOIN qpl_questions q2
11073 ON q2.question_id = q1.original_id
11074
11075 WHERE $IN_questions
11076 AND q1.obj_fi = q2.obj_fi
11077 ";
11078
11079 $rset = $ilDB->query($query);
11080
11081 $row = $ilDB->fetchAssoc($rset);
11082
11083 return $row['cnt'] > 0;
11084 }
11085
11092 public static function _lookupFinishedUserTests($a_user_id)
11093 {
11094 global $ilDB;
11095
11096 $result = $ilDB->queryF("SELECT test_fi,MAX(pass) AS pass FROM tst_active".
11097 " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)".
11098 " WHERE user_fi=%s".
11099 " GROUP BY test_fi",
11100 array('integer', 'integer'),
11101 array($a_user_id, 1)
11102 );
11103 $all = array();
11104 while($row = $ilDB->fetchAssoc($result))
11105 {
11106 $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
11107 $all[$obj_id] = (bool)$row["pass"];
11108 }
11109 return $all;
11110 }
11111 public function getQuestions()
11112 {
11113 return $this->questions;
11114 }
11115
11116 public function isOnline()
11117 {
11118 return $this->online;
11119 }
11120
11121 public function setOnline($a_online = true)
11122 {
11123 $this->online = (bool)$a_online;
11124 }
11125
11126 public function setPrintBestSolutionWithResult($status)
11127 {
11128 $this->print_best_solution_with_result = (bool) $status;
11129 }
11130
11132 {
11134 }
11135
11142 {
11144 }
11145
11152 {
11153 $this->offeringQuestionHintsEnabled = (bool)$offeringQuestionHintsEnabled;
11154 }
11155
11156 function setActivationVisibility($a_value)
11157 {
11158 $this->activation_visibility = (bool) $a_value;
11159 }
11160
11162 {
11164 }
11165
11167 {
11168 return (bool)$this->activation_limited;
11169 }
11170
11171 function setActivationLimited($a_value)
11172 {
11173 $this->activation_limited = (bool)$a_value;
11174 }
11175
11176 /* GET/SET for highscore feature */
11177
11183 public function setHighscoreEnabled($a_enabled)
11184 {
11185 $this->_highscore_enabled = (bool)$a_enabled;
11186 }
11187
11193 public function getHighscoreEnabled()
11194 {
11195 return (bool) $this->_highscore_enabled;
11196 }
11197
11205 public function setHighscoreAnon($a_anon)
11206 {
11207 $this->_highscore_anon = (bool)$a_anon;
11208 }
11209
11219 public function getHighscoreAnon()
11220 {
11221 return (bool) $this->_highscore_anon;
11222 }
11223
11232 public function isHighscoreAnon()
11233 {
11234 if ($this->getAnonymity() == 1)
11235 {
11236 return true;
11237 }
11238 else
11239 {
11240 return (bool)$this->getHighscoreAnon();
11241 }
11242 }
11243
11249 public function setHighscoreAchievedTS($a_achieved_ts)
11250 {
11251 $this->_highscore_achieved_ts = (bool)$a_achieved_ts;
11252 }
11253
11259 public function getHighscoreAchievedTS()
11260 {
11261 return (bool) $this->_highscore_achieved_ts;
11262 }
11263
11269 public function setHighscoreScore($a_score)
11270 {
11271 $this->_highscore_score = (bool)$a_score;
11272 }
11273
11279 public function getHighscoreScore()
11280 {
11281 return (bool) $this->_highscore_score;
11282 }
11283
11289 public function setHighscorePercentage($a_percentage)
11290 {
11291 $this->_highscore_percentage = (bool)$a_percentage;
11292 }
11293
11299 public function getHighscorePercentage()
11300 {
11301 return (bool) $this->_highscore_percentage;
11302 }
11303
11309 public function setHighscoreHints($a_hints)
11310 {
11311 $this->_highscore_hints = (bool)$a_hints;
11312 }
11313
11319 public function getHighscoreHints()
11320 {
11321 return (bool) $this->_highscore_hints;
11322 }
11323
11329 public function setHighscoreWTime($a_wtime)
11330 {
11331 $this->_highscore_wtime = (bool)$a_wtime;
11332 }
11333
11339 public function getHighscoreWTime()
11340 {
11341 return (bool) $this->_highscore_wtime;
11342 }
11343
11349 public function setHighscoreOwnTable($a_own_table)
11350 {
11351 $this->_highscore_own_table = (bool)$a_own_table;
11352 }
11353
11359 public function getHighscoreOwnTable()
11360 {
11361 return (bool) $this->_highscore_own_table;
11362 }
11363
11369 public function setHighscoreTopTable($a_top_table)
11370 {
11371 $this->_highscore_top_table = (bool)$a_top_table;
11372 }
11373
11379 public function getHighscoreTopTable()
11380 {
11381 return (bool) $this->_highscore_top_table;
11382 }
11383
11390 public function setHighscoreTopNum($a_top_num)
11391 {
11392 $this->_highscore_top_num = (int)$a_top_num;
11393 }
11394
11403 public function getHighscoreTopNum($a_retval = 10)
11404 {
11405 $retval = $a_retval;
11406 if ( (int) $this->_highscore_top_num != 0)
11407 {
11408 $retval = $this->_highscore_top_num;
11409 }
11410
11411 return $retval;
11412 }
11413
11417 public function getHighscoreMode()
11418 {
11419 switch(true)
11420 {
11421 case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
11423 break;
11424
11425 case $this->getHighscoreTopTable():
11427 break;
11428
11429 case $this->getHighscoreOwnTable():
11430 default:
11432 break;
11433 }
11434 }
11435
11439 public function setHighscoreMode($mode)
11440 {
11441 switch($mode)
11442 {
11444 $this->setHighscoreTopTable(1);
11445 $this->setHighscoreOwnTable(1);
11446 break;
11447
11449 $this->setHighscoreTopTable(1);
11450 $this->setHighscoreOwnTable(0);
11451 break;
11452
11454 default:
11455 $this->setHighscoreTopTable(0);
11456 $this->setHighscoreOwnTable(1);
11457 break;
11458 }
11459 }
11460 /* End GET/SET for highscore feature*/
11461
11462 public function setSpecificAnswerFeedback($specific_answer_feedback)
11463 {
11464 switch ($specific_answer_feedback)
11465 {
11466 case 1:
11467 $this->specific_answer_feedback = 1;
11468 break;
11469 default:
11470 $this->specific_answer_feedback = 0;
11471 break;
11472 }
11473 }
11474
11476 {
11477 switch ($this->specific_answer_feedback)
11478 {
11479 case 1:
11480 return 1;
11481 default:
11482 return 0;
11483 }
11484 }
11485
11492 {
11493 $this->obligationsEnabled = (bool)$obligationsEnabled;
11494 }
11495
11501 public function areObligationsEnabled()
11502 {
11503 return (bool)$this->obligationsEnabled;
11504 }
11505
11512 public static function isQuestionObligationPossible($questionId)
11513 {
11514 require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11515
11516 $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11517
11518 assQuestion::_includeClass($classConcreteQuestion, 0);
11519
11520 // static binder is not at work yet (in PHP < 5.3)
11521 //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11522 $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11523
11524 return $obligationPossible;
11525 }
11526
11533 public static function isQuestionObligatory($question_id)
11534 {
11535 global $ilDB;
11536
11537 $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11538
11539 if( $row = $ilDB->fetchAssoc($rset) )
11540 {
11541 return (bool) $row['obligatory'];
11542 }
11543
11544 return false;
11545 }
11546
11559 public static function allObligationsAnswered($test_id, $active_id, $pass)
11560 {
11561 global $ilDB;
11562
11563 $rset = $ilDB->queryF(
11564 'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11565 array('integer', 'integer'),
11566 array($active_id, $pass)
11567 );
11568
11569 if( $row = $ilDB->fetchAssoc($rset) )
11570 {
11571 return (bool)$row['obligations_answered'];
11572 }
11573
11575 }
11576
11585 public static function hasObligations($test_id)
11586 {
11587 global $ilDB;
11588
11589 $rset = $ilDB->queryF(
11590 'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11591 array('integer'), array($test_id)
11592 );
11593
11594 $row = $ilDB->fetchAssoc($rset);
11595
11596 return (bool)$row['cnt'] > 0;
11597 }
11598
11599 public function setAutosave($autosave)
11600 {
11601 $this->autosave = $autosave;
11602 }
11603
11604 public function getAutosave()
11605 {
11606 return $this->autosave;
11607 }
11608
11610 {
11611 $this->autosave_ival = $autosave_ival;
11612 }
11613
11614 public function getAutosaveIval()
11615 {
11616 return $this->autosave_ival;
11617 }
11618
11624 public function isPassDeletionAllowed()
11625 {
11627 }
11628
11635 {
11636 $this->passDeletionAllowed = (bool)$passDeletionAllowed;
11637 }
11638
11639 #region Examview / PDF Examview
11644 {
11645 $this->show_examview_html = $show_examview_html;
11646 }
11647
11651 public function getShowExamviewHtml()
11652 {
11654 }
11655
11660 {
11661 $this->show_examview_pdf = $show_examview_pdf;
11662 }
11663
11667 public function getShowExamviewPdf()
11668 {
11670 }
11671
11676 {
11677 $this->enable_examview = $enable_examview;
11678 }
11679
11683 public function getEnableExamview()
11684 {
11686 }
11687
11688 #endregion
11689
11691 {
11692 $this->activation_starting_time = $starting_time;
11693 }
11694
11696 {
11697 $this->activation_ending_time = $ending_time;
11698 }
11699
11701 {
11702 return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
11703 }
11704
11706 {
11707 return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
11708 }
11709
11711 {
11712 global $ilDB;
11713
11714 $times = array();
11715 $result = $ilDB->query("SELECT tst_times.active_fi, tst_times.started FROM tst_times, tst_active WHERE tst_times.active_fi = tst_active.active_id ORDER BY tst_times.tstamp DESC");
11716 while ($row = $ilDB->fetchAssoc($result))
11717 {
11718 $times[$row['active_fi']] = $row['started'];
11719 }
11720 return $times;
11721 }
11722
11724 {
11725 global $ilDB;
11726
11727 $times = array();
11728 $result = $ilDB->queryF("SELECT tst_addtime.active_fi, tst_addtime.additionaltime FROM tst_addtime, tst_active WHERE tst_addtime.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
11729 array('integer'),
11730 array($this->getTestId())
11731 );
11732 while ($row = $ilDB->fetchAssoc($result))
11733 {
11734 $times[$row['active_fi']] = $row['additionaltime'];
11735 }
11736 return $times;
11737 }
11738
11739 public function getExtraTime($active_id)
11740 {
11741 global $ilDB;
11742
11743 $result = $ilDB->queryF("SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11744 array('integer'),
11745 array($active_id)
11746 );
11747 if ($result->numRows() > 0)
11748 {
11749 $row = $ilDB->fetchAssoc($result);
11750 return $row['additionaltime'];
11751 }
11752 return 0;
11753 }
11754
11755 public function addExtraTime($active_id, $minutes)
11756 {
11757 global $ilDB;
11758
11759 $participants = array();
11760 if ($active_id == 0)
11761 {
11762 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
11763 array('integer'),
11764 array($this->getTestId())
11765 );
11766 while ($row = $ilDB->fetchAssoc($result))
11767 {
11768 array_push($participants, $row['active_id']);
11769 }
11770 }
11771 else
11772 {
11773 array_push($participants, $active_id);
11774 }
11775 foreach ($participants as $active_id)
11776 {
11777 $result = $ilDB->queryF("SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11778 array('integer'),
11779 array($active_id)
11780 );
11781 if ($result->numRows() > 0)
11782 {
11783 $ilDB->manipulateF("DELETE FROM tst_addtime WHERE active_fi = %s",
11784 array('integer'),
11785 array($active_id)
11786 );
11787 }
11788
11789 $ilDB->manipulateF("UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11790 array('integer','integer','timestamp','integer'),
11791 array(0, 0, NULL, $active_id)
11792 );
11793
11794 $ilDB->manipulateF("INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11795 array('integer','integer','integer'),
11796 array($active_id, $minutes, time())
11797 );
11798
11799 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11801 {
11802 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11803 }
11804 }
11805 }
11806
11813 {
11814 $this->enable_archiving = $enable_archiving;
11815 return $this;
11816 }
11817
11821 public function getEnableArchiving()
11822 {
11824 }
11825
11826 public function getMaxPassOfTest()
11827 {
11831 global $ilDB;
11832
11833 $query = '
11834 SELECT MAX(tst_pass_result.pass) + 1 max_res
11835 FROM tst_pass_result
11836 INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11837 WHERE test_fi = '.$ilDB->quote($this->getTestId(), 'integer').'
11838 ';
11839 $res = $ilDB->query($query);
11840 $data = $ilDB->fetchAssoc($res);
11841 return (int)$data['max_res'];
11842 }
11843
11849 public function lookupExamId($active_id, $pass)
11850 {
11852 global $ilDB, $ilSetting;
11853
11854 $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11855 $exam_id_result = $ilDB->queryF( $exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ) );
11856 if ($ilDB->numRows( $exam_id_result ) == 1)
11857 {
11858 $exam_id_row = $ilDB->fetchAssoc( $exam_id_result );
11859
11860 if ($exam_id_row['exam_id'] != null)
11861 {
11862 return $exam_id_row['exam_id'];
11863 }
11864 }
11865
11866 return null;
11867 }
11868
11875 public static function buildExamId($active_id, $pass, $test_obj_id = null)
11876 {
11878 global $ilSetting;
11879
11880 $inst_id = $ilSetting->get( 'inst_id', null );
11881
11882 if($test_obj_id === null)
11883 {
11884 $obj_id = self::_getObjectIDFromActiveID($active_id);
11885 }
11886 else
11887 {
11888 $obj_id = $test_obj_id;
11889 }
11890
11891 $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11892
11893 return $examId;
11894 }
11895
11897 {
11898 $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11899 }
11900
11902 {
11904 }
11905
11910 {
11911 $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11912 }
11913
11918 {
11920 }
11921
11926 {
11927 $this->sign_submission = $sign_submission;
11928 }
11929
11933 public function getSignSubmission()
11934 {
11936 }
11937
11941 public function setCharSelectorAvailability($availability)
11942 {
11943 $this->char_selector_availability = (int) $availability;
11944 }
11945
11950 {
11952 }
11953
11957 public function setCharSelectorDefinition($definition = '')
11958 {
11959 $this->char_selector_definition = $definition;
11960 }
11961
11966 {
11968 }
11969
11970
11977 {
11978 $this->questionSetType = $questionSetType;
11979 }
11980
11986 public function getQuestionSetType()
11987 {
11989 }
11990
11998 public static function lookupQuestionSetType($objId)
11999 {
12000 global $ilDB;
12001
12002 $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
12003
12004 $res = $ilDB->queryF($query, array('integer'), array($objId));
12005
12006 $questionSetType = null;
12007
12008 while( $row = $ilDB->fetchAssoc($res) )
12009 {
12010 $questionSetType = $row['question_set_type'];
12011 }
12012
12013 return $questionSetType;
12014 }
12015
12021 public function isFixedTest()
12022 {
12024 }
12025
12031 public function isRandomTest()
12032 {
12034 }
12035
12041 public function isDynamicTest()
12042 {
12044 }
12045
12053 public static function _lookupRandomTest($a_obj_id)
12054 {
12056 }
12057
12059 {
12060 switch( $questionSetType )
12061 {
12063 return $lng->txt('tst_question_set_type_fixed');
12064
12066 return $lng->txt('tst_question_set_type_random');
12067
12069 return $lng->txt('tst_question_set_type_dynamic');
12070 }
12071
12072 throw new ilTestException('invalid question set type value given: '.$questionSetType);
12073 }
12074
12075 public function participantDataExist()
12076 {
12077 if( $this->participantDataExist === null )
12078 {
12079 $this->participantDataExist = (bool)$this->evalTotalPersons();
12080 }
12081
12083 }
12084
12086 {
12087 if ($this->getScoreReporting() == 4)
12088 {
12089 return false;
12090 }
12091
12092 if ($this->getScoreReporting() == 3 && $this->getReportingDate() > time())
12093 {
12094 return false;
12095 }
12096
12097 return true;
12098 }
12099
12100 public function recalculateScores($preserve_manscoring = false)
12101 {
12102 require_once 'class.ilTestScoring.php';
12103 $scoring = new ilTestScoring($this);
12104 $scoring->setPreserveManualScores($preserve_manscoring);
12105 $scoring->recalculateSolutions();
12106 }
12107
12108 public static function getPoolQuestionChangeListeners(ilDB $db, $poolObjId)
12109 {
12110 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
12111
12112 $questionChangeListeners = array(
12114 );
12115
12116 return $questionChangeListeners;
12117 }
12118
12119 public static function getTestObjIdsWithActiveForUserId($userId)
12120 {
12121 global $ilDB;
12122
12123 $query = "
12124 SELECT obj_fi
12125 FROM tst_active
12126 INNER JOIN tst_tests
12127 ON test_id = test_fi
12128 WHERE user_fi = %s
12129 ";
12130
12131 $res = $ilDB->queryF($query, array('integer'), array($userId));
12132
12133 $objIds = array();
12134
12135 while( $row = $ilDB->fetchAssoc($res) )
12136 {
12137 $objIds[] = (int)$row['obj_fi'];
12138 }
12139
12140 return $objIds;
12141 }
12142
12144 {
12145 $this->skillServiceEnabled = $skillServiceEnabled;
12146 }
12147
12148 public function isSkillServiceEnabled()
12149 {
12151 }
12152
12154 {
12155 $this->resultFilterTaxIds = $resultFilterTaxIds;
12156 }
12157
12158 public function getResultFilterTaxIds()
12159 {
12161 }
12162
12164 {
12165 if( !$this->isSkillServiceEnabled() )
12166 {
12167 return false;
12168 }
12169
12170 if( !self::isSkillManagementGloballyActivated() )
12171 {
12172 return false;
12173 }
12174
12175 return true;
12176 }
12177
12179
12180 public static function isSkillManagementGloballyActivated()
12181 {
12182 if( self::$isSkillManagementGloballyActivated === null )
12183 {
12184 include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
12185 $skmgSet = new ilSkillManagementSettings();
12186
12187 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
12188 }
12189
12191 }
12192
12194 {
12195 $this->showGradingStatusEnabled = $showGradingStatusEnabled;
12196 }
12197
12199 {
12201 }
12202
12204 {
12205 $this->showGradingMarkEnabled = $showGradingMarkEnabled;
12206 }
12207
12208
12210 {
12212 }
12213
12215 {
12216 $this->instantFeedbackAnswerFixationEnabled = $instantFeedbackAnswerFixationEnabled;
12217 }
12218
12220 {
12222 }
12223
12224 public static function ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run = FALSE)
12225 {
12226 global $ilDB, $lng, $ilPluginAdmin;
12227
12228 /* @var ilObjTest $testOBJ */
12229
12230 $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12231
12232 $activeId = $testOBJ->getActiveIdOfUser($userId);
12233
12234 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12235 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12236
12237 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12238 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12239
12240 $testSession = $testSessionFactory->getSession($activeId);
12241 $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $testSession->getPass());
12242 $testSequence->loadFromDb();
12243
12244 // begin-patch lok changed smeyer
12245 if($a_force_new_run)
12246 {
12247 if( $testSequence->hasSequence() )
12248 {
12249 $testSession->increasePass();
12250 }
12251 $testSession->setLastSequence(0);
12252 $testSession->saveToDb();
12253 }
12254 // end-patch lok
12255 }
12256
12257 public static function isParticipantsLastPassActive($testObjId, $userId)
12258 {
12259 global $ilDB, $lng, $ilPluginAdmin;
12260
12261 /* @var ilObjTest $testOBJ */
12262
12263 $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12264
12265
12266 $activeId = $testOBJ->getActiveIdOfUser($userId);
12267
12268 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12269 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12270 // Added temporarily bugfix smeyer
12271 $testSessionFactory->reset();
12272
12273 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12274 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12275
12276 $testSession = $testSessionFactory->getSession($activeId);
12277 $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $testSession->getPass());
12278 $testSequence->loadFromDb();
12279
12280 return $testSequence->hasSequence();
12281 }
12282
12286 public function isTestFinalBroken()
12287 {
12289 }
12290
12295 {
12296 $this->testFinalBroken = $testFinalBroken;
12297 }
12298}
$result
print $file
$test
Definition: Utf8Test.php:85
$filename
Definition: buildRTE.php:89
$_GET["client_id"]
A class defining mark schemas for assessment test objects.
isError($data, $code=null)
Tell whether a value is a PEAR error.
Definition: PEAR.php:279
const IL_COMP_MODULE
const IL_CAL_TIMESTAMP
_getQuestionTitle($question_id)
Returns the question title of a question with a given id.
static getFeedbackClassNameByQuestionType($questionType)
static _getOriginalId($question_id)
Returns the original id of a question.
_getSolutionMaxPass($question_id, $active_id)
Returns the maximum pass a users question solution.
_updateTestResultCache($active_id, ilAssQuestionProcessLocker $processLocker=null)
@TODO Move this to a proper place.
static _getSuggestedSolutionOutput($question_id)
Returns the output of the suggested solution.
static getGuiClassNameByQuestionType($questionType)
static _isWorkedThrough($active_id, $question_id, $pass=NULL)
Returns true if the question was worked through in the given pass Worked through means that the user ...
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
_getQuestionType($question_id)
Returns the question type of a question with a given id.
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
deleteRequestsByActiveIds($activeIds)
Deletes all hint requests relating to a testactive included in given active ids.
deleteRequestsByQuestionIds($questionIds)
Deletes all hint requests relating to a question included in given question ids.
Question page object.
Create PDF certificates.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
Database Wrapper.
Definition: class.ilDB.php:29
static formatDate(ilDateTime $date)
Format a date @access public.
@classDescription Date and time handling
TableGUI class for evaluation of all users.
This class handles all operations on files (attachments) in directory ilias_data/mail.
recursive_dirscan($dir, &$arr)
Recursively scans a given directory and writes path and filename into referenced array.
language handling
_addLog($user_id, $object_id, $logtext, $question_id="", $original_id="", $test_only=FALSE, $test_ref_id=NULL)
Add an assessment log entry.
_getLogLanguage()
retrieve the log language for assessment logging
_enabledAssessmentLogging()
check wether assessment logging is enabled or not
_getManualScoring()
Retrieve the manual scoring settings.
Class ilObjFile.
Class ilObjGroup.
Class ilObjMediaObject.
_saveUsage($a_mob_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
Save usage of mob within another container (e.g.
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
& _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
static _exists($a_id)
checks wether a lm content object with specified id exists or not
_removeUsage($a_mob_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
Remove usage of mob in another container.
& _getAvailableQuestionpools($use_object_id=FALSE, $equal_points=FALSE, $could_be_offline=FALSE, $showPath=FALSE, $with_questioncount=FALSE, $permission="read", $usr_id="")
Returns the available question pools for the active user.
_getParticipantData($active_id)
Retrieves a participant name from active id.
Class ilObjTestGUI.
static _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
{Returns the ECTS grade for a number of reached points.string The ECTS grade short description}
setHighscorePercentage($a_percentage)
Sets if the percentages of the scores pass should be shown.
setShowSolutionFeedback($a_feedback=TRUE)
Sets if the the feedback should be presented to the user in the solution or not.
getResetProcessingTime()
Returns wheather the processing time should be reset or not.
_buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
Builds a user name for the output depending on test type and existence of the user.
& _getAvailableTests($use_object_id=FALSE)
Returns the available tests for the active user.
setPrintBestSolutionWithResult($status)
setAnswerFeedback($answer_feedback=0)
Sets the generic feedback for the test @deprecate Use setGenericAnswerFeedback instead.
__construct($a_id=0, $a_call_by_reference=true)
Constructor.
_getPassScoring($active_id)
Gets the pass scoring type.
getPassed($active_id)
setIntroduction($introduction="")
Sets the introduction text of the ilObjTest object.
exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
export page objects to xml (see ilias_co.dtd)
setECTSFX($a_ects_fx)
{}
getProcessingTimeAsMinutes()
getEstimatedWorkingTime()
Returns the estimated working time for the test calculated from the working time of the contained que...
setShowInfo($a_info=1)
Set whether the complete information page is shown or the required data only.
const QUESTION_SET_TYPE_DYNAMIC
type setting value for dynamic question set (continues testing mode)
getTestId()
Gets the database id of the additional test data.
getECTSOutput()
{int|bool}
& createQuestionGUI($question_type, $question_id=-1)
Creates a question GUI instance of a given question type.
endingTimeReached()
Returns true if the ending time of a test is reached An ending time is not available for self assessm...
canShowTestResults($testSession, $user_id)
setClientIP($user_id, $client_ip)
setAllowedUsersTimeGap($a_allowed_users_time_gap)
getQuestionSetType()
getter for question set type
getQuestionTitle($title)
Returns the title of a test question and checks if the title output is allowed.
setTestId($a_id)
Sets the test ID.
& getExistingQuestions($pass=NULL)
Get the id's of the questions which are already part of the test.
getShowKioskModeParticipant()
Returns the status of the kiosk mode participant.
setKiosk($kiosk=0)
Sets the kiosk mode for the test.
getHighscoreWTime()
Gets if the column with the workingtime should be shown.
getHighscoreOwnTable()
Gets if the own rankings table should be shown.
getShowKioskModeTitle()
Returns the status of the kiosk mode title.
hasRandomQuestionsForPass($active_id, $pass)
Checkes wheather a random test has already created questions for a given pass or not.
getHighscoreTopTable()
Gets, if the top-rankings table should be shown.
getCountSystem()
Gets the count system for the calculation of points.
isShowExamIdInTestPassEnabled()
setPostponingEnabled($postponingEnabled)
setInstantFeedbackSolution($instant_feedback=0)
Sets the instant feedback for the solution.
getEnableProcessingTime()
Returns the state of the processing time (enabled/disabled)
_getObjectIDFromTestID($test_id)
Returns the ILIAS test object id for a given test id.
getListOfQuestionsStart()
Returns if the list of questions should be presented as the first page of the test.
& getCompleteEvaluationData($withStatistics=TRUE, $filterby="", $filtertext="")
loadFromDb()
Loads a ilObjTest object from a database.
pcArrayShuffle($array)
Shuffles the values of a given array.
_getTitleOutput($active_id)
Returns the value of the title_output status.
isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
Returns true, if a test is complete for use and can be set online.
getInstantFeedbackSolution()
Returns 1 if the correct solution will be shown after answering a question.
setFinalStatement($a_statement="")
Sets the final statement text of the ilObjTest object.
setFixedParticipants($a_value=1)
Sets the fixed participants status.
& getTestResult($active_id, $pass=NULL, $ordered_sequence=FALSE)
Calculates the results of a test for a given user and returns an array with all test results.
getStartingTimeOfUser($active_id, $pass=null)
Returns the unix timestamp of the time a user started a test.
_getLastAccess($active_id)
getStartTestLabel($active_id)
Returns the "Start the Test" label for the Info page.
static _getTestDefaults($test_defaults_id)
setOnline($a_online=true)
_getActiveIdOfUser($user_id="", $test_id="")
Gets the active id of the tst_active table for the active user.
& getParticipants()
Returns all persons who started the test.
setProcessingTime($processing_time="00:00:00")
Sets the processing time for the test.
setHighscoreAnon($a_anon)
Sets if the highscores should be anonymized.
setScoringFeedbackOptionsByArray($options)
getDetailedTestResults($participants)
returns all test results for all participants
_getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
setActivationEndingTime($ending_time=NULL)
setAllowedUsers($a_allowed_users)
isNrOfTriesReached($tries)
returns if number of tries are reached
_lookupAnonymity($a_obj_id)
Returns the anonymity status of a test with a given object id.
static getTestObjIdsWithActiveForUserId($userId)
setTemplate($template_id)
setShowExamviewPdf($show_examview_pdf)
_getCountSystem($active_id)
Gets the count system for the calculation of points.
setShowExamIdInTestPassEnabled($show_exam_id_in_test_pass_enabled)
inviteUser($user_id, $client_ip="")
Invites a user to a test.
setScoreCutting($a_score_cutting=SCORE_CUT_QUESTION)
Sets the type of score cutting.
getQuestionCount()
Returns the number of questions in the test.
create($a_upload=false)
create test object
getQuestiontext($question_id)
Returns the question text for a given question.
setResultsPresentationOptionsByArray($options)
QTIMaterialToString($a_material)
Reads an QTI material tag an creates a text string.
& getTestDefaults($test_defaults_id)
Returns the test defaults for a given id.
const QUESTION_SET_TYPE_RANDOM
type setting value for random question set
prepareTextareaOutput($txt_output, $prepare_for_latex_output=FALSE, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
saveAuthorToMetadata($a_author="")
Saves an authors name into the lifecycle metadata if no lifecycle metadata exists This will only be c...
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
setPassDeletionAllowed($passDeletionAllowed)
setter for the test setting passDeletionAllowed
setHighscoreScore($a_score)
Sets if the actual score should be displayed.
const HIGHSCORE_SHOW_ALL_TABLES
sendSimpleNotification($active_id)
getXMLZip()
Get zipped xml file for test.
getShowSolutionListComparison()
loadQuestions($active_id="", $pass=NULL)
Load the test question id's from the database.
createExportDirectory()
creates data directory for export files (data_dir/tst_data/tst_<id>/export, depending on data directo...
setShowGradingStatusEnabled($showGradingStatusEnabled)
getExtraTime($active_id)
& getAvailableQuestionpools($use_object_id=false, $equal_points=false, $could_be_offline=false, $show_path=FALSE, $with_questioncount=FALSE, $permission="read")
Returns the available question pools for the active user.
setListOfQuestionsStart($a_value=TRUE)
Sets if the the list of questions as the start page of the test.
_getImportDirectory()
Get the import directory location of the test.
getFixedParticipants()
Returns the fixed participants status.
isBestSolutionPrintedWithResult()
getAnsweredQuestionCount($active_id, $pass=NULL)
Retrieves the number of answered questions for a given user in a given test.
_lookupRandomTestFromActiveId($active_id)
Returns the random status of a test with a given object id.
setShowSolutionDetails($a_details=1)
Sets if the the solution details should be presented to the user or not.
& createTestSequence($active_id, $pass, $shuffle)
$show_exam_id_in_test_results_enabled
getFinalStatement()
Gets the final statement.
getProcessingTimeAsArray()
Returns the processing time for the test.
deliverPDFfromHTML($content, $title=NULL)
Delivers a PDF file from XHTML.
questionMoveDown($question_id)
Moves a question down in order.
setShowFinalStatement($show=0)
Sets whether the final statement should be shown or not.
logAction($logtext="", $question_id="")
Logs an action into the Test&Assessment log.
createMetaData()
Create meta data entry.
getEvaluationAdditionalFields()
Gets additional user fields that should be shown in the user evaluation.
setListOfQuestionsDescription($a_value=TRUE)
Sets the show_summary attribute to TRUE if the list of questions should be presented with the questio...
setEndingTimeEnabled($ending_time_enabled)
setShowPassDetails($a_details=1)
Sets if the pass details should be shown when a test is not finished.
insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly=false)
Insert a question in the list of questions.
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
buildName($user_id, $firstname, $lastname, $title)
Builds a user name for the output depending on test type and existence of the user.
hasQuestionsWithoutQuestionpool()
$print_best_solution_with_result
setCountSystem($a_count_system=COUNT_PARTIAL_SOLUTIONS)
Sets the count system for the calculation of points.
setStartingTime($starting_time=NULL)
Sets the starting time in database timestamp format for the test.
_getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
$instantFeedbackAnswerFixationEnabled
removeAllTestEditings($question_id="")
Removes all references to the question in executed tests in case the question has been changed.
setShowSolutionSuggested($a_solution=FALSE)
Set to TRUE, if the suggested solution should be shown in the solution.
getImagePath()
Returns the image path for web accessable images of a test The image path is under the CLIENT_WEB_DIR...
setActivationStartingTime($starting_time=NULL)
getShowSolutionSignature()
Returns if the signature field should be shown in the test results.
getHighscoreAnon()
Gets if the highscores should be anonymized per setting.
exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
export media objects to xml (see ilias_co.dtd)
getPassScoring()
Gets the pass scoring type.
setInstantFeedbackAnswerFixationEnabled($instantFeedbackAnswerFixationEnabled)
setHighscoreHints($a_hints)
Sets if the number of requested hints should be shown.
getPassword()
Returns the password for test access.
setPasswordEnabled($passwordEnabled)
setPassScoring($a_pass_scoring=SCORE_LAST_PASS)
Sets the pass scoring.
isHighscoreAnon()
Gets if the highscores should be displayed anonymized.
setOfferingQuestionHintsEnabled($offeringQuestionHintsEnabled)
sets offering question hints enabled/disabled
randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id=0, $qpls="", $pass=NULL)
Returns a random selection of questions.
setShowSolutionListComparison($a_comparison=FALSE)
Set to TRUE, if the list of answers should be shown prior to finish the test.
getShowSolutionAnswersOnly()
Returns if the full solution (including ILIAS content) should be presented to the solution or not.
setShowSolutionPrintview($a_printview=1)
Sets if the the solution printview should be presented to the user or not.
_setImportDirectory($a_import_dir=null)
set import directory
& evalTotalPersonsArray($name_sort_order="asc")
Returns all persons who started the test.
& evalStatistical($active_id)
Returns the statistical evaluation of the test for a specified user.
const SCORE_REPORTING_IMMIDIATLY
& getTestParticipants()
Returns a list of all participants in a test.
getStartingTime()
Returns the starting time of the test.
canEditEctsGrades()
{boolean}
startingTimeReached()
Returns true if the starting time of a test is reached A starting time is not available for self asse...
setAutosave($autosave)
& getTotalPointsPassedArray()
Returns an array with the total points of all users who passed the test This array could be used for ...
_getSolvedQuestions($active_id, $question_fi=null)
get solved questions
getShowPassDetails()
Returns if the pass details should be shown when a test is not finished.
getQuestionSetTypeTranslation(ilLanguage $lng, $questionSetType)
& evalResultsOverview()
Creates an associated array with the results of all participants of a test.
getResultsPresentation()
Returns the combined results presentation value.
$show_exam_id_in_test_pass_enabled
saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
Checks if the test is complete and saves the status in the database.
getKioskMode()
Returns the kiosk mode.
getSequenceSettings()
SEQUENCE SETTING = POSTPONING ENABLED !!
static allObligationsAnswered($test_id, $active_id, $pass)
checks wether all questions marked as obligatory were answered within the test pass with given testId...
_getBestPass($active_id)
Retrieves the best pass of a given user for a given test.
getShowSolutionFeedback()
Returns if the feedback should be presented to the solution or not.
setShowSolutionSignature($a_signature=FALSE)
Set to TRUE, if the signature field should be shown in the solution.
setHighscoreTopNum($a_top_num)
Sets the number of entries which are to be shown in the top-rankings table.
evalTotalFinished()
Returns the number of total finished tests.
getTimeExtensionsOfParticipants()
evalTotalStartedAverageTime()
Returns the average processing time for all started tests.
removeTestResultsForUser($user_id)
const QUESTION_SET_TYPE_FIXED
type setting value for fixed question set
setHighscoreEnabled($a_enabled)
Sets if the highscore feature should be enabled.
duplicateQuestionForTest($question_id)
Takes a question and creates a copy of the question for use in the test.
setRedirectionMode($redirection_mode=0)
hasSingleChoiceQuestions()
Returns TRUE if the test contains single choice results.
setMailNotification($a_notification)
Set mail notification settings.
isActiveTestSubmitted($user_id=null)
returns if the active for user_id has been submitted
setQuestionSetType($questionSetType)
setter for question set type
setReportingDate($reporting_date)
Sets the reporting date of the ilObjTest object.
static lookupQuestionSetType($objId)
lookup-er for question set type
moveQuestionAfterOLD($previous_question_id, $new_question_id)
setCharSelectorDefinition($definition='')
saveToDb($properties_only=FALSE)
Saves a ilObjTest object to a database.
setCustomStyle($a_customStyle=NULL)
Set the custom style.
setKioskMode($a_kiosk=FALSE)
Sets the kiosk mode for the test.
getKiosk()
Returns the kiosk mode.
getResultsForActiveId($active_id)
isExecutable($testSession, $user_id, $allowPassIncrease=FALSE)
Checks if the test is executable by the given user.
getShowSolutionDetails()
Returns if the solution details should be presented to the user or not.
setAuthor($author="")
Sets the authors name of the ilObjTest object.
setQuestionOrderAndObligations($orders, $obligations)
setListOfQuestions($a_value=TRUE)
Sets if the the list of questions should be presented to the user or not.
getAuthor()
Gets the authors name of the ilObjTest object.
getAnswerFeedbackPoints()
Returns 1 if answer specific feedback as reached points is activated.
setIntroductionEnabled($introductionEnabled)
getProcessingTimeInSeconds($active_id="")
Returns the processing time for the test in seconds.
inviteGroup($group_id)
Invites all users of a group to a test.
getScoreCutting()
Determines if the score of a question should be cut at 0 points or the score of the whole test.
_lookupTestObjIdForQuestionId($a_q_id)
Get test Object ID for question ID.
getHighscorePercentage()
Gets if the percentage column should be shown.
const SCORE_REPORTING_FINISHED
addDefaults($a_name)
Adds the defaults of this test to the test defaults.
getCustomStyles()
Return the available custom styles.
setCertificateVisibility($a_value)
Sets the visibility settings of the certificate.
_getMCScoring($active_id)
Gets the scoring type for multiple choice questions.
setResetProcessingTime($reset=0)
Sets wheather the processing time should be reset or not.
moveQuestions($move_questions, $target_index, $insert_mode)
Move questions to another position.
setListOfQuestionsSettings($a_value=0)
Sets the settings for the list of questions options in the test properties This could contain one of ...
isSkillServiceToBeConsidered()
sendAdvancedNotification($active_id)
modifyExportIdentifier($a_tag, $a_param, $a_value)
Returns the installation id for a given identifier.
updateWorkingTime($times_id)
Update the working time of a test when a question is answered.
static isSkillManagementGloballyActivated()
getHighscoreHints()
Gets, if the column with the number of requested hints should be shown.
getMCScoring()
Gets the scoring type for multiple choice questions.
getGenericAnswerFeedback()
Returns 1 if generic answer feedback is to be shown.
setObligationsEnabled($obligationsEnabled=true)
sets obligations enabled/disabled
setSkillServiceEnabled($skillServiceEnabled)
fromXML(ilQTIAssessment $assessment)
Receives parameters from a QTI parser and creates a valid ILIAS test object.
setHighscoreTopTable($a_top_table)
Sets if the top-rankings table should be shown.
isRandomTest()
Returns the fact wether this test is a random questions test or not.
getQuestionType($question_id)
Returns the question type of a question with a given id.
_lookupAuthor($obj_id)
Gets the authors name of the ilObjTest object.
getShowSolutionPrintview()
Returns if the solution printview should be presented to the user or not.
exportXMLMetaData(&$a_xml_writer)
export content objects meta data to xml (see ilias_co.dtd)
getShowInfo()
Gets whether the complete information page is shown or the required data only.
setListOfQuestionsEnd($a_value=TRUE)
Sets if the the list of questions as the end page of the test.
setActivationVisibility($a_value)
setQuestionSetSolved($value, $question_id, $user_id)
sets question solved state to value for given user_id
isFixedTest()
Returns the fact wether this test is a fixed question set test or not.
getMarkSchema()
{ASS_MarkSchema}
& _getCompleteWorkingTimeOfParticipants($test_id)
Returns the complete working time in seconds for all test participants.
deleteTest()
Deletes the test and all related objects, files and database entries.
setHighscoreMode($mode)
deleteDefaults($test_default_id)
Deletes the defaults for a test.
getListOfQuestionsEnd()
Returns if the list of questions should be presented as the last page of the test.
getHighscoreEnabled()
Gets the setting which determines if the highscore feature is enabled.
getReportingDate()
Gets the reporting date of the ilObjTest object.
setForceJS($a_js=1)
Set whether JavaScript should be forced for tests.
isTestFinished($active_id)
returns if the active for user_id has been submitted
static _lookupRandomTest($a_obj_id)
Returns the fact wether the test with passed obj id is a random questions test or not.
const HIGHSCORE_SHOW_OWN_TABLE
getQuestionDataset($question_id)
Returns the dataset for a given question id.
getTitleOutput()
Returns the value of the title_output status.
getAggregatedResultsData()
Returns the aggregated test results.
isDynamicTest()
Returns the fact wether this test is a dynamic question set test or not.
setShowExamIdInTestResultsEnabled($show_exam_id_in_test_results_enabled)
getHighscoreAchievedTS()
Returns if date and time of the scores achievement should be displayed.
& getQuestionTitlesAndIndexes()
Returns the titles of the test questions in question sequence.
getAllTestResults($participants, $prepareForCSV=true)
returns all test results for all participants
getListOfQuestions()
Returns if the list of questions should be presented to the user or not.
canViewResults()
Returns true, if the test results can be viewed.
isMaxProcessingTimeReached($starting_time, $active_id)
Returns whether the maximum processing time for a test is reached or not.
isHTML($a_text)
Checks if a given string contains HTML or not.
moveQuestionAfter($question_to_move, $question_before)
saveQuestionsToDb()
Saves the test questions to the database.
setShuffleQuestions($a_shuffle)
Sets the status of the shuffle_questions variable.
getUsePreviousAnswers()
Returns if the previous answers should be shown for a learner.
getAvailableQuestions($arrFilter, $completeonly=0)
Calculates the available questions for a test.
getListOfQuestionsSettings()
Returns the settings for the list of questions options in the test properties This could contain one ...
removeTestResultsByActiveIds($activeIds)
startWorkingTime($active_id, $pass)
Write the initial entry for the tests working time to the database.
getHighscoreTopNum($a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
setSpecificAnswerFeedback($specific_answer_feedback)
setMailNotificationType($a_type)
static ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run=FALSE)
setTitleOutput($title_output=0)
Sets the status of the title output.
isOfferingQuestionHintsEnabled()
returns the fact wether offering hints is enabled or not
& getGroupData($ids)
getCompleteWorkingTime($user_id)
Returns the complete working time in seconds a user worked on the test.
static buildExamId($active_id, $pass, $test_obj_id=null)
& processCSVRow($row, $quoteAll=FALSE, $separator=";")
Processes an array as a CSV row and converts the array values to correct CSV values.
& getQuestionsOfTest($active_id)
Retrieves all the assigned questions for all test passes of a test participant.
lookupExamId($active_id, $pass)
getForceJS()
Gets whether JavaScript should be forced for tests.
setPassword($a_password=NULL)
Sets the password for test access.
read($a_force_db=false)
read object data from db into object
removeTestResults(ilTestParticipantData $participantData)
applyDefaults($test_defaults)
Applies given test defaults to this test.
disinviteUser($user_id)
Disinvites a user from a test.
setAnswerFeedbackPoints($answer_feedback_points=0)
Sets the answer specific feedback of reached points for the test.
getExportDirectory()
Get the location of the export directory for the test.
setStartingTimeEnabled($starting_time_enabled)
setECTSGrades(array $a_ects_grades)
{}
static lookupQuestionSetTypeByActiveId($active_id)
returns the question set type of test relating to passed active id
& getQuestionsOfPass($active_id, $pass)
Retrieves all the assigned questions for a test participant in a given test pass.
getImagePathWeb()
Returns the web image path for web accessable images of a test The image path is under the web access...
static isQuestionObligationPossible($questionId)
checks wether the obligation for question with given id is possible or not
setActivationLimited($a_value)
_isComplete($obj_id)
Returns true, if a test is complete for use.
isShowExamIdInTestResultsEnabled()
setPoolUsage($usage)
areObligationsEnabled()
returns the fact wether obligations are enabled or not
const DEFAULT_PROCESSING_TIME_MINUTES
getEndingTime()
Returns the ending time of the test.
_getMaxPass($active_id)
Retrieves the maximum pass of a given user for a given test in which the user answered at least one q...
setHighscoreOwnTable($a_own_table)
Sets if the table with the own ranking should be shown.
saveCertificateVisibility($a_value)
Saves the visibility settings of the certificate.
setShowGradingMarkEnabled($showGradingMarkEnabled)
& _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
getCompleteWorkingTimeOfParticipant($active_id)
Returns the complete working time in seconds for a test participant.
evalTotalPersons()
Returns the number of persons who started the test.
setEnableExamview($enable_examview)
notify($a_event, $a_ref_id, $a_parent_non_rbac_id, $a_node_id, $a_params=0)
notifys an object about an event occured Based on the event happend, each object may decide how it re...
static $isSkillManagementGloballyActivated
getScoreReporting()
Gets the score reporting of the ilObjTest object.
getMailNotification()
Get mail notification settings.
setSignSubmission($sign_submission)
setEndingTime($ending_time=NULL)
Sets the ending time in database timestamp format for the test.
setEnableArchiving($enable_archiving)
& _evalResultsOverview($test_id)
Creates an associated array with the results of all participants of a test.
_getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
setResultFilterTaxIds($resultFilterTaxIds)
isInstantFeedbackAnswerFixationEnabled()
& getQuestionTitles()
Returns the titles of the test questions in question sequence.
getAllRTEContent()
Returns the content of all RTE enabled text areas in the test.
_getVisitTimeOfParticipant($test_id, $active_id)
Returns the first and last visit of a participant.
getExportSettingsSingleChoiceShort()
setShowCancel($a_value=1)
Sets the cancel test button status.
getECTSGrades()
{array}
getMarkSchemaForeignId()
{int}
addQTIMaterial(&$a_xml_writer, $a_material)
Creates a QTI material tag from a plain text or xhtml text.
static _getUserIdFromActiveId($active_id)
isPluginActive($a_pname)
Checks wheather or not a question plugin with a given name is active.
& evalTotalParticipantsArray($name_sort_order="asc")
Returns all participants who started the test.
setAutosaveIval($autosave_ival)
getAnonymity()
Returns the anonymity status of the test.
static isParticipantsLastPassActive($testObjId, $userId)
deliverPDFfromFO($fo, $title=null)
Delivers a PDF file from a XSL-FO string.
static hasObligations($test_id)
returns the fact wether the test with given test id contains questions markes as obligatory or not
setTestFinalBroken($testFinalBroken)
setResultsPresentation($a_results_presentation=3)
Sets the combined results presentation value.
removeQuestion($question_id)
Removes a question from the test object.
setLimitUsersEnabled($limitUsersEnabled)
& getWorkedQuestions($active_id, $pass=NULL)
Gets the id's of all questions a user already worked through.
toXML()
Returns a QTI xml representation of the test.
& getRoleData($ids)
isSingleChoiceTest()
Returns TRUE if the test contains single choice results only.
& evalResultsOverviewOfParticipant($active_id)
Creates an associated array with the results for a given participant of a test.
getShowCancel()
Returns wheather the cancel test button is shown or not.
getCertificateVisibility()
Returns the visibility settings of the certificate.
setHighscoreWTime($a_wtime)
Sets if the workingtime of the scores should be shown.
setShowSolutionAnswersOnly($a_full=TRUE)
Set to true, if the full solution (including the ILIAS content pages) should be shown in the solution...
setNrOfTries($nr_of_tries=0)
Sets the nr of tries for the test.
getTestStyleLocation($mode="output")
get full style sheet file name (path inclusive) of current user
$participantDataExist
holds the fact wether participant data exists or not DO NOT USE TIS PROPERTY DRIRECTLY ALWAYS USE ilO...
getHighscoreScore()
Gets if the score column should be shown.
getPassFinishDate($active_id, $pass)
Retrieves the number of answered questions for a given user in a given test.
setECTSOutput($a_ects_output)
{}
& getInvitedUsers($user_id="", $order="login, lastname, firstname")
Returns a list of all invited users in a test.
setProcessingTimeByMinutes($minutes)
static _lookupFinishedUserTests($a_user_id)
Gather all finished tests for user.
static getPoolQuestionChangeListeners(ilDB $db, $poolObjId)
canShowSolutionPrintview($user_id=NULL)
Calculates if a user may see the solution printview of his/her test results.
setRedirectionUrl($redirection_url=NULL)
setHighscoreAchievedTS($a_achieved_ts)
Sets if the date and time of the scores achievement should be displayed.
removeTestActives($activeIds)
getShowMarker()
Returns wheather the marker button is shown or not.
getImportMapping()
get array of (two) new created questions for import id
isSingleChoiceTestWithoutShuffle()
Returns TRUE if the test contains single choice results and no shuffle only.
setCharSelectorAvailability($availability)
setAnonymity($a_value=0)
Sets the anonymity status of the test.
getShuffleQuestions()
Returns the status of the shuffle_questions variable.
setShowKioskModeTitle($a_title=FALSE)
Set to true, if the full test title should be shown in kiosk mode.
_getTestIDFromObjectID($object_id)
Returns the ILIAS test id for a given object id.
$online
the object's online status
setExportSettingsSingleChoiceShort($a_settings)
& getQuestionTypeTranslations()
removeTestResultsByUserIds($userIds)
& getUserData($ids)
Returns a data of all users specified by id list.
isNewRandomTest()
Checks wheather the test is a new random test (using tst_rnd_cpy) or an old one.
getListOfQuestionsDescription()
Returns TRUE if the list of questions should be presented with the question descriptions.
getECTSGrade($passed_array, $reached_points, $max_points)
{Returns the ECTS grade for a number of reached points.string The ECTS grade short description}
getActiveIdOfUser($user_id="", $anonymous_id="")
Gets the active id of a given user.
getCustomStyle()
Get the custom style.
checkMarks()
{boolean|string True or an error string which can be used for display purposes}
recalculateScores($preserve_manscoring=false)
setEnabledViewMode($mode)
getSecondsUntilEndingTime()
Returns the seconds left from the actual time until the ending time.
isPassDeletionAllowed()
getter for the test setting passDeletionAllowed
getNrOfTries()
Returns the nr of tries for the test.
_getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
setShowExamviewHtml($show_examview_html)
const SCORE_REPORTING_DATE
setMCScoring($a_mc_scoring=SCORE_ZERO_POINTS_WHEN_UNANSWERED)
Sets the multiple choice scoring.
getTextAnswer($active_id, $question_id, $pass=NULL)
Returns the text answer of a given user for a given question.
setEnableProcessingTime($enable=0)
Sets the processing time enabled or disabled.
setUsePreviousAnswers($use_previous_answers=1)
Sets the status of the visibility of previous learner answers.
setGenericAnswerFeedback($generic_answer_feedback=0)
Sets if the generic feedback is to be shown in the test.
static getManualFeedback($active_id, $question_id, $pass)
Retrieves the manual feedback for a question in a test.
inviteRole($role_id)
Invites all users of a role to a test.
_getScoreCutting($active_id)
Determines if the score of a question should be cut at 0 points or the score of the whole test.
getJavaScriptOutput()
Returns if Javascript should be chosen for drag & drop actions for the active user.
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
getTestParticipantsForManualScoring($filter=NULL)
update()
update object data
canShowCertificate($testSession, $user_id, $active_id)
Checks whether the certificate button could be shown on the info page or not.
setShowKioskModeParticipant($a_participant=FALSE)
Set to true, if the participant's name should be shown in kiosk mode.
getNrOfResultsForPass($active_id, $pass)
Calculates the number of user results for a specific test pass.
createRandomSolutions($number)
getECTSFX()
{float|null}
setExportSettings($a_settings)
getStartingTimeOfParticipants()
addExtraTime($active_id, $minutes)
cleanupMediaobjectUsage()
Cleans up the media objects for all text fields in a test which are using an RTE field.
userLookupFullName($user_id, $overwrite_anonymity=FALSE, $sorted_order=FALSE, $suffix="")
Returns the full name of a test user according to the anonymity status.
setScoreReporting($score_reporting=0)
Sets the score reporting of the ilObjTest object.
isTestFinishedToViewResults($active_id, $currentpass)
Returns true if an active user completed a test pass and did not start a new pass.
exportFileItems($a_target_dir, &$expLog)
export files of file itmes
hasNrOfTriesRestriction()
returns if the numbers of tries have to be checked
const SCORE_REPORTING_DISABLED
getVisitTimeOfParticipant($active_id)
Returns the first and last visit of a participant.
& getAllQuestions($pass=NULL)
Returns all questions of a test in test order.
getShowFinalStatement()
Returns whether the final statement should be shown or not.
questionMoveUp($question_id)
Moves a question up in order.
getProcessingTime()
Returns the processing time for the test.
setSequenceSettings($sequence_settings=0)
SEQUENCE SETTING = POSTPONING ENABLED !!
& getCompleteWorkingTimeOfParticipants()
Returns the complete working time in seconds for all test participants.
_getWorkingTimeOfParticipantForPass($active_id, $pass)
Returns the complete working time in seconds for a test participant.
getIntroduction()
Gets the introduction text of the ilObjTest object.
getAnswerFeedback()
Returns 1 if generic answer feedback is activated.
_createImportDirectory()
creates data directory for import files (data_dir/tst_data/tst_<id>/import, depending on data directo...
const HIGHSCORE_SHOW_TOP_TABLE
exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
export pages of test to xml (see ilias_co.dtd)
setShowMarker($a_value=1)
Sets the marker button status.
static _lookupName($a_user_id)
lookup user name
_lookupClientIP($a_user_id)
Lookup client ip.
Class ilObjectActivation.
setTimingType($a_type)
Set timing type.
static getItem($a_ref_id)
Get item data.
getInstanceByRefId($a_ref_id, $stop_on_error=true)
get an instance of an Ilias object by reference id
static getInstance($a_obj_id)
Class ilObject Basic functions for all objects.
getType()
get object type @access public
getOwner()
get object owner
static _lookupObjId($a_id)
cloneObject($a_target_id, $a_copy_id=0, $a_omit_tree=false)
Clone object permissions, put in tree ...
static _lookupTitle($a_id)
lookup object title
setTitle($a_title)
set object title
ilObject($a_id=0, $a_reference=true)
Constructor @access public.
deleteMetaData()
delete meta data entry
static _lookupDescription($a_id)
lookup object description
_lookupOwner($a_id)
lookup object owner
setDescription($a_desc)
set object description
getRefId()
get reference id @access public
getDescription()
get object description
cloneMetaData($target_obj)
Copy meta data.
getId()
get object id @access public
static _prepareCloneSelection($a_ref_ids, $new_type, $show_path=true)
Prepare copy wizard object selection.
getTitle()
get object title @access public
static collectFileItems($a_page, $a_domdoc)
Get all file items that are used within the page.
static getPluginObject($a_ctype, $a_cname, $a_slot_id, $a_pname)
Get plugin object.
getPresentationMaterial()
{ilQTIPresentationMaterial|null}
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...
_cleanupMediaObjectUsage($a_text, $a_usage_type, $a_usage_id)
synchronises appearances of media objects in $a_text with media object usage table
static factory($a_package)
Create an XML_RPC2 client instance.
ILIAS Setting Class.
special template class to simplify handling of ITX/PEAR
Base Exception for all Exceptions relating to Modules/Test.
Export class for tests.
Class ilTestMailNotification.
Class ilTestScoring.
Test sequence handler.
Test session handler.
static getDataDir()
get data directory (outside webspace)
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static insertInstIntoID($a_value)
inserts installation id into ILIAS id
static prepareTextareaOutput($txt_output, $prepare_for_latex_output=FALSE, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free,...
static getStyleSheetLocation($mode="output", $a_css_name="", $a_css_location="")
get full style sheet file name (path inclusive) of current user
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
static _getObjectsByOperations($a_obj_type, $a_operation, $a_usr_id=0, $limit=0)
Get all objects of a specific type and check access This function is not recursive,...
static ilTempnam()
Create a temporary file in an ILIAS writable directory.
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
static removeTrailingPathSeparators($path)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
XML writer class.
xmlHeader()
Writes xml header @access public.
$GLOBALS['ct_recipient']
< a tabindex="-1" style="border-style: none;" href="#" title="Refresh Image" onclick="document.getElementById('siimage').src = './securimage_show.php?sid=' + Math.random(); this.blur(); return false">< img src="./images/refresh.png" alt="Reload Image" height="32" width="32" onclick="this.blur()" align="bottom" border="0"/></a >< br/>< strong > Enter Code *if($_SERVER['REQUEST_METHOD']=='POST' &&@ $_POST['do']=='contact') $_SESSION['ctform']['success']
global $ilBench
Definition: ilias.php:18
global $ilCtrl
Definition: ilias.php:18
const SCORE_BEST_PASS
const REPORT_AFTER_TEST
const SCORE_ZERO_POINTS_WHEN_UNANSWERED
const COUNT_PARTIAL_SOLUTIONS
const TEST_FIXED_SEQUENCE
Test constants.
const SCORE_CUT_QUESTION
const SCORE_LAST_PASS
const INVITATION_OFF
$separator
xslt_error(&$proc)
xslt_free(&$proc)
xslt_create()
redirection script todo: (a better solution should control the processing via a xml file)
global $ilSetting
Definition: privfeed.php:40
$results
global $ilDB
if(!is_array($argv)) $options
$mobs
global $ilUser
Definition: imgupload.php:15
const ILIAS_ABSOLUTE_PATH