ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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
575
580
581 #endregion
582
591 public function __construct($a_id = 0,$a_call_by_reference = true)
592 {
593 global $ilUser, $lng;
594 $this->type = "tst";
595
596 $lng->loadLanguageModule("assessment");
597 // Defaults:
598 include_once "./Modules/Test/classes/class.assMarkSchema.php";
599 $this->mark_schema = new ASS_MarkSchema();
600 $this->mark_schema->createSimpleSchema(
601 $lng->txt("failed_short"),
602 $lng->txt("failed_official"),
603 0,
604 0,
605 $lng->txt("passed_short"),
606 $lng->txt("passed_official"),
607 50,
608 1
609 );
610
611 $this->test_id = -1;
612 $this->author = $ilUser->fullname;
613 $this->introductionEnabled = false;
614 $this->introduction = "";
615 $this->questions = array();
616 $this->sequence_settings = TEST_FIXED_SEQUENCE;
617 $this->score_reporting = REPORT_AFTER_TEST;
618 $this->instant_verification = 0;
619 $this->answer_feedback_points = 0;
620 $this->reporting_date = "";
621 $this->nr_of_tries = 0;
622 $this->_kiosk = 0;
623 $this->use_previous_answers = 1;
624 $this->title_output = 0;
625 $this->starting_time = "";
626 $this->ending_time = "";
627 $this->processing_time = "";
628 $this->enable_processing_time = "0";
629 $this->reset_processing_time = 0;
630 $this->ects_output = FALSE;
631 $this->ects_fx = NULL;
632 $this->shuffle_questions = FALSE;
633 $this->mailnottype = 0;
634 $this->exportsettings = 0;
635 $this->show_summary = 8;
636 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
637 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
638 $this->score_cutting = SCORE_CUT_QUESTION;
639 $this->pass_scoring = SCORE_LAST_PASS;
640 $this->answer_feedback = 0;
641 $this->password = "";
642 $this->certificate_visibility = 0;
643 $this->allowedUsers = "";
644 $this->_showfinalstatement = FALSE;
645 $this->_finalstatement = "";
646 $this->_showinfo = TRUE;
647 $this->_forcejs = TRUE;
648 $this->_customStyle = "";
649 $this->allowedUsersTimeGap = "";
650 $this->anonymity = 0;
651 $this->show_cancel = 0;
652 $this->show_marker = 0;
653 $this->fixed_participants = 0;
654 $this->setShowPassDetails(TRUE);
655 $this->setShowSolutionDetails(TRUE);
656 $this->setShowSolutionAnswersOnly(FALSE);
657 $this->setShowSolutionSignature(FALSE);
658 $this->testSession = FALSE;
659 $this->testSequence = FALSE;
660 $this->mailnotification = 0;
661 $this->poolUsage = 1;
662
663 $this->ects_grades = array(
664 'A' => 90,
665 'B' => 65,
666 'C' => 35,
667 'D' => 10,
668 'E' => 0
669 );
670
671 $this->autosave = FALSE;
672 $this->autosave_ival = 30000;
673
674 $this->enable_examview = false;
675 $this->show_examview_html = false;
676 $this->show_examview_pdf = false;
677 $this->enable_archiving = false;
678
679 $this->express_mode = false;
680 $this->template_id = '';
681 $this->redirection_mode = 0;
682 $this->redirection_url = NULL;
683 $this->show_exam_id_in_test_pass_enabled = false;
684 $this->show_exam_id_in_test_results_enabled = false;
685 $this->sign_submission = false;
686 $this->char_selector_availability = 0;
687 $this->char_selector_definition = null;
688
689 $this->showGradingStatusEnabled = true;
690 $this->showGradingMarkEnabled = true;
691
692 $this->instantFeedbackAnswerFixationEnabled = false;
693
694 $this->testFinalBroken = false;
695
696 $this->tmpCopyWizardCopyId = null;
697
698 $this->ilObject($a_id, $a_call_by_reference);
699 }
700
704 public function getTmpCopyWizardCopyId()
705 {
707 }
708
713 {
714 $this->tmpCopyWizardCopyId = $tmpCopyWizardCopyId;
715 }
716
720 function create($a_upload = false)
721 {
722 parent::create();
723
724 // meta data will be created by
725 // import parser
726 if (!$a_upload)
727 {
728 $this->createMetaData();
729 }
730 }
731
738 function update()
739 {
740 if (!parent::update())
741 {
742 return false;
743 }
744
745 // put here object specific stuff
746
747 return true;
748 }
749
755 function read($a_force_db = false)
756 {
757 parent::read($a_force_db);
758 $this->loadFromDb();
759 }
760
761
768 function delete()
769 {
770 // always call parent delete function first!!
771 if (!parent::delete())
772 {
773 return false;
774 }
775
776 // delet meta data
777 $this->deleteMetaData();
778
779 //put here your module specific stuff
780 $this->deleteTest();
781
782 return true;
783 }
784
790 function deleteTest()
791 {
792 global $tree, $ilDB, $ilPluginAdmin, $lng;
793
794 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
795 $participantData = new ilTestParticipantData($ilDB, $lng);
796 $participantData->load($this->getTestId());
797 $this->removeTestResults($participantData);
798
799 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_mark WHERE test_fi = %s",
800 array('integer'),
801 array($this->getTestId())
802 );
803
804 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_tests WHERE test_id = %s",
805 array('integer'),
806 array($this->getTestId())
807 );
808
809 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
810 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
811 $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
812
813 // delete export files
814 include_once "./Services/Utilities/classes/class.ilUtil.php";
815 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
816 $directory = $tst_data_dir."/tst_".$this->getId();
817 if (is_dir($directory))
818 {
819 include_once "./Services/Utilities/classes/class.ilUtil.php";
820 ilUtil::delDir($directory);
821 }
822 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
823 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
824 // remaining usages are not in text anymore -> delete them
825 // and media objects (note: delete method of ilObjMediaObject
826 // checks whether object is used in another context; if yes,
827 // the object is not deleted!)
828 foreach($mobs as $mob)
829 {
830 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
832 {
833 $mob_obj =& new ilObjMediaObject($mob);
834 $mob_obj->delete();
835 }
836 }
837 }
838
839
853 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
854 {
855 global $tree;
856
857 switch ($a_event)
858 {
859 case "link":
860
861 //var_dump("<pre>",$a_params,"</pre>");
862 //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
863 //exit;
864 break;
865
866 case "cut":
867
868 //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
869 //exit;
870 break;
871
872 case "copy":
873
874 //var_dump("<pre>",$a_params,"</pre>");
875 //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
876 //exit;
877 break;
878
879 case "paste":
880
881 //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
882 //exit;
883 break;
884
885 case "new":
886
887 //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
888 //exit;
889 break;
890 }
891
892 // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
893 if ($a_node_id==$_GET["ref_id"])
894 {
895 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
896 $parent_type = $parent_obj->getType();
897 if ($parent_type == $this->getType())
898 {
899 $a_node_id = (int) $tree->getParentId($a_node_id);
900 }
901 }
902
903 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
904 }
905
912 {
913 include_once "./Services/Utilities/classes/class.ilUtil.php";
914 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
915 ilUtil::makeDir($tst_data_dir);
916 if (!is_writable($tst_data_dir))
917 {
918 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
919 .") not writeable.",$this->ilias->error_obj->MESSAGE);
920 }
921
922 // create learning module directory (data_dir/lm_data/lm_<id>)
923 $tst_dir = $tst_data_dir."/tst_".$this->getId();
924 ilUtil::makeDir($tst_dir);
925 if (!@is_dir($tst_dir))
926 {
927 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
928 }
929 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
930 $export_dir = $tst_dir."/export";
931 ilUtil::makeDir($export_dir);
932 if (!@is_dir($export_dir))
933 {
934 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
935 }
936 }
937
944 {
945 include_once "./Services/Utilities/classes/class.ilUtil.php";
946 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
947 return $export_dir;
948 }
949
956 function getExportFiles($dir)
957 {
958 // quit if import dir not available
959 if(!@is_dir($dir) || !is_writeable($dir))
960 {
961 return array();
962 }
963
964 $files = array();
965 foreach(new DirectoryIterator($dir) as $file)
966 {
970 if($file->isDir())
971 {
972 continue;
973 }
974
975 $files[] = $file->getBasename();
976 }
977
978 sort($files);
979
980 return $files;
981 }
982
986 function _setImportDirectory($a_import_dir = null)
987 {
988 if (strlen($a_import_dir))
989 {
990 $_SESSION["tst_import_dir"] = $a_import_dir;
991 }
992 else
993 {
994 unset($_SESSION["tst_import_dir"]);
995 }
996 }
997
1005 {
1006 if (strlen($_SESSION["tst_import_dir"]))
1007 {
1008 return $_SESSION["tst_import_dir"];
1009 }
1010 return null;
1011 }
1012
1014 {
1016 }
1017
1024 {
1025 global $ilias;
1026 include_once "./Services/Utilities/classes/class.ilUtil.php";
1027 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
1028 ilUtil::makeDir($tst_data_dir);
1029
1030 if (!is_writable($tst_data_dir))
1031 {
1032 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
1033 .") not writeable.",$this->ilias->error_obj->FATAL);
1034 }
1035
1036 // create test directory (data_dir/tst_data/tst_import)
1037 $tst_dir = $tst_data_dir."/tst_import";
1038 ilUtil::makeDir($tst_dir);
1039 if (!@is_dir($tst_dir))
1040 {
1041 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
1042 }
1043 return $tst_dir;
1044 }
1045
1053 {
1054 global $ilDB;
1055
1056 $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",
1057 array('integer'),
1058 array($this->getTestId())
1059 );
1060 $hasSC = false;
1061 while ($row = $ilDB->fetchAssoc($result))
1062 {
1063 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1064 {
1065 $hasSC = true;
1066 }
1067 }
1068 return $hasSC;
1069 }
1070
1078 {
1079 global $ilDB;
1080
1081 $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",
1082 array('integer'),
1083 array($this->getTestId())
1084 );
1085 if ($result->numRows() == 1)
1086 {
1087 $row = $ilDB->fetchAssoc($result);
1088 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1089 {
1090 return TRUE;
1091 }
1092 else
1093 {
1094 return false;
1095 }
1096 }
1097 return FALSE;
1098 }
1099
1107 {
1108 global $ilDB;
1109
1110 if (!$this->hasSingleChoiceQuestions()) return false;
1111
1112 $result = $ilDB->queryF("
1113 SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1114 FROM qpl_questions,
1115 qpl_qst_sc,
1116 tst_test_result,
1117 qpl_qst_type,
1118 tst_active
1119 WHERE tst_test_result.question_fi = qpl_questions.question_id
1120 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1121 AND tst_test_result.active_fi = tst_active.active_id
1122 AND qpl_questions.question_id = qpl_qst_sc.question_fi
1123 AND tst_active.test_fi = %s
1124 AND qpl_qst_type.type_tag = %s
1125 ",
1126 array('integer', 'text'),
1127 array($this->getTestId(), 'assSingleChoice')
1128 );
1129 if ($result->numRows() == 1)
1130 {
1131 $row = $ilDB->fetchAssoc($result);
1132 return ($row['foundshuffles'] == 0);
1133 }
1134 return FALSE;
1135 }
1136
1143 final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1144 {
1145 if( !count($this->mark_schema->mark_steps) )
1146 {
1147 return false;
1148 }
1149
1150 if( !$testQuestionSetConfig->isQuestionSetConfigured() )
1151 {
1152 return false;
1153 }
1154
1155 return true;
1156 }
1157
1164 function _isComplete($obj_id)
1165 {
1166 global $tree, $ilDB, $ilPluginAdmin;
1167
1168 $test = new ilObjTest($obj_id, false);
1169 $test->loadFromDb();
1170
1171 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1172 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1173
1174 return $test->isComplete( $testQuestionSetConfigFactory->getQuestionSetConfig() );
1175 }
1176
1180 public function saveECTSStatus()
1181 {
1185 global $ilDB;
1186
1187 if($this->getTestId() > 0)
1188 {
1189 $this->setECTSFX(preg_replace('/,/', '.', $this->getECTSFX()));
1190 if(!preg_match('/\d+/', $this->getECTSFX()))
1191 {
1192 $this->setECTSFX(NULL);
1193 }
1194
1195 $grades = $this->getECTSGrades();
1196 $ilDB->manipulateF(
1197 "UPDATE tst_tests
1198 SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s
1199 WHERE test_id = %s",
1200 array('text', 'float', 'float', 'float', 'float', 'float', 'float', 'integer'),
1201 array(
1202 (int)$this->getECTSOutput(),
1203 $grades['A'], $grades['B'], $grades['C'], $grades['D'], $grades['E'],
1204 $this->getECTSFX(),
1205 $this->getTestId()
1206 )
1207 );
1208 }
1209 }
1210
1215 public function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1216 {
1217 global $ilDB;
1218
1219 $complete = 0;
1220 if($this->isComplete($testQuestionSetConfig))
1221 {
1222 $complete = 1;
1223 }
1224 if($this->getTestId() > 0)
1225 {
1226 $ilDB->manipulateF(
1227 "UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1228 array('text', 'integer'),
1229 array($complete, $this->test_id)
1230 );
1231 }
1232 }
1233
1240 {
1241 $result = array();
1242 array_push($result, $this->getIntroduction());
1243 array_push($result, $this->getFinalStatement());
1244 return $result;
1245 }
1246
1253 {
1254 include_once("./Services/RTE/classes/class.ilRTE.php");
1255 $completecontent = "";
1256 foreach ($this->getAllRTEContent() as $content)
1257 {
1258 $completecontent .= $content;
1259 }
1260 ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
1261 $this->getId());
1262 }
1263
1269 public function saveToDb($properties_only = FALSE)
1270 {
1271 global $tree, $ilDB, $ilPluginAdmin;
1272
1273 // moved online_status to ilObjectActivation (see below)
1274
1275 // cleanup RTE images
1276 $this->cleanupMediaobjectUsage();
1277
1278 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1279 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1280 $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1281
1282 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1283 if ($this->test_id == -1)
1284 {
1285 // Create new dataset
1286 $next_id = $ilDB->nextId('tst_tests');
1287
1288 $ilDB->insert('tst_tests', array(
1289 'test_id' => array('integer', $next_id),
1290 'obj_fi' => array('integer', $this->getId()),
1291 'author' => array('text', $this->getAuthor()),
1292 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1293 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1294 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1295 'showinfo' => array('integer', $this->getShowInfo()),
1296 'forcejs' => array('integer', $this->getForceJS()),
1297 'customstyle' => array('text', $this->getCustomStyle()),
1298 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1299 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1300 'score_reporting' => array('integer', $this->getScoreReporting()),
1301 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1302 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1303 'answer_feedback' => array('text', $this->getAnswerFeedback()),
1304 'anonymity' => array('text', $this->getAnonymity()),
1305 'show_cancel' => array('text', $this->getShowCancel()),
1306 'show_marker' => array('integer', $this->getShowMarker()),
1307 'fixed_participants' => array('text', $this->getFixedParticipants()),
1308 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1309 'kiosk' => array('integer', $this->getKiosk()),
1310 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1311 'title_output' => array('text', $this->getTitleOutput()),
1312 'processing_time' => array('text', $this->getProcessingTime()),
1313 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1314 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1315 'reporting_date' => array('text', $this->getReportingDate()),
1316 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1317 'starting_time' => array('text', $this->getStartingTime()),
1318 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1319 'ending_time' => array('text', $this->getEndingTime()),
1320 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1321 'ects_output' => array('text', $this->getECTSOutput()),
1322 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1323 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1324 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1325 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1326 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1327 'ects_fx' => array('float', $this->getECTSFX()),
1328 'count_system' => array('text', $this->getCountSystem()),
1329 'mc_scoring' => array('text', $this->getMCScoring()),
1330 'score_cutting' => array('text', $this->getScoreCutting()),
1331 'pass_scoring' => array('text', $this->getPassScoring()),
1332 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1333 'results_presentation' => array('integer', $this->getResultsPresentation()),
1334 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1335 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1336 'password' => array('text', $this->getPassword()),
1337 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1338 'allowedusers' => array('integer', $this->getAllowedUsers()),
1339 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1340 'mailnottype' => array('integer', $this->getMailNotificationType()),
1341 'exportsettings' => array('integer', $this->getExportSettings()),
1342 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1343 'mailnotification' => array('integer', $this->getMailNotification()),
1344 'created' => array('integer', time()),
1345 'tstamp' => array('integer', time()),
1346 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1347 'template_id' => array('integer', $this->getTemplate()),
1348 'pool_usage' => array('integer', $this->getPoolUsage()),
1349 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1350 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1351 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1352 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1353 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1354 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1355 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1356 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1357 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1358 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1359 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1360 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1361 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1362 'online_status' => array('integer', (int)$this->isOnline()),
1363 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1364 'autosave' => array('integer', (int)$this->getAutosave()),
1365 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1366 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1367 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1368 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1369 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1370 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1371 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1372 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1373 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1374 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1375 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1376 'question_set_type' => array('text', $this->getQuestionSetType()),
1377 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1378 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1379 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1380 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1381 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1382 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1383 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1384 'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
1385 'broken' => array('integer', (int)$this->isTestFinalBroken())
1386 ));
1387
1388 $this->test_id = $next_id;
1389
1391 {
1392 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1393 }
1394 }
1395 else
1396 {
1397 // Modify existing dataset
1398 $oldrow = array();
1400 {
1401 $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1402 array('integer'),
1403 array($this->test_id)
1404 );
1405 if ($result->numRows() == 1)
1406 {
1407 $oldrow = $ilDB->fetchAssoc($result);
1408 }
1409 }
1410
1411 $ilDB->update('tst_tests',
1412 array(
1413 'author' => array('text', $this->getAuthor()),
1414 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1415 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1416 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1417 'showinfo' => array('integer', $this->getShowInfo()),
1418 'forcejs' => array('integer', $this->getForceJS()),
1419 'customstyle' => array('text', $this->getCustomStyle()),
1420 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1421 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1422 'score_reporting' => array('integer', $this->getScoreReporting()),
1423 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1424 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1425 'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1426 'anonymity' => array('text', $this->getAnonymity()),
1427 'show_cancel' => array('text', $this->getShowCancel()),
1428 'show_marker' => array('integer', $this->getShowMarker()),
1429 'fixed_participants' => array('text', $this->getFixedParticipants()),
1430 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1431 'kiosk' => array('integer', $this->getKiosk()),
1432 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1433 'title_output' => array('text', $this->getTitleOutput()),
1434 'processing_time' => array('text', $this->getProcessingTime()),
1435 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1436 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1437 'reporting_date' => array('text', $this->getReportingDate()),
1438 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1439 'starting_time' => array('text', $this->getStartingTime()),
1440 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1441 'ending_time' => array('text', $this->getEndingTime()),
1442 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1443 'ects_output' => array('text', $this->getECTSOutput()),
1444 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1445 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1446 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1447 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1448 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1449 'ects_fx' => array('float', $this->getECTSFX()),
1450 'count_system' => array('text', $this->getCountSystem()),
1451 'mc_scoring' => array('text', $this->getMCScoring()),
1452 'score_cutting' => array('text', $this->getScoreCutting()),
1453 'pass_scoring' => array('text', $this->getPassScoring()),
1454 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1455 'results_presentation' => array('integer', $this->getResultsPresentation()),
1456 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1457 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1458 'password' => array('text', $this->getPassword()),
1459 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1460 'allowedusers' => array('integer', $this->getAllowedUsers()),
1461 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1462 'mailnottype' => array('integer', $this->getMailNotificationType()),
1463 'exportsettings' => array('integer', $this->getExportSettings()),
1464 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1465 'mailnotification' => array('integer', $this->getMailNotification()),
1466 'tstamp' => array('integer', time()),
1467 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1468 'template_id' => array('integer', $this->getTemplate()),
1469 'pool_usage' => array('integer', $this->getPoolUsage()),
1470 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1471 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1472 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1473 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1474 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1475 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1476 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1477 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1478 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1479 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1480 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1481 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1482 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1483 'online_status' => array('integer', (int)$this->isOnline()),
1484 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1485 'autosave' => array('integer', (int)$this->getAutosave()),
1486 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1487 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1488 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1489 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1490 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1491 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1492 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1493 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1494 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1495 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1496 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1497 'question_set_type' => array('text', $this->getQuestionSetType()),
1498 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1499 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1500 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1501 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1502 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1503 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1504 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1505 'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
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->setForceInstantFeedbackEnabled((bool)$data->force_inst_fb);
2001 $this->setTestFinalBroken((bool)$data->broken);
2002 $this->loadQuestions();
2003 }
2004
2005 // moved activation to ilObjectActivation
2006 if($this->ref_id)
2007 {
2008 include_once "./Services/Object/classes/class.ilObjectActivation.php";
2009 $activation = ilObjectActivation::getItem($this->ref_id);
2010 switch($activation["timing_type"])
2011 {
2013 $this->setActivationLimited(true);
2014 $this->setActivationStartingTime($activation["timing_start"]);
2015 $this->setActivationEndingTime($activation["timing_end"]);
2016 $this->setActivationVisibility($activation["visible"]);
2017 break;
2018
2019 default:
2020 $this->setActivationLimited(false);
2021 break;
2022 }
2023 }
2024 }
2025
2032function loadQuestions($active_id = "", $pass = NULL)
2033{
2034 global $ilUser;
2035 global $ilDB;
2036
2037 $this->questions = array();
2038 if ($this->isRandomTest())
2039 {
2040 if (strcmp($active_id, "") == 0)
2041 {
2042 $active_id = $this->getActiveIdOfUser($ilUser->getId());
2043 }
2044 if (is_null($pass))
2045 {
2046 $pass = $this->_getPass($active_id);
2047 }
2048 $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",
2049 array('integer', 'integer'),
2050 array($active_id, $pass)
2051 );
2052 // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
2053 // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
2054 // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
2055 // no questions are present for a newer pass.
2056 if ($result->numRows() == 0)
2057 {
2058 $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",
2059 array('integer'),
2060 array($active_id)
2061 );
2062 }
2063 }
2064 else
2065 {
2066 $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",
2067 array('integer'),
2068 array($this->test_id)
2069 );
2070 }
2071 $index = 1;
2072 while ($data = $ilDB->fetchAssoc($result))
2073 {
2074 $this->questions[$index++] = $data["question_fi"];
2075 }
2076}
2077
2081 public function isIntroductionEnabled()
2082 {
2084 }
2085
2090 {
2091 $this->introductionEnabled = $introductionEnabled;
2092 }
2093
2100 public function getIntroduction()
2101 {
2102 return (strlen($this->introduction)) ? $this->introduction : NULL;
2103 }
2104
2112 public function setIntroduction($introduction = "")
2113 {
2114 $this->introduction = $introduction;
2115 }
2116
2117
2125 public function setFinalStatement($a_statement = "")
2126 {
2127 $this->_finalstatement = $a_statement;
2128 }
2129
2137 public function setShowInfo($a_info = 1)
2138 {
2139 $this->_showinfo = ($a_info) ? 1 : 0;
2140 }
2141
2149 public function setForceJS($a_js = 1)
2150 {
2151 $this->_forcejs = ($a_js) ? 1 : 0;
2152 }
2153
2161 public function setCustomStyle($a_customStyle = NULL)
2162 {
2163 $this->_customStyle = $a_customStyle;
2164 }
2165
2173 public function getCustomStyle()
2174 {
2175 return (strlen($this->_customStyle)) ? $this->_customStyle : NULL;
2176 }
2177
2185 public function getCustomStyles()
2186 {
2187 $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2188 $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2189 $customstyles = array();
2190 if (is_dir($css_path))
2191 {
2192 $results = array();
2193 include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2195 if (is_array($results["file"]))
2196 {
2197 foreach ($results["file"] as $filename)
2198 {
2199 if (strpos($filename, ".css"))
2200 {
2201 array_push($customstyles, $filename);
2202 }
2203 }
2204 }
2205 }
2206 return $customstyles;
2207 }
2208
2216 public function getTestStyleLocation($mode = "output")
2217 {
2218 if (strlen($this->getCustomStyle()))
2219 {
2220 $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2221 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2222 if (file_exists($custom))
2223 {
2224 $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2225 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2226 return $custom;
2227 }
2228 else
2229 {
2230 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2231 }
2232 }
2233 else
2234 {
2235 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2236 }
2237 }
2238
2246 public function setShowFinalStatement($show = 0)
2247 {
2248 $this->_showfinalstatement = ($show) ? 1 : 0;
2249 }
2250
2257 public function getFinalStatement()
2258 {
2259 return (strlen($this->_finalstatement)) ? $this->_finalstatement : NULL;
2260 }
2261
2269 public function getShowInfo()
2270 {
2271 return ($this->_showinfo) ? 1 : 0;
2272 }
2273
2281 public function getForceJS()
2282 {
2283 return ($this->_forcejs) ? 1 : 0;
2284 }
2285
2293 public function getShowFinalStatement()
2294 {
2295 return ($this->_showfinalstatement) ? 1 : 0;
2296 }
2297
2305 function getTestId()
2306 {
2307 return $this->test_id;
2308 }
2309
2313 public function getECTSOutput()
2314 {
2315 return ($this->ects_output) ? 1 : 0;
2316 }
2317
2321 public function setECTSOutput($a_ects_output)
2322 {
2323 $this->ects_output = $a_ects_output ? 1 : 0;
2324 }
2325
2329 public function getECTSFX()
2330 {
2331 return (strlen($this->ects_fx)) ? $this->ects_fx : NULL;
2332 }
2333
2337 public function setECTSFX($a_ects_fx)
2338 {
2339 $this->ects_fx = $a_ects_fx;
2340 }
2341
2345 public function getECTSGrades()
2346 {
2347 return $this->ects_grades;
2348 }
2349
2353 public function setECTSGrades(array $a_ects_grades)
2354 {
2355 $this->ects_grades = $a_ects_grades;
2356 }
2357
2363 public function getSequenceSettings()
2364 {
2365 return ($this->sequence_settings) ? $this->sequence_settings : 0;
2366 }
2367
2374 {
2375 $this->sequence_settings = $sequence_settings;
2376 }
2377
2381 public function isPostponingEnabled()
2382 {
2383 return (bool)$this->getSequenceSettings();
2384 }
2385
2389 public function setPostponingEnabled($postponingEnabled)
2390 {
2391 $this->setSequenceSettings((int)$postponingEnabled);
2392 }
2393
2402 {
2403 $this->score_reporting = $score_reporting;
2404 }
2405
2413 function setInstantFeedbackSolution($instant_feedback = 0)
2414 {
2415 switch ($instant_feedback)
2416 {
2417 case 1:
2418 $this->instant_verification = 1;
2419 break;
2420 default:
2421 $this->instant_verification = 0;
2422 break;
2423 }
2424 }
2425
2434{
2435 switch ($answer_feedback)
2436 {
2437 case 1:
2438 $this->answer_feedback = 1;
2439 break;
2440 default:
2441 $this->answer_feedback = 0;
2442 break;
2443 }
2444}
2445
2452function setGenericAnswerFeedback($generic_answer_feedback = 0)
2453{
2454 switch ($generic_answer_feedback)
2455 {
2456 case 1:
2457 $this->answer_feedback = 1;
2458 break;
2459 default:
2460 $this->answer_feedback = 0;
2461 break;
2462 }
2463}
2464
2473 {
2475 {
2476 case 1:
2477 $this->answer_feedback_points = 1;
2478 break;
2479 default:
2480 $this->answer_feedback_points = 0;
2481 break;
2482 }
2483 }
2484
2490 {
2491 if(!$reporting_date)
2492 {
2493 $this->reporting_date = '';
2494 $this->setECTSOutput(false);
2495 }
2496 else
2497 {
2498 $this->reporting_date = $reporting_date;
2499 }
2500 }
2501
2506
2515 {
2516 return ($this->score_reporting) ? $this->score_reporting : 0;
2517 }
2518
2519 public function isScoreReportingEnabled()
2520 {
2521 return $this->getScoreReporting() > 0 && $this->getScoreReporting() < 4;
2522 }
2523
2532 {
2533 return ($this->instant_verification) ? $this->instant_verification : 0;
2534 }
2535
2544 public function getAnswerFeedback()
2545 {
2546 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2547 }
2548
2558 {
2559 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2560 }
2561
2570{
2571 return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2572}
2573
2582 {
2583 return ($this->count_system) ? $this->count_system : 0;
2584 }
2585
2593 function _getCountSystem($active_id)
2594 {
2595 global $ilDB;
2596 $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",
2597 array('integer'),
2598 array($active_id)
2599 );
2600 if ($result->numRows())
2601 {
2602 $row = $ilDB->fetchAssoc($result);
2603 return $row["count_system"];
2604 }
2605 return FALSE;
2606 }
2607
2615 function getMCScoring()
2616 {
2617 return ($this->mc_scoring) ? $this->mc_scoring : 0;
2618 }
2619
2628 {
2629 return ($this->score_cutting) ? $this->score_cutting : 0;
2630 }
2631
2640 {
2641 return ($this->pass_scoring) ? $this->pass_scoring : 0;
2642 }
2643
2651 function _getPassScoring($active_id)
2652 {
2653 global $ilDB;
2654 $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",
2655 array('integer'),
2656 array($active_id)
2657 );
2658 if ($result->numRows())
2659 {
2660 $row = $ilDB->fetchAssoc($result);
2661 return $row["pass_scoring"];
2662 }
2663 return 0;
2664 }
2665
2673 function _getMCScoring($active_id)
2674 {
2675 global $ilDB;
2676 $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",
2677 array('integer'),
2678 array($active_id)
2679 );
2680 if ($result->numRows())
2681 {
2682 $row = $ilDB->fetchAssoc($result);
2683 return $row["mc_scoring"];
2684 }
2685 return FALSE;
2686 }
2687
2695 function _getScoreCutting($active_id)
2696 {
2697 global $ilDB;
2698 $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",
2699 array('integer'),
2700 array($active_id)
2701 );
2702 if ($result->numRows())
2703 {
2704 $row = $ilDB->fetchAssoc($result);
2705 return $row["score_cutting"];
2706 }
2707 return FALSE;
2708 }
2709
2718 {
2719 return (strlen($this->reporting_date)) ? $this->reporting_date : NULL;
2720 }
2721
2729 function getNrOfTries()
2730 {
2731 return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2732 }
2733
2741 function getKiosk()
2742 {
2743 return ($this->_kiosk) ? $this->_kiosk : 0;
2744 }
2745
2746
2754 function setKiosk($kiosk = 0)
2755 {
2756 $this->_kiosk = $kiosk;
2757 }
2758
2766 function getKioskMode()
2767 {
2768 if (($this->_kiosk & 1) > 0)
2769 {
2770 return TRUE;
2771 }
2772 else
2773 {
2774 return FALSE;
2775 }
2776 }
2777
2785 public function setKioskMode($a_kiosk = FALSE)
2786 {
2787 if ($a_kiosk)
2788 {
2789 $this->_kiosk = $this->_kiosk | 1;
2790 }
2791 else
2792 {
2793 if ($this->getKioskMode())
2794 {
2795 $this->_kiosk = $this->_kiosk ^ 1;
2796 }
2797 }
2798 }
2799
2807 public function getShowKioskModeTitle()
2808 {
2809 if (($this->_kiosk & 2) > 0)
2810 {
2811 return TRUE;
2812 }
2813 else
2814 {
2815 return FALSE;
2816 }
2817 }
2818
2825 public function setShowKioskModeTitle($a_title = FALSE)
2826 {
2827 if ($a_title)
2828 {
2829 $this->_kiosk = $this->_kiosk | 2;
2830 }
2831 else
2832 {
2833 if ($this->getShowKioskModeTitle())
2834 {
2835 $this->_kiosk = $this->_kiosk ^ 2;
2836 }
2837 }
2838 }
2839
2848 {
2849 if (($this->_kiosk & 4) > 0)
2850 {
2851 return TRUE;
2852 }
2853 else
2854 {
2855 return FALSE;
2856 }
2857 }
2858
2865 public function setShowKioskModeParticipant($a_participant = FALSE)
2866 {
2867 if ($a_participant)
2868 {
2869 $this->_kiosk = $this->_kiosk | 4;
2870 }
2871 else
2872 {
2873 if ($this->getShowKioskModeParticipant())
2874 {
2875 $this->_kiosk = $this->_kiosk ^ 4;
2876 }
2877 }
2878 }
2879
2888 {
2889 return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2890 }
2891
2900 {
2901 return ($this->title_output) ? $this->title_output : 0;
2902 }
2903
2912 function _getTitleOutput($active_id)
2913 {
2914 global $ilDB;
2915
2916 $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",
2917 array('integer'),
2918 array($active_id)
2919 );
2920 if ($result->numRows())
2921 {
2922 $row = $ilDB->fetchAssoc($result);
2923 return $row["title_output"];
2924 }
2925 return 0;
2926 }
2927
2937 function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2938 {
2939 global $ilDB;
2940 global $ilUser;
2941
2943
2944 $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",
2945 array("integer"),
2946 array($active_id)
2947 );
2948 if ($result->numRows())
2949 {
2950 $row = $ilDB->fetchAssoc($result);
2951 $use_previous_answers = $row["use_previous_answers"];
2952 }
2953
2954 if ($use_previous_answers == 1)
2955 {
2956 if ($user_active_user_setting)
2957 {
2958 $res = $ilUser->getPref("tst_use_previous_answers");
2959 if ($res !== FALSE)
2960 {
2962 }
2963 }
2964 }
2965 return $use_previous_answers;
2966 }
2967
2976 {
2977 return (strlen($this->processing_time)) ? $this->processing_time : NULL;
2978 }
2979
2987 {
2988 if (strlen($this->processing_time))
2989 {
2990 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
2991 {
2992 if ((int)$matches[1]+(int)$matches[2]+(int)$matches[3] == 0)
2993 {
2994 return $this->getEstimatedWorkingTime();
2995 }
2996 else
2997 {
2998 return array(
2999 'hh' => $matches[1],
3000 'mm' => $matches[2],
3001 'ss' => $matches[3],
3002 );
3003 }
3004 }
3005 }
3006 return $this->getEstimatedWorkingTime();
3007 }
3008
3010 {
3011 if (strlen($this->processing_time))
3012 {
3013 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
3014 {
3015 return ($matches[1] * 60) + $matches[2];
3016 }
3017 }
3018
3020 }
3021
3029 function getProcessingTimeInSeconds($active_id = "")
3030 {
3031 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
3032 {
3033 $extratime = $this->getExtraTime($active_id) * 60;
3034 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
3035 }
3036 else
3037 {
3038 return 0;
3039 }
3040 }
3041
3050 {
3051 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
3052 {
3053 $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
3054 $now = time();
3055 return $ending - $now;
3056 }
3057 else
3058 {
3059 return 0;
3060 }
3061 }
3062
3071 {
3072 return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
3073 }
3074
3083 {
3084 return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
3085 }
3086
3090 public function isStartingTimeEnabled()
3091 {
3093 }
3094
3099 {
3100 $this->starting_time_enabled = $starting_time_enabled;
3101 }
3102
3110 public function getStartingTime()
3111 {
3112 return (strlen($this->starting_time)) ? $this->starting_time : NULL;
3113 }
3114
3122 public function setStartingTime($starting_time = NULL)
3123 {
3124 $this->starting_time = $starting_time;
3125 }
3126
3130 public function isEndingTimeEnabled()
3131 {
3133 }
3134
3139 {
3140 $this->ending_time_enabled = $ending_time_enabled;
3141 }
3142
3150 public function getEndingTime()
3151 {
3152 return (strlen($this->ending_time)) ? $this->ending_time : NULL;
3153 }
3154
3162 public function setEndingTime($ending_time = NULL)
3163 {
3164 $this->ending_time = $ending_time;
3165 }
3166
3175 {
3176 $this->nr_of_tries = $nr_of_tries;
3177 }
3178
3187 {
3189 {
3190 $this->use_previous_answers = 1;
3191 }
3192 else
3193 {
3194 $this->use_previous_answers = 0;
3195 }
3196 }
3197
3199 {
3200 $this->redirection_mode = $redirection_mode;
3201 }
3203 {
3205 }
3207 {
3208 $this->redirection_url = $redirection_url;
3209 }
3211 {
3213 }
3214
3223 {
3224 switch ($title_output)
3225 {
3226 case 1:
3227 $this->title_output = 1;
3228 break;
3229 case 2:
3230 $this->title_output = 2;
3231 break;
3232 default:
3233 $this->title_output = 0;
3234 break;
3235 }
3236 }
3237
3246 {
3247 $this->processing_time = $processing_time;
3248 }
3249
3250 public function setProcessingTimeByMinutes($minutes)
3251 {
3252 $this->processing_time = sprintf("%02d:%02d:00", floor($minutes/60), $minutes%60);
3253 }
3254
3262 function setEnableProcessingTime($enable = 0)
3263 {
3264 if ($enable) {
3265 $this->enable_processing_time = "1";
3266 } else {
3267 $this->enable_processing_time = "0";
3268 }
3269 }
3270
3278 function setResetProcessingTime($reset = 0)
3279 {
3280 if ($reset)
3281 {
3282 $this->reset_processing_time = 1;
3283 }
3284 else
3285 {
3286 $this->reset_processing_time = 0;
3287 }
3288 }
3289
3297 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3298 {
3299 $this->count_system = $a_count_system;
3300 }
3301
3305 public function isPasswordEnabled()
3306 {
3308 }
3309
3314 {
3315 $this->passwordEnabled = $passwordEnabled;
3316 }
3317
3325 public function getPassword()
3326 {
3327 return (strlen($this->password)) ? $this->password : NULL;
3328 }
3329
3337 public function setPassword($a_password = NULL)
3338 {
3339 $this->password = $a_password;
3340 }
3341
3349 function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3350 {
3351 $this->score_cutting = $a_score_cutting;
3352 }
3353
3362 {
3363 $this->mc_scoring = $a_mc_scoring;
3364 }
3365
3373 function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3374 {
3375 switch ($a_pass_scoring)
3376 {
3377 case SCORE_BEST_PASS:
3378 $this->pass_scoring = SCORE_BEST_PASS;
3379 break;
3380 default:
3381 $this->pass_scoring = SCORE_LAST_PASS;
3382 break;
3383 }
3384 }
3385
3389 public function removeQuestions($removeQuestionIds)
3390 {
3391 foreach ($removeQuestionIds as $value) {
3392 $this->removeQuestion($value);
3393 }
3394
3396 }
3397
3405 function removeQuestion($question_id)
3406 {
3407 $question =& ilObjTest::_instanciateQuestion($question_id);
3408 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3410 {
3411 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3412 }
3413 $question->delete($question_id);
3414 }
3415
3425 {
3426 $this->removeTestResultsByUserIds($userIds);
3427
3428 $ilDB = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
3429 $lng = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['lng'] : $GLOBALS['lng'];
3430
3431 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3432 $participantData = new ilTestParticipantData($ilDB, $lng);
3433 $participantData->setUserIds($userIds);
3434 $participantData->load($this->getTestId());
3435
3436 $this->removeTestActives($participantData->getActiveIds());
3437 }
3438
3439 public function removeTestResults(ilTestParticipantData $participantData)
3440 {
3441 if( count($participantData->getAnonymousActiveIds()) )
3442 {
3443 $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3444 }
3445
3446 if( count($participantData->getUserIds()) )
3447 {
3448 /* @var ilTestLP $testLP */
3449 require_once 'Services/Object/classes/class.ilObjectLP.php';
3450 $testLP = ilObjectLP::getInstance($this->getId());
3451 $testLP->setTestObject($this);
3452 $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3453 }
3454
3455 if( count($participantData->getActiveIds()) )
3456 {
3457 $this->removeTestActives($participantData->getActiveIds());
3458 }
3459 }
3460
3461 public function removeTestResultsByUserIds($userIds)
3462 {
3463 global $ilDB, $lng;
3464
3465 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3466 $participantData = new ilTestParticipantData($ilDB, $lng);
3467 $participantData->setUserIds($userIds);
3468 $participantData->load($this->getTestId());
3469
3470 $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3471 $ilDB->manipulateF("DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3472 array('text'), array("tst_password_".$this->getTestId())
3473 );
3474
3475 if( count($participantData->getActiveIds()) )
3476 {
3477 $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3478 }
3479 }
3480
3481 public function removeTestResultsByActiveIds($activeIds)
3482 {
3483 global $ilDB;
3484
3485 $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3486
3487 $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3488 $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3489 $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3490 $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3491 $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3492 $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3493 $ilDB->manipulate("DELETE FROM tst_times WHERE $IN_activeIds");
3494
3495 if( $this->isRandomTest() )
3496 {
3497 $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3498 }
3499 elseif( $this->isDynamicTest() )
3500 {
3501 $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3502 $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3503 $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3504 $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3505 }
3506
3507 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3508
3509 foreach ($activeIds as $active_id)
3510 {
3511 // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3512 // remove file uploads
3513 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3514 {
3515 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3516 }
3517
3519 {
3520 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3521 }
3522 }
3523
3524 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3526 }
3527
3528 public function removeTestActives($activeIds)
3529 {
3530 global $ilDB;
3531
3532 $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3533 $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3534 }
3535
3543 function questionMoveUp($question_id)
3544 {
3545 global $ilDB;
3546
3547 // Move a question up in sequence
3548 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3549 array('integer', 'integer'),
3550 array($this->getTestId(), $question_id)
3551 );
3552 $data = $ilDB->fetchObject($result);
3553 if ($data->sequence > 1)
3554 {
3555 // OK, it's not the top question, so move it up
3556 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3557 array('integer','integer'),
3558 array($this->getTestId(), $data->sequence - 1)
3559 );
3560 $data_previous = $ilDB->fetchObject($result);
3561 // change previous dataset
3562 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3563 array('integer','integer'),
3564 array($data->sequence, $data_previous->test_question_id)
3565 );
3566 // move actual dataset up
3567 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3568 array('integer','integer'),
3569 array($data->sequence - 1, $data->test_question_id)
3570 );
3571 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3573 {
3574 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3575 }
3576 }
3577 $this->loadQuestions();
3578 }
3579
3587 function questionMoveDown($question_id)
3588 {
3589 global $ilDB;
3590
3591 // Move a question down in sequence
3592 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3593 array('integer','integer'),
3594 array($this->getTestId(), $question_id)
3595 );
3596 $data = $ilDB->fetchObject($result);
3597 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3598 array('integer','integer'),
3599 array($this->getTestId(), $data->sequence + 1)
3600 );
3601 if ($result->numRows() == 1)
3602 {
3603 // OK, it's not the last question, so move it down
3604 $data_next = $ilDB->fetchObject($result);
3605 // change next dataset
3606 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3607 array('integer','integer'),
3608 array($data->sequence, $data_next->test_question_id)
3609 );
3610 // move actual dataset down
3611 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3612 array('integer','integer'),
3613 array($data->sequence + 1, $data->test_question_id)
3614 );
3615 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3617 {
3618 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3619 }
3620 }
3621 $this->loadQuestions();
3622 }
3623
3631 function duplicateQuestionForTest($question_id)
3632 {
3633 global $ilUser;
3634 $question =& ilObjTest::_instanciateQuestion($question_id);
3635 $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3636
3637 return $duplicate_id;
3638 }
3639
3648 public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3649 {
3650 global $ilDB;
3651#var_dump($question_id);
3652 if ($linkOnly)
3653 {
3654 $duplicate_id = $question_id;
3655 }
3656 else
3657 {
3658 $duplicate_id = $this->duplicateQuestionForTest($question_id);
3659 }
3660
3661 // get maximum sequence index in test
3662 $result = $ilDB->queryF("SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3663 array('integer'),
3664 array($this->getTestId())
3665 );
3666 $sequence = 1;
3667
3668 if ($result->numRows() == 1)
3669 {
3670 $data = $ilDB->fetchObject($result);
3671 $sequence = $data->seq + 1;
3672 }
3673
3674 $next_id = $ilDB->nextId('tst_test_question');
3675 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3676 array('integer', 'integer','integer','integer','integer'),
3677 array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3678 );
3679 if ($affectedRows == 1)
3680 {
3681 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3683 {
3684 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3685 }
3686 }
3687 // remove test_active entries, because test has changed
3688 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3689 array('integer'),
3690 array($this->getTestId())
3691 );
3692 $this->loadQuestions();
3693 $this->saveCompleteStatus($testQuestionSetConfig);
3694 return $duplicate_id;
3695 }
3696
3705 {
3706 $titles = array();
3707 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3708 {
3709 global $ilDB;
3710 $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",
3711 array('integer'),
3712 array($this->getTestId())
3713 );
3714 while ($row = $ilDB->fetchAssoc($result))
3715 {
3716 array_push($titles, $row["title"]);
3717 }
3718 }
3719 return $titles;
3720 }
3721
3730 {
3731 $titles = array();
3732 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3733 {
3734 global $ilDB;
3735 $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",
3736 array('integer'),
3737 array($this->getTestId())
3738 );
3739 while ($row = $ilDB->fetchAssoc($result))
3740 {
3741 $titles[$row['question_id']] = $row["title"];
3742 }
3743 }
3744 return $titles;
3745 }
3746
3756 {
3757 if ($this->getTitleOutput() == 2)
3758 {
3759 return $this->lng->txt("ass_question");
3760 }
3761 else
3762 {
3763 return $title;
3764 }
3765 }
3766
3775 function getQuestionDataset($question_id)
3776 {
3777 global $ilDB;
3778
3779 $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",
3780 array('integer'),
3781 array($question_id)
3782 );
3783 $row = $ilDB->fetchObject($result);
3784 return $row;
3785 }
3786
3793 function &getExistingQuestions($pass = NULL)
3794 {
3795 global $ilUser;
3796 global $ilDB;
3797
3798 $existing_questions = array();
3799 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3800 if ($this->isRandomTest())
3801 {
3802 if (is_null($pass)) $pass = 0;
3803 $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",
3804 array('integer','integer'),
3805 array($active_id, $pass)
3806 );
3807 }
3808 else
3809 {
3810 $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",
3811 array('integer'),
3812 array($this->getTestId())
3813 );
3814 }
3815 while ($data = $ilDB->fetchObject($result))
3816 {
3817 if( $data->original_id === null )
3818 {
3819 continue;
3820 }
3821
3822 array_push($existing_questions, $data->original_id);
3823 }
3824 return $existing_questions;
3825 }
3826
3834 function getQuestionType($question_id)
3835 {
3836 global $ilDB;
3837
3838 if ($question_id < 1) return -1;
3839 $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",
3840 array('integer'),
3841 array($question_id)
3842 );
3843 if ($result->numRows() == 1)
3844 {
3845 $data = $ilDB->fetchObject($result);
3846 return $data->type_tag;
3847 }
3848 else
3849 {
3850 return "";
3851 }
3852 }
3853
3860 function startWorkingTime($active_id, $pass)
3861 {
3862 global $ilDB;
3863
3864 $next_id = $ilDB->nextId('tst_times');
3865 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
3866 array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
3867 array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
3868 );
3869 return $next_id;
3870 }
3871
3878 function updateWorkingTime($times_id)
3879 {
3880 global $ilDB;
3881
3882 $affectedRows = $ilDB->manipulateF("UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
3883 array('timestamp', 'integer', 'integer'),
3884 array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
3885 );
3886 }
3887
3894 function &getWorkedQuestions($active_id, $pass = NULL)
3895 {
3896 global $ilUser;
3897 global $ilDB;
3898
3899 if (is_null($pass))
3900 {
3901 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3902 array('integer','integer'),
3903 array($active_id, 0)
3904 );
3905 }
3906 else
3907 {
3908 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3909 array('integer','integer'),
3910 array($active_id, $pass)
3911 );
3912 }
3913 $result_array = array();
3914 while ($row = $ilDB->fetchAssoc($result))
3915 {
3916 array_push($result_array, $row["question_fi"]);
3917 }
3918 return $result_array;
3919 }
3920
3929 function isTestFinishedToViewResults($active_id, $currentpass)
3930 {
3931 $num = $this->getPassFinishDate($active_id, $currentpass);
3932 return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
3933 }
3934
3941 function &getAllQuestions($pass = NULL)
3942 {
3943 global $ilUser;
3944 global $ilDB;
3945
3946 $result_array = array();
3947 if ($this->isRandomTest())
3948 {
3949 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3950 $this->loadQuestions($active_id, $pass);
3951 if (count($this->questions) == 0) return $result_array;
3952 if (is_null($pass))
3953 {
3954 $pass = $this->_getPass($active_id);
3955 }
3956 $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'),
3957 array('integer','integer'),
3958 array($active_id, $pass)
3959 );
3960 }
3961 else
3962 {
3963 if (count($this->questions) == 0) return $result_array;
3964 $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'));
3965 }
3966 while ($row = $ilDB->fetchAssoc($result))
3967 {
3968 $result_array[$row["question_id"]] = $row;
3969 }
3970 return $result_array;
3971 }
3972
3981 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
3982 {
3983 global $ilDB;
3984 global $ilUser;
3985
3986 if (!$user_id) $user_id = $ilUser->getId();
3987 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
3988 {
3989 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3990 array('integer','integer','text'),
3991 array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
3992 );
3993 }
3994 else if (strlen($anonymous_id))
3995 {
3996 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3997 array('integer','integer','text'),
3998 array($user_id, $this->test_id, $anonymous_id)
3999 );
4000 }
4001 else
4002 {
4003 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
4004 {
4005 return NULL;
4006 }
4007 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4008 array('integer','integer'),
4009 array($user_id, $this->test_id)
4010 );
4011 }
4012 if ($result->numRows())
4013 {
4014 $row = $ilDB->fetchAssoc($result);
4015 return $row["active_id"];
4016 }
4017 else
4018 {
4019 return 0;
4020 }
4021 }
4022
4031 function _getActiveIdOfUser($user_id = "", $test_id = "")
4032 {
4033 global $ilDB;
4034 global $ilUser;
4035
4036 if (!$user_id) {
4037 $user_id = $ilUser->id;
4038 }
4039 if (!$test_id)
4040 {
4041 return "";
4042 }
4043 $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4044 array('integer', 'integer'),
4045 array($user_id, $test_id)
4046 );
4047 if ($result->numRows())
4048 {
4049 $row = $ilDB->fetchAssoc($result);
4050 return $row["active_id"];
4051 }
4052 else
4053 {
4054 return "";
4055 }
4056 }
4057
4064 function pcArrayShuffle($array)
4065 {
4066 $keys = array_keys($array);
4067 shuffle($keys);
4068 $result = array();
4069 foreach ($keys as $key)
4070 {
4071 $result[$key] = $array[$key];
4072 }
4073 return $result;
4074 }
4075
4083 function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE, $considerHiddenQuestions = true, $considerOptionalQuestions = true)
4084 {
4085 global $tree, $ilDB, $lng, $ilPluginAdmin;
4086
4087 $results = $this->getResultsForActiveId($active_id);
4088
4089 if( is_null($pass) )
4090 {
4091 $pass = $results['pass'];
4092 }
4093
4094 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
4095 $testSessionFactory = new ilTestSessionFactory($this);
4096 $testSession = $testSessionFactory->getSession($active_id);
4097
4098 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4099 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
4100 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
4101
4102 if( $this->isDynamicTest() )
4103 {
4104 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4105 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
4106 $dynamicQuestionSetConfig->loadFromDb();
4107
4108 $testSequence->loadFromDb($dynamicQuestionSetConfig);
4109 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4110
4111 $sequence = $testSequence->getUserSequenceQuestions();
4112 }
4113 else
4114 {
4115 $testSequence->setConsiderHiddenQuestionsEnabled($considerHiddenQuestions);
4116 $testSequence->setConsiderOptionalQuestionsEnabled($considerOptionalQuestions);
4117
4118 $testSequence->loadFromDb();
4119 $testSequence->loadQuestions();
4120
4121 if( $ordered_sequence )
4122 {
4123 $sequence = $testSequence->getOrderedSequenceQuestions();
4124 }
4125 else
4126 {
4127 $sequence = $testSequence->getUserSequenceQuestions();
4128 }
4129 }
4130
4131 $arrResults = array();
4132
4133 $query = "
4134 SELECT tst_test_result.question_fi,
4135 tst_test_result.points reached,
4136 tst_test_result.hint_count requested_hints,
4137 tst_test_result.hint_points hint_points,
4138 tst_test_result.answered answered
4139
4140 FROM tst_test_result
4141
4142 LEFT JOIN tst_solutions
4143 ON tst_solutions.active_fi = tst_test_result.active_fi
4144 AND tst_solutions.question_fi = tst_test_result.question_fi
4145
4146 WHERE tst_test_result.active_fi = %s
4147 AND tst_test_result.pass = %s
4148 ";
4149
4150 $solutionresult = $ilDB->queryF(
4151 $query, array('integer', 'integer'), array($active_id, $pass)
4152 );
4153
4154 while( $row = $ilDB->fetchAssoc($solutionresult) )
4155 {
4156 $arrResults[ $row['question_fi'] ] = $row;
4157 }
4158
4159 $numWorkedThrough = count($arrResults);
4160
4161 require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4162
4163 $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4164
4165 $query = "
4166 SELECT qpl_questions.*,
4167 qpl_qst_type.type_tag,
4168 qpl_sol_sug.question_fi has_sug_sol
4169
4170 FROM qpl_qst_type,
4171 qpl_questions
4172
4173 LEFT JOIN qpl_sol_sug
4174 ON qpl_sol_sug.question_fi = qpl_questions.question_id
4175
4176 WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4177 AND $IN_question_ids
4178 ";
4179
4180 $result = $ilDB->query($query);
4181
4182 $unordered = array();
4183
4184 $key = 1;
4185
4186 $obligationsAnswered = true;
4187
4188 while( $row = $ilDB->fetchAssoc($result) )
4189 {
4190 $percentvalue = (
4191 $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4192 );
4193
4194 if( $percentvalue < 0 ) $percentvalue = 0.0;
4195
4196 $data = array(
4197 "nr" => "$key",
4198 "title" => ilUtil::prepareFormOutput($row['title']),
4199 "max" => round($row['points'], 2),
4200 "reached" => round($arrResults[$row['question_id']]['reached'],2),
4201 'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4202 'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4203 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4204 "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4205 "type" => $row["type_tag"],
4206 "qid" => $row['question_id'],
4207 "original_id" => $row["original_id"],
4208 "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4209 'answered' => $arrResults[$row['question_id']]['answered']
4210 );
4211
4212 if( !$arrResults[ $row['question_id'] ]['answered'] )
4213 {
4214 $obligationsAnswered = false;
4215 }
4216
4217 $unordered[ $row['question_id'] ] = $data;
4218
4219 $key++;
4220 }
4221
4222 $numQuestionsTotal = count($unordered);
4223
4224 $pass_max = 0;
4225 $pass_reached = 0;
4226 $pass_requested_hints = 0;
4227 $pass_hint_points = 0;
4228 $key = 1;
4229
4230 $found = array();
4231
4232 foreach( $sequence as $qid )
4233 {
4234 // building pass point sums based on prepared data
4235 // for question that exists in users qst sequence
4236 $pass_max += round($unordered[$qid]['max'], 2);
4237 $pass_reached += round($unordered[$qid]['reached'], 2);
4238 $pass_requested_hints += $unordered[$qid]['requested_hints'];
4239 $pass_hint_points += $unordered[$qid]['hint_points'];
4240
4241 // pickup prepared data for question
4242 // that exists in users qst sequence
4243 $unordered[$qid]['nr'] = $key;
4244 array_push($found, $unordered[$qid]);
4245
4246 // increment key counter
4247 $key++;
4248 }
4249
4250 $unordered = null;
4251
4252 if( $this->getScoreCutting() == 1 )
4253 {
4254 if( $results['reached_points'] < 0 )
4255 {
4256 $results['reached_points'] = 0;
4257 }
4258
4259 if( $pass_reached < 0 ) $pass_reached = 0;
4260 }
4261
4262 $found['pass']['total_max_points'] = $pass_max;
4263 $found['pass']['total_reached_points'] = $pass_reached;
4264 $found['pass']['total_requested_hints'] = $pass_requested_hints;
4265 $found['pass']['total_hint_points'] = $pass_hint_points;
4266 $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4267 $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4268 $found['pass']['num_workedthrough'] = $numWorkedThrough;
4269 $found['pass']['num_questions_total'] = $numQuestionsTotal;
4270
4271 $found["test"]["total_max_points"] = $results['max_points'];
4272 $found["test"]["total_reached_points"] = $results['reached_points'];
4273 $found["test"]["total_requested_hints"] = $results['hint_count'];
4274 $found["test"]["total_hint_points"] = $results['hint_points'];
4275 $found["test"]["result_pass"] = $results['pass'];
4276 $found['test']['obligations_answered'] = $results['obligations_answered'];
4277
4278 if( (!$total_reached_points) or (!$total_max_points) )
4279 {
4280 $percentage = 0.0;
4281 }
4282 else
4283 {
4284 $percentage = ($total_reached_points / $total_max_points) * 100.0;
4285
4286 if( $percentage < 0 ) $percentage = 0.0;
4287 }
4288
4289 $found["test"]["passed"] = $results['passed'];
4290
4291 return $found;
4292 }
4293
4301 {
4302 global $ilDB;
4303
4304 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4305 array('integer'),
4306 array($this->getTestId())
4307 );
4308 $row = $ilDB->fetchAssoc($result);
4309 return $row["total"];
4310 }
4311
4318 function getCompleteWorkingTime($user_id)
4319 {
4320 global $ilDB;
4321
4322 $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",
4323 array('integer','integer'),
4324 array($this->getTestId(), $user_id)
4325 );
4326 $time = 0;
4327 while ($row = $ilDB->fetchAssoc($result))
4328 {
4329 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4330 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4331 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4332 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4333 $time += ($epoch_2 - $epoch_1);
4334 }
4335 return $time;
4336 }
4337
4345 {
4346 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4347 }
4348
4357 {
4358 global $ilDB;
4359
4360 $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",
4361 array('integer'),
4362 array($test_id)
4363 );
4364 $time = 0;
4365 $times = array();
4366 while ($row = $ilDB->fetchAssoc($result))
4367 {
4368 if (!array_key_exists($row["active_fi"], $times))
4369 {
4370 $times[$row["active_fi"]] = 0;
4371 }
4372 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4373 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4374 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4375 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4376 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4377 }
4378 return $times;
4379 }
4380
4388 {
4389 global $ilDB;
4390
4391 $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",
4392 array('integer','integer'),
4393 array($this->getTestId(), $active_id)
4394 );
4395 $time = 0;
4396 while ($row = $ilDB->fetchAssoc($result))
4397 {
4398 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4399 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4400 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4401 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4402 $time += ($epoch_2 - $epoch_1);
4403 }
4404 return $time;
4405 }
4406
4414 {
4415 global $ilDB;
4416
4417 $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4418 array('integer','integer'),
4419 array($active_id, $pass)
4420 );
4421 $time = 0;
4422 while ($row = $ilDB->fetchAssoc($result))
4423 {
4424 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4425 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4426 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4427 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4428 $time += ($epoch_2 - $epoch_1);
4429 }
4430 return $time;
4431 }
4432
4440 function getVisitTimeOfParticipant($active_id)
4441 {
4442 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4443 }
4444
4454 {
4455 global $ilDB;
4456
4457 $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",
4458 array('integer','integer'),
4459 array($test_id, $active_id)
4460 );
4461 $firstvisit = 0;
4462 $lastvisit = 0;
4463 while ($row = $ilDB->fetchAssoc($result))
4464 {
4465 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4466 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4467 if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
4468 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4469 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4470 if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
4471 }
4472 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4473 }
4474
4481 function &evalStatistical($active_id)
4482 {
4483 global $ilDB;
4484// global $ilBench;
4485 $pass = ilObjTest::_getResultPass($active_id);
4486 $test_result =& $this->getTestResult($active_id, $pass);
4487 $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",
4488 array('integer'),
4489 array($active_id)
4490 );
4491 $times = array();
4492 $first_visit = 0;
4493 $last_visit = 0;
4494 while ($row = $ilDB->fetchObject($result))
4495 {
4496 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4497 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4498 if (!$first_visit) {
4499 $first_visit = $epoch_1;
4500 }
4501 if ($epoch_1 < $first_visit) {
4502 $first_visit = $epoch_1;
4503 }
4504 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4505 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4506 if (!$last_visit) {
4507 $last_visit = $epoch_2;
4508 }
4509 if ($epoch_2 > $last_visit) {
4510 $last_visit = $epoch_2;
4511 }
4512 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4513 }
4514 $max_time = 0;
4515 foreach ($times as $key => $value) {
4516 $max_time += $value;
4517 }
4518 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
4519 {
4520 $percentage = 0.0;
4521 }
4522 else
4523 {
4524 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4525 if ($percentage < 0) $percentage = 0.0;
4526 }
4527 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4528 $first_date = getdate($first_visit);
4529 $last_date = getdate($last_visit);
4530 $qworkedthrough = 0;
4531 foreach ($test_result as $key => $value)
4532 {
4533 if (preg_match("/\d+/", $key))
4534 {
4535 $qworkedthrough += $value["workedthrough"];
4536 }
4537 }
4538 if (!$qworkedthrough)
4539 {
4540 $atimeofwork = 0;
4541 }
4542 else
4543 {
4544 $atimeofwork = $max_time / $qworkedthrough;
4545 }
4546
4547 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4548
4549 $result_mark = "";
4550 $passed = "";
4551
4552 if ($mark_obj)
4553 {
4554 $result_mark = $mark_obj->getShortName();
4555
4556 if( $mark_obj->getPassed() && $obligationsAnswered )
4557 {
4558 $passed = 1;
4559 }
4560 else
4561 {
4562 $passed = 0;
4563 }
4564 }
4565 $percent_worked_through = 0;
4566 if (count($this->questions))
4567 {
4568 $percent_worked_through = $qworkedthrough / count($this->questions);
4569 }
4570 $result_array = array(
4571 "qworkedthrough" => $qworkedthrough,
4572 "qmax" => count($this->questions),
4573 "pworkedthrough" => $percent_worked_through,
4574 "timeofwork" => $max_time,
4575 "atimeofwork" => $atimeofwork,
4576 "firstvisit" => $first_date,
4577 "lastvisit" => $last_date,
4578 "resultspoints" => $test_result["test"]["total_reached_points"],
4579 "maxpoints" => $test_result["test"]["total_max_points"],
4580 "resultsmarks" => $result_mark,
4581 "passed" => $passed,
4582 "distancemedian" => "0"
4583 );
4584 foreach ($test_result as $key => $value)
4585 {
4586 if (preg_match("/\d+/", $key))
4587 {
4588 $result_array[$key] = $value;
4589 }
4590 }
4591 return $result_array;
4592 }
4593
4602 {
4603 $totalpoints_array = array();
4604 $all_users =& $this->evalTotalParticipantsArray();
4605 foreach ($all_users as $active_id => $user_name)
4606 {
4607 $test_result =& $this->getTestResult($active_id);
4608 $reached = $test_result["test"]["total_reached_points"];
4609 $total = $test_result["test"]["total_max_points"];
4610 $percentage = $total != 0 ? $reached/$total : 0;
4611 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4612
4613 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4614
4615 if ($mark)
4616 {
4617 if( $mark->getPassed() && $obligationsAnswered )
4618 {
4619 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4620 }
4621 }
4622 }
4623 return $totalpoints_array;
4624 }
4625
4631 public function &getParticipants()
4632 {
4633 global $ilDB;
4634 $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",
4635 array('integer'),
4636 array($this->getTestId())
4637 );
4638 $persons_array = array();
4639 while ($row = $ilDB->fetchAssoc($result))
4640 {
4641 $name = $this->lng->txt("anonymous");
4642 $fullname = $this->lng->txt("anonymous");
4643 $login = "";
4644 if (!$this->getAnonymity())
4645 {
4646 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4647 {
4648 $name = $this->lng->txt("deleted_user");
4649 $fullname = $this->lng->txt("deleted_user");
4650 $login = $this->lng->txt("unknown");
4651 }
4652 else
4653 {
4654 $login = $row["login"];
4655 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4656 {
4657 $name = $this->lng->txt("anonymous");
4658 $fullname = $this->lng->txt("anonymous");
4659 }
4660 else
4661 {
4662 $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4663 $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4664 }
4665 }
4666 }
4667 $persons_array[$row["active_id"]] = array(
4668 "name" => $name,
4669 "fullname" => $fullname,
4670 "login" => $login
4671 );
4672 }
4673 return $persons_array;
4674 }
4675
4682 function &evalTotalPersonsArray($name_sort_order = "asc")
4683 {
4684 global $ilDB;
4685 $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),
4686 array('integer'),
4687 array($this->getTestId())
4688 );
4689 $persons_array = array();
4690 while ($row = $ilDB->fetchAssoc($result))
4691 {
4692 if ($this->getAnonymity())
4693 {
4694 $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
4695 }
4696 else
4697 {
4698 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4699 {
4700 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4701 }
4702 else
4703 {
4704 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4705 {
4706 $persons_array[$row["active_id"]] = $row["lastname"];
4707 }
4708 else
4709 {
4710 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4711 }
4712 }
4713 }
4714 }
4715 return $persons_array;
4716 }
4717
4724 function &evalTotalParticipantsArray($name_sort_order = "asc")
4725 {
4726 global $ilDB;
4727 $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),
4728 array('integer'),
4729 array($this->getTestId())
4730 );
4731 $persons_array = array();
4732 while ($row = $ilDB->fetchAssoc($result))
4733 {
4734 if ($this->getAnonymity())
4735 {
4736 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
4737 }
4738 else
4739 {
4740 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4741 {
4742 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4743 }
4744 else
4745 {
4746 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4747 {
4748 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4749 }
4750 else
4751 {
4752 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4753 }
4754 }
4755 }
4756 }
4757 return $persons_array;
4758 }
4759
4767 {
4768 global $ilDB;
4769
4770 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4771 array('integer', 'integer'),
4772 array($this->getTestId(), 1)
4773 );
4774 $row = $ilDB->fetchAssoc($result);
4775 return $row["total"];
4776 }
4777
4784 function &getQuestionsOfTest($active_id)
4785 {
4786 global $ilDB;
4787 if ($this->isRandomTest())
4788 {
4789 $ilDB->setLimit($this->getQuestionCount(), 0);
4790 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4791 "tst_test_rnd_qst.pass, qpl_questions.points " .
4792 "FROM tst_test_rnd_qst, qpl_questions " .
4793 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4794 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4795 array('integer'),
4796 array($active_id)
4797 );
4798 }
4799 else
4800 {
4801 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4802 "qpl_questions.points " .
4803 "FROM tst_test_question, tst_active, qpl_questions " .
4804 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4805 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4806 array('integer'),
4807 array($active_id)
4808 );
4809 }
4810 $qtest = array();
4811 if ($result->numRows())
4812 {
4813 while ($row = $ilDB->fetchAssoc($result))
4814 {
4815 array_push($qtest, $row);
4816 }
4817 }
4818 return $qtest;
4819 }
4820
4827 function &getQuestionsOfPass($active_id, $pass)
4828 {
4829 global $ilDB;
4830 if ($this->isRandomTest())
4831 {
4832 $ilDB->setLimit($this->getQuestionCount(), 0);
4833 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4834 "qpl_questions.points " .
4835 "FROM tst_test_rnd_qst, qpl_questions " .
4836 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4837 "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4838 "ORDER BY tst_test_rnd_qst.sequence",
4839 array('integer', 'integer'),
4840 array($active_id, $pass)
4841 );
4842 }
4843 else
4844 {
4845 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4846 "qpl_questions.points " .
4847 "FROM tst_test_question, tst_active, qpl_questions " .
4848 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4849 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4850 array('integer'),
4851 array($active_id)
4852 );
4853 }
4854 $qpass = array();
4855 if ($result->numRows())
4856 {
4857 while ($row = $ilDB->fetchAssoc($result))
4858 {
4859 array_push($qpass, $row);
4860 }
4861 }
4862 return $qpass;
4863 }
4864
4866 {
4867 global $ilDB;
4868
4869 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
4870 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
4871 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
4872
4873 $data = new ilTestEvaluationData($this);
4874
4875 $query = "
4876 SELECT tst_test_result.*,
4877 qpl_questions.original_id,
4878 qpl_questions.title questiontitle,
4879 qpl_questions.points maxpoints
4880
4881 FROM tst_test_result, qpl_questions, tst_active
4882
4883 WHERE tst_active.active_id = tst_test_result.active_fi
4884 AND qpl_questions.question_id = tst_test_result.question_fi
4885 AND tst_active.test_fi = %s
4886
4887 ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
4888 ";
4889
4890 $result = $ilDB->queryF(
4891 $query, array('integer'), array($this->getTestId())
4892 );
4893
4894 $pass = NULL;
4895 $checked = array();
4896 $datasets = 0;
4897 $questionData = array();
4898
4899 while( $row = $ilDB->fetchAssoc($result) )
4900 {
4901 $participantObject = $data->getParticipant($row["active_fi"]);
4902
4903 if( !($participantObject instanceof ilTestEvaluationUserData) )
4904 {
4905 continue;
4906 }
4907
4908 $passObject = $participantObject->getPass($row["pass"]);
4909
4910 if( !($passObject instanceof ilTestEvaluationPassData) )
4911 {
4912 continue;
4913 }
4914
4915 $passObject->addAnsweredQuestion(
4916 $row["question_fi"], $row["maxpoints"], $row["points"], $row['answered'], null, $row['manual']
4917 );
4918 }
4919
4920 foreach( array_keys($data->getParticipants()) as $active_id )
4921 {
4922 if( $this->isRandomTest() )
4923 {
4924 for( $testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++ )
4925 {
4926 $ilDB->setLimit($this->getQuestionCount(), 0);
4927 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id, " .
4928 "tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title " .
4929 "FROM tst_test_rnd_qst, qpl_questions " .
4930 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4931 "AND tst_test_rnd_qst.pass = %s " .
4932 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4933 array('integer','integer'),
4934 array($testpass, $active_id)
4935 );
4936 if ($result->numRows())
4937 {
4938 while ($row = $ilDB->fetchAssoc($result))
4939 {
4940 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
4941 $data->getParticipant($active_id)->addQuestion($row["original_id"], $row["question_fi"], $row["points"], $row["sequence"], $tpass);
4942 $data->addQuestionTitle($row["question_fi"], $row["title"]);
4943 }
4944 }
4945 }
4946 }
4947 else if($this->isDynamicTest())
4948 {
4949 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4950 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4951 require_once 'Modules/Test/classes/class.ilTestDynamicQuestionSetFilterSelection.php';
4952
4953 $lastPass = $data->getParticipant($active_id)->getLastPass();
4954 for($testpass = 0; $testpass <= $lastPass; $testpass++)
4955 {
4956 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4957 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig(
4958 $GLOBALS['tree'], $ilDB, $GLOBALS['ilPluginAdmin'], $this
4959 );
4960 $dynamicQuestionSetConfig->loadFromDb();
4961
4962 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4963 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $GLOBALS['lng'], $GLOBALS['ilPluginAdmin'], $this);
4964 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $testpass);
4965
4966 $testSequence->loadFromDb($dynamicQuestionSetConfig);
4967 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4968
4969 $sequence = (array)$testSequence->getUserSequenceQuestions();
4970
4971 $questionsIdsToRequest = array_diff(array_values($sequence), array_values($questionData));
4972 if(count($questionsIdsToRequest) > 0)
4973 {
4974 $questionIdsCondition = ' ' . $ilDB->in('question_id', array_values($questionsIdsToRequest), false, 'integer') . ' ';
4975
4976 $res = $ilDB->queryF("
4977 SELECT *
4978 FROM qpl_questions
4979 WHERE {$questionIdsCondition}",
4980 array('integer'),
4981 array($active_id)
4982 );
4983 while($row = $ilDB->fetchAssoc($res))
4984 {
4985 $questionData[$row['question_id']] = $row;
4986 $data->addQuestionTitle($row['question_id'], $row['title']);
4987 }
4988 }
4989
4990 foreach($sequence as $questionId)
4991 {
4992 if(!isset($questionData[$questionId]))
4993 {
4994 continue;
4995 }
4996
4997 $row = $questionData[$questionId];
4998
4999 $data->getParticipant(
5000 $active_id)->addQuestion($row['original_id'], $row['question_id'], $row['points'],
5001 NULL, $testpass
5002 );
5003 }
5004 }
5005 }
5006 else
5007 {
5008 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
5009 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
5010 "FROM tst_test_question, tst_active, qpl_questions " .
5011 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
5012 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
5013 array('integer'),
5014 array($active_id)
5015 );
5016 if ($result->numRows())
5017 {
5018 $questionsbysequence = array();
5019
5020 while ($row = $ilDB->fetchAssoc($result))
5021 {
5022 $questionsbysequence[$row["sequence"]] = $row;
5023 }
5024
5025 $seqresult = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s",
5026 array('integer'),
5027 array($active_id)
5028 );
5029
5030 while ($seqrow = $ilDB->fetchAssoc($seqresult))
5031 {
5032 $questionsequence = unserialize($seqrow["sequence"]);
5033 foreach ($questionsequence as $sidx => $seq)
5034 {
5035 $data->getParticipant($active_id)->addQuestion($questionsbysequence[$seq]["original_id"], $questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
5036 $data->addQuestionTitle($questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["title"]);
5037 }
5038 }
5039 }
5040 }
5041 }
5042
5043 if($this->getECTSOutput())
5044 {
5045 $passed_array =& $this->getTotalPointsPassedArray();
5046 }
5047
5048 foreach( array_keys($data->getParticipants()) as $active_id )
5049 {
5050 $tstUserData = $data->getParticipant($active_id);
5051
5052 $percentage = $tstUserData->getReachedPointsInPercent();
5053
5054 $obligationsAnswered = $tstUserData->areObligationsAnswered();
5055
5056 $mark = $this->mark_schema->getMatchingMark($percentage);
5057
5058 if (is_object($mark))
5059 {
5060 $tstUserData->setMark($mark->getShortName());
5061 $tstUserData->setMarkOfficial($mark->getOfficialName());
5062
5063 $tstUserData->setPassed(
5064 $mark->getPassed() && $tstUserData->areObligationsAnswered()
5065 );
5066 }
5067
5068 if($this->getECTSOutput())
5069 {
5070 $ects_mark = $this->getECTSGrade(
5071 $passed_array, $tstUserData->getReached(), $tstUserData->getMaxPoints()
5072 );
5073
5074 $tstUserData->setECTSMark($ects_mark);
5075 }
5076
5077 $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
5078
5079 $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
5080 $tstUserData->setLastVisit($visitingTime["lastvisit"]);
5081 }
5082
5083 return $data;
5084 }
5085
5087 {
5088 global $ilDB;
5089
5091
5092 switch( $questionSetType )
5093 {
5095
5096 $res = $ilDB->queryF("
5097 SELECT COUNT(qpl_questions.question_id) qcount,
5098 SUM(qpl_questions.points) qsum
5099 FROM tst_active
5100 INNER JOIN tst_tests
5101 ON tst_tests.test_id = tst_active.test_fi
5102 INNER JOIN tst_dyn_quest_set_cfg
5103 ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
5104 INNER JOIN qpl_questions
5105 ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
5106 AND qpl_questions.original_id IS NULL
5107 AND qpl_questions.complete = %s
5108 WHERE tst_active.active_id = %s
5109 ",
5110 array('integer', 'integer'),
5111 array(1, $active_id)
5112 );
5113
5114 break;
5115
5117
5118 $res = $ilDB->queryF("
5119 SELECT tst_test_rnd_qst.pass,
5120 COUNT(tst_test_rnd_qst.question_fi) qcount,
5121 SUM(qpl_questions.points) qsum
5122
5123 FROM tst_test_rnd_qst,
5124 qpl_questions
5125
5126 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
5127 AND tst_test_rnd_qst.active_fi = %s
5128 AND pass = %s
5129
5130 GROUP BY tst_test_rnd_qst.active_fi,
5131 tst_test_rnd_qst.pass
5132 ",
5133 array('integer', 'integer'),
5134 array($active_id, $pass)
5135 );
5136
5137 break;
5138
5140
5141 $res = $ilDB->queryF("
5142 SELECT COUNT(tst_test_question.question_fi) qcount,
5143 SUM(qpl_questions.points) qsum
5144
5145 FROM tst_test_question,
5146 qpl_questions,
5147 tst_active
5148
5149 WHERE tst_test_question.question_fi = qpl_questions.question_id
5150 AND tst_test_question.test_fi = tst_active.test_fi
5151 AND tst_active.active_id = %s
5152
5153 GROUP BY tst_test_question.test_fi
5154 ",
5155 array('integer'),
5156 array($active_id)
5157 );
5158
5159 break;
5160
5161 default:
5162
5163 throw new ilTestException("not supported question set type: $questionSetType");
5164 }
5165
5166 $row = $ilDB->fetchAssoc($res);
5167
5168 if( is_array($row) )
5169 {
5170 return array("count" => $row["qcount"], "points" => $row["qsum"]);
5171 }
5172
5173 return array("count" => 0, "points" => 0);
5174 }
5175
5176 function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
5177 {
5178 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5179 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5180 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5182 if ($withStatistics)
5183 {
5184 $data->calculateStatistics();
5185 }
5186 $data->setFilter($filterby, $filtertext);
5187 return $data;
5188 }
5189
5197 {
5198 return $this->_evalResultsOverview($this->getTestId());
5199 }
5200
5207 function &_evalResultsOverview($test_id)
5208 {
5209 global $ilDB;
5210
5211 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5212 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5213 "qpl_questions.points maxpoints " .
5214 "FROM tst_test_result, qpl_questions, tst_active " .
5215 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5216 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5217 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5218 "AND tst_active.test_fi = %s " .
5219 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5220 array('integer'),
5221 array($test_id)
5222 );
5223 $overview = array();
5224 while ($row = $ilDB->fetchAssoc($result))
5225 {
5226 if (!array_key_exists($row["active_fi"], $overview))
5227 {
5228 $overview[$row["active_fi"]] = array();
5229 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5230 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5231 $overview[$row["active_fi"]]["title"] = $row["title"];
5232 $overview[$row["active_fi"]]["login"] = $row["login"];
5233 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5234 $overview[$row["active_fi"]]["started"] = $row["started"];
5235 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5236 }
5237 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5238 {
5239 $overview[$row["active_fi"]][$row["pass"]] = array();
5240 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5241 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5242 }
5243 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5244 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5245 }
5246 return $overview;
5247 }
5248
5257 {
5258 global $ilDB;
5259
5260 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5261 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5262 "qpl_questions.points maxpoints " .
5263 "FROM tst_test_result, qpl_questions, tst_active " .
5264 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5265 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5266 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5267 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5268 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5269 array('integer', 'integer'),
5270 array($this->getTestId(), $active_id)
5271 );
5272 $overview = array();
5273 while ($row = $ilDB->fetchAssoc($result))
5274 {
5275 if (!array_key_exists($row["active_fi"], $overview))
5276 {
5277 $overview[$row["active_fi"]] = array();
5278 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5279 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5280 $overview[$row["active_fi"]]["title"] = $row["title"];
5281 $overview[$row["active_fi"]]["login"] = $row["login"];
5282 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5283 $overview[$row["active_fi"]]["started"] = $row["started"];
5284 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5285 }
5286 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5287 {
5288 $overview[$row["active_fi"]][$row["pass"]] = array();
5289 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5290 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5291 }
5292 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5293 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5294 }
5295 return $overview;
5296 }
5297
5309 function buildName($user_id, $firstname, $lastname, $title)
5310 {
5311 $name = "";
5312 if (strlen($firstname.$lastname.$title) == 0)
5313 {
5314 $name = $this->lng->txt("deleted_user");
5315 }
5316 else
5317 {
5318 if ($user_id == ANONYMOUS_USER_ID)
5319 {
5320 $name = $lastname;
5321 }
5322 else
5323 {
5324 $name = trim($lastname . ", " . $firstname . " " . $title);
5325 }
5326 if ($this->getAnonymity())
5327 {
5328 $name = $this->lng->txt("anonymous");
5329 }
5330 }
5331 return $name;
5332 }
5333
5346 function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5347 {
5348 global $lng;
5349 $name = "";
5350 if (strlen($firstname.$lastname.$title) == 0)
5351 {
5352 $name = $lng->txt("deleted_user");
5353 }
5354 else
5355 {
5356 if ($user_id == ANONYMOUS_USER_ID)
5357 {
5358 $name = $lastname;
5359 }
5360 else
5361 {
5362 $name = trim($lastname . ", " . $firstname . " " . $title);
5363 }
5364 if ($is_anonymous)
5365 {
5366 $name = $lng->txt("anonymous");
5367 }
5368 }
5369 return $name;
5370 }
5371
5379 {
5380 global $ilDB;
5381
5382 $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",
5383 array('integer'),
5384 array($this->getTestId())
5385 );
5386 $times = array();
5387 while ($row = $ilDB->fetchObject($result))
5388 {
5389 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5390 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5391 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5392 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5393 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5394 }
5395 $max_time = 0;
5396 $counter = 0;
5397 foreach ($times as $key => $value)
5398 {
5399 $max_time += $value;
5400 $counter++;
5401 }
5402 if ($counter)
5403 {
5404 $average_time = round($max_time / $counter);
5405 }
5406 else
5407 {
5408 $average_time = 0;
5409 }
5410 return $average_time;
5411 }
5412
5419 function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
5420 {
5421 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5422 return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5423 }
5424
5432 {
5433 $time_in_seconds = 0;
5434 foreach ($this->questions as $question_id)
5435 {
5436 $question =& ilObjTest::_instanciateQuestion($question_id);
5437 $est_time = $question->getEstimatedWorkingTime();
5438 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5439 }
5440 $hours = (int)($time_in_seconds / 3600) ;
5441 $time_in_seconds = $time_in_seconds - ($hours * 3600);
5442 $minutes = (int)($time_in_seconds / 60);
5443 $time_in_seconds = $time_in_seconds - ($minutes * 60);
5444 $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5445 return $result;
5446 }
5447
5454 function getImagePath()
5455 {
5456 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5457 }
5458
5466 {
5467 include_once "./Services/Utilities/classes/class.ilUtil.php";
5468 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5470 }
5471
5480 function &createQuestionGUI($question_type, $question_id = -1)
5481 {
5482 if ((!$question_type) and ($question_id > 0))
5483 {
5484 $question_type = $this->getQuestionType($question_id);
5485 }
5486
5487 if (!strlen($question_type)) return null;
5488
5489 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5490 assQuestion::_includeClass($question_type, 1);
5491
5492 $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5493 $question = new $question_type_gui();
5494
5495 if ($question_id > 0)
5496 {
5497 $question->object->loadFromDb($question_id);
5498
5499 global $ilCtrl, $ilDB, $ilUser, $lng;
5500
5501 $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5502 $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5503
5504 $assSettings = new ilSetting('assessment');
5505 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5506 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5507 $processLockerFactory->setQuestionId($question->object->getId());
5508 $processLockerFactory->setUserId($ilUser->getId());
5509 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5510 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5511 $question->object->setProcessLocker($processLockerFactory->getLocker());
5512 }
5513
5514 return $question;
5515 }
5516
5526 function &_instanciateQuestion($question_id)
5527 {
5528 if (strcmp($question_id, "") != 0)
5529 {
5530 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5531 return assQuestion::_instanciateQuestion($question_id);
5532 }
5533 }
5534
5543 function moveQuestions($move_questions, $target_index, $insert_mode)
5544 {
5545 $this->questions = array_values($this->questions);
5546 $array_pos = array_search($target_index, $this->questions);
5547 if ($insert_mode == 0)
5548 {
5549 $part1 = array_slice($this->questions, 0, $array_pos);
5550 $part2 = array_slice($this->questions, $array_pos);
5551 }
5552 else if ($insert_mode == 1)
5553 {
5554 $part1 = array_slice($this->questions, 0, $array_pos + 1);
5555 $part2 = array_slice($this->questions, $array_pos + 1);
5556 }
5557 foreach ($move_questions as $question_id)
5558 {
5559 if (!(array_search($question_id, $part1) === FALSE))
5560 {
5561 unset($part1[array_search($question_id, $part1)]);
5562 }
5563 if (!(array_search($question_id, $part2) === FALSE))
5564 {
5565 unset($part2[array_search($question_id, $part2)]);
5566 }
5567 }
5568 $part1 = array_values($part1);
5569 $part2 = array_values($part2);
5570 $new_array = array_values(array_merge($part1, $move_questions, $part2));
5571 $this->questions = array();
5572 $counter = 1;
5573 foreach ($new_array as $question_id)
5574 {
5575 $this->questions[$counter] = $question_id;
5576 $counter++;
5577 }
5578 $this->saveQuestionsToDb();
5579 }
5580
5581
5590 {
5591 if( $this->isStartingTimeEnabled() && $this->getStartingTime() )
5592 {
5593 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
5594 {
5595 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5596 $now = mktime();
5597 if ($now < $epoch_time)
5598 {
5599 // starting time not reached
5600 return false;
5601 }
5602 }
5603 }
5604 return true;
5605 }
5606
5615 {
5616 if( $this->isEndingTimeEnabled() && $this->getEndingTime() )
5617 {
5618 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
5619 {
5620 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5621 $now = mktime();
5622 if ($now > $epoch_time)
5623 {
5624 // ending time reached
5625 return true;
5626 }
5627 }
5628 }
5629 return false;
5630 }
5631
5637 function getAvailableQuestions($arrFilter, $completeonly = 0)
5638 {
5639 global $ilUser;
5640 global $ilDB;
5641
5642 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5643 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
5644 $available = "";
5645 if (count($available_pools))
5646 {
5647 $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5648 }
5649 else
5650 {
5651 return array();
5652 }
5653 if ($completeonly)
5654 {
5655 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5656 }
5657
5658 $where = "";
5659 if (is_array($arrFilter))
5660 {
5661 if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
5662 {
5663 $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5664 }
5665 if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
5666 {
5667 $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5668 }
5669 if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
5670 {
5671 $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5672 }
5673 if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
5674 {
5675 $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5676 }
5677 if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl']))
5678 {
5679 $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5680 }
5681 }
5682
5683 $original_ids =& $this->getExistingQuestions();
5684 $original_clause = " qpl_questions.original_id IS NULL";
5685 if (count($original_ids))
5686 {
5687 $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5688 }
5689
5690 $query_result = $ilDB->query(
5691 "SELECT qpl_questions.*, qpl_questions.tstamp, qpl_qst_type.type_tag, qpl_qst_type.plugin, object_data.title qpl " .
5692 "FROM qpl_questions, qpl_qst_type, object_data WHERE $original_clause $available AND " .
5693 "object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.tstamp > 0 AND " .
5694 "qpl_questions.question_type_fi = qpl_qst_type.question_type_id$where");
5695 $rows = array();
5696 $types = $this->getQuestionTypeTranslations();
5697 if ($query_result->numRows())
5698 {
5699 while ($row = $ilDB->fetchAssoc($query_result))
5700 {
5701 $row['ttype'] = $types[$row['type_tag']];
5702 if ($row["plugin"])
5703 {
5704 if ($this->isPluginActive($row["type_tag"]))
5705 {
5706 array_push($rows, $row);
5707 }
5708 }
5709 else
5710 {
5711 array_push($rows, $row);
5712 }
5713 }
5714 }
5715 return $rows;
5716 }
5717
5719 {
5720 global $ilDB;
5721 global $lng;
5722 global $ilLog;
5723 global $ilPluginAdmin;
5724
5725 $lng->loadLanguageModule("assessment");
5726 $result = $ilDB->query("SELECT * FROM qpl_qst_type");
5727 $types = array();
5728 while ($row = $ilDB->fetchAssoc($result))
5729 {
5730 if ($row["plugin"] == 0)
5731 {
5732 $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
5733 }
5734 else
5735 {
5736 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
5737 foreach ($pl_names as $pl_name)
5738 {
5739 $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
5740 if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0)
5741 {
5742 $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
5743 }
5744 }
5745 }
5746 }
5747 ksort($types);
5748 return $types;
5749 }
5750
5755 public function fromXML(ilQTIAssessment $assessment)
5756 {
5757 unset($_SESSION["import_mob_xhtml"]);
5758
5759 $this->setDescription($assessment->getComment());
5760 $this->setTitle($assessment->getTitle());
5761
5762 $this->setIntroductionEnabled(false);
5763 foreach ($assessment->objectives as $objectives)
5764 {
5765 foreach ($objectives->materials as $material)
5766 {
5767 $intro = $this->QTIMaterialToString($material);
5768 $this->setIntroduction($intro);
5769 $this->setIntroductionEnabled(strlen($intro) > 0);
5770 }
5771 }
5772
5773 if(
5774 $assessment->getPresentationMaterial() &&
5775 $assessment->getPresentationMaterial()->getFlowMat(0) &&
5776 $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5777 )
5778 {
5779 $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5780 }
5781
5782 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
5783 {
5784 switch ($assessmentcontrol->getSolutionswitch())
5785 {
5786 case "Yes":
5788 break;
5789 default:
5791 break;
5792 }
5793 }
5794
5795 $this->setStartingTimeEnabled(false);
5796 $this->setEndingTimeEnabled(false);
5797 $this->setPasswordEnabled(false);
5798 $this->setLimitUsersEnabled(false);
5799
5800 foreach ($assessment->qtimetadata as $metadata)
5801 {
5802 switch ($metadata["label"])
5803 {
5804 case "test_type":
5805 // for old tests with a test type
5806 $type = $metadata["entry"];
5807 switch ($type)
5808 {
5809 case 1:
5810 // assessment
5811 $this->setAnonymity(1);
5812 break;
5813 case 2:
5814 // self assessment
5815 break;
5816 case 4:
5817 // online exam
5818 $this->setFixedParticipants(1);
5820 $this->setShowSolutionPrintview(1);
5821 break;
5822 case 5:
5823 // varying random test
5824 break;
5825 }
5826 break;
5827 case "sequence_settings":
5828 $this->setSequenceSettings($metadata["entry"]);
5829 break;
5830 case "solution_details":
5831 $this->setShowSolutionDetails((int)$metadata["entry"]);
5832 break;
5833 case "print_bs_with_res":
5834 $this->setPrintBestSolutionWithResult((int)$metadata["entry"]);
5835 break;
5836 case "author":
5837 $this->setAuthor($metadata["entry"]);
5838 break;
5839 case "nr_of_tries":
5840 $this->setNrOfTries($metadata["entry"]);
5841 break;
5842 case "kiosk":
5843 $this->setKiosk($metadata["entry"]);
5844 break;
5845 case "showfinalstatement":
5846 $this->setShowFinalStatement($metadata["entry"]);
5847 break;
5848 case "showinfo":
5849 $this->setShowInfo($metadata["entry"]);
5850 break;
5851 case "forcejs":
5852 $this->setForceJS($metadata["entry"]);
5853 break;
5854 case "customstyle":
5855 $this->setCustomStyle($metadata["entry"]);
5856 break;
5857
5858 case "highscore_enabled":
5859 $this->setHighscoreEnabled($metadata["entry"]);
5860 break;
5861
5862 case "highscore_anon":
5863 $this->setHighscoreAnon($metadata["entry"]);
5864 break;
5865
5866 case "highscore_achieved_ts":
5867 $this->setHighscoreAchievedTS($metadata["entry"]);
5868 break;
5869
5870 case "highscore_score":
5871 $this->setHighscoreScore($metadata["entry"]);
5872 break;
5873
5874 case "highscore_percentage":
5875 $this->setHighscorePercentage($metadata["entry"]);
5876 break;
5877
5878 case "highscore_hints":
5879 $this->setHighscoreHints($metadata["entry"]);
5880 break;
5881
5882 case "highscore_wtime":
5883 $this->setHighscoreWTime($metadata["entry"]);
5884 break;
5885
5886 case "highscore_own_table":
5887 $this->setHighscoreOwnTable($metadata["entry"]);
5888 break;
5889
5890 case "highscore_top_table":
5891 $this->setHighscoreTopTable($metadata["entry"]);
5892 break;
5893
5894 case "highscore_top_num":
5895 $this->setHighscoreTopNum($metadata["entry"]);
5896 break;
5897
5898 case "hide_previous_results":
5899 if ($metadata["entry"] == 0)
5900 {
5901 $this->setUsePreviousAnswers(1);
5902 }
5903 else
5904 {
5905 $this->setUsePreviousAnswers(0);
5906 }
5907 break;
5908 case "use_previous_answers":
5909 $this->setUsePreviousAnswers($metadata["entry"]);
5910 break;
5911 case "answer_feedback":
5912 $this->setAnswerFeedback($metadata["entry"]);
5913 break;
5914 case "hide_title_points":
5915 $this->setTitleOutput($metadata["entry"]);
5916 break;
5917 case "title_output":
5918 $this->setTitleOutput($metadata["entry"]);
5919 break;
5920 case "question_set_type":
5921 $this->setQuestionSetType($metadata["entry"]);
5922 break;
5923 case "random_test":
5924 if( $metadata["entry"] )
5925 {
5926 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
5927 }
5928 else
5929 {
5930 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
5931 }
5932 break;
5933 case "results_presentation":
5934 $this->setResultsPresentation($metadata["entry"]);
5935 break;
5936 case "reset_processing_time":
5937 $this->setResetProcessingTime($metadata["entry"]);
5938 break;
5939 case "instant_verification":
5940 $this->setInstantFeedbackSolution($metadata["entry"]);
5941 break;
5942 case "instant_feedback_answer_fixation":
5943 $this->setInstantFeedbackAnswerFixationEnabled((bool)$metadata["entry"]);
5944 break;
5945 case "force_instant_feedback":
5946 $this->setForceInstantFeedbackEnabled((bool)$metadata["entry"]);
5947 break;
5948 case "answer_feedback_points":
5949 $this->setAnswerFeedbackPoints($metadata["entry"]);
5950 break;
5951 case "anonymity":
5952 $this->setAnonymity($metadata["entry"]);
5953 break;
5954 case "use_pool":
5955 $this->setPoolUsage((int)$metadata["entry"]);
5956 break;
5957 case "show_cancel":
5958 $this->setShowCancel($metadata["entry"]);
5959 break;
5960 case "show_marker":
5961 $this->setShowMarker($metadata["entry"]);
5962 break;
5963 case "fixed_participants":
5964 $this->setFixedParticipants($metadata["entry"]);
5965 break;
5966 case "score_reporting":
5967 $this->setScoreReporting($metadata["entry"]);
5968 break;
5969 case "shuffle_questions":
5970 $this->setShuffleQuestions($metadata["entry"]);
5971 break;
5972 case "count_system":
5973 $this->setCountSystem($metadata["entry"]);
5974 break;
5975 case "mc_scoring":
5976 $this->setMCScoring($metadata["entry"]);
5977 break;
5978 case "mailnotification":
5979 $this->setMailNotification($metadata["entry"]);
5980 break;
5981 case "mailnottype":
5982 $this->setMailNotificationType($metadata["entry"]);
5983 break;
5984 case "exportsettings":
5985 $this->setExportSettings($metadata['entry']);
5986 break;
5987 case "score_cutting":
5988 $this->setScoreCutting($metadata["entry"]);
5989 break;
5990 case "password":
5991 $this->setPassword($metadata["entry"]);
5992 $this->setPasswordEnabled(strlen($metadata["entry"]) > 0);
5993 break;
5994 case "allowedUsers":
5995 $this->setAllowedUsers($metadata["entry"]);
5996 $this->setLimitUsersEnabled((int)$metadata["entry"] > 0);
5997 break;
5998 case "allowedUsersTimeGap":
5999 $this->setAllowedUsersTimeGap($metadata["entry"]);
6000 break;
6001 case "pass_scoring":
6002 $this->setPassScoring($metadata["entry"]);
6003 break;
6004 case 'pass_deletion_allowed':
6005 $this->setPassDeletionAllowed((int)$metadata['entry']);
6006 break;
6007 case "show_summary":
6008 $this->setListOfQuestionsSettings($metadata["entry"]);
6009 break;
6010 case "reporting_date":
6011 $iso8601period = $metadata["entry"];
6012 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6013 {
6014 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6015 }
6016 break;
6017 case 'enable_processing_time':
6018 $this->setEnableProcessingTime($metadata['entry']);
6019 break;
6020 case "processing_time":
6021 $this->setProcessingTime($metadata['entry']);
6022 break;
6023 case "starting_time":
6024 $iso8601period = $metadata["entry"];
6025 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6026 {
6027 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6028 $this->setStartingTimeEnabled(true);
6029 }
6030 break;
6031 case "ending_time":
6032 $iso8601period = $metadata["entry"];
6033 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6034 {
6035 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6036 $this->setEndingTimeEnabled(true);
6037 }
6038 break;
6039 case "enable_examview":
6040 $this->setEnableExamview($metadata["entry"]);
6041 break;
6042 case 'show_examview_html':
6043 $this->setShowExamviewHtml($metadata['entry']);
6044 break;
6045 case 'show_examview_pdf':
6046 $this->setShowExamviewPdf($metadata['entry']);
6047 break;
6048 case 'redirection_mode':
6049 $this->setRedirectionMode($metadata['entry']);
6050 break;
6051 case 'redirection_url':
6052 $this->setRedirectionUrl($metadata['entry']);
6053 break;
6054 case 'examid_in_kiosk':
6055 case 'examid_in_test_pass':
6056 $this->setShowExamIdInTestPassEnabled($metadata['entry']);
6057 break;
6058 case 'show_exam_id':
6059 case 'examid_in_test_res':
6060 $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
6061 break;
6062 case 'enable_archiving':
6063 $this->setEnableArchiving($metadata['entry']);
6064 break;
6065 case 'sign_submission':
6066 $this->setSignSubmission($metadata['entry']);
6067 break;
6068 case 'char_selector_availability':
6069 $this->setCharSelectorAvailability($metadata['entry']);
6070 break;
6071 case 'char_selector_definition':
6072 $this->setCharSelectorDefinition($metadata['entry']);
6073 break;
6074 case 'skill_service':
6075 $this->setSkillServiceEnabled((bool)$metadata['entry']);
6076 break;
6077 case 'result_tax_filters':
6078 $this->setResultFilterTaxIds(strlen($metadata['entry']) ? unserialize($metadata['entry']) : array());
6079 break;
6080 case 'show_grading_status':
6081 $this->setShowGradingStatusEnabled((bool)$metadata['entry']);
6082 break;
6083 case 'show_grading_mark':
6084 $this->setShowGradingMarkEnabled((bool)$metadata['entry']);
6085 break;
6086 case 'activation_limited':
6087 $this->setActivationLimited($metadata['entry']);
6088 break;
6089 case 'activation_start_time':
6090 $this->setActivationStartingTime($metadata['entry']);
6091 break;
6092 case 'activation_end_time':
6093 $this->setActivationEndingTime($metadata['entry']);
6094 break;
6095 case 'activation_visibility':
6096 $this->setActivationVisibility($metadata['entry']);
6097 break;
6098 case 'autosave':
6099 $this->setAutosave($metadata['entry']);
6100 break;
6101 case 'autosave_ival':
6102 $this->setAutosaveIval($metadata['entry']);
6103 break;
6104 case 'offer_question_hints':
6105 $this->setOfferingQuestionHintsEnabled($metadata['entry']);
6106 break;
6107 case 'instant_feedback_specific':
6108 $this->setSpecificAnswerFeedback($metadata['entry']);
6109 break;
6110 case 'obligations_enabled':
6111 $this->setObligationsEnabled($metadata['entry']);
6112 break;
6113 }
6114 if (preg_match("/mark_step_\d+/", $metadata["label"]))
6115 {
6116 $xmlmark = $metadata["entry"];
6117 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
6118 $mark_short = $matches[1];
6119 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
6120 $mark_official = $matches[1];
6121 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
6122 $mark_percentage = $matches[1];
6123 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
6124 $mark_passed = $matches[1];
6125 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
6126 }
6127 }
6128 // handle the import of media objects in XHTML code
6129 if (is_array($_SESSION["import_mob_xhtml"]))
6130 {
6131 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6132 include_once "./Services/RTE/classes/class.ilRTE.php";
6133 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
6134 foreach ($_SESSION["import_mob_xhtml"] as $mob)
6135 {
6136 $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
6137 if (file_exists($importfile))
6138 {
6139 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
6140 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
6141 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
6142 $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
6143 }
6144 else
6145 {
6146 global $ilLog;
6147 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
6148 }
6149 }
6150 $this->saveToDb();
6151 }
6152 }
6153
6159 public function toXML()
6160 {
6161 include_once("./Services/Xml/classes/class.ilXmlWriter.php");
6162 $a_xml_writer = new ilXmlWriter;
6163 // set xml header
6164 $a_xml_writer->xmlHeader();
6165 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
6166 $a_xml_writer->xmlStartTag("questestinterop");
6167
6168 $attrs = array(
6169 "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
6170 "title" => $this->getTitle()
6171 );
6172 $a_xml_writer->xmlStartTag("assessment", $attrs);
6173 // add qti comment
6174 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
6175
6176 // add qti duration
6177 if ($this->enable_processing_time)
6178 {
6179 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
6180 $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
6181 }
6182
6183 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
6184 $a_xml_writer->xmlStartTag("qtimetadata");
6185 $a_xml_writer->xmlStartTag("qtimetadatafield");
6186 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
6187 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
6188 $a_xml_writer->xmlEndTag("qtimetadatafield");
6189
6190 // anonymity
6191 $a_xml_writer->xmlStartTag("qtimetadatafield");
6192 $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
6193 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
6194 $a_xml_writer->xmlEndTag("qtimetadatafield");
6195
6196 $a_xml_writer->xmlStartTag("qtimetadatafield");
6197 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_pool");
6198 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPoolUsage() ? 1 : 0);
6199 $a_xml_writer->xmlEndTag("qtimetadatafield");
6200
6201 // question set type (fixed, random, dynamic, ...)
6202 $a_xml_writer->xmlStartTag("qtimetadatafield");
6203 $a_xml_writer->xmlElement("fieldlabel", NULL, "question_set_type");
6204 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getQuestionSetType());
6205 $a_xml_writer->xmlEndTag("qtimetadatafield");
6206
6207 // sequence settings
6208 $a_xml_writer->xmlStartTag("qtimetadatafield");
6209 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
6210 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
6211 $a_xml_writer->xmlEndTag("qtimetadatafield");
6212
6213 // author
6214 $a_xml_writer->xmlStartTag("qtimetadatafield");
6215 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
6216 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
6217 $a_xml_writer->xmlEndTag("qtimetadatafield");
6218
6219 // reset processing time
6220 $a_xml_writer->xmlStartTag("qtimetadatafield");
6221 $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
6222 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
6223 $a_xml_writer->xmlEndTag("qtimetadatafield");
6224
6225 // count system
6226 $a_xml_writer->xmlStartTag("qtimetadatafield");
6227 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
6228 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
6229 $a_xml_writer->xmlEndTag("qtimetadatafield");
6230
6231 // multiple choice scoring
6232 $a_xml_writer->xmlStartTag("qtimetadatafield");
6233 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
6234 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
6235 $a_xml_writer->xmlEndTag("qtimetadatafield");
6236
6237 // multiple choice scoring
6238 $a_xml_writer->xmlStartTag("qtimetadatafield");
6239 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
6240 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
6241 $a_xml_writer->xmlEndTag("qtimetadatafield");
6242
6243 // multiple choice scoring
6244 $a_xml_writer->xmlStartTag("qtimetadatafield");
6245 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
6246 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
6247 $a_xml_writer->xmlEndTag("qtimetadatafield");
6248
6249 // allowed users
6250 $a_xml_writer->xmlStartTag("qtimetadatafield");
6251 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
6252 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
6253 $a_xml_writer->xmlEndTag("qtimetadatafield");
6254
6255 // allowed users time gap
6256 $a_xml_writer->xmlStartTag("qtimetadatafield");
6257 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
6258 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
6259 $a_xml_writer->xmlEndTag("qtimetadatafield");
6260
6261 // pass scoring
6262 $a_xml_writer->xmlStartTag("qtimetadatafield");
6263 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
6264 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
6265 $a_xml_writer->xmlEndTag("qtimetadatafield");
6266
6267 $a_xml_writer->xmlStartTag('qtimetadatafield');
6268 $a_xml_writer->xmlElement('fieldlabel', NULL, 'pass_deletion_allowed');
6269 $a_xml_writer->xmlElement('fieldentry', NULL, (int)$this->isPassDeletionAllowed());
6270 $a_xml_writer->xmlEndTag('qtimetadatafield');
6271
6272 // score reporting date
6273 if ($this->getReportingDate())
6274 {
6275 $a_xml_writer->xmlStartTag("qtimetadatafield");
6276 $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
6277 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6278 $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]));
6279 $a_xml_writer->xmlEndTag("qtimetadatafield");
6280 }
6281 // number of tries
6282 $a_xml_writer->xmlStartTag("qtimetadatafield");
6283 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
6284 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
6285 $a_xml_writer->xmlEndTag("qtimetadatafield");
6286
6287 // kiosk
6288 $a_xml_writer->xmlStartTag("qtimetadatafield");
6289 $a_xml_writer->xmlElement("fieldlabel", NULL, "kiosk");
6290 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getKiosk()));
6291 $a_xml_writer->xmlEndTag("qtimetadatafield");
6292
6293
6294 //redirection_mode
6295 $a_xml_writer->xmlStartTag('qtimetadatafield');
6296 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_mode");
6297 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionMode());
6298 $a_xml_writer->xmlEndTag("qtimetadatafield");
6299
6300 //redirection_url
6301 $a_xml_writer->xmlStartTag('qtimetadatafield');
6302 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_url");
6303 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionUrl());
6304 $a_xml_writer->xmlEndTag("qtimetadatafield");
6305
6306 // use previous answers
6307 $a_xml_writer->xmlStartTag("qtimetadatafield");
6308 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
6309 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
6310 $a_xml_writer->xmlEndTag("qtimetadatafield");
6311
6312 // hide title points
6313 $a_xml_writer->xmlStartTag("qtimetadatafield");
6314 $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
6315 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
6316 $a_xml_writer->xmlEndTag("qtimetadatafield");
6317
6318 // results presentation
6319 $a_xml_writer->xmlStartTag("qtimetadatafield");
6320 $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
6321 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
6322 $a_xml_writer->xmlEndTag("qtimetadatafield");
6323
6324 // examid in test pass
6325 $a_xml_writer->xmlStartTag("qtimetadatafield");
6326 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_pass");
6327 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6328 $a_xml_writer->xmlEndTag("qtimetadatafield");
6329
6330 // examid in kiosk
6331 $a_xml_writer->xmlStartTag("qtimetadatafield");
6332 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_res");
6333 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6334 $a_xml_writer->xmlEndTag("qtimetadatafield");
6335
6336 // solution details
6337 $a_xml_writer->xmlStartTag("qtimetadatafield");
6338 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
6339 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
6340 $a_xml_writer->xmlEndTag("qtimetadatafield");
6341
6342 // solution details
6343 $a_xml_writer->xmlStartTag("qtimetadatafield");
6344 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
6345 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
6346 $a_xml_writer->xmlEndTag("qtimetadatafield");
6347
6348 $a_xml_writer->xmlStartTag("qtimetadatafield");
6349 $a_xml_writer->xmlElement("fieldlabel", NULL, "solution_details");
6350 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails());
6351 $a_xml_writer->xmlEndTag("qtimetadatafield");
6352 $a_xml_writer->xmlStartTag("qtimetadatafield");
6353 $a_xml_writer->xmlElement("fieldlabel", NULL, "print_bs_with_res");
6354 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails() ? (int)$this->isBestSolutionPrintedWithResult() : 0);
6355 $a_xml_writer->xmlEndTag("qtimetadatafield");
6356
6357 // solution details
6358 $a_xml_writer->xmlStartTag("qtimetadatafield");
6359 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
6360 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
6361 $a_xml_writer->xmlEndTag("qtimetadatafield");
6362
6363 // answer specific feedback
6364 $a_xml_writer->xmlStartTag("qtimetadatafield");
6365 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
6366 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
6367 $a_xml_writer->xmlEndTag("qtimetadatafield");
6368
6369 // answer specific feedback of reached points
6370 $a_xml_writer->xmlStartTag("qtimetadatafield");
6371 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
6372 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
6373 $a_xml_writer->xmlEndTag("qtimetadatafield");
6374
6375 // instant response answer freezing
6376 $a_xml_writer->xmlStartTag("qtimetadatafield");
6377 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6378 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6379 $a_xml_writer->xmlEndTag("qtimetadatafield");
6380
6381 // instant response forced
6382 $a_xml_writer->xmlStartTag("qtimetadatafield");
6383 $a_xml_writer->xmlElement("fieldlabel", NULL, "force_instant_feedback");
6384 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isForceInstantFeedbackEnabled());
6385 $a_xml_writer->xmlEndTag("qtimetadatafield");
6386
6387
6388 // highscore
6389 $highscore_metadata = array(
6390 'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6391 'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6392 'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6393 'highscore_score' => array('value' => $this->getHighscoreScore()),
6394 'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6395 'highscore_hints' => array('value' => $this->getHighscoreHints()),
6396 'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6397 'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6398 'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6399 'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6400 );
6401 foreach($highscore_metadata as $label => $data)
6402 {
6403 $a_xml_writer->xmlStartTag("qtimetadatafield");
6404 $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
6405 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $data['value']));
6406 $a_xml_writer->xmlEndTag("qtimetadatafield");
6407 }
6408
6409 // show cancel
6410 $a_xml_writer->xmlStartTag("qtimetadatafield");
6411 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
6412 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
6413 $a_xml_writer->xmlEndTag("qtimetadatafield");
6414
6415 // show marker
6416 $a_xml_writer->xmlStartTag("qtimetadatafield");
6417 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
6418 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
6419 $a_xml_writer->xmlEndTag("qtimetadatafield");
6420
6421 // fixed participants
6422 $a_xml_writer->xmlStartTag("qtimetadatafield");
6423 $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
6424 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
6425 $a_xml_writer->xmlEndTag("qtimetadatafield");
6426
6427 // show final statement
6428 $a_xml_writer->xmlStartTag("qtimetadatafield");
6429 $a_xml_writer->xmlElement("fieldlabel", NULL, "showfinalstatement");
6430 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6431 $a_xml_writer->xmlEndTag("qtimetadatafield");
6432
6433 // show introduction only
6434 $a_xml_writer->xmlStartTag("qtimetadatafield");
6435 $a_xml_writer->xmlElement("fieldlabel", NULL, "showinfo");
6436 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6437 $a_xml_writer->xmlEndTag("qtimetadatafield");
6438
6439 // mail notification
6440 $a_xml_writer->xmlStartTag("qtimetadatafield");
6441 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnotification");
6442 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotification());
6443 $a_xml_writer->xmlEndTag("qtimetadatafield");
6444
6445 // mail notification type
6446 $a_xml_writer->xmlStartTag("qtimetadatafield");
6447 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnottype");
6448 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotificationType());
6449 $a_xml_writer->xmlEndTag("qtimetadatafield");
6450
6451 // export settings
6452 $a_xml_writer->xmlStartTag("qtimetadatafield");
6453 $a_xml_writer->xmlElement("fieldlabel", NULL, "exportsettings");
6454 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getExportSettings());
6455 $a_xml_writer->xmlEndTag("qtimetadatafield");
6456
6457 // force JavaScript
6458 $a_xml_writer->xmlStartTag("qtimetadatafield");
6459 $a_xml_writer->xmlElement("fieldlabel", NULL, "forcejs");
6460 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6461 $a_xml_writer->xmlEndTag("qtimetadatafield");
6462
6463 // custom style
6464 $a_xml_writer->xmlStartTag("qtimetadatafield");
6465 $a_xml_writer->xmlElement("fieldlabel", NULL, "customstyle");
6466 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCustomStyle());
6467 $a_xml_writer->xmlEndTag("qtimetadatafield");
6468
6469 // shuffle questions
6470 $a_xml_writer->xmlStartTag("qtimetadatafield");
6471 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
6472 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
6473 $a_xml_writer->xmlEndTag("qtimetadatafield");
6474
6475 // processing time
6476 $a_xml_writer->xmlStartTag("qtimetadatafield");
6477 $a_xml_writer->xmlElement("fieldlabel", NULL, "processing_time");
6478 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getProcessingTime());
6479 $a_xml_writer->xmlEndTag("qtimetadatafield");
6480
6481 // enable_examview
6482 $a_xml_writer->xmlStartTag("qtimetadatafield");
6483 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_examview");
6484 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableExamview());
6485 $a_xml_writer->xmlEndTag("qtimetadatafield");
6486
6487 // show_examview_html
6488 $a_xml_writer->xmlStartTag("qtimetadatafield");
6489 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_html");
6490 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewHtml());
6491 $a_xml_writer->xmlEndTag("qtimetadatafield");
6492
6493 // show_examview_pdf
6494 $a_xml_writer->xmlStartTag("qtimetadatafield");
6495 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_pdf");
6496 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewPdf());
6497 $a_xml_writer->xmlEndTag("qtimetadatafield");
6498
6499 // enable_archiving
6500 $a_xml_writer->xmlStartTag("qtimetadatafield");
6501 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_archiving");
6502 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableArchiving());
6503 $a_xml_writer->xmlEndTag("qtimetadatafield");
6504
6505 // sign_submission
6506 $a_xml_writer->xmlStartTag("qtimetadatafield");
6507 $a_xml_writer->xmlElement("fieldlabel", NULL, "sign_submission");
6508 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSignSubmission());
6509 $a_xml_writer->xmlEndTag("qtimetadatafield");
6510
6511 // char_selector_availability
6512 $a_xml_writer->xmlStartTag("qtimetadatafield");
6513 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_availability");
6514 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getCharSelectorAvailability()));
6515 $a_xml_writer->xmlEndTag("qtimetadatafield");
6516
6517 // char_selector_definition
6518 $a_xml_writer->xmlStartTag("qtimetadatafield");
6519 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_definition");
6520 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCharSelectorDefinition());
6521 $a_xml_writer->xmlEndTag("qtimetadatafield");
6522
6523 // skill_service
6524 $a_xml_writer->xmlStartTag("qtimetadatafield");
6525 $a_xml_writer->xmlElement("fieldlabel", NULL, "skill_service");
6526 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isSkillServiceEnabled());
6527 $a_xml_writer->xmlEndTag("qtimetadatafield");
6528
6529 // result_tax_filters
6530 $a_xml_writer->xmlStartTag("qtimetadatafield");
6531 $a_xml_writer->xmlElement("fieldlabel", NULL, "result_tax_filters");
6532 $a_xml_writer->xmlElement("fieldentry", NULL, serialize((array)$this->getResultFilterTaxIds()));
6533 $a_xml_writer->xmlEndTag("qtimetadatafield");
6534
6535 // show_grading_status
6536 $a_xml_writer->xmlStartTag("qtimetadatafield");
6537 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_status");
6538 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingStatusEnabled());
6539 $a_xml_writer->xmlEndTag("qtimetadatafield");
6540
6541 // show_grading_mark
6542 $a_xml_writer->xmlStartTag("qtimetadatafield");
6543 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_mark");
6544 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingMarkEnabled());
6545 $a_xml_writer->xmlEndTag("qtimetadatafield");
6546
6547
6548 // starting time
6549 if ($this->getStartingTime())
6550 {
6551 $a_xml_writer->xmlStartTag("qtimetadatafield");
6552 $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
6553 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
6554 $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]));
6555 $a_xml_writer->xmlEndTag("qtimetadatafield");
6556 }
6557 // ending time
6558 if ($this->getEndingTime())
6559 {
6560 $a_xml_writer->xmlStartTag("qtimetadatafield");
6561 $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
6562 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
6563 $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]));
6564 $a_xml_writer->xmlEndTag("qtimetadatafield");
6565 }
6566
6567
6568 //activation_limited
6569 $a_xml_writer->xmlStartTag("qtimetadatafield");
6570 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_limited");
6571 $a_xml_writer->xmlElement("fieldentry", NULL,(int)$this->isActivationLimited());
6572 $a_xml_writer->xmlEndTag("qtimetadatafield");
6573
6574 //activation_start_time
6575 $a_xml_writer->xmlStartTag("qtimetadatafield");
6576 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_start_time");
6577 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationStartingTime());
6578 $a_xml_writer->xmlEndTag("qtimetadatafield");
6579
6580 //activation_end_time
6581 $a_xml_writer->xmlStartTag("qtimetadatafield");
6582 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_end_time");
6583 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationEndingTime());
6584 $a_xml_writer->xmlEndTag("qtimetadatafield");
6585
6586 //activation_visibility
6587 $a_xml_writer->xmlStartTag("qtimetadatafield");
6588 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_visibility");
6589 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationVisibility());
6590 $a_xml_writer->xmlEndTag("qtimetadatafield");
6591
6592 // autosave
6593 $a_xml_writer->xmlStartTag("qtimetadatafield");
6594 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave");
6595 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosave());
6596 $a_xml_writer->xmlEndTag("qtimetadatafield");
6597
6598 // autosave_ival
6599 $a_xml_writer->xmlStartTag("qtimetadatafield");
6600 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave_ival");
6601 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosaveIval());
6602 $a_xml_writer->xmlEndTag("qtimetadatafield");
6603
6604 //offer_question_hints
6605 $a_xml_writer->xmlStartTag("qtimetadatafield");
6606 $a_xml_writer->xmlElement("fieldlabel", NULL, "offer_question_hints");
6607 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isOfferingQuestionHintsEnabled());
6608 $a_xml_writer->xmlEndTag("qtimetadatafield");
6609
6610 //instant_feedback_specific
6611 $a_xml_writer->xmlStartTag("qtimetadatafield");
6612 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_specific");
6613 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSpecificAnswerFeedback());
6614 $a_xml_writer->xmlEndTag("qtimetadatafield");
6615
6616 //instant_feedback_answer_fixation
6617 $a_xml_writer->xmlStartTag("qtimetadatafield");
6618 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6619 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6620 $a_xml_writer->xmlEndTag("qtimetadatafield");
6621
6622 //obligations_enabled
6623 $a_xml_writer->xmlStartTag("qtimetadatafield");
6624 $a_xml_writer->xmlElement("fieldlabel", NULL, "obligations_enabled");
6625 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->areObligationsEnabled());
6626 $a_xml_writer->xmlEndTag("qtimetadatafield");
6627
6628 //enable_processing_time
6629 $a_xml_writer->xmlStartTag("qtimetadatafield");
6630 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_processing_time");
6631 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableProcessingTime());
6632 $a_xml_writer->xmlEndTag("qtimetadatafield");
6633
6634 foreach ($this->mark_schema->mark_steps as $index => $mark)
6635 {
6636 // mark steps
6637 $a_xml_writer->xmlStartTag("qtimetadatafield");
6638 $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
6639 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf(
6640 "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6641 $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()
6642 ));
6643 $a_xml_writer->xmlEndTag("qtimetadatafield");
6644 }
6645 $a_xml_writer->xmlEndTag("qtimetadata");
6646
6647 // add qti objectives
6648 $a_xml_writer->xmlStartTag("objectives");
6649 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6650 $a_xml_writer->xmlEndTag("objectives");
6651
6652 // add qti assessmentcontrol
6653 if ($this->getInstantFeedbackSolution() == 1)
6654 {
6655 $attrs = array(
6656 "solutionswitch" => "Yes"
6657 );
6658 }
6659 else
6660 {
6661 $attrs = NULL;
6662 }
6663 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
6664
6665 if (strlen($this->getFinalStatement()))
6666 {
6667 // add qti presentation_material
6668 $a_xml_writer->xmlStartTag("presentation_material");
6669 $a_xml_writer->xmlStartTag("flow_mat");
6670 $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6671 $a_xml_writer->xmlEndTag("flow_mat");
6672 $a_xml_writer->xmlEndTag("presentation_material");
6673 }
6674
6675 $attrs = array(
6676 "ident" => "1"
6677 );
6678 $a_xml_writer->xmlElement("section", $attrs, NULL);
6679 $a_xml_writer->xmlEndTag("assessment");
6680 $a_xml_writer->xmlEndTag("questestinterop");
6681
6682 $xml = $a_xml_writer->xmlDumpMem(FALSE);
6683
6684 foreach ($this->questions as $question_id)
6685 {
6686 $question =& ilObjTest::_instanciateQuestion($question_id);
6687 $qti_question = $question->toXML(false);
6688 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
6689 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
6690 if (strpos($xml, "</section>") !== false)
6691 {
6692 $xml = str_replace("</section>", "$qti_question</section>", $xml);
6693 }
6694 else
6695 {
6696 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
6697 }
6698 }
6699 return $xml;
6700 }
6701
6708 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6709 {
6710 global $ilBench;
6711
6712 $this->mob_ids = array();
6713 $this->file_ids = array();
6714
6715 $attrs = array();
6716 $attrs["Type"] = "Test";
6717 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
6718
6719 // MetaData
6720 $this->exportXMLMetaData($a_xml_writer);
6721
6722 // PageObjects
6723 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
6724 $ilBench->start("ContentObjectExport", "exportPageObjects");
6725 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6726 $ilBench->stop("ContentObjectExport", "exportPageObjects");
6727 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
6728
6729 // MediaObjects
6730 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
6731 $ilBench->start("ContentObjectExport", "exportMediaObjects");
6732 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6733 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6734 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
6735
6736 // FileItems
6737 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
6738 $ilBench->start("ContentObjectExport", "exportFileItems");
6739 $this->exportFileItems($a_target_dir, $expLog);
6740 $ilBench->stop("ContentObjectExport", "exportFileItems");
6741 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
6742
6743 $a_xml_writer->xmlEndTag("ContentObject");
6744 }
6745
6752 function exportXMLMetaData(&$a_xml_writer)
6753 {
6754 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6755 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6756 $md2xml->setExportMode(true);
6757 $md2xml->startExport();
6758 $a_xml_writer->appendXML($md2xml->getXML());
6759 }
6760
6766 function modifyExportIdentifier($a_tag, $a_param, $a_value)
6767 {
6768 if ($a_tag == "Identifier" && $a_param == "Entry")
6769 {
6770 include_once "./Services/Utilities/classes/class.ilUtil.php";
6771 $a_value = ilUtil::insertInstIntoID($a_value);
6772 }
6773
6774 return $a_value;
6775 }
6776
6777
6784 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6785 {
6786 global $ilBench;
6787
6788 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6789
6790 foreach ($this->questions as $question_id)
6791 {
6792 $ilBench->start("ContentObjectExport", "exportPageObject");
6793 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
6794
6795 $attrs = array();
6796 $a_xml_writer->xmlStartTag("PageObject", $attrs);
6797
6798
6799 // export xml to writer object
6800 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6801 include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6802 $page_object = new ilAssQuestionPage($question_id);
6803 $page_object->buildDom();
6804 $page_object->insertInstIntoIDs($a_inst);
6805 $mob_ids = $page_object->collectMediaObjects(false);
6806 require_once 'Services/COPage/classes/class.ilPCFileList.php';
6807 $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6808 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6809 $xml = str_replace("&","&amp;", $xml);
6810 $a_xml_writer->appendXML($xml);
6811 $page_object->freeDom();
6812 unset ($page_object);
6813
6814 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6815
6816 // collect media objects
6817 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6818 //$mob_ids = $page_obj->getMediaObjectIDs();
6819 foreach($mob_ids as $mob_id)
6820 {
6821 $this->mob_ids[$mob_id] = $mob_id;
6822 }
6823 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6824
6825 // collect all file items
6826 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6827 //$file_ids = $page_obj->getFileItemIds();
6828 foreach($file_ids as $file_id)
6829 {
6830 $this->file_ids[$file_id] = $file_id;
6831 }
6832 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6833
6834 $a_xml_writer->xmlEndTag("PageObject");
6835 //unset($page_obj);
6836
6837 $ilBench->stop("ContentObjectExport", "exportPageObject");
6838
6839
6840 }
6841 }
6842
6849 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6850 {
6851 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6852
6853 foreach ($this->mob_ids as $mob_id)
6854 {
6855 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
6856 if (ilObjMediaObject::_exists($mob_id))
6857 {
6858 $media_obj = new ilObjMediaObject($mob_id);
6859 $media_obj->exportXML($a_xml_writer, $a_inst);
6860 $media_obj->exportFiles($a_target_dir);
6861 unset($media_obj);
6862 }
6863 }
6864 }
6865
6870 function exportFileItems($a_target_dir, &$expLog)
6871 {
6872 include_once "./Modules/File/classes/class.ilObjFile.php";
6873
6874 foreach ($this->file_ids as $file_id)
6875 {
6876 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
6877 $file_obj = new ilObjFile($file_id, false);
6878 $file_obj->export($a_target_dir);
6879 unset($file_obj);
6880 }
6881 }
6882
6888 {
6889 if (!is_array($this->import_mapping))
6890 {
6891 return array();
6892 }
6893 else
6894 {
6895 return $this->import_mapping;
6896 }
6897 }
6898
6902 public function canEditEctsGrades()
6903 {
6904 return $this->getReportingDate();
6905 }
6906
6910 public function getECTSGrade($passed_array, $reached_points, $max_points)
6911 {
6912 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);
6913 }
6914
6918 public static function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
6919 {
6920 include_once "./Modules/Test/classes/class.ilStatistics.php";
6921 // calculate the median
6922 $passed_statistics = new ilStatistics();
6923 $passed_statistics->setData($points_passed);
6924 $ects_percentiles = array
6925 (
6926 "A" => $passed_statistics->quantile($a),
6927 "B" => $passed_statistics->quantile($b),
6928 "C" => $passed_statistics->quantile($c),
6929 "D" => $passed_statistics->quantile($d),
6930 "E" => $passed_statistics->quantile($e)
6931 );
6932 if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
6933 {
6934 return "A";
6935 }
6936 else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
6937 {
6938 return "B";
6939 }
6940 else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
6941 {
6942 return "C";
6943 }
6944 else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
6945 {
6946 return "D";
6947 }
6948 else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
6949 {
6950 return "E";
6951 }
6952 else if (strcmp($fx, "") != 0)
6953 {
6954 if ($max_points > 0)
6955 {
6956 $percentage = ($reached_points / $max_points) * 100.0;
6957 if ($percentage < 0) $percentage = 0.0;
6958 }
6959 else
6960 {
6961 $percentage = 0.0;
6962 }
6963 if ($percentage >= $fx)
6964 {
6965 return "FX";
6966 }
6967 else
6968 {
6969 return "F";
6970 }
6971 }
6972 else
6973 {
6974 return "F";
6975 }
6976 }
6977
6981 public function checkMarks()
6982 {
6983 return $this->mark_schema->checkMarks();
6984 }
6985
6989 public function getMarkSchema()
6990 {
6991 return $this->mark_schema;
6992 }
6993
6997 public function getMarkSchemaForeignId()
6998 {
6999 return $this->getTestId();
7000 }
7001
7004 public function onMarkSchemaSaved()
7005 {
7011 global $ilDB, $ilPluginAdmin, $tree;
7012
7013 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7014 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7015 $this->saveCompleteStatus($testQuestionSetConfigFactory->getQuestionSetConfig());
7016
7017 if( $this->participantDataExist() )
7018 {
7019 $this->recalculateScores(true);
7020 }
7021 }
7022
7026 public function canEditMarks()
7027 {
7028 $total = $this->evalTotalPersons();
7029 if($total > 0)
7030 {
7031 if($this->getReportingDate())
7032 {
7033 if(preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
7034 {
7035 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
7036 $now = mktime();
7037 if($now < $epoch_time)
7038 {
7039 return true;
7040 }
7041 }
7042 }
7043 return false;
7044 }
7045 else
7046 {
7047 return true;
7048 }
7049 }
7050
7058 function setAuthor($author = "")
7059 {
7060 $this->author = $author;
7061 }
7062
7072 function saveAuthorToMetadata($a_author = "")
7073 {
7074 $md =& new ilMD($this->getId(), 0, $this->getType());
7075 $md_life =& $md->getLifecycle();
7076 if (!$md_life)
7077 {
7078 if (strlen($a_author) == 0)
7079 {
7080 global $ilUser;
7081 $a_author = $ilUser->getFullname();
7082 }
7083
7084 $md_life =& $md->addLifecycle();
7085 $md_life->save();
7086 $con =& $md_life->addContribute();
7087 $con->setRole("Author");
7088 $con->save();
7089 $ent =& $con->addEntity();
7090 $ent->setEntity($a_author);
7091 $ent->save();
7092 }
7093 }
7094
7101 {
7102 parent::createMetaData();
7103 $this->saveAuthorToMetadata();
7104 }
7105
7113 function getAuthor()
7114 {
7115 $author = array();
7116 include_once "./Services/MetaData/classes/class.ilMD.php";
7117 $md =& new ilMD($this->getId(), 0, $this->getType());
7118 $md_life =& $md->getLifecycle();
7119 if ($md_life)
7120 {
7121 $ids =& $md_life->getContributeIds();
7122 foreach ($ids as $id)
7123 {
7124 $md_cont =& $md_life->getContribute($id);
7125 if (strcmp($md_cont->getRole(), "Author") == 0)
7126 {
7127 $entids =& $md_cont->getEntityIds();
7128 foreach ($entids as $entid)
7129 {
7130 $md_ent =& $md_cont->getEntity($entid);
7131 array_push($author, $md_ent->getEntity());
7132 }
7133 }
7134 }
7135 }
7136 return join($author, ",");
7137 }
7138
7146 function _lookupAuthor($obj_id)
7147 {
7148 $author = array();
7149 include_once "./Services/MetaData/classes/class.ilMD.php";
7150 $md =& new ilMD($obj_id, 0, "tst");
7151 $md_life =& $md->getLifecycle();
7152 if ($md_life)
7153 {
7154 $ids =& $md_life->getContributeIds();
7155 foreach ($ids as $id)
7156 {
7157 $md_cont =& $md_life->getContribute($id);
7158 if (strcmp($md_cont->getRole(), "Author") == 0)
7159 {
7160 $entids =& $md_cont->getEntityIds();
7161 foreach ($entids as $entid)
7162 {
7163 $md_ent =& $md_cont->getEntity($entid);
7164 array_push($author, $md_ent->getEntity());
7165 }
7166 }
7167 }
7168 }
7169 return join($author, ",");
7170 }
7171
7178 function &_getAvailableTests($use_object_id = FALSE)
7179 {
7180 global $ilUser;
7181 global $ilDB;
7182
7183 $result_array = array();
7184 $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
7185 if (count($tests))
7186 {
7187 $titles = ilObject::_prepareCloneSelection($tests, "tst");
7188 foreach ($tests as $ref_id)
7189 {
7190 if ($use_object_id)
7191 {
7193 $result_array[$obj_id] = $titles[$ref_id];
7194 }
7195 else
7196 {
7197 $result_array[$ref_id] = $titles[$ref_id];
7198 }
7199 }
7200 }
7201 return $result_array;
7202 }
7203
7212 public function cloneObject($a_target_id,$a_copy_id = 0)
7213 {
7214 global $ilLog, $tree, $ilDB, $ilPluginAdmin;
7215
7216 $this->loadFromDb();
7217
7218 // Copy settings
7220 $newObj = parent::cloneObject($a_target_id,$a_copy_id);
7221 $newObj->setTmpCopyWizardCopyId($a_copy_id);
7222 $this->cloneMetaData($newObj);
7223
7224 //copy online status if object is not the root copy object
7225 $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
7226
7227 if(!$cp_options->isRootNode($this->getRefId()))
7228 {
7229 $newObj->setOnline($this->isOnline());
7230 }
7231
7232 $newObj->setAnonymity($this->getAnonymity());
7233 $newObj->setAnswerFeedback($this->getAnswerFeedback());
7234 $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
7235 $newObj->setAuthor($this->getAuthor());
7236 $newObj->setLimitUsersEnabled($this->isLimitUsersEnabled());
7237 $newObj->setAllowedUsers($this->getAllowedUsers());
7238 $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
7239 $newObj->setCountSystem($this->getCountSystem());
7240 $newObj->setECTSFX($this->getECTSFX());
7241 $newObj->setECTSGrades($this->getECTSGrades());
7242 $newObj->setECTSOutput($this->getECTSOutput());
7243 $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
7244 $newObj->setEndingTimeEnabled($this->isEndingTimeEnabled());
7245 $newObj->setEndingTime($this->getEndingTime());
7246 $newObj->setFixedParticipants($this->getFixedParticipants());
7247 $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
7248 $newObj->setIntroductionEnabled($this->isIntroductionEnabled());
7249 $newObj->setIntroduction($this->getIntroduction());
7250 $newObj->setFinalStatement($this->getFinalStatement());
7251 $newObj->setShowInfo($this->getShowInfo());
7252 $newObj->setForceJS($this->getForceJS());
7253 $newObj->setCustomStyle($this->getCustomStyle());
7254 $newObj->setKiosk($this->getKiosk());
7255 $newObj->setShowFinalStatement($this->getShowFinalStatement());
7256 $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
7257 $newObj->setMCScoring($this->getMCScoring());
7258 $newObj->setMailNotification($this->getMailNotification());
7259 $newObj->setMailNotificationType($this->getMailNotificationType());
7260 $newObj->setNrOfTries($this->getNrOfTries());
7261 $newObj->setPassScoring($this->getPassScoring());
7262 $newObj->setPasswordEnabled($this->isPasswordEnabled());
7263 $newObj->setPassword($this->getPassword());
7264 $newObj->setProcessingTime($this->getProcessingTime());
7265 $newObj->setQuestionSetType($this->getQuestionSetType());
7266 $newObj->setReportingDate($this->getReportingDate());
7267 $newObj->setResetProcessingTime($this->getResetProcessingTime());
7268 $newObj->setResultsPresentation($this->getResultsPresentation());
7269 $newObj->setScoreCutting($this->getScoreCutting());
7270 $newObj->setScoreReporting($this->getScoreReporting());
7271 $newObj->setSequenceSettings($this->getSequenceSettings());
7272 $newObj->setShowCancel($this->getShowCancel());
7273 $newObj->setShowMarker($this->getShowMarker());
7274 $newObj->setShuffleQuestions($this->getShuffleQuestions());
7275 $newObj->setStartingTimeEnabled($this->isStartingTimeEnabled());
7276 $newObj->setStartingTime($this->getStartingTime());
7277 $newObj->setTitleOutput($this->getTitleOutput());
7278 $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
7279 $newObj->setRedirectionMode($this->getRedirectionMode());
7280 $newObj->setRedirectionUrl($this->getRedirectionUrl());
7281 $newObj->setCertificateVisibility($this->getCertificateVisibility());
7282 $newObj->mark_schema = clone $this->mark_schema;
7283 $newObj->setEnabledViewMode($this->getEnabledViewMode());
7284 $newObj->setTemplate($this->getTemplate());
7285 $newObj->setPoolUsage($this->getPoolUsage());
7286 $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
7287 $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
7288 $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
7289 $newObj->setEnableExamView($this->getEnableExamview());
7290 $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7291 $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7292 $newObj->setEnableArchiving($this->getEnableArchiving());
7293 $newObj->setSignSubmission($this->getSignSubmission());
7294 $newObj->setCharSelectorAvailability((int)$this->getCharSelectorAvailability());
7295 $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7296 $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
7297 $newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
7298 $newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
7299 $newObj->setForceInstantFeedbackEnabled($this->isForceInstantFeedbackEnabled());
7300 $newObj->setAutosave($this->getAutosave());
7301 $newObj->setAutosaveIval($this->getAutosaveIval());
7302 $newObj->setOfferingQuestionHintsEnabled($this->isOfferingQuestionHintsEnabled());
7303 $newObj->setSpecificAnswerFeedback($this->getSpecificAnswerFeedback());
7304 $newObj->setObligationsEnabled($this->areObligationsEnabled());
7305 $newObj->saveToDb();
7306
7307 // clone certificate
7308 include_once "./Services/Certificate/classes/class.ilCertificate.php";
7309 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7310 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7311 $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7312 $cert->cloneCertificate($newcert);
7313
7314 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7315 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7316 $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7317
7318 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdList.php';
7319 $skillLevelThresholdList = new ilTestSkillLevelThresholdList($ilDB);
7320 $skillLevelThresholdList->setTestId($this->getTestId());
7321 $skillLevelThresholdList->loadFromDb();
7322 $skillLevelThresholdList->cloneListForTest($newObj->getTestId());
7323
7324 $newObj->saveToDb();
7325 $newObj->updateMetaData();// #14467
7326
7327 include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
7328 $obj_settings = new ilLPObjSettings($this->getId());
7329 $obj_settings->cloneSettings($newObj->getId());
7330
7331 return $newObj;
7332 }
7333
7341 {
7342 $num = 0;
7343
7344 if( $this->isRandomTest() )
7345 {
7346 global $tree, $ilDB, $ilPluginAdmin;
7347
7348 $questionSetConfig = new ilTestRandomQuestionSetConfig(
7349 $tree, $ilDB, $ilPluginAdmin, $this
7350 );
7351
7352 $questionSetConfig->loadFromDb();
7353
7354 if( $questionSetConfig->isQuestionAmountConfigurationModePerPool() )
7355 {
7356 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7357 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7358 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7359
7360 $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList(
7362 );
7363
7364 $sourcePoolDefinitionList->loadDefinitions();
7365
7366 $num = $sourcePoolDefinitionList->getQuestionAmount();
7367 }
7368 else
7369 {
7370 $num = $questionSetConfig->getQuestionAmountPerTest();
7371 }
7372 }
7373 else
7374 {
7375 $num = count($this->questions);
7376 }
7377
7378 return $num;
7379 }
7380
7388 function logAction($logtext = "", $question_id = "")
7389 {
7390 global $ilUser;
7391
7392 $original_id = "";
7393 if (strcmp($question_id, "") != 0)
7394 {
7395 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7396 $original_id = assQuestion::_getOriginalId($question_id);
7397 }
7398 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7399 ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
7400 }
7401
7410 {
7411 global $ilDB;
7412 $object_id = FALSE;
7413 $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7414 array('integer'),
7415 array($test_id)
7416 );
7417 if ($result->numRows())
7418 {
7419 $row = $ilDB->fetchAssoc($result);
7420 $object_id = $row["obj_fi"];
7421 }
7422 return $object_id;
7423 }
7424
7432 function _getObjectIDFromActiveID($active_id)
7433 {
7434 global $ilDB;
7435 $object_id = FALSE;
7436 $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",
7437 array('integer'),
7438 array($active_id)
7439 );
7440 if ($result->numRows())
7441 {
7442 $row = $ilDB->fetchAssoc($result);
7443 $object_id = $row["obj_fi"];
7444 }
7445 return $object_id;
7446 }
7447
7455 function _getTestIDFromObjectID($object_id)
7456 {
7457 global $ilDB;
7458 $test_id = FALSE;
7459 $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7460 array('integer'),
7461 array($object_id)
7462 );
7463 if ($result->numRows())
7464 {
7465 $row = $ilDB->fetchAssoc($result);
7466 $test_id = $row["test_id"];
7467 }
7468 return $test_id;
7469 }
7470
7479 function getTextAnswer($active_id, $question_id, $pass = NULL)
7480 {
7481 global $ilDB;
7482
7483 $res = "";
7484 if (($active_id) && ($question_id))
7485 {
7486 if (is_null($pass))
7487 {
7488 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7489 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7490 }
7491 $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7492 array('integer', 'integer', 'integer'),
7493 array($active_id, $question_id, $pass)
7494 );
7495 if ($result->numRows() == 1)
7496 {
7497 $row = $ilDB->fetchAssoc($result);
7498 $res = $row["value1"];
7499 }
7500 }
7501 return $res;
7502 }
7503
7511 function getQuestiontext($question_id)
7512 {
7513 global $ilDB;
7514
7515 $res = "";
7516 if ($question_id)
7517 {
7518 $result = $ilDB->queryF("SELECT question_text FROM qpl_questions WHERE question_id = %s",
7519 array('integer'),
7520 array($question_id)
7521 );
7522 if ($result->numRows() == 1)
7523 {
7524 $row = $ilDB->fetchAssoc($result);
7525 $res = $row["question_text"];
7526 }
7527 }
7528 return $res;
7529 }
7530
7537 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7538 {
7539 global $ilDB;
7540
7541 $result_array = array();
7542
7543 if ($this->getAnonymity())
7544 {
7545 if (is_numeric($user_id))
7546 {
7547 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7548 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7549 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7550 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7551 "ORDER BY $order",
7552 array('text', 'text', 'text', 'integer', 'integer'),
7553 array("", $this->lng->txt("anonymous"), "", $this->getTestId(), $user_id)
7554 );
7555 }
7556 else
7557 {
7558 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7559 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7560 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7561 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7562 "ORDER BY $order",
7563 array('text', 'text', 'text', 'integer'),
7564 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7565 );
7566 }
7567 }
7568 else
7569 {
7570 if (is_numeric($user_id))
7571 {
7572 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7573 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7574 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7575 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7576 "ORDER BY $order",
7577 array('integer', 'integer'),
7578 array($this->getTestId(), $user_id)
7579 );
7580 }
7581 else
7582 {
7583 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7584 "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7585 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7586 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7587 "ORDER BY $order",
7588 array('integer'),
7589 array($this->getTestId())
7590 );
7591 }
7592 }
7593 $result_array = array();
7594 while ($row = $ilDB->fetchAssoc($result))
7595 {
7596 $result_array[$row['usr_id']]= $row;
7597 }
7598 return $result_array;
7599 }
7600
7608 {
7609 global $ilDB;
7610
7611 if ($this->getAnonymity())
7612 {
7613 $query = "
7614 SELECT tst_active.active_id,
7615 tst_active.tries,
7616 tst_active.user_fi usr_id,
7617 %s login,
7618 %s lastname,
7619 %s firstname,
7620 tst_active.submitted test_finished,
7621 usr_data.matriculation,
7622 usr_data.active,
7623 tst_active.lastindex
7624 FROM tst_active
7625 LEFT JOIN usr_data
7626 ON tst_active.user_fi = usr_data.usr_id
7627 WHERE tst_active.test_fi = %s
7628 ORDER BY usr_data.lastname
7629 ";
7630 $result = $ilDB->queryF($query,
7631 array('text', 'text', 'text', 'integer'),
7632 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7633 );
7634 }
7635 else
7636 {
7637 $query = "
7638 SELECT tst_active.active_id,
7639 tst_active.tries,
7640 tst_active.user_fi usr_id,
7641 usr_data.login,
7642 usr_data.lastname,
7643 usr_data.firstname,
7644 tst_active.submitted test_finished,
7645 usr_data.matriculation,
7646 usr_data.active,
7647 tst_active.lastindex
7648 FROM tst_active
7649 LEFT JOIN usr_data
7650 ON tst_active.user_fi = usr_data.usr_id
7651 WHERE tst_active.test_fi = %s
7652 ORDER BY usr_data.lastname
7653 ";
7654 $result = $ilDB->queryF(
7655 $query, array('integer'), array($this->getTestId())
7656 );
7657 }
7658 $data = array();
7659 while ($row = $ilDB->fetchAssoc($result))
7660 {
7661 $data[$row['active_id']] = $row;
7662 }
7663 foreach ($data as $index => $participant)
7664 {
7665 if (strlen(trim($participant["firstname"].$participant["lastname"])) == 0)
7666 {
7667 $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7668 }
7669 }
7670 return $data;
7671 }
7672
7673 public function getTestParticipantsForManualScoring($filter = NULL)
7674 {
7675 global $ilDB;
7676
7677 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7679 if (count($scoring) == 0) return array();
7680
7681 $participants =& $this->getTestParticipants();
7682 $filtered_participants = array();
7683 foreach ($participants as $active_id => $participant)
7684 {
7685 $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7686
7687 $queryString = "
7688 SELECT tst_test_result.manual
7689
7690 FROM tst_test_result
7691
7692 INNER JOIN qpl_questions
7693 ON tst_test_result.question_fi = qpl_questions.question_id
7694
7695 WHERE tst_test_result.active_fi = %s
7696 AND $qstType_IN_manScoreableQstTypes
7697 ";
7698
7699 $result = $ilDB->queryF(
7700 $queryString, array("integer"), array($active_id)
7701 );
7702
7703 $count = $result->numRows();
7704
7705 if ($count > 0)
7706 {
7707 switch ($filter)
7708 {
7709 case 1: // only active users
7710 if ($participant->active) $filtered_participants[$active_id] = $participant;
7711 break;
7712 case 2: // only inactive users
7713 if (!$participant->active) $filtered_participants[$active_id] = $participant;
7714 break;
7715 case 3: // all users
7716 $filtered_participants[$active_id] = $participant;
7717 break;
7718 case 4:
7719 // already scored participants
7720 //$found = 0;
7721 //while ($row = $ilDB->fetchAssoc($result))
7722 //{
7723 // if ($row["manual"]) $found++;
7724 //}
7725 //if ($found == $count)
7726 //{
7727 //$filtered_participants[$active_id] = $participant;
7728 //}
7729 //else
7730 //{
7731 $assessmentSetting = new ilSetting("assessment");
7732 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7733 if ($manscoring_done) $filtered_participants[$active_id] = $participant;
7734 //}
7735 break;
7736 case 5:
7737 // unscored participants
7738 //$found = 0;
7739 //while ($row = $ilDB->fetchAssoc($result))
7740 //{
7741 // if ($row["manual"]) $found++;
7742 //}
7743 //if ($found == 0)
7744 //{
7745 $assessmentSetting = new ilSetting("assessment");
7746 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7747 if (!$manscoring_done) $filtered_participants[$active_id] = $participant;
7748 //}
7749 break;
7750 case 6:
7751 // partially scored participants
7752 $found = 0;
7753 while ($row = $ilDB->fetchAssoc($result))
7754 {
7755 if ($row["manual"]) $found++;
7756 }
7757 if (($found > 0) && ($found < $count)) $filtered_participants[$active_id] = $participant;
7758 break;
7759 default:
7760 $filtered_participants[$active_id] = $participant;
7761 break;
7762 }
7763 }
7764 }
7765 return $filtered_participants;
7766 }
7767
7775 function &getUserData($ids)
7776 {
7777 global $ilDB;
7778
7779 if (!is_array($ids) || count($ids) ==0) return array();
7780
7781 if ($this->getAnonymity())
7782 {
7783 $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",
7784 array('text', 'text', 'text'),
7785 array("", $this->lng->txt("anonymous"), "")
7786 );
7787 }
7788 else
7789 {
7790 $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");
7791 }
7792
7793 $result_array = array();
7794 while ($row = $ilDB->fetchAssoc($result))
7795 {
7796 $result_array[$row["usr_id"]]= $row;
7797 }
7798 return $result_array;
7799 }
7800
7801 function &getGroupData($ids)
7802 {
7803 if (!is_array($ids) || count($ids) ==0) return array();
7804 $result = array();
7805 foreach ($ids as $ref_id)
7806 {
7808 $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7809 }
7810 return $result;
7811 }
7812
7813 function &getRoleData($ids)
7814 {
7815 if (!is_array($ids) || count($ids) ==0) return array();
7816 $result = array();
7817 foreach ($ids as $obj_id)
7818 {
7819 $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7820 }
7821 return $result;
7822 }
7823
7824
7831 function inviteGroup($group_id)
7832 {
7833 include_once "./Modules/Group/classes/class.ilObjGroup.php";
7834 $group = new ilObjGroup($group_id);
7835 $members = $group->getGroupMemberIds();
7836 include_once './Services/User/classes/class.ilObjUser.php';
7837 foreach ($members as $user_id)
7838 {
7839 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7840 }
7841 }
7842
7849 function inviteRole($role_id)
7850 {
7851 global $rbacreview;
7852 $members = $rbacreview->assignedUsers($role_id,"usr_id");
7853 include_once './Services/User/classes/class.ilObjUser.php';
7854 foreach ($members as $user_id)
7855 {
7856 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7857 }
7858 }
7859
7860
7861
7868 function disinviteUser($user_id)
7869 {
7870 global $ilDB;
7871
7872 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7873 array('integer', 'integer'),
7874 array($this->getTestId(), $user_id)
7875 );
7876 }
7877
7884 function inviteUser($user_id, $client_ip="")
7885 {
7886 global $ilDB;
7887
7888 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7889 array('integer', 'integer'),
7890 array($this->getTestId(), $user_id)
7891 );
7892 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7893 array('integer', 'integer', 'text', 'integer'),
7894 array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : NULL, time())
7895 );
7896 }
7897
7898
7899 function setClientIP($user_id, $client_ip)
7900 {
7901 global $ilDB;
7902
7903 $affectedRows = $ilDB->manipulateF("UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7904 array('text', 'integer', 'integer', 'integer'),
7905 array((strlen($client_ip)) ? $client_ip : NULL, time(), $this->getTestId(), $user_id)
7906 );
7907 }
7908
7914 function _getSolvedQuestions($active_id, $question_fi = null)
7915 {
7916 global $ilDB;
7917 if (is_numeric($question_fi))
7918 {
7919 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7920 array('integer', 'integer'),
7921 array($active_id, $question_fi)
7922 );
7923 }
7924 else
7925 {
7926 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7927 array('integer'),
7928 array($active_id)
7929 );
7930 }
7931 $result_array = array();
7932 while ($row = $ilDB->fetchAssoc($result))
7933 {
7934 $result_array[$row["question_fi"]]= $row;
7935 }
7936 return $result_array;
7937 }
7938
7939
7943 function setQuestionSetSolved($value, $question_id, $user_id)
7944 {
7945 global $ilDB;
7946
7947 $active_id = $this->getActiveIdOfUser($user_id);
7948 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
7949 array('integer', 'integer'),
7950 array($active_id, $question_id)
7951 );
7952 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
7953 array('integer', 'integer', 'integer'),
7954 array($value, $question_id, $active_id)
7955 );
7956 }
7957
7961 function isTestFinished($active_id)
7962 {
7963 global $ilDB;
7964
7965 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
7966 array('integer', 'integer'),
7967 array($active_id, 1)
7968 );
7969 return $result->numRows() == 1;
7970 }
7971
7975 function isActiveTestSubmitted($user_id = null)
7976 {
7977 global $ilUser;
7978 global $ilDB;
7979
7980 if (!is_numeric($user_id))
7981 $user_id = $ilUser->getId();
7982
7983 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
7984 array('integer', 'integer', 'integer'),
7985 array($this->getTestId(), $user_id, 1)
7986 );
7987 return $result->numRows() == 1;
7988 }
7989
7994 {
7995 return $this->getNrOfTries() != 0;
7996 }
7997
7998
8004 function isNrOfTriesReached($tries)
8005 {
8006 return $tries >= (int) $this->getNrOfTries();
8007 }
8008
8009
8018 function getAllTestResults($participants, $prepareForCSV = true)
8019 {
8020 $results = array();
8021 $row = array(
8022 "user_id" => $this->lng->txt("user_id"),
8023 "matriculation" => $this->lng->txt("matriculation"),
8024 "lastname" => $this->lng->txt("lastname"),
8025 "firstname" => $this->lng->txt("firstname"),
8026 "login" =>$this->lng->txt("login"),
8027 "reached_points" => $this->lng->txt("tst_reached_points"),
8028 "max_points" => $this->lng->txt("tst_maximum_points"),
8029 "percent_value" => $this->lng->txt("tst_percent_solved"),
8030 "mark" => $this->lng->txt("tst_mark"),
8031 "ects" => $this->lng->txt("ects_grade")
8032 );
8033 $results[] = $row;
8034 if (count($participants))
8035 {
8036 if($this->getECTSOutput())
8037 {
8038 $passed_array =& $this->getTotalPointsPassedArray();
8039 }
8040 foreach ($participants as $active_id => $user_rec)
8041 {
8042 $mark = $ects_mark = '';
8043 $row = array();
8044 $reached_points = 0;
8045 $max_points = 0;
8046 foreach ($this->questions as $value)
8047 {
8048 $question =& ilObjTest::_instanciateQuestion($value);
8049 if (is_object($question))
8050 {
8051 $max_points += $question->getMaximumPoints();
8052 $reached_points += $question->getReachedPoints($active_id);
8053 }
8054 }
8055 if ($max_points > 0)
8056 {
8057 $percentvalue = $reached_points / $max_points;
8058 if ($percentvalue < 0) $percentvalue = 0.0;
8059 }
8060 else
8061 {
8062 $percentvalue = 0;
8063 }
8064 $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
8065 $passed = "";
8066 if ($mark_obj)
8067 {
8068 $mark = $mark_obj->getOfficialName();
8069 if($this->getECTSOutput())
8070 {
8071 $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
8072 }
8073 }
8074 if ($this->getAnonymity())
8075 {
8076 $user_rec['firstname'] = "";
8077 $user_rec['lastname'] = $this->lng->txt("anonymous");
8078 }
8079 $row = array(
8080 "user_id"=>$user_rec['usr_id'],
8081 "matriculation" => $user_rec['matriculation'],
8082 "lastname" => $user_rec['lastname'],
8083 "firstname" => $user_rec['firstname'],
8084 "login"=>$user_rec['login'],
8085 "reached_points" => $reached_points,
8086 "max_points" => $max_points,
8087 "percent_value" => $percentvalue,
8088 "mark" => $mark,
8089 "ects" => $ects_mark
8090 );
8091 $results[] = $prepareForCSV ? $this->processCSVRow ($row, true) : $row;
8092 }
8093 }
8094 return $results;
8095 }
8096
8107 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
8108 {
8109 $resultarray = array();
8110 foreach ($row as $rowindex => $entry)
8111 {
8112 $surround = FALSE;
8113 if ($quoteAll)
8114 {
8115 $surround = TRUE;
8116 }
8117 if (strpos($entry, "\"") !== FALSE)
8118 {
8119 $entry = str_replace("\"", "\"\"", $entry);
8120 $surround = TRUE;
8121 }
8122 if (strpos($entry, $separator) !== FALSE)
8123 {
8124 $surround = TRUE;
8125 }
8126 // replace all CR LF with LF (for Excel for Windows compatibility
8127 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
8128
8129 if ($surround)
8130 {
8131 $entry = "\"" . $entry . "\"";
8132 }
8133
8134 $resultarray[$rowindex] = $entry;
8135 }
8136 return $resultarray;
8137 }
8138
8147 function _getPass($active_id)
8148 {
8149 global $ilDB;
8150 $result = $ilDB->queryF("SELECT tries FROM tst_active WHERE active_id = %s",
8151 array('integer'),
8152 array($active_id)
8153 );
8154 if ($result->numRows())
8155 {
8156 $row = $ilDB->fetchAssoc($result);
8157 return $row["tries"];
8158 }
8159 else
8160 {
8161 return 0;
8162 }
8163 }
8164
8174 function _getMaxPass($active_id)
8175 {
8176 global $ilDB;
8177 $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
8178 array('integer'),
8179 array($active_id)
8180 );
8181 if ($result->numRows())
8182 {
8183 $row = $ilDB->fetchAssoc($result);
8184 $max = $row["maxpass"];
8185 }
8186 else
8187 {
8188 $max = NULL;
8189 }
8190 return $max;
8191 }
8192
8203 function _getBestPass($active_id)
8204 {
8205 global $ilDB;
8206
8207 $result = $ilDB->queryF("SELECT * FROM tst_pass_result WHERE active_fi = %s",
8208 array('integer'),
8209 array($active_id)
8210 );
8211 if ($result->numRows())
8212 {
8213 $bestrow = null;
8214 $bestfactor = 0;
8215 while ($row = $ilDB->fetchAssoc($result))
8216 {
8217 if($row["maxpoints"] > 0)
8218 {
8219 $factor = $row["points"] / $row["maxpoints"];
8220 }
8221 else
8222 {
8223 $factor = 0;
8224 }
8225
8226 if($factor > $bestfactor)
8227 {
8228 $bestrow = $row;
8229 $bestfactor = $factor;
8230 }
8231 }
8232 if (is_array($bestrow))
8233 {
8234 return $bestrow["pass"];
8235 }
8236 else
8237 {
8238 return 0;
8239 }
8240 }
8241 else
8242 {
8243 return 0;
8244 }
8245 }
8246
8255 function _getResultPass($active_id)
8256 {
8257 $counted_pass = NULL;
8259 {
8260 $counted_pass = ilObjTest::_getBestPass($active_id);
8261 }
8262 else
8263 {
8264 $counted_pass = ilObjTest::_getMaxPass($active_id);
8265 }
8266 return $counted_pass;
8267 }
8268
8278 function getAnsweredQuestionCount($active_id, $pass = NULL)
8279 {
8280 if( $this->isDynamicTest() )
8281 {
8282 global $tree, $ilDB, $lng, $ilPluginAdmin;
8283
8284 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
8285 $testSessionFactory = new ilTestSessionFactory($this);
8286 $testSession = $testSessionFactory->getSession($active_id);
8287
8288 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
8289 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
8290 $testSequence = $testSequenceFactory->getSequenceByTestSession($testSession);
8291
8292 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
8293 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
8294 $dynamicQuestionSetConfig->loadFromDb();
8295
8296 $testSequence->loadFromDb($dynamicQuestionSetConfig);
8297 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
8298
8299 return $testSequence->getTrackedQuestionCount();
8300 }
8301
8302 if ($this->isRandomTest())
8303 {
8304 $this->loadQuestions($active_id, $pass);
8305 }
8306 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
8307 $workedthrough = 0;
8308 foreach ($this->questions as $value)
8309 {
8310 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
8311 {
8312 $workedthrough += 1;
8313 }
8314 }
8315 return $workedthrough;
8316 }
8317
8327 function getPassFinishDate($active_id, $pass)
8328 {
8329 global $ilDB;
8330
8331 if (is_null($pass))
8332 {
8333 $pass = 0;
8334 }
8335
8336 $query = "
8337 SELECT tst_pass_result.tstamp pass_res_tstamp,
8338 tst_test_result.tstamp quest_res_tstamp
8339
8340 FROM tst_pass_result
8341
8342 LEFT JOIN tst_test_result
8343 ON tst_test_result.active_fi = tst_pass_result.active_fi
8344 AND tst_test_result.pass = tst_pass_result.pass
8345
8346 WHERE tst_pass_result.active_fi = %s
8347 AND tst_pass_result.pass = %s
8348
8349 ORDER BY tst_test_result.tstamp DESC
8350 ";
8351
8352 $result = $ilDB->queryF($query,
8353 array('integer', 'integer'),
8354 array($active_id, $pass)
8355 );
8356
8357 while( $row = $ilDB->fetchAssoc($result) )
8358 {
8359 if( $row['qres_tstamp'] )
8360 {
8361 return $row['quest_res_tstamp'];
8362 }
8363
8364 return $row['pass_res_tstamp'];
8365 }
8366
8367 return 0;
8368 }
8369
8378 function isExecutable($testSession, $user_id, $allowPassIncrease = FALSE)
8379 {
8380 $result = array(
8381 "executable" => true,
8382 "errormessage" => ""
8383 );
8384 if (!$this->startingTimeReached())
8385 {
8386 $result["executable"] = false;
8387 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getStartingTime(), IL_CAL_TIMESTAMP)));
8388 return $result;
8389 }
8390 if ($this->endingTimeReached())
8391 {
8392 $result["executable"] = false;
8393 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getEndingTime(), IL_CAL_TIMESTAMP)));
8394 return $result;
8395 }
8396
8397 $active_id = $this->getActiveIdOfUser($user_id);
8398
8399 if ($this->getEnableProcessingTime())
8400 {
8401 if ($active_id > 0)
8402 {
8403 $starting_time = $this->getStartingTimeOfUser($active_id);
8404 if ($starting_time !== FALSE)
8405 {
8406 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8407 {
8408 if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > ($this->_getPass($active_id)+1))))
8409 {
8410 // a test pass was quitted because the maximum processing time was reached, but the time
8411 // will be resetted for future passes, so if there are more passes allowed, the participant may
8412 // start the test again.
8413 // This code block is only called when $allowPassIncrease is TRUE which only happens when
8414 // the test info page is opened. Otherwise this will lead to unexpected results!
8415 $testSession->increasePass();
8416 $testSession->setLastSequence(0);
8417 $testSession->saveToDb();
8418 }
8419 else
8420 {
8421 $result["executable"] = false;
8422 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8423 }
8424 return $result;
8425 }
8426 }
8427 }
8428 }
8429
8430 if ($this->hasNrOfTriesRestriction() && ($active_id > 0))
8431 {
8432 require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8433 $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8434 $testPassesSelector->setActiveId($active_id);
8435 $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8436
8437 $closedPasses = $testPassesSelector->getClosedPasses();
8438
8439 if( count($closedPasses) >= $this->getNrOfTries() )
8440 {
8441 $result["executable"] = false;
8442 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8443 return $result;
8444 }
8445 }
8446
8447 return $result;
8448 }
8449
8458 {
8459 // this logic was implemented before, it got stabled only for now
8460 // this method is not as exact as it's required, it's to be replaced in the long time
8461
8462 switch( $this->getScoreReporting() )
8463 {
8465 case self::SCORE_REPORTING_FINISHED: // this isn't excact enough
8466
8467 return true;
8468
8470
8471 if (!$this->getReportingDate())
8472 {
8473 return false;
8474 }
8475
8476 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8477 {
8478 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8479 $now = mktime();
8480 if ($now < $epoch_time)
8481 {
8482 return false;
8483 }
8484 }
8485
8486 return true;
8487 }
8488
8489 return false;
8490 }
8491
8493 {
8494 $active_id = $testSession->getActiveId();
8495 if ($active_id > 0)
8496 {
8497 $starting_time = $this->getStartingTimeOfUser($active_id);
8498 }
8499 $notimeleft = FALSE;
8500 if ($starting_time !== FALSE)
8501 {
8502 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8503 {
8504 $notimeleft = TRUE;
8505 }
8506 }
8507 $result = TRUE;
8508 if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
8509 {
8510 $result = FALSE;
8511 }
8512 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
8513 $result = $result & $this->canViewResults();
8514 return $result;
8515 }
8516
8524 function getStartingTimeOfUser($active_id, $pass = null)
8525 {
8526 global $ilDB;
8527
8528 if ($active_id < 1) return FALSE;
8529 if($pass === null)
8530 {
8531 $pass = ($this->getResetProcessingTime()) ? $this->_getPass($active_id) : 0;
8532 }
8533 $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",
8534 array('integer', 'integer'),
8535 array($active_id, $pass)
8536 );
8537 if ($result->numRows())
8538 {
8539 $row = $ilDB->fetchAssoc($result);
8540 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
8541 {
8542 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8543 }
8544 else
8545 {
8546 return mktime();
8547 }
8548 }
8549 else
8550 {
8551 return mktime();
8552 }
8553 }
8554
8564 {
8565 if ($this->getEnableProcessingTime())
8566 {
8567 $processing_time = $this->getProcessingTimeInSeconds($active_id);
8568 $now = mktime();
8569 if ($now > ($starting_time + $processing_time))
8570 {
8571 return TRUE;
8572 }
8573 else
8574 {
8575 return FALSE;
8576 }
8577 }
8578 else
8579 {
8580 return FALSE;
8581 }
8582 }
8583
8585 {
8586 global $ilDB;
8587
8588 $query = "
8589 SELECT questions.*,
8590 questtypes.type_tag,
8591 tstquest.sequence,
8592 tstquest.obligatory,
8593 origquest.obj_fi orig_obj_fi
8594
8595 FROM qpl_questions questions
8596
8597 INNER JOIN qpl_qst_type questtypes
8598 ON questtypes.question_type_id = questions.question_type_fi
8599
8600 INNER JOIN tst_test_question tstquest
8601 ON tstquest.question_fi = questions.question_id
8602
8603 LEFT JOIN qpl_questions origquest
8604 ON origquest.question_id = questions.original_id
8605
8606 WHERE tstquest.test_fi = %s
8607
8608 ORDER BY tstquest.sequence
8609 ";
8610
8611 $query_result = $ilDB->queryF(
8612 $query, array('integer'), array($this->getTestId())
8613 );
8614
8615 $questions = array();
8616
8617 while ($row = $ilDB->fetchAssoc($query_result))
8618 {
8619 $question = $row;
8620
8621 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8622
8623 $questions[] = $question;
8624 }
8625
8626 return $questions;
8627 }
8628
8632 public function getPotentialRandomTestQuestions()
8633 {
8637 global $ilDB;
8638
8639 $query = "
8640 SELECT questions.*,
8641 questtypes.type_tag,
8642 origquest.obj_fi orig_obj_fi
8643
8644 FROM qpl_questions questions
8645
8646 INNER JOIN qpl_qst_type questtypes
8647 ON questtypes.question_type_id = questions.question_type_fi
8648
8649 INNER JOIN tst_rnd_cpy tstquest
8650 ON tstquest.qst_fi = questions.question_id
8651
8652 LEFT JOIN qpl_questions origquest
8653 ON origquest.question_id = questions.original_id
8654
8655 WHERE tstquest.tst_fi = %s
8656 ";
8657
8658 $query_result = $ilDB->queryF(
8659 $query, array('integer'), array($this->getTestId())
8660 );
8661
8662 $questions = array();
8663
8664 while ($row = $ilDB->fetchAssoc($query_result))
8665 {
8666 $question = $row;
8667
8668 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8669
8670 $questions[] = $question;
8671 }
8672
8673 return $questions;
8674 }
8675
8683 {
8684 return ($this->shuffle_questions) ? 1 : 0;
8685 }
8686
8693 function setShuffleQuestions($a_shuffle)
8694 {
8695 $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8696 }
8697
8711 {
8712 return ($this->show_summary) ? $this->show_summary : 0;
8713 }
8714
8727 function setListOfQuestionsSettings($a_value = 0)
8728 {
8729 $this->show_summary = $a_value;
8730 }
8731
8739 {
8740 if (($this->show_summary & 1) > 0)
8741 {
8742 return TRUE;
8743 }
8744 else
8745 {
8746 return FALSE;
8747 }
8748 }
8749
8756 function setListOfQuestions($a_value = TRUE)
8757 {
8758 if ($a_value)
8759 {
8760 $this->show_summary = 1;
8761 }
8762 else
8763 {
8764 $this->show_summary = 0;
8765 }
8766 }
8767
8775 {
8776 if (($this->show_summary & 2) > 0)
8777 {
8778 return TRUE;
8779 }
8780 else
8781 {
8782 return FALSE;
8783 }
8784 }
8785
8792 function setListOfQuestionsStart($a_value = TRUE)
8793 {
8794 if ($a_value && $this->getListOfQuestions())
8795 {
8796 $this->show_summary = $this->show_summary | 2;
8797 }
8798 if (!$a_value && $this->getListOfQuestions())
8799 {
8800 if ($this->getListOfQuestionsStart())
8801 {
8802 $this->show_summary = $this->show_summary ^ 2;
8803 }
8804 }
8805 }
8806
8814 {
8815 if (($this->show_summary & 4) > 0)
8816 {
8817 return TRUE;
8818 }
8819 else
8820 {
8821 return FALSE;
8822 }
8823 }
8824
8831 function setListOfQuestionsEnd($a_value = TRUE)
8832 {
8833 if ($a_value && $this->getListOfQuestions())
8834 {
8835 $this->show_summary = $this->show_summary | 4;
8836 }
8837 if (!$a_value && $this->getListOfQuestions())
8838 {
8839 if ($this->getListOfQuestionsEnd())
8840 {
8841 $this->show_summary = $this->show_summary ^ 4;
8842 }
8843 }
8844 }
8845
8853 {
8854 if (($this->show_summary & 8) > 0)
8855 {
8856 return TRUE;
8857 }
8858 else
8859 {
8860 return FALSE;
8861 }
8862 }
8863
8870 function setListOfQuestionsDescription($a_value = TRUE)
8871 {
8872 if ($a_value && $this->getListOfQuestions())
8873 {
8874 $this->show_summary = $this->show_summary | 8;
8875 }
8876 if (!$a_value && $this->getListOfQuestions())
8877 {
8878 if ($this->getListOfQuestionsDescription())
8879 {
8880 $this->show_summary = $this->show_summary ^ 8;
8881 }
8882 }
8883 }
8884
8892 {
8893 return ($this->results_presentation) ? $this->results_presentation : 0;
8894 }
8895
8903 {
8904 if (($this->results_presentation & 1) > 0)
8905 {
8906 return TRUE;
8907 }
8908 else
8909 {
8910 return FALSE;
8911 }
8912 }
8913
8921 {
8922 if (($this->results_presentation & 2) > 0)
8923 {
8924 return TRUE;
8925 }
8926 else
8927 {
8928 return FALSE;
8929 }
8930 }
8931
8939 {
8940 if (($this->results_presentation & 4) > 0)
8941 {
8942 return TRUE;
8943 }
8944 else
8945 {
8946 return FALSE;
8947 }
8948 }
8949
8957 {
8958 if (($this->results_presentation & 8) > 0)
8959 {
8960 return TRUE;
8961 }
8962 else
8963 {
8964 return FALSE;
8965 }
8966 }
8967
8975 {
8976 if (($this->results_presentation & 16) > 0)
8977 {
8978 return TRUE;
8979 }
8980 else
8981 {
8982 return FALSE;
8983 }
8984 }
8985
8993 {
8994 if (($this->results_presentation & 32) > 0)
8995 {
8996 return TRUE;
8997 }
8998 else
8999 {
9000 return FALSE;
9001 }
9002 }
9003
9009 {
9010 if (($this->results_presentation & 64) > 0)
9011 {
9012 return TRUE;
9013 }
9014 else
9015 {
9016 return FALSE;
9017 }
9018 }
9019
9025 {
9026 if(($this->results_presentation & 128) > 0)
9027 {
9028 return TRUE;
9029 }
9030 else
9031 {
9032 return FALSE;
9033 }
9034 }
9035
9042 function setResultsPresentation($a_results_presentation = 3)
9043 {
9044 $this->results_presentation = $a_results_presentation;
9045 }
9046
9055 function setShowPassDetails($a_details = 1)
9056 {
9057 if ($a_details)
9058 {
9059 $this->results_presentation = $this->results_presentation | 1;
9060 }
9061 else
9062 {
9063 if ($this->getShowPassDetails())
9064 {
9065 $this->results_presentation = $this->results_presentation ^ 1;
9066 }
9067 }
9068 }
9069
9076 function setShowSolutionDetails($a_details = 1)
9077 {
9078 if ($a_details)
9079 {
9080 $this->results_presentation = $this->results_presentation | 2;
9081 }
9082 else
9083 {
9084 if ($this->getShowSolutionDetails())
9085 {
9086 $this->results_presentation = $this->results_presentation ^ 2;
9087 }
9088 }
9089 }
9090
9097 function canShowSolutionPrintview($user_id = NULL)
9098 {
9099 return $this->getShowSolutionPrintview();
9100 }
9101
9108 function setShowSolutionPrintview($a_printview = 1)
9109 {
9110 if ($a_printview)
9111 {
9112 $this->results_presentation = $this->results_presentation | 4;
9113 }
9114 else
9115 {
9116 if ($this->getShowSolutionPrintview())
9117 {
9118 $this->results_presentation = $this->results_presentation ^ 4;
9119 }
9120 }
9121 }
9122
9129 function setShowSolutionFeedback($a_feedback = TRUE)
9130 {
9131 if ($a_feedback)
9132 {
9133 $this->results_presentation = $this->results_presentation | 8;
9134 }
9135 else
9136 {
9137 if ($this->getShowSolutionFeedback())
9138 {
9139 $this->results_presentation = $this->results_presentation ^ 8;
9140 }
9141 }
9142 }
9143
9150 function setShowSolutionAnswersOnly($a_full = TRUE)
9151 {
9152 if ($a_full)
9153 {
9154 $this->results_presentation = $this->results_presentation | 16;
9155 }
9156 else
9157 {
9158 if ($this->getShowSolutionAnswersOnly())
9159 {
9160 $this->results_presentation = $this->results_presentation ^ 16;
9161 }
9162 }
9163 }
9164
9171 function setShowSolutionSignature($a_signature = FALSE)
9172 {
9173 if ($a_signature)
9174 {
9175 $this->results_presentation = $this->results_presentation | 32;
9176 }
9177 else
9178 {
9179 if ($this->getShowSolutionSignature())
9180 {
9181 $this->results_presentation = $this->results_presentation ^ 32;
9182 }
9183 }
9184 }
9185
9192 function setShowSolutionSuggested($a_solution = FALSE)
9193 {
9194 if ($a_solution)
9195 {
9196 $this->results_presentation = $this->results_presentation | 64;
9197 }
9198 else
9199 {
9200 if ($this->getShowSolutionSuggested())
9201 {
9202 $this->results_presentation = $this->results_presentation ^ 64;
9203 }
9204 }
9205 }
9206
9212 public function setShowSolutionListComparison($a_comparison = FALSE)
9213 {
9214 if($a_comparison)
9215 {
9216 $this->results_presentation = $this->results_presentation | 128;
9217 }
9218 else
9219 {
9221 {
9222 $this->results_presentation = $this->results_presentation ^ 128;
9223 }
9224 }
9225 }
9226
9230 public static function _getUserIdFromActiveId($active_id)
9231 {
9232 global $ilDB;
9233 $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
9234 array('integer'),
9235 array($active_id)
9236 );
9237 if ($result->numRows())
9238 {
9239 $row = $ilDB->fetchAssoc($result);
9240 return $row["user_fi"];
9241 }
9242 else
9243 {
9244 return -1;
9245 }
9246 }
9247
9251 public function isLimitUsersEnabled()
9252 {
9254 }
9255
9260 {
9261 $this->limitUsersEnabled = $limitUsersEnabled;
9262 }
9263
9264 public function getAllowedUsers()
9265 {
9266 return ($this->allowedUsers) ? $this->allowedUsers : 0;
9267 }
9268
9269 public function setAllowedUsers($a_allowed_users)
9270 {
9271 $this->allowedUsers = $a_allowed_users;
9272 }
9273
9274 public function getAllowedUsersTimeGap()
9275 {
9276 return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
9277 }
9278
9279 public function setAllowedUsersTimeGap($a_allowed_users_time_gap)
9280 {
9281 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
9282 }
9283
9285 {
9286 global $ilDB;
9287
9288 $nr_of_users = $this->getAllowedUsers();
9289 $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
9290 if (($nr_of_users > 0) && ($time_gap > 0))
9291 {
9292 $now = mktime();
9293 $time_border = $now - $time_gap;
9294 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
9295 $query = "
9296 SELECT DISTINCT tst_times.active_fi
9297 FROM tst_times
9298 INNER JOIN tst_active
9299 ON tst_times.active_fi = tst_active.active_id
9300 AND (
9301 tst_times.pass > tst_active.last_finished_pass OR tst_active.last_finished_pass IS NULL
9302 )
9303 WHERE tst_times.tstamp > %s
9304 AND tst_active.test_fi = %s
9305 ";
9306 $result = $ilDB->queryF($query, array('integer', 'integer'), array($time_border, $this->getTestId()));
9307 if ($result->numRows() >= $nr_of_users)
9308 {
9309 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
9311 {
9312 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
9313 }
9314 return FALSE;
9315 }
9316 else
9317 {
9318 return TRUE;
9319 }
9320 }
9321 return TRUE;
9322 }
9323
9324 function _getLastAccess($active_id)
9325 {
9326 global $ilDB;
9327
9328 $result = $ilDB->queryF("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
9329 array('integer'),
9330 array($active_id)
9331 );
9332 if ($result->numRows())
9333 {
9334 $row = $ilDB->fetchAssoc($result);
9335 return $row["finished"];
9336 }
9337 return "";
9338 }
9339
9347 function isHTML($a_text)
9348 {
9349 if (preg_match("/<[^>]*?>/", $a_text))
9350 {
9351 return TRUE;
9352 }
9353 else
9354 {
9355 return FALSE;
9356 }
9357 }
9358
9366 function QTIMaterialToString($a_material)
9367 {
9368 $result = "";
9369 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
9370 {
9371 $material = $a_material->getMaterial($i);
9372 if (strcmp($material["type"], "mattext") == 0)
9373 {
9374 $result .= $material["material"]->getContent();
9375 }
9376 if (strcmp($material["type"], "matimage") == 0)
9377 {
9378 $matimage = $material["material"];
9379 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
9380 {
9381 // import an mediaobject which was inserted using tiny mce
9382 if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
9383 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
9384 }
9385 }
9386 }
9387 global $ilLog;
9388 $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
9389 return $result;
9390 }
9391
9400 function addQTIMaterial(&$a_xml_writer, $a_material)
9401 {
9402 include_once "./Services/RTE/classes/class.ilRTE.php";
9403 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9404
9405 $a_xml_writer->xmlStartTag("material");
9406 $attrs = array(
9407 "texttype" => "text/plain"
9408 );
9409 if ($this->isHTML($a_material))
9410 {
9411 $attrs["texttype"] = "text/xhtml";
9412 }
9413 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9414
9415 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9416 foreach ($mobs as $mob)
9417 {
9418 $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9419 if (strpos($a_material, "mm_$mob") !== FALSE)
9420 {
9421 if (ilObjMediaObject::_exists($mob))
9422 {
9423 $mob_obj =& new ilObjMediaObject($mob);
9424 $imgattrs = array(
9425 "label" => $moblabel,
9426 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9427 );
9428 }
9429 $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
9430 }
9431 }
9432 $a_xml_writer->xmlEndTag("material");
9433 }
9434
9441 function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE, $omitNl2BrWhenTextArea = false)
9442 {
9443 include_once "./Services/Utilities/classes/class.ilUtil.php";
9444 return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output, $omitNl2BrWhenTextArea);
9445 }
9446
9453 function saveCertificateVisibility($a_value)
9454 {
9455 global $ilDB;
9456
9457 $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9458 array('text', 'integer', 'integer'),
9459 array($a_value, time(), $this->getTestId())
9460 );
9461 }
9462
9470 {
9471 return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9472 }
9473
9480 function setCertificateVisibility($a_value)
9481 {
9482 $this->certificate_visibility = $a_value;
9483 }
9484
9491 function getAnonymity()
9492 {
9493 return ($this->anonymity) ? 1 : 0;
9494 }
9495
9502 function setAnonymity($a_value = 0)
9503 {
9504 switch ($a_value)
9505 {
9506 case 1:
9507 $this->anonymity = 1;
9508 break;
9509 default:
9510 $this->anonymity = 0;
9511 break;
9512 }
9513 }
9514
9521 function getShowCancel()
9522 {
9523 return ($this->show_cancel) ? 1 : 0;
9524 }
9525
9532 function setShowCancel($a_value = 1)
9533 {
9534 switch ($a_value)
9535 {
9536 case 1:
9537 $this->show_cancel = 1;
9538 break;
9539 default:
9540 $this->show_cancel = 0;
9541 break;
9542 }
9543 }
9544
9551 function getShowMarker()
9552 {
9553 return ($this->show_marker) ? 1 : 0;
9554 }
9555
9562 function setShowMarker($a_value = 1)
9563 {
9564 switch ($a_value)
9565 {
9566 case 1:
9567 $this->show_marker = 1;
9568 break;
9569 default:
9570 $this->show_marker = 0;
9571 break;
9572 }
9573 }
9574
9582 {
9583 return ($this->fixed_participants) ? 1 : 0;
9584 }
9585
9592 function setFixedParticipants($a_value = 1)
9593 {
9594 switch ($a_value)
9595 {
9596 case 1:
9597 $this->fixed_participants = 1;
9598 break;
9599 default:
9600 $this->fixed_participants = 0;
9601 break;
9602 }
9603 }
9604
9612 function _lookupAnonymity($a_obj_id)
9613 {
9614 global $ilDB;
9615
9616 $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9617 array('integer'),
9618 array($a_obj_id)
9619 );
9620 while($row = $ilDB->fetchAssoc($result))
9621 {
9622 return $row['anonymity'];
9623 }
9624 return 0;
9625 }
9626
9633 public static function lookupQuestionSetTypeByActiveId($active_id)
9634 {
9635 global $ilDB;
9636
9637 $query = "
9638 SELECT tst_tests.question_set_type
9639 FROM tst_active
9640 INNER JOIN tst_tests
9641 ON tst_active.test_fi = tst_tests.test_id
9642 WHERE tst_active.active_id = %s
9643 ";
9644
9645 $res = $ilDB->queryF( $query, array('integer'), array($active_id) );
9646
9647 while($row = $ilDB->fetchAssoc($res))
9648 {
9649 return $row['question_set_type'];
9650 }
9651
9652 return null;
9653 }
9654
9664 {
9665 throw new Exception(__METHOD__.' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9666
9667 global $ilDB;
9668
9669 $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",
9670 array('integer'),
9671 array($active_id)
9672 );
9673 while($row = $ilDB->fetchAssoc($result))
9674 {
9675 return $row['random_test'];
9676 }
9677 return 0;
9678 }
9679
9690 function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
9691 {
9692 if ($this->getAnonymity() && !$overwrite_anonymity)
9693 {
9694 return $this->lng->txt("anonymous") . $suffix;
9695 }
9696 else
9697 {
9698 include_once './Services/User/classes/class.ilObjUser.php';
9699 $uname = ilObjUser::_lookupName($user_id);
9700 if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
9701 if ($sorted_order)
9702 {
9703 return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9704 }
9705 else
9706 {
9707 return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9708 }
9709 }
9710 }
9711
9719 function getStartTestLabel($active_id)
9720 {
9721 if ($this->getNrOfTries() == 1)
9722 {
9723 return $this->lng->txt("tst_start_test");
9724 }
9725 $active_pass = $this->_getPass($active_id);
9726 $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9727 if ($res == 0)
9728 {
9729 if ($active_pass == 0)
9730 {
9731 return $this->lng->txt("tst_start_test");
9732 }
9733 else
9734 {
9735 return $this->lng->txt("tst_start_new_test_pass");
9736 }
9737 }
9738 else
9739 {
9740 return $this->lng->txt("tst_resume_test");
9741 }
9742 }
9743
9749 public function getAvailableDefaults()
9750 {
9755 global $ilDB, $ilUser;
9756
9757 $result = $ilDB->queryF(
9758 "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9759 array('integer'),
9760 array($ilUser->getId())
9761 );
9762 $defaults = array();
9763 while($row = $ilDB->fetchAssoc($result))
9764 {
9765 $defaults[$row["test_defaults_id"]] = $row;
9766 }
9767 return $defaults;
9768 }
9769
9777 function &getTestDefaults($test_defaults_id)
9778 {
9779 return self::_getTestDefaults($test_defaults_id);
9780 }
9781
9782 public static function _getTestDefaults($test_defaults_id)
9783 {
9784 global $ilDB;
9785
9786 $result = $ilDB->queryF("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9787 array('integer'),
9788 array($test_defaults_id)
9789 );
9790 if ($result->numRows() == 1)
9791 {
9792 $row = $ilDB->fetchAssoc($result);
9793 return $row;
9794 }
9795 else
9796 {
9797 return NULL;
9798 }
9799 }
9800
9807 function deleteDefaults($test_default_id)
9808 {
9809 global $ilDB;
9810 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9811 array('integer'),
9812 array($test_default_id)
9813 );
9814 }
9815
9822 function addDefaults($a_name)
9823 {
9824 global $ilDB;
9825 global $ilUser;
9826 $testsettings = array(
9827 "TitleOutput" => $this->getTitleOutput(),
9828 "PassScoring" => $this->getPassScoring(),
9829 "IntroEnabled" => $this->isIntroductionEnabled(),
9830 "Introduction" => $this->getIntroduction(),
9831 "FinalStatement" => $this->getFinalStatement(),
9832 "ShowInfo" => $this->getShowInfo(),
9833 "ForceJS" => $this->getForceJS(),
9834 "CustomStyle" => $this->getCustomStyle(),
9835 "ShowFinalStatement" => $this->getShowFinalStatement(),
9836 "SequenceSettings" => $this->getSequenceSettings(),
9837 "ScoreReporting" => $this->getScoreReporting(),
9838 "ScoreCutting" => $this->getScoreCutting(),
9839 'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9840 'PrintBsWithRes' => (int)$this->isBestSolutionPrintedWithResult(),
9841 "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9842 "AnswerFeedback" => $this->getAnswerFeedback(),
9843 "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9844 "ResultsPresentation" => $this->getResultsPresentation(),
9845 "Anonymity" => $this->getAnonymity(),
9846 "ShowCancel" => $this->getShowCancel(),
9847 "ShowMarker" => $this->getShowMarker(),
9848 "ReportingDate" => $this->getReportingDate(),
9849 "NrOfTries" => $this->getNrOfTries(),
9850 "Shuffle" => $this->getShuffleQuestions(),
9851 "Kiosk" => $this->getKiosk(),
9852 "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9853 "ProcessingTime" => $this->getProcessingTime(),
9854 "EnableProcessingTime" => $this->getEnableProcessingTime(),
9855 "ResetProcessingTime" => $this->getResetProcessingTime(),
9856 "StartingTimeEnabled" => $this->isStartingTimeEnabled(),
9857 "StartingTime" => $this->getStartingTime(),
9858 "EndingTimeEnabled" => $this->isEndingTimeEnabled(),
9859 "EndingTime" => $this->getEndingTime(),
9860 "ECTSOutput" => $this->getECTSOutput(),
9861 "ECTSFX" => $this->getECTSFX(),
9862 "ECTSGrades" => $this->getECTSGrades(),
9863 "questionSetType" => $this->getQuestionSetType(),
9864 "CountSystem" => $this->getCountSystem(),
9865 "MCScoring" => $this->getMCScoring(),
9866 "mailnotification" => $this->getMailNotification(),
9867 "mailnottype" => $this->getMailNotificationType(),
9868 "exportsettings" => $this->getExportSettings(),
9869 "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9870 'obligations_enabled' => (int)$this->areObligationsEnabled(),
9871 'offer_question_hints' => (int)$this->isOfferingQuestionHintsEnabled(),
9872 'pass_deletion_allowed' => (int)$this->isPassDeletionAllowed(),
9873 'enable_examview' => $this->getEnableExamview(),
9874 'show_examview_html' => $this->getShowExamviewHtml(),
9875 'show_examview_pdf' => $this->getShowExamviewPdf(),
9876 'char_selector_availability' => $this->getCharSelectorAvailability(),
9877 'char_selector_definition' => $this->getCharSelectorDefinition(),
9878 'skill_service' => (int)$this->isSkillServiceEnabled(),
9879 'result_tax_filters' => (array)$this->getResultFilterTaxIds(),
9880 'show_grading_status' => (int)$this->isShowGradingStatusEnabled(),
9881 'show_grading_mark' => (int)$this->isShowGradingMarkEnabled(),
9882
9883 'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
9884 'force_inst_fb' => $this->isForceInstantFeedbackEnabled(),
9885 'redirection_mode' => $this->getRedirectionMode(),
9886 'redirection_url' => $this->getRedirectionUrl(),
9887 'sign_submission' => $this->getSignSubmission(),
9888 'autosave' => (int)$this->getAutosave(),
9889 'autosave_ival' => (int)$this->getAutosaveIval(),
9890 'examid_in_test_pass' => (int)$this->isShowExamIdInTestPassEnabled(),
9891 'examid_in_test_res' => (int)$this->isShowExamIdInTestResultsEnabled(),
9892
9893 'enable_archiving' => (int)$this->getEnableArchiving(),
9894 'password_enabled' => (int)$this->isPasswordEnabled(),
9895 'password' => (string)$this->getPassword(),
9896 'fixed_participants' => $this->getFixedParticipants(),
9897 'limit_users_enabled' => $this->isLimitUsersEnabled(),
9898 'allowedusers' => $this->getAllowedUsers(),
9899 'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9900 'pool_usage' => $this->getPoolUsage(),
9901 'activation_limited' => $this->isActivationLimited(),
9902 'activation_start_time' => $this->getActivationStartingTime(),
9903 'activation_end_time' => $this->getActivationEndingTime(),
9904 'activation_visibility' => $this->getActivationVisibility(),
9905 'highscore_enabled' => $this->getHighscoreEnabled(),
9906 'highscore_anon' => $this->getHighscoreAnon(),
9907 'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9908 'highscore_score' => $this->getHighscoreScore(),
9909 'highscore_percentage' => $this->getHighscorePercentage(),
9910 'highscore_hints' => $this->getHighscoreHints(),
9911 'highscore_wtime' => $this->getHighscoreWTime(),
9912 'highscore_own_table' => $this->getHighscoreOwnTable(),
9913 'highscore_top_table' => $this->getHighscoreTopTable(),
9914 'highscore_top_num' => $this->getHighscoreTopNum(),
9915 'use_previous_answers' => (string)$this->getUsePreviousAnswers()
9916 );
9917
9918 $next_id = $ilDB->nextId('tst_test_defaults');
9919 $ilDB->insert(
9920 'tst_test_defaults',
9921 array(
9922 'test_defaults_id' => array('integer', $next_id),
9923 'name' => array('text', $a_name),
9924 'user_fi' => array('integer', $ilUser->getId()),
9925 'defaults' => array('clob', serialize($testsettings)),
9926 'marks' => array('clob', serialize($this->mark_schema)),
9927 'tstamp' => array('integer', time())
9928 )
9929 );
9930 }
9931
9939 public function applyDefaults($test_defaults)
9940 {
9941 $testsettings = unserialize($test_defaults["defaults"]);
9942 include_once "./Modules/Test/classes/class.assMarkSchema.php";
9943 $this->mark_schema = unserialize($test_defaults["marks"]);
9944
9945 $this->setTitleOutput($testsettings["TitleOutput"]);
9946 $this->setPassScoring($testsettings["PassScoring"]);
9947 $this->setIntroductionEnabled($testsettings["IntroEnabled"]);
9948 $this->setIntroduction($testsettings["Introduction"]);
9949 $this->setFinalStatement($testsettings["FinalStatement"]);
9950 $this->setShowInfo($testsettings["ShowInfo"]);
9951 $this->setForceJS($testsettings["ForceJS"]);
9952 $this->setCustomStyle($testsettings["CustomStyle"]);
9953 $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
9954 $this->setSequenceSettings($testsettings["SequenceSettings"]);
9955 $this->setScoreReporting($testsettings["ScoreReporting"]);
9956 $this->setScoreCutting($testsettings['ScoreCutting']);
9957 $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
9958 $this->setPrintBestSolutionWithResult((bool)$testsettings['PrintBsWithRes']);
9959 $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
9960 $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
9961 $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
9962 $this->setResultsPresentation($testsettings["ResultsPresentation"]);
9963 $this->setAnonymity($testsettings["Anonymity"]);
9964 $this->setShowCancel($testsettings["ShowCancel"]);
9965 $this->setShuffleQuestions($testsettings["Shuffle"]);
9966 $this->setShowMarker($testsettings["ShowMarker"]);
9967 $this->setReportingDate($testsettings["ReportingDate"]);
9968 $this->setNrOfTries($testsettings["NrOfTries"]);
9969 $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
9970 $this->setRedirectionMode($testsettings['redirection_mode']);
9971 $this->setRedirectionUrl($testsettings['redirection_url']);
9972 $this->setProcessingTime($testsettings["ProcessingTime"]);
9973 $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
9974 $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
9975 $this->setStartingTimeEnabled($testsettings["StartingTimeEnabled"]);
9976 $this->setStartingTime($testsettings["StartingTime"]);
9977 $this->setKiosk($testsettings["Kiosk"]);
9978 $this->setEndingTimeEnabled($testsettings["EndingTimeEnabled"]);
9979 $this->setEndingTime($testsettings["EndingTime"]);
9980 $this->setECTSOutput($testsettings["ECTSOutput"]);
9981 $this->setECTSFX($testsettings["ECTSFX"]);
9982 $this->setECTSGrades($testsettings["ECTSGrades"]);
9983 if( isset($testsettings["isRandomTest"]) )
9984 {
9985 if( $testsettings["isRandomTest"] )
9986 {
9987 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
9988 }
9989 else
9990 {
9991 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
9992 }
9993 }
9994 elseif( isset($testsettings["questionSetType"]) )
9995 {
9996 $this->setQuestionSetType($testsettings["questionSetType"]);
9997 }
9998 $this->setCountSystem($testsettings["CountSystem"]);
9999 $this->setMCScoring($testsettings["MCScoring"]);
10000 $this->setMailNotification($testsettings["mailnotification"]);
10001 $this->setMailNotificationType($testsettings["mailnottype"]);
10002 $this->setExportSettings($testsettings['exportsettings']);
10003 $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
10004 $this->setObligationsEnabled($testsettings["obligations_enabled"]);
10005 $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
10006 $this->setHighscoreEnabled($testsettings['highscore_enabled']);
10007 $this->setHighscoreAnon($testsettings['highscore_anon']);
10008 $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
10009 $this->setHighscoreScore($testsettings['highscore_score']);
10010 $this->setHighscorePercentage($testsettings['highscore_percentage']);
10011 $this->setHighscoreHints($testsettings['highscore_hints']);
10012 $this->setHighscoreWTime($testsettings['highscore_wtime']);
10013 $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
10014 $this->setHighscoreTopTable($testsettings['highscore_top_table']);
10015 $this->setHighscoreTopNum($testsettings['highscore_top_num']);
10016 $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
10017 if( isset($testsettings['examid_in_kiosk']) )
10018 {
10019 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
10020 }
10021 else
10022 {
10023 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
10024 }
10025 if( isset($testsettings['show_exam_id']) )
10026 {
10027 $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
10028 }
10029 else
10030 {
10031 $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
10032 }
10033 $this->setEnableExamview($testsettings['enable_examview']);
10034 $this->setShowExamviewHtml($testsettings['show_examview_html']);
10035 $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
10036 $this->setEnableArchiving($testsettings['enable_archiving']);
10037 $this->setSignSubmission($testsettings['sign_submission']);
10038 $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
10039 $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
10040 $this->setSkillServiceEnabled((bool)$testsettings['skill_service']);
10041 $this->setResultFilterTaxIds((array)$testsettings['result_tax_filters']);
10042 $this->setShowGradingStatusEnabled((bool)$testsettings['show_grading_status']);
10043 $this->setShowGradingMarkEnabled((bool)$testsettings['show_grading_mark']);
10044
10045 $this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
10046 $this->setForceInstantFeedbackEnabled($testsettings['force_inst_fb']);
10047 $this->setRedirectionMode($testsettings['redirection_mode']);
10048 $this->setRedirectionUrl($testsettings['redirection_url']);
10049
10050 $this->setAutosave($testsettings['autosave']);
10051 $this->setAutosaveIval($testsettings['autosave_ival']);
10052 $this->setShowExamIdInTestResultsEnabled((int)$testsettings['examid_in_test_res']);
10053 $this->setPasswordEnabled($testsettings['password_enabled']);
10054 $this->setPassword($testsettings['password']);
10055 $this->setFixedParticipants($testsettings['fixed_participants'] );
10056 $this->setLimitUsersEnabled($testsettings['limit_users_enabled']);
10057 $this->setAllowedUsers($testsettings['allowedusers']);
10058 $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
10059 $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
10060 $this->setPoolUsage($testsettings['pool_usage']);
10061 $this->setActivationLimited($testsettings['activation_limited']);
10062 $this->setActivationStartingTime($testsettings['activation_start_time']);
10063 $this->setActivationEndingTime($testsettings['activation_end_time']);
10064 $this->setActivationVisibility($testsettings['activation_visibility']);
10065
10066 $this->saveToDb();
10067
10068 return true;
10069 }
10070
10078 function processPrintoutput2FO($print_output)
10079 {
10080 if (extension_loaded("tidy"))
10081 {
10082 $config = array(
10083 "indent" => false,
10084 "output-xml" => true,
10085 "numeric-entities" => true
10086 );
10087 $tidy = new tidy();
10088 $tidy->parseString($print_output, $config, 'utf8');
10089 $tidy->cleanRepair();
10090 $print_output = tidy_get_output($tidy);
10091 $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
10092 }
10093 else
10094 {
10095 $print_output = str_replace("&nbsp;", "&#160;", $print_output);
10096 $print_output = str_replace("&otimes;", "X", $print_output);
10097 }
10098 $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
10099
10100 // additional font support
10101 $xsl = str_replace(
10102 'font-family="Helvetica, unifont"',
10103 'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
10104 $xsl
10105 );
10106
10107 $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
10108 $xh = xslt_create();
10109 $params = array();
10110 $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
10111 xslt_error($xh);
10112 xslt_free($xh);
10113 return $output;
10114 }
10115
10122 public function deliverPDFfromHTML($content, $title = NULL)
10123 {
10124 $content = preg_replace("/href=\".*?\"/", "", $content);
10125 $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", TRUE, TRUE, "Modules/Test");
10126 $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
10127 $printbody->setVariable("ADM_CONTENT", $content);
10128 $printbody->setCurrentBlock("css_file");
10129 $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
10130 $printbody->parseCurrentBlock();
10131 $printbody->setCurrentBlock("css_file");
10132 $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
10133 $printbody->parseCurrentBlock();
10134 $printoutput = $printbody->get();
10135 $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
10136 $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
10137 if (extension_loaded("tidy"))
10138 {
10139 $config = array(
10140 "indent" => false,
10141 "output-xml" => true,
10142 "numeric-entities" => true
10143 );
10144 $tidy = new tidy();
10145 $tidy->parseString($html, $config, 'utf8');
10146 $tidy->cleanRepair();
10147 $html = tidy_get_output($tidy);
10148 $html = preg_replace("/^.*?(<html)/", "\\1", $html);
10149 }
10150 else
10151 {
10152 $html = str_replace("&nbsp;", "&#160;", $html);
10153 $html = str_replace("&otimes;", "X", $html);
10154 }
10155 $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
10157 }
10158
10165 public function deliverPDFfromFO($fo, $title = null)
10166 {
10167 global $ilLog;
10168
10169 include_once "./Services/Utilities/classes/class.ilUtil.php";
10170 $fo_file = ilUtil::ilTempnam() . ".fo";
10171 $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
10172
10173 include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
10174 try
10175 {
10176 $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
10177 $filename = (strlen($title)) ? $title : $this->getTitle();
10178 ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10179 return true;
10180 }
10181 catch(XML_RPC2_FaultException $e)
10182 {
10183 $ilLog->write(__METHOD__.': '.$e->getMessage());
10184 return false;
10185 }
10186 catch(Exception $e)
10187 {
10188 $ilLog->write(__METHOD__.': '.$e->getMessage());
10189 return false;
10190 }
10191
10192 /*
10193 include_once "./Services/Transformation/classes/class.ilFO2PDF.php";
10194 $fo2pdf = new ilFO2PDF();
10195 $fo2pdf->setFOString($fo);
10196 $result = $fo2pdf->send();
10197 $filename = (strlen($title)) ? $title : $this->getTitle();
10198 ilUtil::deliverData($result, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10199 */
10200 }
10201
10211 static function getManualFeedback($active_id, $question_id, $pass)
10212 {
10213 global $ilDB;
10214 $feedback = "";
10215 $result = $ilDB->queryF("SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10216 array('integer', 'integer', 'integer'),
10217 array($active_id, $question_id, $pass)
10218 );
10219 if ($result->numRows())
10220 {
10221 $row = $ilDB->fetchAssoc($result);
10222 include_once("./Services/RTE/classes/class.ilRTE.php");
10223 $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
10224 }
10225 return $feedback;
10226 }
10227
10238 function saveManualFeedback($active_id, $question_id, $pass, $feedback)
10239 {
10240 global $ilDB;
10241
10242 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10243 array('integer', 'integer', 'integer'),
10244 array($active_id, $question_id, $pass)
10245 );
10246
10247 if (strlen($feedback))
10248 {
10249 $next_id = $ilDB->nextId('tst_manual_fb');
10251 $result = $ilDB->insert('tst_manual_fb', array(
10252 'manual_feedback_id' => array( 'integer', $next_id ),
10253 'active_fi' => array( 'integer', $active_id ),
10254 'question_fi' => array( 'integer', $question_id ),
10255 'pass' => array( 'integer', $pass),
10256 'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0) ),
10257 'tstamp' => array( 'integer', time() ),
10258 )
10259 );
10260 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10262 {
10263 global $lng, $ilUser;
10264 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
10265 $username = ilObjTestAccess::_getParticipantData($active_id);
10266 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10267 $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
10268 }
10269 }
10270 if (PEAR::isError($result))
10271 {
10272 global $ilias;
10273 $ilias->raiseError($result->getMessage());
10274 }
10275 else
10276 {
10277 return TRUE;
10278 }
10279 }
10280
10289 {
10290 return TRUE;
10291
10292// global $ilUser;
10293// if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
10294// if ($this->getForceJS()) return TRUE;
10295// $assessmentSetting = new ilSetting("assessment");
10296// return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
10297 }
10298
10299 function &createTestSequence($active_id, $pass, $shuffle)
10300 {
10301 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10302 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10303 }
10304
10310 public function setTestId($a_id)
10311 {
10312 $this->test_id = $a_id;
10313 }
10314
10323 function getDetailedTestResults($participants)
10324 {
10325 $results = array();
10326 if (count($participants))
10327 {
10328 foreach ($participants as $active_id => $user_rec)
10329 {
10330 $row = array();
10331 $reached_points = 0;
10332 $max_points = 0;
10333 foreach ($this->questions as $value)
10334 {
10335 $question =& ilObjTest::_instanciateQuestion($value);
10336 if (is_object($question))
10337 {
10338 $max_points += $question->getMaximumPoints();
10339 $reached_points += $question->getReachedPoints($active_id);
10340 if ($max_points > 0)
10341 {
10342 $percentvalue = $reached_points / $max_points;
10343 if ($percentvalue < 0) $percentvalue = 0.0;
10344 }
10345 else
10346 {
10347 $percentvalue = 0;
10348 }
10349 if ($this->getAnonymity())
10350 {
10351 $user_rec['firstname'] = "";
10352 $user_rec['lastname'] = $this->lng->txt("anonymous");
10353 }
10354 $row = array(
10355 "user_id"=>$user_rec['usr_id'],
10356 "matriculation" => $user_rec['matriculation'],
10357 "lastname" => $user_rec['lastname'],
10358 "firstname" => $user_rec['firstname'],
10359 "login"=>$user_rec['login'],
10360 "question_id" => $question->getId(),
10361 "question_title" => $question->getTitle(),
10362 "reached_points" => $reached_points,
10363 "max_points" => $max_points
10364 );
10365 $results[] = $row;
10366 }
10367 }
10368 }
10369 }
10370 return $results;
10371 }
10372
10377 {
10378 global $ilDB;
10379
10380 $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",
10381 array('integer'),
10382 array($a_q_id)
10383 );
10384 $rec = $ilDB->fetchAssoc($result);
10385 return $rec["obj_id"];
10386 }
10387
10394 function isPluginActive($a_pname)
10395 {
10396 global $ilPluginAdmin;
10397 if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname))
10398 {
10399 return TRUE;
10400 }
10401 else
10402 {
10403 return FALSE;
10404 }
10405 }
10406
10407 public function getPassed($active_id)
10408 {
10409 global $ilDB;
10410
10411 $result = $ilDB->queryF("SELECT passed FROM tst_result_cache WHERE active_fi = %s",
10412 array('integer'),
10413 array($active_id)
10414 );
10415 if ($result->numRows())
10416 {
10417 $row = $ilDB->fetchAssoc($result);
10418 return $row['passed'];
10419 }
10420 else
10421 {
10422 $counted_pass = ilObjTest::_getResultPass($active_id);
10423 $result_array =& $this->getTestResult($active_id, $counted_pass);
10424 return $result_array["test"]["passed"];
10425 }
10426 }
10427
10433 function canShowCertificate($testSession, $user_id, $active_id)
10434 {
10435 if ($this->canShowTestResults($testSession))
10436 {
10437 include_once "./Services/Certificate/classes/class.ilCertificate.php";
10438 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
10439 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
10440 if ($cert->isComplete())
10441 {
10442 $vis = $this->getCertificateVisibility();
10443 $showcert = FALSE;
10444 switch ($vis)
10445 {
10446 case 0:
10447 $showcert = TRUE;
10448 break;
10449 case 1:
10450 if ($this->getPassed($active_id))
10451 {
10452 $showcert = TRUE;
10453 }
10454 break;
10455 case 2:
10456 $showcert = FALSE;
10457 break;
10458 }
10459 if ($showcert)
10460 {
10461 return TRUE;
10462 }
10463 else
10464 {
10465 return FALSE;
10466 }
10467 }
10468 else
10469 {
10470 return FALSE;
10471 }
10472 }
10473 else
10474 {
10475 return FALSE;
10476 }
10477 }
10478
10482 public function getParticipantsForTestAndQuestion($test_id, $question_id)
10483 {
10485 global $ilDB;
10486
10487 $query = "
10488 SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10489 FROM tst_test_result
10490 INNER JOIN tst_active ON tst_active.active_id = tst_test_result.active_fi AND tst_active.test_fi = %s
10491 INNER JOIN qpl_questions ON qpl_questions.question_id = tst_test_result.question_fi
10492 LEFT JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
10493 WHERE tst_test_result.question_fi = %s
10494 ORDER BY usr_data.lastname ASC, usr_data.firstname ASC
10495 ";
10496
10497 $result = $ilDB->queryF($query,
10498 array('integer', 'integer'),
10499 array($test_id, $question_id)
10500 );
10501 $foundusers = array();
10503 while ($row = $ilDB->fetchAssoc($result))
10504 {
10505 if (!array_key_exists($row["active_fi"], $foundusers))
10506 {
10507 $foundusers[$row["active_fi"]] = array();
10508 }
10509 array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10510 }
10511 return $foundusers;
10512 }
10513
10520 {
10521 $data =& $this->getCompleteEvaluationData();
10522 $foundParticipants =& $data->getParticipants();
10523 $results = array("overview" => array(), "questions" => array());
10524 if (count($foundParticipants))
10525 {
10526 $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10527 $total_finished = $this->evalTotalFinished();
10528 $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10529 $average_time = $this->evalTotalStartedAverageTime();
10530 $diff_seconds = $average_time;
10531 $diff_hours = floor($diff_seconds/3600);
10532 $diff_seconds -= $diff_hours * 3600;
10533 $diff_minutes = floor($diff_seconds/60);
10534 $diff_seconds -= $diff_minutes * 60;
10535 $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10536 $total_passed = 0;
10537 $total_passed_reached = 0;
10538 $total_passed_max = 0;
10539 $total_passed_time = 0;
10540 foreach ($foundParticipants as $userdata)
10541 {
10542 if ($userdata->getPassed())
10543 {
10544 $total_passed++;
10545 $total_passed_reached += $userdata->getReached();
10546 $total_passed_max += $userdata->getMaxpoints();
10547 $total_passed_time += $userdata->getTimeOfWork();
10548 }
10549 }
10550 $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10551 $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10552 $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10553 $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10554 $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);
10555 $average_time = $average_passed_time;
10556 $diff_seconds = $average_time;
10557 $diff_hours = floor($diff_seconds/3600);
10558 $diff_seconds -= $diff_hours * 3600;
10559 $diff_minutes = floor($diff_seconds/60);
10560 $diff_seconds -= $diff_minutes * 60;
10561 $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10562 }
10563
10564 foreach ($data->getQuestionTitles() as $question_id => $question_title)
10565 {
10566 $answered = 0;
10567 $reached = 0;
10568 $max = 0;
10569 foreach ($foundParticipants as $userdata)
10570 {
10571 for ($i = 0; $i <= $userdata->getLastPass(); $i++)
10572 {
10573 if (is_object($userdata->getPass($i)))
10574 {
10575 $question =& $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10576 if (is_array($question))
10577 {
10578 $answered++;
10579 $reached += $question["reached"];
10580 $max += $question["points"];
10581 }
10582 }
10583 }
10584 }
10585 $percent = $max ? $reached/$max * 100.0 : 0;
10586 $counter++;
10587 $results["questions"][$question_id] = array(
10588 $question_title,
10589 sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10590 sprintf("%.2f", $percent) . "%",
10591 $answered,
10592 sprintf("%.2f", $answered ? $reached / $answered : 0),
10593 sprintf("%.2f", $answered ? $max / $answered : 0),
10594 $percent / 100.0
10595 );
10596 }
10597 return $results;
10598 }
10599
10603 function getXMLZip()
10604 {
10605 include_once("./Modules/Test/classes/class.ilTestExport.php");
10606 $test_exp = new ilTestExport($this, "xml");
10607 return $test_exp->buildExportFile();
10608 }
10609
10613 public function getMailNotification()
10614 {
10616 }
10617
10623 public function setMailNotification($a_notification)
10624 {
10625 $this->mailnotification = $a_notification;
10626 }
10627
10628 public function sendSimpleNotification($active_id)
10629 {
10630 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10631
10632 $mail = new ilTestMailNotification();
10633 $owner_id = $this->getOwner();
10634 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10635 $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10636 }
10637
10644 {
10645 include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10646 include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10647 $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(), 'outEvaluation', $this->getAnonymity());
10648 return $table_gui->getSelectedColumns();
10649 }
10650
10651 public function sendAdvancedNotification($active_id)
10652 {
10653 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10654
10655 $mail = new ilTestMailNotification();
10656 $owner_id = $this->getOwner();
10657 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10658
10659 include_once "./Modules/Test/classes/class.ilTestExport.php";
10660 $exportObj = new ilTestExport($this, "results");
10661 $file = $exportObj->exportToExcel($deliver = FALSE, 'active_id', $active_id, $passedonly = FALSE);
10662 include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10663 $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10664 $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10665 $file_names[] = "result_" . $active_id . ".xls";
10666
10667 $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10668
10669 if(count($file_names))
10670 {
10671 $fd->unlinkFiles($file_names);
10672 unset($fd);
10673 @unlink($file);
10674 }
10675 }
10676
10677 function createRandomSolutions($number)
10678 {
10679 global $ilDB;
10680
10681 // 1. get a user
10682 $query = "SELECT usr_id FROM usr_data";
10683 $result = $ilDB->query($query);
10684 while ($data = $ilDB->fetchAssoc($result))
10685 {
10686 $activequery = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10687 $ilDB->quote($this->getTestId()),
10688 $ilDB->quote($data['usr_id'])
10689 );
10690 $activeresult = $ilDB->query($activequery);
10691 if ($activeresult->numRows() == 0)
10692 {
10693 $user_id = $data['usr_id'];
10694 if ($user_id != 13)
10695 {
10696 include_once "./Modules/Test/classes/class.ilTestSession.php";
10698 $testSession->setRefId($this->getRefId());
10699 $testSession->setTestId($this->getTestId());
10700 $testSession->setUserId($user_id);
10701 $testSession->saveToDb();
10702 $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10703 $nr_of_passes = rand(1, $passes);
10704 $active_id = $testSession->getActiveId();
10705 for ($pass = 0; $pass < $nr_of_passes; $pass++)
10706 {
10707 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10708 $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10709 $testSequence->loadFromDb();
10710 $testSequence->loadQuestions();
10711 if (!$testSequence->hasSequence())
10712 {
10713 $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10714 $testSequence->saveToDb();
10715 }
10716 for ($seq = 1; $seq <= count($this->questions); $seq++)
10717 {
10718 $question_id = $testSequence->getQuestionForSequence($seq);
10719 $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10720 $assSettings = new ilSetting('assessment');
10721 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
10722 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
10723 $processLockerFactory->setQuestionId($objQuestion->getId());
10724 $processLockerFactory->setUserId($testSession->getUserId());
10725 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10726 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
10727 $objQuestion->setProcessLocker($processLockerFactory->getLocker());
10728 $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10729 }
10730 $testSession->increasePass();
10731 $testSession->setLastSequence(0);
10732 $testSession->setLastFinishedPass($pass);
10733 $testSession->setSubmitted(1);
10734 $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10735 $testSession->saveToDb();
10736 }
10737 $number--;
10738 if ($number == 0) return;
10739 }
10740 }
10741 }
10742 }
10743
10744 public function getResultsForActiveId($active_id)
10745 {
10746 global $ilDB;
10747
10748 $query = "
10749 SELECT *
10750 FROM tst_result_cache
10751 WHERE active_fi = %s
10752 ";
10753
10754 $result = $ilDB->queryF(
10755 $query, array('integer'), array($active_id)
10756 );
10757
10758 if( !$result->numRows() )
10759 {
10760 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10761
10763
10764 $query = "
10765 SELECT *
10766 FROM tst_result_cache
10767 WHERE active_fi = %s
10768 ";
10769
10770 $result = $ilDB->queryF(
10771 $query, array('integer'), array($active_id)
10772 );
10773 }
10774
10775 $row = $ilDB->fetchAssoc($result);
10776
10777 return $row;
10778
10779 }
10780
10781 public function getMailNotificationType()
10782 {
10783 if ($this->mailnottype == 1)
10784 {
10785 return $this->mailnottype;
10786 }
10787 else
10788 {
10789 return 0;
10790 }
10791 }
10792
10793 public function setMailNotificationType($a_type)
10794 {
10795 if ($a_type == 1)
10796 {
10797 $this->mailnottype = 1;
10798 }
10799 else
10800 {
10801 $this->mailnottype = 0;
10802 }
10803 }
10804
10805 public function getExportSettings()
10806 {
10807 if ($this->exportsettings)
10808 {
10809 return $this->exportsettings;
10810 }
10811 else
10812 {
10813 return 0;
10814 }
10815 }
10816
10817 public function setExportSettings($a_settings)
10818 {
10819 if ($a_settings)
10820 {
10821 $this->exportsettings = $a_settings;
10822 }
10823 else
10824 {
10825 $this->exportsettings = 0;
10826 }
10827 }
10828
10830 {
10831 if (($this->exportsettings & 1) > 0)
10832 {
10833 return true;
10834 }
10835 else
10836 {
10837 return false;
10838 }
10839 }
10840
10841 public function setExportSettingsSingleChoiceShort($a_settings)
10842 {
10843 if ($a_settings)
10844 {
10845 $this->exportsettings = $this->exportsettings | 1;
10846 }
10847 else
10848 {
10850 {
10851 $this->exportsettings = $this->exportsettings ^ 1;
10852 }
10853 }
10854 }
10855
10856 public function getEnabledViewMode() {
10857 return $this->enabled_view_mode;
10858 }
10859
10860 public function setEnabledViewMode($mode) {
10861 $this->enabled_view_mode = $mode;
10862 }
10863
10865 $this->template_id = (int)$template_id;
10866 }
10867
10868 function getTemplate() {
10869 return $this->template_id;
10870 }
10871
10872 public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
10873 $new_array = array();
10874 $position = 1;
10875
10876 $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10877 $types = array('integer');
10878 $values = array($this->getTestId());
10879
10880 $new_question_id += 1;
10881
10882 global $ilDB;
10883 $inserted = false;
10884 $res = $ilDB->queryF($query, $types, $values);
10885 while($row = $ilDB->fetchAssoc($res)) {
10886
10887 $qid = $row['question_fi'];
10888
10889 if ($qid == $new_question_id) {
10890 continue;
10891 }
10892 else if ($qid == $previous_question_id) {
10893 $new_array[$position++] = $qid;
10894 $new_array[$position++] = $new_question_id;
10895 $inserted = true;
10896 }
10897 else {
10898 $new_array[$position++] = $qid;
10899 }
10900 }
10901
10902 $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10903 $update_types = array('integer', 'integer', 'integer');
10904
10905 foreach($new_array as $position => $qid) {
10906 $ilDB->manipulateF(
10907 $update_query,
10908 $update_types,
10909 $vals = array(
10910 $position,
10911 $this->getTestId(),
10912 $qid
10913 )
10914 );
10915 }
10916 }
10917
10919 {
10920 if (is_array($options))
10921 {
10922 $this->setGenericAnswerFeedback( in_array('instant_feedback_generic', $options) ? 1 : 0);
10923 $this->setSpecificAnswerFeedback( in_array('instant_feedback_specific', $options) ? 1 : 0);
10924 $this->setAnswerFeedbackPoints( in_array('instant_feedback_points', $options) ? 1 : 0);
10925 $this->setInstantFeedbackSolution( in_array('instant_feedback_solution', $options) ? 1 : 0);
10926 }
10927 else
10928 {
10929 $this->setGenericAnswerFeedback(0);
10930 $this->setSpecificAnswerFeedback(0);
10931 $this->setAnswerFeedbackPoints(0);
10933 }
10934 }
10935
10937 $setter = array(
10938 'pass_details' => 'setShowPassDetails',
10939 'solution_details' => 'setShowSolutionDetails',
10940 'solution_printview' => 'setShowSolutionPrintview',
10941 'solution_feedback' => 'setShowSolutionFeedback',
10942 'solution_answers_only' => 'setShowSolutionAnswersOnly',
10943 'solution_signature' => 'setShowSolutionSignature',
10944 'solution_suggested' => 'setShowSolutionSuggested',
10945 );
10946 foreach($setter as $key => $setter) {
10947 if (in_array($key, $options)) {
10948 $this->$setter(1);
10949 }
10950 else {
10951 $this->$setter(0);
10952 }
10953 }
10954 }
10955
10956 public function getPoolUsage() {
10957 return (boolean) $this->poolUsage;
10958 }
10959
10960 public function setPoolUsage($usage) {
10961 $this->poolUsage = (boolean)$usage;
10962 }
10963
10965 {
10966 $tree = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tree'] : $GLOBALS['tree'];
10967 $db = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
10968 $pluginAdmin = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilPluginAdmin'] : $GLOBALS['ilPluginAdmin'];
10969
10970 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
10971 $qscFactory = new ilTestQuestionSetConfigFactory($tree, $db, $pluginAdmin, $this);
10972 $questionSetConfig = $qscFactory->getQuestionSetConfig();
10973
10974 /* @var ilTestFixedQuestionSetConfig $questionSetConfig */
10975 $questionSetConfig->reindexQuestionOrdering();
10976
10977 $this->loadQuestions();
10978 }
10979
10980 public function setQuestionOrderAndObligations($orders, $obligations)
10981 {
10982 global $ilDB;
10983
10984 asort($orders);
10985
10986 $i = 0;
10987
10988 foreach($orders as $id => $position)
10989 {
10990 $i++;
10991
10992 $obligatory = (
10993 isset($obligations[$id]) && $obligations[$id] ? 1 : 0
10994 );
10995
10996 $query = "
10997 UPDATE tst_test_question
10998 SET sequence = %s,
10999 obligatory = %s
11000 WHERE question_fi = %s
11001 ";
11002
11003 $ilDB->manipulateF(
11004 $query, array('integer', 'integer', 'integer'), array($i, $obligatory, $id)
11005 );
11006 }
11007
11008 $this->loadQuestions();
11009 }
11010
11011 public function moveQuestionAfter($question_to_move, $question_before) {
11012 global $ilDB;
11013 //var_dump(func_get_args());
11014 if ($question_before) {
11015 $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
11016 $types = array('integer');
11017 $values = array($question_before);
11018 $rset = $ilDB->queryF($query, $types, $values);
11019 }
11020
11021 if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
11022 $row = array(
11023 'sequence' => 0,
11024 'test_fi' => $this->getTestId(),
11025 );
11026 }
11027
11028 $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
11029 $types = array('integer', 'integer');
11030 $values = array($row['sequence'], $row['test_fi']);
11031 $ilDB->manipulateF($update, $types, $values);
11032
11033 $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
11034 $types = array('integer', 'integer');
11035 $values = array($row['sequence'] + 1, $question_to_move);
11036 $ilDB->manipulateF($update, $types, $values);
11037
11039 }
11040
11042 {
11043 global $ilDB;
11044
11046
11047 $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
11048
11049 $query = "
11050 SELECT count(q1.question_id) cnt
11051
11052 FROM qpl_questions q1
11053
11054 INNER JOIN qpl_questions q2
11055 ON q2.question_id = q1.original_id
11056
11057 WHERE $IN_questions
11058 AND q1.obj_fi = q2.obj_fi
11059 ";
11060
11061 $rset = $ilDB->query($query);
11062
11063 $row = $ilDB->fetchAssoc($rset);
11064
11065 return $row['cnt'] > 0;
11066 }
11067
11074 public static function _lookupFinishedUserTests($a_user_id)
11075 {
11076 global $ilDB;
11077
11078 $result = $ilDB->queryF("SELECT test_fi,MAX(pass) AS pass FROM tst_active".
11079 " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)".
11080 " WHERE user_fi=%s".
11081 " GROUP BY test_fi",
11082 array('integer', 'integer'),
11083 array($a_user_id, 1)
11084 );
11085 $all = array();
11086 while($row = $ilDB->fetchAssoc($result))
11087 {
11088 $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
11089 $all[$obj_id] = (bool)$row["pass"];
11090 }
11091 return $all;
11092 }
11093 public function getQuestions()
11094 {
11095 return $this->questions;
11096 }
11097
11098 public function isOnline()
11099 {
11100 return $this->online;
11101 }
11102
11103 public function setOnline($a_online = true)
11104 {
11105 $this->online = (bool)$a_online;
11106 }
11107
11108 public function setPrintBestSolutionWithResult($status)
11109 {
11110 $this->print_best_solution_with_result = (bool) $status;
11111 }
11112
11114 {
11116 }
11117
11124 {
11126 }
11127
11134 {
11135 $this->offeringQuestionHintsEnabled = (bool)$offeringQuestionHintsEnabled;
11136 }
11137
11138 function setActivationVisibility($a_value)
11139 {
11140 $this->activation_visibility = (bool) $a_value;
11141 }
11142
11144 {
11146 }
11147
11149 {
11150 return (bool)$this->activation_limited;
11151 }
11152
11153 function setActivationLimited($a_value)
11154 {
11155 $this->activation_limited = (bool)$a_value;
11156 }
11157
11158 /* GET/SET for highscore feature */
11159
11165 public function setHighscoreEnabled($a_enabled)
11166 {
11167 $this->_highscore_enabled = (bool)$a_enabled;
11168 }
11169
11175 public function getHighscoreEnabled()
11176 {
11177 return (bool) $this->_highscore_enabled;
11178 }
11179
11187 public function setHighscoreAnon($a_anon)
11188 {
11189 $this->_highscore_anon = (bool)$a_anon;
11190 }
11191
11201 public function getHighscoreAnon()
11202 {
11203 return (bool) $this->_highscore_anon;
11204 }
11205
11214 public function isHighscoreAnon()
11215 {
11216 if ($this->getAnonymity() == 1)
11217 {
11218 return true;
11219 }
11220 else
11221 {
11222 return (bool)$this->getHighscoreAnon();
11223 }
11224 }
11225
11231 public function setHighscoreAchievedTS($a_achieved_ts)
11232 {
11233 $this->_highscore_achieved_ts = (bool)$a_achieved_ts;
11234 }
11235
11241 public function getHighscoreAchievedTS()
11242 {
11243 return (bool) $this->_highscore_achieved_ts;
11244 }
11245
11251 public function setHighscoreScore($a_score)
11252 {
11253 $this->_highscore_score = (bool)$a_score;
11254 }
11255
11261 public function getHighscoreScore()
11262 {
11263 return (bool) $this->_highscore_score;
11264 }
11265
11271 public function setHighscorePercentage($a_percentage)
11272 {
11273 $this->_highscore_percentage = (bool)$a_percentage;
11274 }
11275
11281 public function getHighscorePercentage()
11282 {
11283 return (bool) $this->_highscore_percentage;
11284 }
11285
11291 public function setHighscoreHints($a_hints)
11292 {
11293 $this->_highscore_hints = (bool)$a_hints;
11294 }
11295
11301 public function getHighscoreHints()
11302 {
11303 return (bool) $this->_highscore_hints;
11304 }
11305
11311 public function setHighscoreWTime($a_wtime)
11312 {
11313 $this->_highscore_wtime = (bool)$a_wtime;
11314 }
11315
11321 public function getHighscoreWTime()
11322 {
11323 return (bool) $this->_highscore_wtime;
11324 }
11325
11331 public function setHighscoreOwnTable($a_own_table)
11332 {
11333 $this->_highscore_own_table = (bool)$a_own_table;
11334 }
11335
11341 public function getHighscoreOwnTable()
11342 {
11343 return (bool) $this->_highscore_own_table;
11344 }
11345
11351 public function setHighscoreTopTable($a_top_table)
11352 {
11353 $this->_highscore_top_table = (bool)$a_top_table;
11354 }
11355
11361 public function getHighscoreTopTable()
11362 {
11363 return (bool) $this->_highscore_top_table;
11364 }
11365
11372 public function setHighscoreTopNum($a_top_num)
11373 {
11374 $this->_highscore_top_num = (int)$a_top_num;
11375 }
11376
11385 public function getHighscoreTopNum($a_retval = 10)
11386 {
11387 $retval = $a_retval;
11388 if ( (int) $this->_highscore_top_num != 0)
11389 {
11390 $retval = $this->_highscore_top_num;
11391 }
11392
11393 return $retval;
11394 }
11395
11399 public function getHighscoreMode()
11400 {
11401 switch(true)
11402 {
11403 case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
11405 break;
11406
11407 case $this->getHighscoreTopTable():
11409 break;
11410
11411 case $this->getHighscoreOwnTable():
11412 default:
11414 break;
11415 }
11416 }
11417
11421 public function setHighscoreMode($mode)
11422 {
11423 switch($mode)
11424 {
11426 $this->setHighscoreTopTable(1);
11427 $this->setHighscoreOwnTable(1);
11428 break;
11429
11431 $this->setHighscoreTopTable(1);
11432 $this->setHighscoreOwnTable(0);
11433 break;
11434
11436 default:
11437 $this->setHighscoreTopTable(0);
11438 $this->setHighscoreOwnTable(1);
11439 break;
11440 }
11441 }
11442 /* End GET/SET for highscore feature*/
11443
11444 public function setSpecificAnswerFeedback($specific_answer_feedback)
11445 {
11446 switch ($specific_answer_feedback)
11447 {
11448 case 1:
11449 $this->specific_answer_feedback = 1;
11450 break;
11451 default:
11452 $this->specific_answer_feedback = 0;
11453 break;
11454 }
11455 }
11456
11458 {
11459 switch ($this->specific_answer_feedback)
11460 {
11461 case 1:
11462 return 1;
11463 default:
11464 return 0;
11465 }
11466 }
11467
11474 {
11475 $this->obligationsEnabled = (bool)$obligationsEnabled;
11476 }
11477
11483 public function areObligationsEnabled()
11484 {
11485 return (bool)$this->obligationsEnabled;
11486 }
11487
11494 public static function isQuestionObligationPossible($questionId)
11495 {
11496 require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11497
11498 $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11499
11500 assQuestion::_includeClass($classConcreteQuestion, 0);
11501
11502 // static binder is not at work yet (in PHP < 5.3)
11503 //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11504 $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11505
11506 return $obligationPossible;
11507 }
11508
11515 public static function isQuestionObligatory($question_id)
11516 {
11517 global $ilDB;
11518
11519 $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11520
11521 if( $row = $ilDB->fetchAssoc($rset) )
11522 {
11523 return (bool) $row['obligatory'];
11524 }
11525
11526 return false;
11527 }
11528
11541 public static function allObligationsAnswered($test_id, $active_id, $pass)
11542 {
11543 global $ilDB;
11544
11545 $rset = $ilDB->queryF(
11546 'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11547 array('integer', 'integer'),
11548 array($active_id, $pass)
11549 );
11550
11551 if( $row = $ilDB->fetchAssoc($rset) )
11552 {
11553 return (bool)$row['obligations_answered'];
11554 }
11555
11557 }
11558
11567 public static function hasObligations($test_id)
11568 {
11569 global $ilDB;
11570
11571 $rset = $ilDB->queryF(
11572 'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11573 array('integer'), array($test_id)
11574 );
11575
11576 $row = $ilDB->fetchAssoc($rset);
11577
11578 return (bool)$row['cnt'] > 0;
11579 }
11580
11581 public function setAutosave($autosave)
11582 {
11583 $this->autosave = $autosave;
11584 }
11585
11586 public function getAutosave()
11587 {
11588 return $this->autosave;
11589 }
11590
11592 {
11593 $this->autosave_ival = $autosave_ival;
11594 }
11595
11596 public function getAutosaveIval()
11597 {
11598 return $this->autosave_ival;
11599 }
11600
11606 public function isPassDeletionAllowed()
11607 {
11609 }
11610
11617 {
11618 $this->passDeletionAllowed = (bool)$passDeletionAllowed;
11619 }
11620
11621 #region Examview / PDF Examview
11626 {
11627 $this->show_examview_html = $show_examview_html;
11628 }
11629
11633 public function getShowExamviewHtml()
11634 {
11636 }
11637
11642 {
11643 $this->show_examview_pdf = $show_examview_pdf;
11644 }
11645
11649 public function getShowExamviewPdf()
11650 {
11652 }
11653
11658 {
11659 $this->enable_examview = $enable_examview;
11660 }
11661
11665 public function getEnableExamview()
11666 {
11668 }
11669
11670 #endregion
11671
11673 {
11674 $this->activation_starting_time = $starting_time;
11675 }
11676
11678 {
11679 $this->activation_ending_time = $ending_time;
11680 }
11681
11683 {
11684 return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
11685 }
11686
11688 {
11689 return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
11690 }
11691
11693 {
11694 global $ilDB;
11695
11696 $times = array();
11697 $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");
11698 while ($row = $ilDB->fetchAssoc($result))
11699 {
11700 $times[$row['active_fi']] = $row['started'];
11701 }
11702 return $times;
11703 }
11704
11706 {
11707 global $ilDB;
11708
11709 $times = array();
11710 $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",
11711 array('integer'),
11712 array($this->getTestId())
11713 );
11714 while ($row = $ilDB->fetchAssoc($result))
11715 {
11716 $times[$row['active_fi']] = $row['additionaltime'];
11717 }
11718 return $times;
11719 }
11720
11721 public function getExtraTime($active_id)
11722 {
11723 global $ilDB;
11724
11725 $result = $ilDB->queryF("SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11726 array('integer'),
11727 array($active_id)
11728 );
11729 if ($result->numRows() > 0)
11730 {
11731 $row = $ilDB->fetchAssoc($result);
11732 return $row['additionaltime'];
11733 }
11734 return 0;
11735 }
11736
11737 public function addExtraTime($active_id, $minutes)
11738 {
11739 global $ilDB;
11740
11741 $participants = array();
11742 if ($active_id == 0)
11743 {
11744 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
11745 array('integer'),
11746 array($this->getTestId())
11747 );
11748 while ($row = $ilDB->fetchAssoc($result))
11749 {
11750 array_push($participants, $row['active_id']);
11751 }
11752 }
11753 else
11754 {
11755 array_push($participants, $active_id);
11756 }
11757 foreach ($participants as $active_id)
11758 {
11759 $result = $ilDB->queryF("SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11760 array('integer'),
11761 array($active_id)
11762 );
11763 if ($result->numRows() > 0)
11764 {
11765 $ilDB->manipulateF("DELETE FROM tst_addtime WHERE active_fi = %s",
11766 array('integer'),
11767 array($active_id)
11768 );
11769 }
11770
11771 $ilDB->manipulateF("UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11772 array('integer','integer','timestamp','integer'),
11773 array(0, 0, NULL, $active_id)
11774 );
11775
11776 $ilDB->manipulateF("INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11777 array('integer','integer','integer'),
11778 array($active_id, $minutes, time())
11779 );
11780
11781 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11783 {
11784 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11785 }
11786 }
11787 }
11788
11795 {
11796 $this->enable_archiving = $enable_archiving;
11797 return $this;
11798 }
11799
11803 public function getEnableArchiving()
11804 {
11806 }
11807
11808 public function getMaxPassOfTest()
11809 {
11813 global $ilDB;
11814
11815 $query = '
11816 SELECT MAX(tst_pass_result.pass) + 1 max_res
11817 FROM tst_pass_result
11818 INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11819 WHERE test_fi = '.$ilDB->quote($this->getTestId(), 'integer').'
11820 ';
11821 $res = $ilDB->query($query);
11822 $data = $ilDB->fetchAssoc($res);
11823 return (int)$data['max_res'];
11824 }
11825
11831 public function lookupExamId($active_id, $pass)
11832 {
11834 global $ilDB, $ilSetting;
11835
11836 $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11837 $exam_id_result = $ilDB->queryF( $exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ) );
11838 if ($ilDB->numRows( $exam_id_result ) == 1)
11839 {
11840 $exam_id_row = $ilDB->fetchAssoc( $exam_id_result );
11841
11842 if ($exam_id_row['exam_id'] != null)
11843 {
11844 return $exam_id_row['exam_id'];
11845 }
11846 }
11847
11848 return null;
11849 }
11850
11857 public static function buildExamId($active_id, $pass, $test_obj_id = null)
11858 {
11860 global $ilSetting;
11861
11862 $inst_id = $ilSetting->get( 'inst_id', null );
11863
11864 if($test_obj_id === null)
11865 {
11866 $obj_id = self::_getObjectIDFromActiveID($active_id);
11867 }
11868 else
11869 {
11870 $obj_id = $test_obj_id;
11871 }
11872
11873 $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11874
11875 return $examId;
11876 }
11877
11879 {
11880 $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11881 }
11882
11884 {
11886 }
11887
11892 {
11893 $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11894 }
11895
11900 {
11902 }
11903
11908 {
11909 $this->sign_submission = $sign_submission;
11910 }
11911
11915 public function getSignSubmission()
11916 {
11918 }
11919
11923 public function setCharSelectorAvailability($availability)
11924 {
11925 $this->char_selector_availability = (int) $availability;
11926 }
11927
11932 {
11934 }
11935
11939 public function setCharSelectorDefinition($definition = '')
11940 {
11941 $this->char_selector_definition = $definition;
11942 }
11943
11948 {
11950 }
11951
11952
11959 {
11960 $this->questionSetType = $questionSetType;
11961 }
11962
11968 public function getQuestionSetType()
11969 {
11971 }
11972
11980 public static function lookupQuestionSetType($objId)
11981 {
11982 global $ilDB;
11983
11984 $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
11985
11986 $res = $ilDB->queryF($query, array('integer'), array($objId));
11987
11988 $questionSetType = null;
11989
11990 while( $row = $ilDB->fetchAssoc($res) )
11991 {
11992 $questionSetType = $row['question_set_type'];
11993 }
11994
11995 return $questionSetType;
11996 }
11997
12003 public function isFixedTest()
12004 {
12006 }
12007
12013 public function isRandomTest()
12014 {
12016 }
12017
12023 public function isDynamicTest()
12024 {
12026 }
12027
12035 public static function _lookupRandomTest($a_obj_id)
12036 {
12038 }
12039
12041 {
12042 switch( $questionSetType )
12043 {
12045 return $lng->txt('tst_question_set_type_fixed');
12046
12048 return $lng->txt('tst_question_set_type_random');
12049
12051 return $lng->txt('tst_question_set_type_dynamic');
12052 }
12053
12054 throw new ilTestException('invalid question set type value given: '.$questionSetType);
12055 }
12056
12057 public function participantDataExist()
12058 {
12059 if( $this->participantDataExist === null )
12060 {
12061 $this->participantDataExist = (bool)$this->evalTotalPersons();
12062 }
12063
12065 }
12066
12068 {
12069 if ($this->getScoreReporting() == 4)
12070 {
12071 return false;
12072 }
12073
12074 if ($this->getScoreReporting() == 3 && $this->getReportingDate() > time())
12075 {
12076 return false;
12077 }
12078
12079 return true;
12080 }
12081
12082 public function recalculateScores($preserve_manscoring = false)
12083 {
12084 require_once 'class.ilTestScoring.php';
12085 $scoring = new ilTestScoring($this);
12086 $scoring->setPreserveManualScores($preserve_manscoring);
12087 $scoring->recalculateSolutions();
12088 }
12089
12090 public static function getPoolQuestionChangeListeners(ilDB $db, $poolObjId)
12091 {
12092 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
12093
12094 $questionChangeListeners = array(
12096 );
12097
12098 return $questionChangeListeners;
12099 }
12100
12101 public static function getTestObjIdsWithActiveForUserId($userId)
12102 {
12103 global $ilDB;
12104
12105 $query = "
12106 SELECT obj_fi
12107 FROM tst_active
12108 INNER JOIN tst_tests
12109 ON test_id = test_fi
12110 WHERE user_fi = %s
12111 ";
12112
12113 $res = $ilDB->queryF($query, array('integer'), array($userId));
12114
12115 $objIds = array();
12116
12117 while( $row = $ilDB->fetchAssoc($res) )
12118 {
12119 $objIds[] = (int)$row['obj_fi'];
12120 }
12121
12122 return $objIds;
12123 }
12124
12126 {
12127 $this->skillServiceEnabled = $skillServiceEnabled;
12128 }
12129
12130 public function isSkillServiceEnabled()
12131 {
12133 }
12134
12136 {
12137 $this->resultFilterTaxIds = $resultFilterTaxIds;
12138 }
12139
12140 public function getResultFilterTaxIds()
12141 {
12143 }
12144
12146 {
12147 if( !$this->isSkillServiceEnabled() )
12148 {
12149 return false;
12150 }
12151
12152 if( !self::isSkillManagementGloballyActivated() )
12153 {
12154 return false;
12155 }
12156
12157 return true;
12158 }
12159
12161
12162 public static function isSkillManagementGloballyActivated()
12163 {
12164 if( self::$isSkillManagementGloballyActivated === null )
12165 {
12166 include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
12167 $skmgSet = new ilSkillManagementSettings();
12168
12169 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
12170 }
12171
12173 }
12174
12176 {
12177 $this->showGradingStatusEnabled = $showGradingStatusEnabled;
12178 }
12179
12181 {
12183 }
12184
12186 {
12187 $this->showGradingMarkEnabled = $showGradingMarkEnabled;
12188 }
12189
12190
12192 {
12194 }
12195
12197 {
12198 $this->instantFeedbackAnswerFixationEnabled = $instantFeedbackAnswerFixationEnabled;
12199 }
12200
12202 {
12204 }
12205
12210 {
12212 }
12213
12218 {
12219 $this->forceInstantFeedbackEnabled = $forceInstantFeedbackEnabled;
12220 }
12221
12222 public static function ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run = FALSE)
12223 {
12224 global $ilDB, $lng, $ilPluginAdmin;
12225
12226 /* @var ilObjTest $testOBJ */
12227
12228 $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12229
12230 $activeId = $testOBJ->getActiveIdOfUser($userId);
12231
12232 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12233 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12234
12235 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12236 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12237
12238 $testSession = $testSessionFactory->getSession($activeId);
12239 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
12240 $testSequence->loadFromDb();
12241
12242 // begin-patch lok changed smeyer
12243 if($a_force_new_run)
12244 {
12245 if( $testSequence->hasSequence() )
12246 {
12247 $testSession->increasePass();
12248 }
12249 $testSession->setLastSequence(0);
12250 $testSession->saveToDb();
12251 }
12252 // end-patch lok
12253 }
12254
12255 public static function isParticipantsLastPassActive($testRefId, $userId)
12256 {
12257 global $ilDB, $lng, $ilPluginAdmin;
12258
12259 /* @var ilObjTest $testOBJ */
12260
12261 $testOBJ = ilObjectFactory::getInstanceByRefId($testRefId,false);
12262
12263
12264 $activeId = $testOBJ->getActiveIdOfUser($userId);
12265
12266 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12267 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12268 // Added temporarily bugfix smeyer
12269 $testSessionFactory->reset();
12270
12271 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12272 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12273
12274 $testSession = $testSessionFactory->getSession($activeId);
12275 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
12276 $testSequence->loadFromDb();
12277
12278 return $testSequence->hasSequence();
12279 }
12280
12284 public function isTestFinalBroken()
12285 {
12287 }
12288
12293 {
12294 $this->testFinalBroken = $testFinalBroken;
12295 }
12296}
$result
print $file
$test
Definition: Utf8Test.php:85
$filename
Definition: buildRTE.php:89
$_GET["client_id"]
$_SESSION["AccountId"]
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.
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.
static _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of 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...
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.
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
reindexFixedQuestionOrdering()
_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
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.
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()
canShowTestResults($testSession)
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.
setForceInstantFeedbackEnabled($forceInstantFeedbackEnabled)
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.
removeQuestions($removeQuestionIds)
lookupExamId($active_id, $pass)
getForceJS()
Gets whether JavaScript should be forced for tests.
& getTestResult($active_id, $pass=NULL, $ordered_sequence=FALSE, $considerHiddenQuestions=true, $considerOptionalQuestions=true)
Calculates the results of a test for a given user and returns an array with all test results.
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.
getUnfilteredEvaluationData()
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.
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)
removeTestResultsFromSoapLpAdministration($userIds)
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)
static isParticipantsLastPassActive($testRefId, $userId)
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
setTmpCopyWizardCopyId($tmpCopyWizardCopyId)
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 !!
isForceInstantFeedbackEnabled()
& 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($a_temp_path=null)
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.
$html
Definition: example_001.php:87
$data
$params
Definition: example_049.php:96
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
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