ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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';
8require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionType.php';
9
21{
23
24 #region Properties
25
29 const QUESTION_SET_TYPE_FIXED = 'FIXED_QUEST_SET';
30
34 const QUESTION_SET_TYPE_RANDOM = 'RANDOM_QUEST_SET';
35
39 const QUESTION_SET_TYPE_DYNAMIC = 'DYNAMIC_QUEST_SET';
40
45
50
55
62
66 private $skillServiceEnabled = false;
67
71 private $resultFilterTaxIds = array();
72
80 protected $_kiosk;
81
88
95
103
110
117
122
129 protected $introduction;
130
137
146
157
166
173
183
190
198
206
216
223
230
237
242
248 protected $starting_time;
249
254
260 protected $ending_time;
261
266 protected $ects_output = FALSE;
267
272 protected $ects_fx = NULL;
273
278 protected $ects_grades = array();
279
280
288
295
302
310
317
324
331
336
342 protected $password;
343
348
354 protected $allowedUsers;
355
362
369
376
383
390
397
404
411
418
425
432
438 private $_showinfo;
439
445 private $_forcejs = TRUE;
446
453
455
456 protected $mailnottype;
457
459
460 protected $poolUsage;
461
463
469 private $online = null;
470
471 protected $oldOnlineStatus = null;
472
477
484
490 private $obligationsEnabled = null;
491
493
495
497
498 protected $autosave;
499
500 protected $autosave_ival;
501
508 private $passDeletionAllowed = null;
509
515 private $participantDataExist = null;
516
519
522
525
528
532 private $redirection_mode = 0;
533
537 private $redirection_url = NULL;
538
541
544
547
550
553
558
563
568
573
578
583
587 protected $pass_waiting = "00:000:00:00:00";
588 #endregion
589
598 public function __construct($a_id = 0,$a_call_by_reference = true)
599 {
600 global $ilUser, $lng;
601 $this->type = "tst";
602
603 $lng->loadLanguageModule("assessment");
604 // Defaults:
605 include_once "./Modules/Test/classes/class.assMarkSchema.php";
606 $this->mark_schema = new ASS_MarkSchema();
607 $this->mark_schema->createSimpleSchema(
608 $lng->txt("failed_short"),
609 $lng->txt("failed_official"),
610 0,
611 0,
612 $lng->txt("passed_short"),
613 $lng->txt("passed_official"),
614 50,
615 1
616 );
617
618 $this->test_id = -1;
619 $this->author = $ilUser->fullname;
620 $this->introductionEnabled = false;
621 $this->introduction = "";
622 $this->questions = array();
623 $this->sequence_settings = TEST_FIXED_SEQUENCE;
624 $this->score_reporting = REPORT_AFTER_TEST;
625 $this->instant_verification = 0;
626 $this->answer_feedback_points = 0;
627 $this->reporting_date = "";
628 $this->nr_of_tries = 0;
629 $this->_kiosk = 0;
630 $this->use_previous_answers = 1;
631 $this->title_output = 0;
632 $this->starting_time = "";
633 $this->ending_time = "";
634 $this->processing_time = "";
635 $this->enable_processing_time = "0";
636 $this->reset_processing_time = 0;
637 $this->ects_output = FALSE;
638 $this->ects_fx = NULL;
639 $this->shuffle_questions = FALSE;
640 $this->mailnottype = 0;
641 $this->exportsettings = 0;
642 $this->show_summary = 8;
643 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
644 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
645 $this->score_cutting = SCORE_CUT_QUESTION;
646 $this->pass_scoring = SCORE_LAST_PASS;
647 $this->answer_feedback = 0;
648 $this->password = "";
649 $this->certificate_visibility = 0;
650 $this->allowedUsers = "";
651 $this->_showfinalstatement = FALSE;
652 $this->_finalstatement = "";
653 $this->_showinfo = TRUE;
654 $this->_forcejs = TRUE;
655 $this->_customStyle = "";
656 $this->allowedUsersTimeGap = "";
657 $this->anonymity = 0;
658 $this->show_cancel = 0;
659 $this->show_marker = 0;
660 $this->fixed_participants = 0;
661 $this->setShowPassDetails(TRUE);
662 $this->setShowSolutionDetails(TRUE);
663 $this->setShowSolutionAnswersOnly(FALSE);
664 $this->setShowSolutionSignature(FALSE);
665 $this->testSession = FALSE;
666 $this->testSequence = FALSE;
667 $this->mailnotification = 0;
668 $this->poolUsage = 1;
669
670 $this->ects_grades = array(
671 'A' => 90,
672 'B' => 65,
673 'C' => 35,
674 'D' => 10,
675 'E' => 0
676 );
677
678 $this->autosave = FALSE;
679 $this->autosave_ival = 30000;
680
681 $this->enable_examview = false;
682 $this->show_examview_html = false;
683 $this->show_examview_pdf = false;
684 $this->enable_archiving = false;
685
686 $this->express_mode = false;
687 $this->template_id = '';
688 $this->redirection_mode = 0;
689 $this->redirection_url = NULL;
690 $this->show_exam_id_in_test_pass_enabled = false;
691 $this->show_exam_id_in_test_results_enabled = false;
692 $this->sign_submission = false;
693 $this->char_selector_availability = 0;
694 $this->char_selector_definition = null;
695
696 $this->showGradingStatusEnabled = true;
697 $this->showGradingMarkEnabled = true;
698
699 $this->instantFeedbackAnswerFixationEnabled = false;
700
701 $this->testFinalBroken = false;
702
703 $this->tmpCopyWizardCopyId = null;
704
705 parent::__construct($a_id, $a_call_by_reference);
706 }
707
714 {
715 require_once 'Services/Utilities/classes/class.ilUtil.php';
716 return ilUtil::getASCIIFilename($this->getTitle());
717 }
718
722 public function getTmpCopyWizardCopyId()
723 {
725 }
726
731 {
732 $this->tmpCopyWizardCopyId = $tmpCopyWizardCopyId;
733 }
734
738 function create()
739 {
740 parent::create();
741
742 // meta data will be created by
743 // import parser
744 if (!$a_upload)
745 {
746 $this->createMetaData();
747 }
748 }
749
756 function update()
757 {
758 if (!parent::update())
759 {
760 return false;
761 }
762
763 // put here object specific stuff
764 $this->updateMetaData();
765 return true;
766 }
767
773 public function read()
774 {
775 parent::read();
776 $this->loadFromDb();
777 }
778
779
786 function delete()
787 {
788 // always call parent delete function first!!
789 if (!parent::delete())
790 {
791 return false;
792 }
793
794 // delet meta data
795 $this->deleteMetaData();
796
797 //put here your module specific stuff
798 $this->deleteTest();
799
800 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentImportFails.php';
801 $qsaImportFails = new ilAssQuestionSkillAssignmentImportFails($this->getId());
802 $qsaImportFails->deleteRegisteredImportFails();
803 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdImportFails.php';
804 $sltImportFails = new ilTestSkillLevelThresholdImportFails($this->getId());
805 $sltImportFails->deleteRegisteredImportFails();
806
807 return true;
808 }
809
815 function deleteTest()
816 {
817 global $tree, $ilDB, $ilPluginAdmin, $lng;
818
819 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
820 $participantData = new ilTestParticipantData($ilDB, $lng);
821 $participantData->load($this->getTestId());
822 $this->removeTestResults($participantData);
823
824 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_mark WHERE test_fi = %s",
825 array('integer'),
826 array($this->getTestId())
827 );
828
829 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_tests WHERE test_id = %s",
830 array('integer'),
831 array($this->getTestId())
832 );
833
834 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
835 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
836 $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
837
838 // delete export files
839 include_once "./Services/Utilities/classes/class.ilUtil.php";
840 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
841 $directory = $tst_data_dir."/tst_".$this->getId();
842 if (is_dir($directory))
843 {
844 include_once "./Services/Utilities/classes/class.ilUtil.php";
845 ilUtil::delDir($directory);
846 }
847 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
848 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
849 // remaining usages are not in text anymore -> delete them
850 // and media objects (note: delete method of ilObjMediaObject
851 // checks whether object is used in another context; if yes,
852 // the object is not deleted!)
853 foreach($mobs as $mob)
854 {
855 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
857 {
858 $mob_obj = new ilObjMediaObject($mob);
859 $mob_obj->delete();
860 }
861 }
862 }
863
870 {
871 include_once "./Services/Utilities/classes/class.ilUtil.php";
872 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
873 ilUtil::makeDir($tst_data_dir);
874 if (!is_writable($tst_data_dir))
875 {
876 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
877 .") not writeable.",$this->ilias->error_obj->MESSAGE);
878 }
879
880 // create learning module directory (data_dir/lm_data/lm_<id>)
881 $tst_dir = $tst_data_dir."/tst_".$this->getId();
882 ilUtil::makeDir($tst_dir);
883 if (!@is_dir($tst_dir))
884 {
885 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
886 }
887 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
888 $export_dir = $tst_dir."/export";
889 ilUtil::makeDir($export_dir);
890 if (!@is_dir($export_dir))
891 {
892 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
893 }
894 }
895
902 {
903 include_once "./Services/Utilities/classes/class.ilUtil.php";
904 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
905 return $export_dir;
906 }
907
914 function getExportFiles($dir)
915 {
916 // quit if import dir not available
917 if(!@is_dir($dir) || !is_writeable($dir))
918 {
919 return array();
920 }
921
922 $files = array();
923 foreach(new DirectoryIterator($dir) as $file)
924 {
928 if($file->isDir())
929 {
930 continue;
931 }
932
933 $files[] = $file->getBasename();
934 }
935
936 sort($files);
937
938 return $files;
939 }
940
944 public static function _setImportDirectory($a_import_dir = null)
945 {
946 if (strlen($a_import_dir))
947 {
948 $_SESSION["tst_import_dir"] = $a_import_dir;
949 }
950 else
951 {
952 unset($_SESSION["tst_import_dir"]);
953 }
954 }
955
962 public static function _getImportDirectory()
963 {
964 if (strlen($_SESSION["tst_import_dir"]))
965 {
966 return $_SESSION["tst_import_dir"];
967 }
968 return null;
969 }
970
972 {
974 }
975
981 public static function _createImportDirectory()
982 {
983 global $ilias;
984 include_once "./Services/Utilities/classes/class.ilUtil.php";
985 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
986 ilUtil::makeDir($tst_data_dir);
987
988 if (!is_writable($tst_data_dir))
989 {
990 $ilias->raiseError("Test Data Directory (".$tst_data_dir
991 .") not writeable.", $ilias->error_obj->FATAL);
992 }
993
994 // create test directory (data_dir/tst_data/tst_import)
995 $tst_dir = $tst_data_dir."/tst_import";
996 ilUtil::makeDir($tst_dir);
997 if (!@is_dir($tst_dir))
998 {
999 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
1000 }
1001
1002 // assert that this is empty and does not contain old data
1003 ilUtil::delDir($tst_dir, true);
1004
1005 return $tst_dir;
1006 }
1007
1015 {
1016 global $ilDB;
1017
1018 $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",
1019 array('integer'),
1020 array($this->getTestId())
1021 );
1022 $hasSC = false;
1023 while ($row = $ilDB->fetchAssoc($result))
1024 {
1025 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1026 {
1027 $hasSC = true;
1028 }
1029 }
1030 return $hasSC;
1031 }
1032
1040 {
1041 global $ilDB;
1042
1043 $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",
1044 array('integer'),
1045 array($this->getTestId())
1046 );
1047 if ($result->numRows() == 1)
1048 {
1049 $row = $ilDB->fetchAssoc($result);
1050 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1051 {
1052 return TRUE;
1053 }
1054 else
1055 {
1056 return false;
1057 }
1058 }
1059 return FALSE;
1060 }
1061
1069 {
1070 global $ilDB;
1071
1072 if (!$this->hasSingleChoiceQuestions()) return false;
1073
1074 $result = $ilDB->queryF("
1075 SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1076 FROM qpl_questions,
1077 qpl_qst_sc,
1078 tst_test_result,
1079 qpl_qst_type,
1080 tst_active
1081 WHERE tst_test_result.question_fi = qpl_questions.question_id
1082 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1083 AND tst_test_result.active_fi = tst_active.active_id
1084 AND qpl_questions.question_id = qpl_qst_sc.question_fi
1085 AND tst_active.test_fi = %s
1086 AND qpl_qst_type.type_tag = %s
1087 ",
1088 array('integer', 'text'),
1089 array($this->getTestId(), 'assSingleChoice')
1090 );
1091 if ($result->numRows() == 1)
1092 {
1093 $row = $ilDB->fetchAssoc($result);
1094 return ($row['foundshuffles'] == 0);
1095 }
1096 return FALSE;
1097 }
1098
1105 final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1106 {
1107 if( !count($this->mark_schema->mark_steps) )
1108 {
1109 return false;
1110 }
1111
1112 if( !$testQuestionSetConfig->isQuestionSetConfigured() )
1113 {
1114 return false;
1115 }
1116
1117 return true;
1118 }
1119
1126 function _isComplete($obj_id)
1127 {
1128 global $tree, $ilDB, $ilPluginAdmin;
1129
1130 $test = new ilObjTest($obj_id, false);
1131 $test->loadFromDb();
1132
1133 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1134 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1135
1136 return $test->isComplete( $testQuestionSetConfigFactory->getQuestionSetConfig() );
1137 }
1138
1142 public function saveECTSStatus()
1143 {
1147 global $ilDB;
1148
1149 if($this->getTestId() > 0)
1150 {
1151 $this->setECTSFX(preg_replace('/,/', '.', $this->getECTSFX()));
1152 if(!preg_match('/\d+/', $this->getECTSFX()))
1153 {
1154 $this->setECTSFX(NULL);
1155 }
1156
1157 $grades = $this->getECTSGrades();
1158 $ilDB->manipulateF(
1159 "UPDATE tst_tests
1160 SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s
1161 WHERE test_id = %s",
1162 array('text', 'float', 'float', 'float', 'float', 'float', 'float', 'integer'),
1163 array(
1164 (int)$this->getECTSOutput(),
1165 $grades['A'], $grades['B'], $grades['C'], $grades['D'], $grades['E'],
1166 $this->getECTSFX(),
1167 $this->getTestId()
1168 )
1169 );
1170 }
1171 }
1172
1177 public function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1178 {
1179 global $ilDB;
1180
1181 $complete = 0;
1182 if($this->isComplete($testQuestionSetConfig))
1183 {
1184 $complete = 1;
1185 }
1186 if($this->getTestId() > 0)
1187 {
1188 $ilDB->manipulateF(
1189 "UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1190 array('text', 'integer'),
1191 array($complete, $this->test_id)
1192 );
1193 }
1194 }
1195
1202 {
1203 $result = array();
1204 array_push($result, $this->getIntroduction());
1205 array_push($result, $this->getFinalStatement());
1206 return $result;
1207 }
1208
1215 {
1216 include_once("./Services/RTE/classes/class.ilRTE.php");
1217 $completecontent = "";
1218 foreach ($this->getAllRTEContent() as $content)
1219 {
1220 $completecontent .= $content;
1221 }
1222 ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
1223 $this->getId());
1224 }
1225
1231 public function saveToDb($properties_only = FALSE)
1232 {
1233 global $tree, $ilDB, $ilPluginAdmin;
1234
1235 // moved online_status to ilObjectActivation (see below)
1236
1237 // cleanup RTE images
1238 $this->cleanupMediaobjectUsage();
1239
1240 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1241 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1242 $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1243
1244 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1245 if ($this->test_id == -1)
1246 {
1247 // Create new dataset
1248 $next_id = $ilDB->nextId('tst_tests');
1249
1250 $ilDB->insert('tst_tests', array(
1251 'test_id' => array('integer', $next_id),
1252 'obj_fi' => array('integer', $this->getId()),
1253 'author' => array('text', $this->getAuthor()),
1254 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1255 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1256 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1257 'showinfo' => array('integer', $this->getShowInfo()),
1258 'forcejs' => array('integer', $this->getForceJS()),
1259 'customstyle' => array('text', $this->getCustomStyle()),
1260 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1261 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1262 'score_reporting' => array('integer', $this->getScoreReporting()),
1263 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1264 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1265 'answer_feedback' => array('text', $this->getAnswerFeedback()),
1266 'anonymity' => array('text', $this->getAnonymity()),
1267 'show_cancel' => array('text', $this->getShowCancel()),
1268 'show_marker' => array('integer', $this->getShowMarker()),
1269 'fixed_participants' => array('text', $this->getFixedParticipants()),
1270 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1271 'kiosk' => array('integer', $this->getKiosk()),
1272 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1273 'title_output' => array('text', $this->getTitleOutput()),
1274 'processing_time' => array('text', $this->getProcessingTime()),
1275 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1276 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1277 'reporting_date' => array('text', $this->getReportingDate()),
1278 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1279 'starting_time' => array('integer', $this->getStartingTime()),
1280 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1281 'ending_time' => array('integer', $this->getEndingTime()),
1282 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1283 'ects_output' => array('text', $this->getECTSOutput()),
1284 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1285 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1286 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1287 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1288 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1289 'ects_fx' => array('float', $this->getECTSFX()),
1290 'count_system' => array('text', $this->getCountSystem()),
1291 'mc_scoring' => array('text', $this->getMCScoring()),
1292 'score_cutting' => array('text', $this->getScoreCutting()),
1293 'pass_scoring' => array('text', $this->getPassScoring()),
1294 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1295 'results_presentation' => array('integer', $this->getResultsPresentation()),
1296 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1297 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1298 'password' => array('text', $this->getPassword()),
1299 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1300 'allowedusers' => array('integer', $this->getAllowedUsers()),
1301 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1302 'mailnottype' => array('integer', $this->getMailNotificationType()),
1303 'exportsettings' => array('integer', $this->getExportSettings()),
1304 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1305 'mailnotification' => array('integer', $this->getMailNotification()),
1306 'created' => array('integer', time()),
1307 'tstamp' => array('integer', time()),
1308 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1309 'template_id' => array('integer', $this->getTemplate()),
1310 'pool_usage' => array('integer', $this->getPoolUsage()),
1311 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1312 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1313 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1314 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1315 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1316 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1317 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1318 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1319 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1320 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1321 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1322 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1323 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1324 'online_status' => array('integer', (int)$this->isOnline()),
1325 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1326 'autosave' => array('integer', (int)$this->getAutosave()),
1327 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1328 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1329 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1330 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1331 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1332 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1333 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1334 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1335 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1336 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1337 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1338 'question_set_type' => array('text', $this->getQuestionSetType()),
1339 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1340 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1341 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1342 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1343 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1344 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1345 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1346 'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
1347 'broken' => array('integer', (int)$this->isTestFinalBroken()),
1348 'pass_waiting' => array('text', (string)$this->getPassWaiting())
1349 ));
1350
1351 $this->test_id = $next_id;
1352
1354 {
1355 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1356 }
1357 }
1358 else
1359 {
1360 // Modify existing dataset
1361 $oldrow = array();
1363 {
1364 $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1365 array('integer'),
1366 array($this->test_id)
1367 );
1368 if ($result->numRows() == 1)
1369 {
1370 $oldrow = $ilDB->fetchAssoc($result);
1371 }
1372 }
1373
1374 $ilDB->update('tst_tests',
1375 array(
1376 'author' => array('text', $this->getAuthor()),
1377 'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1378 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1379 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1380 'showinfo' => array('integer', $this->getShowInfo()),
1381 'forcejs' => array('integer', $this->getForceJS()),
1382 'customstyle' => array('text', $this->getCustomStyle()),
1383 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1384 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1385 'score_reporting' => array('integer', $this->getScoreReporting()),
1386 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1387 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1388 'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1389 'anonymity' => array('text', $this->getAnonymity()),
1390 'show_cancel' => array('text', $this->getShowCancel()),
1391 'show_marker' => array('integer', $this->getShowMarker()),
1392 'fixed_participants' => array('text', $this->getFixedParticipants()),
1393 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1394 'kiosk' => array('integer', $this->getKiosk()),
1395 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1396 'title_output' => array('text', $this->getTitleOutput()),
1397 'processing_time' => array('text', $this->getProcessingTime()),
1398 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1399 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1400 'reporting_date' => array('text', $this->getReportingDate()),
1401 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1402 'starting_time' => array('integer', $this->getStartingTime()),
1403 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1404 'ending_time' => array('integer', $this->getEndingTime()),
1405 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1406 'ects_output' => array('text', $this->getECTSOutput()),
1407 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1408 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1409 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1410 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1411 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1412 'ects_fx' => array('float', $this->getECTSFX()),
1413 'count_system' => array('text', $this->getCountSystem()),
1414 'mc_scoring' => array('text', $this->getMCScoring()),
1415 'score_cutting' => array('text', $this->getScoreCutting()),
1416 'pass_scoring' => array('text', $this->getPassScoring()),
1417 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1418 'results_presentation' => array('integer', $this->getResultsPresentation()),
1419 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1420 'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1421 'password' => array('text', $this->getPassword()),
1422 'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1423 'allowedusers' => array('integer', $this->getAllowedUsers()),
1424 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1425 'mailnottype' => array('integer', $this->getMailNotificationType()),
1426 'exportsettings' => array('integer', $this->getExportSettings()),
1427 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1428 'mailnotification' => array('integer', $this->getMailNotification()),
1429 'tstamp' => array('integer', time()),
1430 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1431 'template_id' => array('integer', $this->getTemplate()),
1432 'pool_usage' => array('integer', $this->getPoolUsage()),
1433 'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1434 'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1435 'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1436 'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1437 'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1438 'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1439 'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1440 'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1441 'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1442 'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1443 'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1444 'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1445 'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1446 'online_status' => array('integer', (int)$this->isOnline()),
1447 'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1448 'autosave' => array('integer', (int)$this->getAutosave()),
1449 'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1450 'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1451 'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1452 'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1453 'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1454 'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1455 'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1456 'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1457 'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1458 'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1459 'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1460 'question_set_type' => array('text', $this->getQuestionSetType()),
1461 'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1462 'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1463 'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1464 'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1465 'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1466 'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1467 'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1468 'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
1469 'broken' => array('integer', (int)$this->isTestFinalBroken()),
1470 'pass_waiting' => array('text', (string)$this->getPassWaiting())
1471 ),
1472 array(
1473 'test_id' => array('integer', (int)$this->getTestId())
1474 )
1475 );
1476
1477 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1479 {
1480 $logresult = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1481 array('integer'),
1482 array($this->getTestId())
1483 );
1484 $newrow = array();
1485 if ($logresult->numRows() == 1)
1486 {
1487 $newrow = $ilDB->fetchAssoc($logresult);
1488 }
1489 $changed_fields = array();
1490 foreach ($oldrow as $key => $value)
1491 {
1492 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
1493 {
1494 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
1495 }
1496 }
1497 $changes = join($changed_fields, ", ");
1498 if (count($changed_fields) > 0)
1499 {
1500 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
1501 }
1502 }
1503 if ($this->evalTotalPersons() > 0)
1504 {
1505 // reset the finished status of participants if the nr of test passes did change
1506 if ($this->getNrOfTries() > 0)
1507 {
1508 // set all unfinished tests with nr of passes >= allowed passes finished
1509 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = %s",
1510 array('integer', 'integer', 'integer'),
1511 array($this->getTestId(), $this->getNrOfTries(), 0)
1512 );
1513 while ($row = $ilDB->fetchAssoc($aresult))
1514 {
1515 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1516 array('integer', 'timestamp', 'integer'),
1517 array(1, date('Y-m-d H:i:s'), $row["active_id"])
1518 );
1519 }
1520
1521 // set all finished tests with nr of passes < allowed passes not finished
1522 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = %s",
1523 array('integer', 'integer', 'integer'),
1524 array($this->getTestId(), $this->getNrOfTries()-1, 1)
1525 );
1526 while ($row = $ilDB->fetchAssoc($aresult))
1527 {
1528 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1529 array('integer', 'timestamp', 'integer'),
1530 array(0, NULL, $row["active_id"])
1531 );
1532 }
1533 }
1534 else
1535 {
1536 // set all finished tests with nr of passes >= allowed passes not finished
1537 $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = %s",
1538 array('integer', 'integer'),
1539 array($this->getTestId(), 1)
1540 );
1541 while ($row = $ilDB->fetchAssoc($aresult))
1542 {
1543 $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1544 array('integer', 'timestamp', 'integer'),
1545 array(0, NULL, $row["active_id"])
1546 );
1547 }
1548 }
1549 }
1550 }
1551
1552 // news item creation/update/deletion
1553 include_once 'Services/News/classes/class.ilNewsItem.php';
1554 if( !$this->getOldOnlineStatus() && $this->isOnline() )
1555 {
1556 global $ilUser;
1557 $newsItem = new ilNewsItem();
1558 $newsItem->setContext($this->getId(), 'tst');
1559 $newsItem->setPriority(NEWS_NOTICE);
1560 $newsItem->setTitle('new_test_online');
1561 $newsItem->setContentIsLangVar(true);
1562 $newsItem->setContent('');
1563 $newsItem->setUserId($ilUser->getId());
1564 $newsItem->setVisibility(NEWS_USERS);
1565 $newsItem->create();
1566 }
1567 elseif( $this->getOldOnlineStatus() && !$this->isOnline() )
1568 {
1569 ilNewsItem::deleteNewsOfContext($this->getId(), 'tst');
1570 }
1571 elseif( $this->isOnline() )
1572 {
1573 $newsId = ilNewsItem::getFirstNewsIdForContext($this->getId(), 'tst');
1574 if($newsId > 0)
1575 {
1576 $newsItem = new ilNewsItem($newsId);
1577 $newsItem->setTitle('new_test_online');
1578 $newsItem->setContentIsLangVar(true);
1579 $newsItem->setContent('');
1580 $newsItem->update();
1581 }
1582 }
1583
1584 // moved activation to ilObjectActivation
1585 if($this->ref_id)
1586 {
1587 include_once "./Services/Object/classes/class.ilObjectActivation.php";
1588 ilObjectActivation::getItem($this->ref_id);
1589
1590 $item = new ilObjectActivation;
1591 if(!$this->isActivationLimited())
1592 {
1594 }
1595 else
1596 {
1597 $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1598 $item->setTimingStart($this->getActivationStartingTime());
1599 $item->setTimingEnd($this->getActivationEndingTime());
1600 $item->toggleVisible($this->getActivationVisibility());
1601 }
1602
1603 $item->update($this->ref_id);
1604 }
1605
1606 if (!$properties_only)
1607 {
1608 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
1609 {
1610 $this->saveQuestionsToDb();
1611 }
1612
1613 $this->mark_schema->saveToDb($this->test_id);
1614 }
1615 }
1616
1624 {
1625 global $ilDB;
1626
1627 $oldquestions = array();
1628 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1630 {
1631 $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1632 array('integer'),
1633 array($this->getTestId())
1634 );
1635 if ($result->numRows() > 0)
1636 {
1637 while ($row = $ilDB->fetchAssoc($result))
1638 {
1639 array_push($oldquestions, $row["question_fi"]);
1640 }
1641 }
1642 }
1643 // workaround for lost obligations
1644 // this method is called if a question is removed
1645 $currentQuestionsObligationsQuery = 'SELECT question_fi, obligatory FROM tst_test_question WHERE test_fi = %s';
1646 $rset = $ilDB->queryF($currentQuestionsObligationsQuery, array('integer'), array($this->getTestId()));
1647 while ($row = $ilDB->fetchAssoc($rset)) {
1648 $obligatoryQuestionState[$row['question_fi']] = $row['obligatory'];
1649 }
1650 // delete existing category relations
1651 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_question WHERE test_fi = %s",
1652 array('integer'),
1653 array($this->getTestId())
1654 );
1655 // create new category relations
1656 foreach ($this->questions as $key => $value)
1657 {
1658 // workaround for import witout obligations information
1659 if( !isset($obligatoryQuestionState[$value]) || is_null($obligatoryQuestionState[$value]) )
1660 {
1661 $obligatoryQuestionState[$value] = 0;
1662 }
1663
1664 // insert question
1665 $next_id = $ilDB->nextId('tst_test_question');
1666 $ilDB->insert('tst_test_question', array(
1667 'test_question_id' => array('integer', $next_id),
1668 'test_fi' => array('integer', $this->getTestId()),
1669 'question_fi' => array('integer', $value),
1670 'sequence' => array('integer', $key),
1671 'obligatory' => array('integer', $obligatoryQuestionState[$value]),
1672 'tstamp' => array('integer', time())
1673 ));
1674 }
1675 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1677 {
1678 $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1679 array('integer'),
1680 array($this->getTestId())
1681 );
1682 $newquestions = array();
1683 if ($result->numRows() > 0)
1684 {
1685 while ($row = $ilDB->fetchAssoc($result))
1686 {
1687 array_push($newquestions, $row["question_fi"]);
1688 }
1689 }
1690 foreach ($oldquestions as $index => $question_id)
1691 {
1692 if (strcmp($newquestions[$index], $question_id) != 0)
1693 {
1694 $pos = array_search($question_id, $newquestions);
1695 if ($pos === FALSE)
1696 {
1697 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
1698 }
1699 else
1700 {
1701 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
1702 }
1703 }
1704 }
1705 foreach ($newquestions as $index => $question_id)
1706 {
1707 if (array_search($question_id, $oldquestions) === FALSE)
1708 {
1709 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
1710 }
1711 }
1712 }
1713 }
1714
1720 protected function isNewRandomTest()
1721 {
1722 global $ilDB;
1723 $result = $ilDB->queryF('SELECT copy_id FROM tst_rnd_cpy WHERE tst_fi = %s',
1724 array('integer'),
1725 array($this->getTestId())
1726 );
1727 return $result->numRows() > 0;
1728 }
1729
1742 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
1743 {
1744 global $rbacsystem;
1745 global $ilDB;
1746
1747 // retrieve object id instead of ref id if necessary
1748 if (($questionpool != 0) && (!$use_obj_id)) $questionpool = ilObject::_lookupObjId($questionpool);
1749
1750 // get original ids of all existing questions in the test
1751 $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",
1752 array("integer"),
1753 array($this->getTestId())
1754 );
1755 $original_ids = array();
1756 $paramtypes = array();
1757 $paramvalues = array();
1758 while ($row = $ilDB->fetchAssoc($result))
1759 {
1760 array_push($original_ids, $row['original_id']);
1761 }
1762
1763 $available = "";
1764 // get a list of all available questionpools
1765 if (($questionpool == 0) && (!is_array($qpls)))
1766 {
1767 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1768 $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())));
1769 if (count($available_pools))
1770 {
1771 $available = " AND " . $ilDB->in('obj_fi', $available_pools, false, 'integer');
1772 }
1773 else
1774 {
1775 return array();
1776 }
1777 }
1778
1779 $constraint_qpls = "";
1780 $result_array = array();
1781 if ($questionpool == 0)
1782 {
1783 if (is_array($qpls))
1784 {
1785 if (count($qpls) > 0)
1786 {
1787 $constraint_qpls = " AND " . $ilDB->in('obj_fi', $qpls, false, 'integer');
1788 }
1789 }
1790 }
1791
1792 $original_clause = "";
1793 if (count($original_ids))
1794 {
1795 $original_clause = " AND " . $ilDB->in('question_id', $original_ids, true, 'integer');
1796 }
1797
1798 if ($questionpool == 0)
1799 {
1800 $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",
1801 array('integer', 'text'),
1802 array(0, "1")
1803 );
1804 }
1805 else
1806 {
1807 $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",
1808 array('integer','integer', 'text'),
1809 array($questionpool, 0, "1")
1810 );
1811 }
1812 $found_ids = array();
1813 while ($row = $ilDB->fetchAssoc($result))
1814 {
1815 array_push($found_ids, $row['question_id']);
1816 }
1817 $nr_of_questions = ($nr_of_questions > count($found_ids)) ? count($found_ids) : $nr_of_questions;
1818 if ($nr_of_questions == 0) return array();
1819 $rand_keys = array_rand($found_ids, $nr_of_questions);
1820 $result = array();
1821 if (is_array($rand_keys))
1822 {
1823 foreach ($rand_keys as $key)
1824 {
1825 $result[$found_ids[$key]] = $found_ids[$key];
1826 }
1827 }
1828 else
1829 {
1830 $result[$found_ids[$rand_keys]] = $found_ids[$rand_keys];
1831 }
1832 return $result;
1833 }
1834
1842 function getNrOfResultsForPass($active_id, $pass)
1843 {
1844 global $ilDB;
1845
1846 $result = $ilDB->queryF("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
1847 array('integer','integer'),
1848 array($active_id, $pass)
1849 );
1850 return $result->numRows();
1851 }
1852
1863 function hasRandomQuestionsForPass($active_id, $pass)
1864 {
1865 global $ilDB;
1866 $result = $ilDB->queryF("SELECT test_random_question_id FROM tst_test_rnd_qst WHERE active_fi = %s AND pass = %s",
1867 array('integer','integer'),
1868 array($active_id, $pass)
1869 );
1870 return ($result->numRows() > 0) ? true : false;
1871 }
1872
1876 public function loadFromDb()
1877 {
1878 global $ilDB;
1879
1880 $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE obj_fi = %s",
1881 array('integer'),
1882 array($this->getId())
1883 );
1884 if ($result->numRows() == 1)
1885 {
1886 $data = $ilDB->fetchObject($result);
1887 $this->setTestId($data->test_id);
1888 if (strlen($this->getAuthor()) == 0)
1889 {
1890 $this->saveAuthorToMetadata($data->author);
1891 }
1892 $this->setAuthor($data->author);
1893 include_once("./Services/RTE/classes/class.ilRTE.php");
1894 $this->setIntroductionEnabled($data->intro_enabled);
1896 $this->setShowInfo($data->showinfo);
1898 $this->setForceJS($data->forcejs);
1899 $this->setCustomStyle($data->customstyle);
1900 $this->setShowFinalStatement($data->showfinalstatement);
1901 $this->setSequenceSettings($data->sequence_settings);
1902 $this->setScoreReporting($data->score_reporting);
1903 $this->setInstantFeedbackSolution($data->instant_verification);
1904 $this->setAnswerFeedbackPoints($data->answer_feedback_points);
1905 $this->setAnswerFeedback($data->answer_feedback);
1906 $this->setAnonymity($data->anonymity);
1907 $this->setShowCancel($data->show_cancel);
1908 $this->setShowMarker($data->show_marker);
1909 $this->setFixedParticipants($data->fixed_participants);
1910 $this->setNrOfTries($data->nr_of_tries);
1911 $this->setKiosk($data->kiosk);
1912 $this->setUsePreviousAnswers($data->use_previous_answers);
1913 $this->setRedirectionMode($data->redirection_mode);
1914 $this->setRedirectionUrl($data->redirection_url);
1915 $this->setTitleOutput($data->title_output);
1916 $this->setProcessingTime($data->processing_time);
1917 $this->setEnableProcessingTime($data->enable_processing_time);
1918 $this->setResetProcessingTime($data->reset_processing_time);
1919 $this->setReportingDate($data->reporting_date);
1920 $this->setShuffleQuestions($data->shuffle_questions);
1921 $this->setResultsPresentation($data->results_presentation);
1922 $this->setStartingTimeEnabled($data->starting_time_enabled);
1923 $this->setStartingTime($data->starting_time);
1924 $this->setEndingTimeEnabled($data->ending_time_enabled);
1925 $this->setEndingTime($data->ending_time);
1926 $this->setListOfQuestionsSettings($data->show_summary);
1927 $this->setECTSOutput($data->ects_output);
1928 $this->setECTSGrades(
1929 array(
1930 "A" => $data->ects_a,
1931 "B" => $data->ects_b,
1932 "C" => $data->ects_c,
1933 "D" => $data->ects_d,
1934 "E" => $data->ects_e
1935 )
1936 );
1937 $this->setECTSFX($data->ects_fx);
1938 $this->mark_schema->flush();
1939 $this->mark_schema->loadFromDb($this->getTestId());
1940 $this->setCountSystem($data->count_system);
1941 $this->setMCScoring($data->mc_scoring);
1942 $this->setMailNotification($data->mailnotification);
1943 $this->setMailNotificationType($data->mailnottype);
1944 $this->setExportSettings($data->exportsettings);
1945 $this->setScoreCutting($data->score_cutting);
1946 $this->setPasswordEnabled($data->password_enabled);
1947 $this->setPassword($data->password);
1948 $this->setLimitUsersEnabled($data->limit_users_enabled);
1949 $this->setAllowedUsers($data->allowedusers);
1950 $this->setAllowedUsersTimeGap($data->alloweduserstimegap);
1951 $this->setPassScoring($data->pass_scoring);
1952 $this->setObligationsEnabled($data->obligations_enabled);
1953 $this->setOfferingQuestionHintsEnabled($data->offer_question_hints);
1954 $this->setCertificateVisibility($data->certificate_visibility);
1955 $this->setEnabledViewMode($data->enabled_view_mode);
1956 $this->setTemplate($data->template_id);
1957 $this->setPoolUsage($data->pool_usage);
1958 $this->setPrintBestSolutionWithResult((bool) $data->print_bs_with_res);
1959 $this->setHighscoreEnabled((bool) $data->highscore_enabled);
1960 $this->setHighscoreAnon((bool) $data->highscore_anon);
1961 $this->setHighscoreAchievedTS((bool) $data->highscore_achieved_ts);
1962 $this->setHighscoreScore((bool) $data->highscore_score);
1963 $this->setHighscorePercentage((bool) $data->highscore_percentage);
1964 $this->setHighscoreHints((bool) $data->highscore_hints);
1965 $this->setHighscoreWTime((bool) $data->highscore_wtime);
1966 $this->setHighscoreOwnTable((bool) $data->highscore_own_table);
1967 $this->setHighscoreTopTable((bool) $data->highscore_top_table);
1968 $this->setHighscoreTopNum((int) $data->highscore_top_num);
1969 $this->setOnline((bool) $data->online_status);
1970 $this->setOldOnlineStatus((bool) $data->online_status);
1971 $this->setSpecificAnswerFeedback((int) $data->specific_feedback);
1972 $this->setAutosave((bool)$data->autosave);
1973 $this->setAutosaveIval((int)$data->autosave_ival);
1974 $this->setPassDeletionAllowed($data->pass_deletion_allowed);
1975 $this->setEnableExamview((bool)$data->enable_examview);
1976 $this->setShowExamviewHtml((bool)$data->show_examview_html);
1977 $this->setShowExamviewPdf((bool)$data->show_examview_pdf);
1978 $this->setEnableArchiving((bool)$data->enable_archiving);
1979 $this->setShowExamIdInTestPassEnabled( (bool)$data->examid_in_test_pass);
1980 $this->setShowExamIdInTestResultsEnabled( (bool)$data->examid_in_test_res);
1981 $this->setSignSubmission( (bool)$data->sign_submission );
1982 $this->setQuestionSetType($data->question_set_type);
1983 $this->setCharSelectorAvailability((int)$data->char_selector_availability);
1984 $this->setCharSelectorDefinition($data->char_selector_definition);
1985 $this->setSkillServiceEnabled((bool)$data->skill_service);
1986 $this->setResultFilterTaxIds(strlen($data->result_tax_filters) ? unserialize($data->result_tax_filters) : array());
1987 $this->setShowGradingStatusEnabled((bool)$data->show_grading_status);
1988 $this->setShowGradingMarkEnabled((bool)$data->show_grading_mark);
1989 $this->setInstantFeedbackAnswerFixationEnabled((bool)$data->inst_fb_answer_fixation);
1990 $this->setForceInstantFeedbackEnabled((bool)$data->force_inst_fb);
1991 $this->setTestFinalBroken((bool)$data->broken);
1992 $this->setPassWaiting($data->pass_waiting);
1993 $this->loadQuestions();
1994 }
1995
1996 // moved activation to ilObjectActivation
1997 if($this->ref_id)
1998 {
1999 include_once "./Services/Object/classes/class.ilObjectActivation.php";
2000 $activation = ilObjectActivation::getItem($this->ref_id);
2001 switch($activation["timing_type"])
2002 {
2004 $this->setActivationLimited(true);
2005 $this->setActivationStartingTime($activation["timing_start"]);
2006 $this->setActivationEndingTime($activation["timing_end"]);
2007 $this->setActivationVisibility($activation["visible"]);
2008 break;
2009
2010 default:
2011 $this->setActivationLimited(false);
2012 break;
2013 }
2014 }
2015 }
2016
2023function loadQuestions($active_id = "", $pass = NULL)
2024{
2025 global $ilUser;
2026 global $ilDB;
2027
2028 $this->questions = array();
2029 if ($this->isRandomTest())
2030 {
2031 if (strcmp($active_id, "") == 0)
2032 {
2033 $active_id = $this->getActiveIdOfUser($ilUser->getId());
2034 }
2035 if (is_null($pass))
2036 {
2037 $pass = self::_getPass($active_id);
2038 }
2039 $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",
2040 array('integer', 'integer'),
2041 array($active_id, $pass)
2042 );
2043 // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
2044 // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
2045 // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
2046 // no questions are present for a newer pass.
2047 if ($result->numRows() == 0)
2048 {
2049 $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",
2050 array('integer'),
2051 array($active_id)
2052 );
2053 }
2054 }
2055 else
2056 {
2057 $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",
2058 array('integer'),
2059 array($this->test_id)
2060 );
2061 }
2062 $index = 1;
2063 while ($data = $ilDB->fetchAssoc($result))
2064 {
2065 $this->questions[$index++] = $data["question_fi"];
2066 }
2067}
2068
2072 public function isIntroductionEnabled()
2073 {
2075 }
2076
2081 {
2082 $this->introductionEnabled = $introductionEnabled;
2083 }
2084
2091 public function getIntroduction()
2092 {
2093 return (strlen($this->introduction)) ? $this->introduction : NULL;
2094 }
2095
2103 public function setIntroduction($introduction = "")
2104 {
2105 $this->introduction = $introduction;
2106 }
2107
2108
2116 public function setFinalStatement($a_statement = "")
2117 {
2118 $this->_finalstatement = $a_statement;
2119 }
2120
2128 public function setShowInfo($a_info = 1)
2129 {
2130 $this->_showinfo = ($a_info) ? 1 : 0;
2131 }
2132
2140 public function setForceJS($a_js = 1)
2141 {
2142 $this->_forcejs = ($a_js) ? 1 : 0;
2143 }
2144
2152 public function setCustomStyle($a_customStyle = NULL)
2153 {
2154 $this->_customStyle = $a_customStyle;
2155 }
2156
2164 public function getCustomStyle()
2165 {
2166 return (strlen($this->_customStyle)) ? $this->_customStyle : NULL;
2167 }
2168
2176 public function getCustomStyles()
2177 {
2178 $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2179 $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2180 $customstyles = array();
2181 if (is_dir($css_path))
2182 {
2183 $results = array();
2184 include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2186 if (is_array($results["file"]))
2187 {
2188 foreach ($results["file"] as $filename)
2189 {
2190 if (strpos($filename, ".css"))
2191 {
2192 array_push($customstyles, $filename);
2193 }
2194 }
2195 }
2196 }
2197 return $customstyles;
2198 }
2199
2207 public function getTestStyleLocation($mode = "output")
2208 {
2209 if (strlen($this->getCustomStyle()))
2210 {
2211 $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2212 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2213 if (file_exists($custom))
2214 {
2215 $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2216 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2217 return $custom;
2218 }
2219 else
2220 {
2221 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2222 }
2223 }
2224 else
2225 {
2226 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2227 }
2228 }
2229
2237 public function setShowFinalStatement($show = 0)
2238 {
2239 $this->_showfinalstatement = ($show) ? 1 : 0;
2240 }
2241
2248 public function getFinalStatement()
2249 {
2250 return (strlen($this->_finalstatement)) ? $this->_finalstatement : NULL;
2251 }
2252
2260 public function getShowInfo()
2261 {
2262 return ($this->_showinfo) ? 1 : 0;
2263 }
2264
2272 public function getForceJS()
2273 {
2274 return ($this->_forcejs) ? 1 : 0;
2275 }
2276
2284 public function getShowFinalStatement()
2285 {
2286 return ($this->_showfinalstatement) ? 1 : 0;
2287 }
2288
2296 function getTestId()
2297 {
2298 return $this->test_id;
2299 }
2300
2304 public function getECTSOutput()
2305 {
2306 return ($this->ects_output) ? 1 : 0;
2307 }
2308
2312 public function setECTSOutput($a_ects_output)
2313 {
2314 $this->ects_output = $a_ects_output ? 1 : 0;
2315 }
2316
2320 public function getECTSFX()
2321 {
2322 return (strlen($this->ects_fx)) ? $this->ects_fx : NULL;
2323 }
2324
2328 public function setECTSFX($a_ects_fx)
2329 {
2330 $this->ects_fx = $a_ects_fx;
2331 }
2332
2336 public function getECTSGrades()
2337 {
2338 return $this->ects_grades;
2339 }
2340
2344 public function setECTSGrades(array $a_ects_grades)
2345 {
2346 $this->ects_grades = $a_ects_grades;
2347 }
2348
2354 public function getSequenceSettings()
2355 {
2356 return ($this->sequence_settings) ? $this->sequence_settings : 0;
2357 }
2358
2365 {
2366 $this->sequence_settings = $sequence_settings;
2367 }
2368
2372 public function isPostponingEnabled()
2373 {
2374 return (bool)$this->getSequenceSettings();
2375 }
2376
2380 public function setPostponingEnabled($postponingEnabled)
2381 {
2382 $this->setSequenceSettings((int)$postponingEnabled);
2383 }
2384
2393 {
2394 $this->score_reporting = $score_reporting;
2395 }
2396
2404 function setInstantFeedbackSolution($instant_feedback = 0)
2405 {
2406 switch ($instant_feedback)
2407 {
2408 case 1:
2409 $this->instant_verification = 1;
2410 break;
2411 default:
2412 $this->instant_verification = 0;
2413 break;
2414 }
2415 }
2416
2425{
2426 switch ($answer_feedback)
2427 {
2428 case 1:
2429 $this->answer_feedback = 1;
2430 break;
2431 default:
2432 $this->answer_feedback = 0;
2433 break;
2434 }
2435}
2436
2442function setGenericAnswerFeedback($generic_answer_feedback = 0)
2443{
2444 switch ($generic_answer_feedback)
2445 {
2446 case 1:
2447 $this->answer_feedback = 1;
2448 break;
2449 default:
2450 $this->answer_feedback = 0;
2451 break;
2452 }
2453}
2454
2463 {
2465 {
2466 case 1:
2467 $this->answer_feedback_points = 1;
2468 break;
2469 default:
2470 $this->answer_feedback_points = 0;
2471 break;
2472 }
2473 }
2474
2480 {
2481 if(!$reporting_date)
2482 {
2483 $this->reporting_date = '';
2484 $this->setECTSOutput(false);
2485 }
2486 else
2487 {
2488 $this->reporting_date = $reporting_date;
2489 }
2490 }
2491
2496
2505 {
2506 return ($this->score_reporting) ? $this->score_reporting : 0;
2507 }
2508
2509 public function isScoreReportingEnabled()
2510 {
2511 return $this->getScoreReporting() > 0 && $this->getScoreReporting() < 4;
2512 }
2513
2522 {
2523 return ($this->instant_verification) ? $this->instant_verification : 0;
2524 }
2525
2534 public function getAnswerFeedback()
2535 {
2536 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2537 }
2538
2546 {
2547 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2548 }
2549
2558{
2559 return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2560}
2561
2570 {
2571 return ($this->count_system) ? $this->count_system : 0;
2572 }
2573
2581 public static function _getCountSystem($active_id)
2582 {
2583 global $ilDB;
2584 $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",
2585 array('integer'),
2586 array($active_id)
2587 );
2588 if ($result->numRows())
2589 {
2590 $row = $ilDB->fetchAssoc($result);
2591 return $row["count_system"];
2592 }
2593 return FALSE;
2594 }
2595
2603 function getMCScoring()
2604 {
2605 return ($this->mc_scoring) ? $this->mc_scoring : 0;
2606 }
2607
2616 {
2617 return ($this->score_cutting) ? $this->score_cutting : 0;
2618 }
2619
2628 {
2629 return ($this->pass_scoring) ? $this->pass_scoring : 0;
2630 }
2631
2639 public static function _getPassScoring($active_id)
2640 {
2641 global $ilDB;
2642 $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",
2643 array('integer'),
2644 array($active_id)
2645 );
2646 if ($result->numRows())
2647 {
2648 $row = $ilDB->fetchAssoc($result);
2649 return $row["pass_scoring"];
2650 }
2651 return 0;
2652 }
2653
2661 public static function _getMCScoring($active_id)
2662 {
2663 global $ilDB;
2664 $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",
2665 array('integer'),
2666 array($active_id)
2667 );
2668 if ($result->numRows())
2669 {
2670 $row = $ilDB->fetchAssoc($result);
2671 return $row["mc_scoring"];
2672 }
2673 return FALSE;
2674 }
2675
2683 public static function _getScoreCutting($active_id)
2684 {
2685 global $ilDB;
2686 $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",
2687 array('integer'),
2688 array($active_id)
2689 );
2690 if ($result->numRows())
2691 {
2692 $row = $ilDB->fetchAssoc($result);
2693 return $row["score_cutting"];
2694 }
2695 return FALSE;
2696 }
2697
2706 {
2707 return (strlen($this->reporting_date)) ? $this->reporting_date : NULL;
2708 }
2709
2717 function getNrOfTries()
2718 {
2719 return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2720 }
2721
2729 function getKiosk()
2730 {
2731 return ($this->_kiosk) ? $this->_kiosk : 0;
2732 }
2733
2734
2742 function setKiosk($kiosk = 0)
2743 {
2744 $this->_kiosk = $kiosk;
2745 }
2746
2754 function getKioskMode()
2755 {
2756 if (($this->_kiosk & 1) > 0)
2757 {
2758 return TRUE;
2759 }
2760 else
2761 {
2762 return FALSE;
2763 }
2764 }
2765
2773 public function setKioskMode($a_kiosk = FALSE)
2774 {
2775 if ($a_kiosk)
2776 {
2777 $this->_kiosk = $this->_kiosk | 1;
2778 }
2779 else
2780 {
2781 if ($this->getKioskMode())
2782 {
2783 $this->_kiosk = $this->_kiosk ^ 1;
2784 }
2785 }
2786 }
2787
2795 public function getShowKioskModeTitle()
2796 {
2797 if (($this->_kiosk & 2) > 0)
2798 {
2799 return TRUE;
2800 }
2801 else
2802 {
2803 return FALSE;
2804 }
2805 }
2806
2813 public function setShowKioskModeTitle($a_title = FALSE)
2814 {
2815 if ($a_title)
2816 {
2817 $this->_kiosk = $this->_kiosk | 2;
2818 }
2819 else
2820 {
2821 if ($this->getShowKioskModeTitle())
2822 {
2823 $this->_kiosk = $this->_kiosk ^ 2;
2824 }
2825 }
2826 }
2827
2836 {
2837 if (($this->_kiosk & 4) > 0)
2838 {
2839 return TRUE;
2840 }
2841 else
2842 {
2843 return FALSE;
2844 }
2845 }
2846
2853 public function setShowKioskModeParticipant($a_participant = FALSE)
2854 {
2855 if ($a_participant)
2856 {
2857 $this->_kiosk = $this->_kiosk | 4;
2858 }
2859 else
2860 {
2861 if ($this->getShowKioskModeParticipant())
2862 {
2863 $this->_kiosk = $this->_kiosk ^ 4;
2864 }
2865 }
2866 }
2867
2876 {
2877 return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2878 }
2879
2888 {
2889 return ($this->title_output) ? $this->title_output : 0;
2890 }
2891
2900 function _getTitleOutput($active_id)
2901 {
2902 global $ilDB;
2903
2904 $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",
2905 array('integer'),
2906 array($active_id)
2907 );
2908 if ($result->numRows())
2909 {
2910 $row = $ilDB->fetchAssoc($result);
2911 return $row["title_output"];
2912 }
2913 return 0;
2914 }
2915
2916 // hey: prevPassSolutions - serious (nonstatic) identifier, for use in high level controller gui
2917 public function isPreviousSolutionReuseEnabled($activeId)
2918 {
2919 // checks if allowed in general and if enabled by participant
2920 return self::_getUsePreviousAnswers($activeId, true);
2921 }
2922 // hey.
2923
2933 public static function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2934 {
2935 global $ilDB;
2936 global $ilUser;
2937
2939
2940 $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",
2941 array("integer"),
2942 array($active_id)
2943 );
2944 if ($result->numRows())
2945 {
2946 $row = $ilDB->fetchAssoc($result);
2947 $use_previous_answers = $row["use_previous_answers"];
2948 }
2949
2950 if ($use_previous_answers == 1)
2951 {
2952 if ($user_active_user_setting)
2953 {
2954 $res = $ilUser->getPref("tst_use_previous_answers");
2955 if ($res !== FALSE)
2956 {
2958 }
2959 }
2960 }
2961 return $use_previous_answers;
2962 }
2963
2972 {
2973 return (strlen($this->processing_time)) ? $this->processing_time : NULL;
2974 }
2975
2983 {
2984 if (strlen($this->processing_time))
2985 {
2986 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
2987 {
2988 if ((int)$matches[1]+(int)$matches[2]+(int)$matches[3] == 0)
2989 {
2990 return $this->getEstimatedWorkingTime();
2991 }
2992 else
2993 {
2994 return array(
2995 'hh' => $matches[1],
2996 'mm' => $matches[2],
2997 'ss' => $matches[3],
2998 );
2999 }
3000 }
3001 }
3002 return $this->getEstimatedWorkingTime();
3003 }
3004
3006 {
3007 if (strlen($this->processing_time))
3008 {
3009 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
3010 {
3011 return ($matches[1] * 60) + $matches[2];
3012 }
3013 }
3014
3016 }
3017
3025 function getProcessingTimeInSeconds($active_id = "")
3026 {
3027 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
3028 {
3029 $extratime = $this->getExtraTime($active_id) * 60;
3030 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
3031 }
3032 else
3033 {
3034 return 0;
3035 }
3036 }
3037
3046 {
3047 if ($this->getEndingTime() != 0)
3048 {
3049 $ending = $this->getEndingTime();
3050 $now = time();
3051 return $ending - $now;
3052 }
3053 else
3054 {
3055 return 0;
3056 }
3057 }
3058
3067 {
3068 return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
3069 }
3070
3079 {
3080 return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
3081 }
3082
3086 public function isStartingTimeEnabled()
3087 {
3089 }
3090
3095 {
3096 $this->starting_time_enabled = $starting_time_enabled;
3097 }
3098
3106 public function getStartingTime()
3107 {
3108 return ($this->starting_time != 0) ? $this->starting_time : 0;
3109 }
3110
3118 public function setStartingTime($starting_time = NULL)
3119 {
3120 $this->starting_time = $starting_time;
3121 }
3122
3126 public function isEndingTimeEnabled()
3127 {
3129 }
3130
3135 {
3136 $this->ending_time_enabled = $ending_time_enabled;
3137 }
3138
3146 public function getEndingTime()
3147 {
3148 return ($this->ending_time != 0) ? $this->ending_time : 0;
3149 }
3150
3158 public function setEndingTime($ending_time = NULL)
3159 {
3160 $this->ending_time = $ending_time;
3161 }
3162
3171 {
3172 $this->nr_of_tries = $nr_of_tries;
3173 }
3174
3183 {
3185 {
3186 $this->use_previous_answers = 1;
3187 }
3188 else
3189 {
3190 $this->use_previous_answers = 0;
3191 }
3192 }
3193
3195 {
3196 $this->redirection_mode = $redirection_mode;
3197 }
3199 {
3201 }
3203 {
3204 $this->redirection_url = $redirection_url;
3205 }
3207 {
3209 }
3210
3219 {
3220 switch ($title_output)
3221 {
3222 case 1:
3223 $this->title_output = 1;
3224 break;
3225 case 2:
3226 $this->title_output = 2;
3227 break;
3228 default:
3229 $this->title_output = 0;
3230 break;
3231 }
3232 }
3233
3242 {
3243 $this->processing_time = $processing_time;
3244 }
3245
3246 public function setProcessingTimeByMinutes($minutes)
3247 {
3248 $this->processing_time = sprintf("%02d:%02d:00", floor($minutes/60), $minutes%60);
3249 }
3250
3258 function setEnableProcessingTime($enable = 0)
3259 {
3260 if ($enable) {
3261 $this->enable_processing_time = "1";
3262 } else {
3263 $this->enable_processing_time = "0";
3264 }
3265 }
3266
3274 function setResetProcessingTime($reset = 0)
3275 {
3276 if ($reset)
3277 {
3278 $this->reset_processing_time = 1;
3279 }
3280 else
3281 {
3282 $this->reset_processing_time = 0;
3283 }
3284 }
3285
3293 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3294 {
3295 $this->count_system = $a_count_system;
3296 }
3297
3301 public function isPasswordEnabled()
3302 {
3304 }
3305
3310 {
3311 $this->passwordEnabled = $passwordEnabled;
3312 }
3313
3321 public function getPassword()
3322 {
3323 return (strlen($this->password)) ? $this->password : NULL;
3324 }
3325
3333 public function setPassword($a_password = NULL)
3334 {
3335 $this->password = $a_password;
3336 }
3337
3345 function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3346 {
3347 $this->score_cutting = $a_score_cutting;
3348 }
3349
3358 {
3359 $this->mc_scoring = $a_mc_scoring;
3360 }
3361
3369 function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3370 {
3371 switch ($a_pass_scoring)
3372 {
3373 case SCORE_BEST_PASS:
3374 $this->pass_scoring = SCORE_BEST_PASS;
3375 break;
3376 default:
3377 $this->pass_scoring = SCORE_LAST_PASS;
3378 break;
3379 }
3380 }
3381
3385 public function getPassWaiting()
3386 {
3387 return $this->pass_waiting;
3388 }
3389
3394 {
3395 $this->pass_waiting = $pass_waiting;
3396 }
3400 public function isPassWaitingEnabled()
3401 {
3402 if(array_sum(explode(':', $this->getPassWaiting())) > 0)
3403 {
3404 return true;
3405 }
3406 return false;
3407 }
3408
3412 public function removeQuestions($removeQuestionIds)
3413 {
3414 foreach ($removeQuestionIds as $value) {
3415 $this->removeQuestion($value);
3416 }
3417
3419 }
3420
3428 function removeQuestion($question_id)
3429 {
3430 $question =& ilObjTest::_instanciateQuestion($question_id);
3431 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3433 {
3434 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3435 }
3436 $question->delete($question_id);
3437 }
3438
3448 {
3449 $this->removeTestResultsByUserIds($userIds);
3450
3451 $ilDB = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
3452 $lng = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['lng'] : $GLOBALS['lng'];
3453
3454 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3455 $participantData = new ilTestParticipantData($ilDB, $lng);
3456 $participantData->setUserIds($userIds);
3457 $participantData->load($this->getTestId());
3458
3459 $this->removeTestActives($participantData->getActiveIds());
3460 }
3461
3462 public function removeTestResults(ilTestParticipantData $participantData)
3463 {
3464 if( count($participantData->getAnonymousActiveIds()) )
3465 {
3466 $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3467 }
3468
3469 if( count($participantData->getUserIds()) )
3470 {
3471 /* @var ilTestLP $testLP */
3472 require_once 'Services/Object/classes/class.ilObjectLP.php';
3473 $testLP = ilObjectLP::getInstance($this->getId());
3474 $testLP->setTestObject($this);
3475 $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3476 }
3477
3478 if( count($participantData->getActiveIds()) )
3479 {
3480 $this->removeTestActives($participantData->getActiveIds());
3481 }
3482 }
3483
3484 public function removeTestResultsByUserIds($userIds)
3485 {
3486 global $ilDB, $lng;
3487
3488 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3489 $participantData = new ilTestParticipantData($ilDB, $lng);
3490 $participantData->setUserIds($userIds);
3491 $participantData->load($this->getTestId());
3492
3493 $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3494 $ilDB->manipulateF("DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3495 array('text'), array("tst_password_".$this->getTestId())
3496 );
3497
3498 if( count($participantData->getActiveIds()) )
3499 {
3500 $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3501 }
3502 }
3503
3504 public function removeTestResultsByActiveIds($activeIds)
3505 {
3506 global $ilDB;
3507
3508 $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3509
3510 $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3511 $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3512 $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3513 $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3514 $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3515 $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3516 $ilDB->manipulate("DELETE FROM tst_times WHERE $IN_activeIds");
3517
3518 if( $this->isRandomTest() )
3519 {
3520 $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3521 }
3522 elseif( $this->isDynamicTest() )
3523 {
3524 $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3525 $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3526 $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3527 $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3528 }
3529
3530 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3531
3532 foreach ($activeIds as $active_id)
3533 {
3534 // remove file uploads
3535 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3536 {
3537 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3538 }
3539
3541 {
3542 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3543 }
3544 }
3545
3546 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3548 }
3549
3550 public function removeTestActives($activeIds)
3551 {
3552 global $ilDB;
3553
3554 $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3555 $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3556 }
3557
3565 function questionMoveUp($question_id)
3566 {
3567 global $ilDB;
3568
3569 // Move a question up in sequence
3570 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3571 array('integer', 'integer'),
3572 array($this->getTestId(), $question_id)
3573 );
3574 $data = $ilDB->fetchObject($result);
3575 if ($data->sequence > 1)
3576 {
3577 // OK, it's not the top question, so move it up
3578 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3579 array('integer','integer'),
3580 array($this->getTestId(), $data->sequence - 1)
3581 );
3582 $data_previous = $ilDB->fetchObject($result);
3583 // change previous dataset
3584 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3585 array('integer','integer'),
3586 array($data->sequence, $data_previous->test_question_id)
3587 );
3588 // move actual dataset up
3589 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3590 array('integer','integer'),
3591 array($data->sequence - 1, $data->test_question_id)
3592 );
3593 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3595 {
3596 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3597 }
3598 }
3599 $this->loadQuestions();
3600 }
3601
3609 function questionMoveDown($question_id)
3610 {
3611 global $ilDB;
3612
3613 // Move a question down in sequence
3614 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3615 array('integer','integer'),
3616 array($this->getTestId(), $question_id)
3617 );
3618 $data = $ilDB->fetchObject($result);
3619 $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3620 array('integer','integer'),
3621 array($this->getTestId(), $data->sequence + 1)
3622 );
3623 if ($result->numRows() == 1)
3624 {
3625 // OK, it's not the last question, so move it down
3626 $data_next = $ilDB->fetchObject($result);
3627 // change next dataset
3628 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3629 array('integer','integer'),
3630 array($data->sequence, $data_next->test_question_id)
3631 );
3632 // move actual dataset down
3633 $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3634 array('integer','integer'),
3635 array($data->sequence + 1, $data->test_question_id)
3636 );
3637 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3639 {
3640 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3641 }
3642 }
3643 $this->loadQuestions();
3644 }
3645
3653 function duplicateQuestionForTest($question_id)
3654 {
3655 global $ilUser;
3656 $question =& ilObjTest::_instanciateQuestion($question_id);
3657 $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3658
3659 return $duplicate_id;
3660 }
3661
3670 public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3671 {
3672 global $ilDB;
3673#var_dump($question_id);
3674 if ($linkOnly)
3675 {
3676 $duplicate_id = $question_id;
3677 }
3678 else
3679 {
3680 $duplicate_id = $this->duplicateQuestionForTest($question_id);
3681 }
3682
3683 // get maximum sequence index in test
3684 $result = $ilDB->queryF("SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3685 array('integer'),
3686 array($this->getTestId())
3687 );
3688 $sequence = 1;
3689
3690 if ($result->numRows() == 1)
3691 {
3692 $data = $ilDB->fetchObject($result);
3693 $sequence = $data->seq + 1;
3694 }
3695
3696 $next_id = $ilDB->nextId('tst_test_question');
3697 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3698 array('integer', 'integer','integer','integer','integer'),
3699 array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3700 );
3701 if ($affectedRows == 1)
3702 {
3703 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3705 {
3706 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3707 }
3708 }
3709 // remove test_active entries, because test has changed
3710 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3711 array('integer'),
3712 array($this->getTestId())
3713 );
3714 $this->loadQuestions();
3715 $this->saveCompleteStatus($testQuestionSetConfig);
3716 return $duplicate_id;
3717 }
3718
3727 {
3728 $titles = array();
3729 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3730 {
3731 global $ilDB;
3732 $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",
3733 array('integer'),
3734 array($this->getTestId())
3735 );
3736 while ($row = $ilDB->fetchAssoc($result))
3737 {
3738 array_push($titles, $row["title"]);
3739 }
3740 }
3741 return $titles;
3742 }
3743
3752 {
3753 $titles = array();
3754 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3755 {
3756 global $ilDB;
3757 $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",
3758 array('integer'),
3759 array($this->getTestId())
3760 );
3761 while ($row = $ilDB->fetchAssoc($result))
3762 {
3763 $titles[$row['question_id']] = $row["title"];
3764 }
3765 }
3766 return $titles;
3767 }
3768
3769// fau: testNav - add number parameter (to show if title should not be shown)
3779 function getQuestionTitle($title, $nr = null)
3780 {
3781 if ($this->getTitleOutput() == 2)
3782 {
3783 if( $this->getQuestionSetType() == self::QUESTION_SET_TYPE_DYNAMIC )
3784 {
3785 // avoid legacy setting combination: ctm without question titles
3786 return $title;
3787 }
3788 else
3789 if (isset($nr))
3790 {
3791 return $this->lng->txt("ass_question"). ' ' . $nr;
3792 }
3793 else
3794 {
3795 return $this->lng->txt("ass_question");
3796 }
3797
3798 }
3799 else
3800 {
3801 return $title;
3802 }
3803 }
3804// fau.
3805
3814 function getQuestionDataset($question_id)
3815 {
3816 global $ilDB;
3817
3818 $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",
3819 array('integer'),
3820 array($question_id)
3821 );
3822 $row = $ilDB->fetchObject($result);
3823 return $row;
3824 }
3825
3832 function &getExistingQuestions($pass = NULL)
3833 {
3834 global $ilUser;
3835 global $ilDB;
3836
3837 $existing_questions = array();
3838 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3839 if ($this->isRandomTest())
3840 {
3841 if (is_null($pass)) $pass = 0;
3842 $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",
3843 array('integer','integer'),
3844 array($active_id, $pass)
3845 );
3846 }
3847 else
3848 {
3849 $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",
3850 array('integer'),
3851 array($this->getTestId())
3852 );
3853 }
3854 while ($data = $ilDB->fetchObject($result))
3855 {
3856 if( $data->original_id === null )
3857 {
3858 continue;
3859 }
3860
3861 array_push($existing_questions, $data->original_id);
3862 }
3863 return $existing_questions;
3864 }
3865
3873 function getQuestionType($question_id)
3874 {
3875 global $ilDB;
3876
3877 if ($question_id < 1) return -1;
3878 $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",
3879 array('integer'),
3880 array($question_id)
3881 );
3882 if ($result->numRows() == 1)
3883 {
3884 $data = $ilDB->fetchObject($result);
3885 return $data->type_tag;
3886 }
3887 else
3888 {
3889 return "";
3890 }
3891 }
3892
3899 function startWorkingTime($active_id, $pass)
3900 {
3901 global $ilDB;
3902
3903 $next_id = $ilDB->nextId('tst_times');
3904 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
3905 array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
3906 array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
3907 );
3908 return $next_id;
3909 }
3910
3917 function updateWorkingTime($times_id)
3918 {
3919 global $ilDB;
3920
3921 $affectedRows = $ilDB->manipulateF("UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
3922 array('timestamp', 'integer', 'integer'),
3923 array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
3924 );
3925 }
3926
3933 function &getWorkedQuestions($active_id, $pass = NULL)
3934 {
3935 global $ilUser;
3936 global $ilDB;
3937
3938 if (is_null($pass))
3939 {
3940 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3941 array('integer','integer'),
3942 array($active_id, 0)
3943 );
3944 }
3945 else
3946 {
3947 $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3948 array('integer','integer'),
3949 array($active_id, $pass)
3950 );
3951 }
3952 $result_array = array();
3953 while ($row = $ilDB->fetchAssoc($result))
3954 {
3955 array_push($result_array, $row["question_fi"]);
3956 }
3957 return $result_array;
3958 }
3959
3968 function isTestFinishedToViewResults($active_id, $currentpass)
3969 {
3970 $num = $this->getPassFinishDate($active_id, $currentpass);
3971 return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
3972 }
3973
3980 function &getAllQuestions($pass = NULL)
3981 {
3982 global $ilUser;
3983 global $ilDB;
3984
3985 $result_array = array();
3986 if ($this->isRandomTest())
3987 {
3988 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3989 $this->loadQuestions($active_id, $pass);
3990 if (count($this->questions) == 0) return $result_array;
3991 if (is_null($pass))
3992 {
3993 $pass = self::_getPass($active_id);
3994 }
3995 $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'),
3996 array('integer','integer'),
3997 array($active_id, $pass)
3998 );
3999 }
4000 else
4001 {
4002 if (count($this->questions) == 0) return $result_array;
4003 $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'));
4004 }
4005 while ($row = $ilDB->fetchAssoc($result))
4006 {
4007 $result_array[$row["question_id"]] = $row;
4008 }
4009 return $result_array;
4010 }
4011
4020 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
4021 {
4022 global $ilDB;
4023 global $ilUser;
4024
4025 if (!$user_id) $user_id = $ilUser->getId();
4026 if (($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
4027 {
4028 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4029 array('integer','integer','text'),
4030 array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
4031 );
4032 }
4033 else if (strlen($anonymous_id))
4034 {
4035 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4036 array('integer','integer','text'),
4037 array($user_id, $this->test_id, $anonymous_id)
4038 );
4039 }
4040 else
4041 {
4042 if ($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID)
4043 {
4044 return NULL;
4045 }
4046 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4047 array('integer','integer'),
4048 array($user_id, $this->test_id)
4049 );
4050 }
4051 if ($result->numRows())
4052 {
4053 $row = $ilDB->fetchAssoc($result);
4054 return $row["active_id"];
4055 }
4056 else
4057 {
4058 return 0;
4059 }
4060 }
4061
4070 public static function _getActiveIdOfUser($user_id = "", $test_id = "")
4071 {
4072 global $ilDB;
4073 global $ilUser;
4074
4075 if (!$user_id) {
4076 $user_id = $ilUser->id;
4077 }
4078 if (!$test_id)
4079 {
4080 return "";
4081 }
4082 $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4083 array('integer', 'integer'),
4084 array($user_id, $test_id)
4085 );
4086 if ($result->numRows())
4087 {
4088 $row = $ilDB->fetchAssoc($result);
4089 return $row["active_id"];
4090 }
4091 else
4092 {
4093 return "";
4094 }
4095 }
4096
4103 function pcArrayShuffle($array)
4104 {
4105 $keys = array_keys($array);
4106 shuffle($keys);
4107 $result = array();
4108 foreach ($keys as $key)
4109 {
4110 $result[$key] = $array[$key];
4111 }
4112 return $result;
4113 }
4114
4122 function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE, $considerHiddenQuestions = true, $considerOptionalQuestions = true)
4123 {
4124 global $tree, $ilDB, $lng, $ilPluginAdmin;
4125
4126 $results = $this->getResultsForActiveId($active_id);
4127
4128 if( is_null($pass) )
4129 {
4130 $pass = $results['pass'];
4131 }
4132
4133 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
4134 $testSessionFactory = new ilTestSessionFactory($this);
4135 $testSession = $testSessionFactory->getSession($active_id);
4136
4137 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4138 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
4139 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
4140
4141 if( $this->isDynamicTest() )
4142 {
4143 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4144 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
4145 $dynamicQuestionSetConfig->loadFromDb();
4146
4147 $testSequence->loadFromDb($dynamicQuestionSetConfig);
4148 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4149
4150 $sequence = $testSequence->getUserSequenceQuestions();
4151 }
4152 else
4153 {
4154 $testSequence->setConsiderHiddenQuestionsEnabled($considerHiddenQuestions);
4155 $testSequence->setConsiderOptionalQuestionsEnabled($considerOptionalQuestions);
4156
4157 $testSequence->loadFromDb();
4158 $testSequence->loadQuestions();
4159
4160 if( $ordered_sequence )
4161 {
4162 $sequence = $testSequence->getOrderedSequenceQuestions();
4163 }
4164 else
4165 {
4166 $sequence = $testSequence->getUserSequenceQuestions();
4167 }
4168 }
4169
4170 $arrResults = array();
4171
4172 $query = "
4173 SELECT tst_test_result.question_fi,
4174 tst_test_result.points reached,
4175 tst_test_result.hint_count requested_hints,
4176 tst_test_result.hint_points hint_points,
4177 tst_test_result.answered answered
4178
4179 FROM tst_test_result
4180
4181 LEFT JOIN tst_solutions
4182 ON tst_solutions.active_fi = tst_test_result.active_fi
4183 AND tst_solutions.question_fi = tst_test_result.question_fi
4184
4185 WHERE tst_test_result.active_fi = %s
4186 AND tst_test_result.pass = %s
4187 ";
4188
4189 $solutionresult = $ilDB->queryF(
4190 $query, array('integer', 'integer'), array($active_id, $pass)
4191 );
4192
4193 while( $row = $ilDB->fetchAssoc($solutionresult) )
4194 {
4195 $arrResults[ $row['question_fi'] ] = $row;
4196 }
4197
4198 $numWorkedThrough = count($arrResults);
4199
4200 require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4201
4202 $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4203
4204 $query = "
4205 SELECT qpl_questions.*,
4206 qpl_qst_type.type_tag,
4207 qpl_sol_sug.question_fi has_sug_sol
4208
4209 FROM qpl_qst_type,
4210 qpl_questions
4211
4212 LEFT JOIN qpl_sol_sug
4213 ON qpl_sol_sug.question_fi = qpl_questions.question_id
4214
4215 WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4216 AND $IN_question_ids
4217 ";
4218
4219 $result = $ilDB->query($query);
4220
4221 $unordered = array();
4222
4223 $key = 1;
4224
4225 $obligationsAnswered = true;
4226
4227 while( $row = $ilDB->fetchAssoc($result) )
4228 {
4229 $percentvalue = (
4230 $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4231 );
4232
4233 if( $percentvalue < 0 ) $percentvalue = 0.0;
4234
4235 $data = array(
4236 "nr" => "$key",
4237 "title" => ilUtil::prepareFormOutput($row['title']),
4238 "max" => round($row['points'], 2),
4239 "reached" => round($arrResults[$row['question_id']]['reached'],2),
4240 'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4241 'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4242 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4243 "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4244 "type" => $row["type_tag"],
4245 "qid" => $row['question_id'],
4246 "original_id" => $row["original_id"],
4247 "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4248 'answered' => $arrResults[$row['question_id']]['answered']
4249 );
4250
4251 if( !$arrResults[ $row['question_id'] ]['answered'] )
4252 {
4253 $obligationsAnswered = false;
4254 }
4255
4256 $unordered[ $row['question_id'] ] = $data;
4257
4258 $key++;
4259 }
4260
4261 $numQuestionsTotal = count($unordered);
4262
4263 $pass_max = 0;
4264 $pass_reached = 0;
4265 $pass_requested_hints = 0;
4266 $pass_hint_points = 0;
4267 $key = 1;
4268
4269 $found = array();
4270
4271 foreach( $sequence as $qid )
4272 {
4273 // building pass point sums based on prepared data
4274 // for question that exists in users qst sequence
4275 $pass_max += round($unordered[$qid]['max'], 2);
4276 $pass_reached += round($unordered[$qid]['reached'], 2);
4277 $pass_requested_hints += $unordered[$qid]['requested_hints'];
4278 $pass_hint_points += $unordered[$qid]['hint_points'];
4279
4280 // pickup prepared data for question
4281 // that exists in users qst sequence
4282 $unordered[$qid]['nr'] = $key;
4283 array_push($found, $unordered[$qid]);
4284
4285 // increment key counter
4286 $key++;
4287 }
4288
4289 $unordered = null;
4290
4291 if( $this->getScoreCutting() == 1 )
4292 {
4293 if( $results['reached_points'] < 0 )
4294 {
4295 $results['reached_points'] = 0;
4296 }
4297
4298 if( $pass_reached < 0 ) $pass_reached = 0;
4299 }
4300
4301 $found['pass']['total_max_points'] = $pass_max;
4302 $found['pass']['total_reached_points'] = $pass_reached;
4303 $found['pass']['total_requested_hints'] = $pass_requested_hints;
4304 $found['pass']['total_hint_points'] = $pass_hint_points;
4305 $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4306 $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4307 $found['pass']['num_workedthrough'] = $numWorkedThrough;
4308 $found['pass']['num_questions_total'] = $numQuestionsTotal;
4309
4310 $found["test"]["total_max_points"] = $results['max_points'];
4311 $found["test"]["total_reached_points"] = $results['reached_points'];
4312 $found["test"]["total_requested_hints"] = $results['hint_count'];
4313 $found["test"]["total_hint_points"] = $results['hint_points'];
4314 $found["test"]["result_pass"] = $results['pass'];
4315 $found['test']['result_tstamp'] = $results['tstamp'];
4316 $found['test']['obligations_answered'] = $results['obligations_answered'];
4317
4318 if( (!$total_reached_points) or (!$total_max_points) )
4319 {
4320 $percentage = 0.0;
4321 }
4322 else
4323 {
4324 $percentage = ($total_reached_points / $total_max_points) * 100.0;
4325
4326 if( $percentage < 0 ) $percentage = 0.0;
4327 }
4328
4329 $found["test"]["passed"] = $results['passed'];
4330
4331 return $found;
4332 }
4333
4341 {
4342 global $ilDB;
4343
4344 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4345 array('integer'),
4346 array($this->getTestId())
4347 );
4348 $row = $ilDB->fetchAssoc($result);
4349 return $row["total"];
4350 }
4351
4358 function getCompleteWorkingTime($user_id)
4359 {
4360 global $ilDB;
4361
4362 $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",
4363 array('integer','integer'),
4364 array($this->getTestId(), $user_id)
4365 );
4366 $time = 0;
4367 while ($row = $ilDB->fetchAssoc($result))
4368 {
4369 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4370 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4371 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4372 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4373 $time += ($epoch_2 - $epoch_1);
4374 }
4375 return $time;
4376 }
4377
4385 {
4386 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4387 }
4388
4397 {
4398 global $ilDB;
4399
4400 $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",
4401 array('integer'),
4402 array($test_id)
4403 );
4404 $time = 0;
4405 $times = array();
4406 while ($row = $ilDB->fetchAssoc($result))
4407 {
4408 if (!array_key_exists($row["active_fi"], $times))
4409 {
4410 $times[$row["active_fi"]] = 0;
4411 }
4412 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4413 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4414 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4415 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4416 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4417 }
4418 return $times;
4419 }
4420
4428 {
4429 global $ilDB;
4430
4431 $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",
4432 array('integer','integer'),
4433 array($this->getTestId(), $active_id)
4434 );
4435 $time = 0;
4436 while ($row = $ilDB->fetchAssoc($result))
4437 {
4438 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4439 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4440 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4441 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4442 $time += ($epoch_2 - $epoch_1);
4443 }
4444 return $time;
4445 }
4446
4453 public static function _getWorkingTimeOfParticipantForPass($active_id, $pass)
4454 {
4455 global $ilDB;
4456
4457 $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4458 array('integer','integer'),
4459 array($active_id, $pass)
4460 );
4461 $time = 0;
4462 while ($row = $ilDB->fetchAssoc($result))
4463 {
4464 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4465 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4466 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4467 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4468 $time += ($epoch_2 - $epoch_1);
4469 }
4470 return $time;
4471 }
4472
4480 function getVisitTimeOfParticipant($active_id)
4481 {
4482 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4483 }
4484
4494 {
4495 global $ilDB;
4496
4497 $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",
4498 array('integer','integer'),
4499 array($test_id, $active_id)
4500 );
4501 $firstvisit = 0;
4502 $lastvisit = 0;
4503 while ($row = $ilDB->fetchAssoc($result))
4504 {
4505 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4506 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4507 if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
4508 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4509 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4510 if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
4511 }
4512 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4513 }
4514
4521 function &evalStatistical($active_id)
4522 {
4523 global $ilDB;
4524// global $ilBench;
4525 $pass = ilObjTest::_getResultPass($active_id);
4526 $test_result =& $this->getTestResult($active_id, $pass);
4527 $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",
4528 array('integer'),
4529 array($active_id)
4530 );
4531 $times = array();
4532 $first_visit = 0;
4533 $last_visit = 0;
4534 while ($row = $ilDB->fetchObject($result))
4535 {
4536 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4537 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4538 if (!$first_visit) {
4539 $first_visit = $epoch_1;
4540 }
4541 if ($epoch_1 < $first_visit) {
4542 $first_visit = $epoch_1;
4543 }
4544 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4545 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4546 if (!$last_visit) {
4547 $last_visit = $epoch_2;
4548 }
4549 if ($epoch_2 > $last_visit) {
4550 $last_visit = $epoch_2;
4551 }
4552 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4553 }
4554 $max_time = 0;
4555 foreach ($times as $key => $value) {
4556 $max_time += $value;
4557 }
4558 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
4559 {
4560 $percentage = 0.0;
4561 }
4562 else
4563 {
4564 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4565 if ($percentage < 0) $percentage = 0.0;
4566 }
4567 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4568 $first_date = getdate($first_visit);
4569 $last_date = getdate($last_visit);
4570 $qworkedthrough = 0;
4571 foreach ($test_result as $key => $value)
4572 {
4573 if (preg_match("/\d+/", $key))
4574 {
4575 $qworkedthrough += $value["workedthrough"];
4576 }
4577 }
4578 if (!$qworkedthrough)
4579 {
4580 $atimeofwork = 0;
4581 }
4582 else
4583 {
4584 $atimeofwork = $max_time / $qworkedthrough;
4585 }
4586
4587 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4588
4589 $result_mark = "";
4590 $passed = "";
4591
4592 if ($mark_obj)
4593 {
4594 $result_mark = $mark_obj->getShortName();
4595
4596 if( $mark_obj->getPassed() && $obligationsAnswered )
4597 {
4598 $passed = 1;
4599 }
4600 else
4601 {
4602 $passed = 0;
4603 }
4604 }
4605 $percent_worked_through = 0;
4606 if (count($this->questions))
4607 {
4608 $percent_worked_through = $qworkedthrough / count($this->questions);
4609 }
4610 $result_array = array(
4611 "qworkedthrough" => $qworkedthrough,
4612 "qmax" => count($this->questions),
4613 "pworkedthrough" => $percent_worked_through,
4614 "timeofwork" => $max_time,
4615 "atimeofwork" => $atimeofwork,
4616 "firstvisit" => $first_date,
4617 "lastvisit" => $last_date,
4618 "resultspoints" => $test_result["test"]["total_reached_points"],
4619 "maxpoints" => $test_result["test"]["total_max_points"],
4620 "resultsmarks" => $result_mark,
4621 "passed" => $passed,
4622 "distancemedian" => "0"
4623 );
4624 foreach ($test_result as $key => $value)
4625 {
4626 if (preg_match("/\d+/", $key))
4627 {
4628 $result_array[$key] = $value;
4629 }
4630 }
4631 return $result_array;
4632 }
4633
4642 {
4643 $totalpoints_array = array();
4644 $all_users =& $this->evalTotalParticipantsArray();
4645 foreach ($all_users as $active_id => $user_name)
4646 {
4647 $test_result =& $this->getTestResult($active_id);
4648 $reached = $test_result["test"]["total_reached_points"];
4649 $total = $test_result["test"]["total_max_points"];
4650 $percentage = $total != 0 ? $reached/$total : 0;
4651 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4652
4653 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4654
4655 if ($mark)
4656 {
4657 if( $mark->getPassed() && $obligationsAnswered )
4658 {
4659 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4660 }
4661 }
4662 }
4663 return $totalpoints_array;
4664 }
4665
4671 public function &getParticipants()
4672 {
4673 global $ilDB;
4674 $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",
4675 array('integer'),
4676 array($this->getTestId())
4677 );
4678 $persons_array = array();
4679 while ($row = $ilDB->fetchAssoc($result))
4680 {
4681 $name = $this->lng->txt("anonymous");
4682 $fullname = $this->lng->txt("anonymous");
4683 $login = "";
4684 if (!$this->getAnonymity())
4685 {
4686 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4687 {
4688 $name = $this->lng->txt("deleted_user");
4689 $fullname = $this->lng->txt("deleted_user");
4690 $login = $this->lng->txt("unknown");
4691 }
4692 else
4693 {
4694 $login = $row["login"];
4695 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4696 {
4697 $name = $this->lng->txt("anonymous");
4698 $fullname = $this->lng->txt("anonymous");
4699 }
4700 else
4701 {
4702 $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4703 $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4704 }
4705 }
4706 }
4707 $persons_array[$row["active_id"]] = array(
4708 "name" => $name,
4709 "fullname" => $fullname,
4710 "login" => $login
4711 );
4712 }
4713 return $persons_array;
4714 }
4715
4722 function &evalTotalPersonsArray($name_sort_order = "asc")
4723 {
4724 global $ilDB;
4725 $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),
4726 array('integer'),
4727 array($this->getTestId())
4728 );
4729 $persons_array = array();
4730 while ($row = $ilDB->fetchAssoc($result))
4731 {
4732 if ($this->getAnonymity())
4733 {
4734 $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
4735 }
4736 else
4737 {
4738 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4739 {
4740 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4741 }
4742 else
4743 {
4744 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4745 {
4746 $persons_array[$row["active_id"]] = $row["lastname"];
4747 }
4748 else
4749 {
4750 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4751 }
4752 }
4753 }
4754 }
4755 return $persons_array;
4756 }
4757
4764 function &evalTotalParticipantsArray($name_sort_order = "asc")
4765 {
4766 global $ilDB;
4767 $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),
4768 array('integer'),
4769 array($this->getTestId())
4770 );
4771 $persons_array = array();
4772 while ($row = $ilDB->fetchAssoc($result))
4773 {
4774 if ($this->getAnonymity())
4775 {
4776 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
4777 }
4778 else
4779 {
4780 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4781 {
4782 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4783 }
4784 else
4785 {
4786 if ($row["user_fi"] == ANONYMOUS_USER_ID)
4787 {
4788 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4789 }
4790 else
4791 {
4792 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4793 }
4794 }
4795 }
4796 }
4797 return $persons_array;
4798 }
4799
4807 {
4808 global $ilDB;
4809
4810 $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4811 array('integer', 'integer'),
4812 array($this->getTestId(), 1)
4813 );
4814 $row = $ilDB->fetchAssoc($result);
4815 return $row["total"];
4816 }
4817
4824 function &getQuestionsOfTest($active_id)
4825 {
4826 global $ilDB;
4827 if ($this->isRandomTest())
4828 {
4829 $ilDB->setLimit($this->getQuestionCount(), 0);
4830 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4831 "tst_test_rnd_qst.pass, qpl_questions.points " .
4832 "FROM tst_test_rnd_qst, qpl_questions " .
4833 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4834 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4835 array('integer'),
4836 array($active_id)
4837 );
4838 }
4839 else
4840 {
4841 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4842 "qpl_questions.points " .
4843 "FROM tst_test_question, tst_active, qpl_questions " .
4844 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4845 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4846 array('integer'),
4847 array($active_id)
4848 );
4849 }
4850 $qtest = array();
4851 if ($result->numRows())
4852 {
4853 while ($row = $ilDB->fetchAssoc($result))
4854 {
4855 array_push($qtest, $row);
4856 }
4857 }
4858 return $qtest;
4859 }
4860
4867 function &getQuestionsOfPass($active_id, $pass)
4868 {
4869 global $ilDB;
4870 if ($this->isRandomTest())
4871 {
4872 $ilDB->setLimit($this->getQuestionCount(), 0);
4873 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4874 "qpl_questions.points " .
4875 "FROM tst_test_rnd_qst, qpl_questions " .
4876 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4877 "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4878 "ORDER BY tst_test_rnd_qst.sequence",
4879 array('integer', 'integer'),
4880 array($active_id, $pass)
4881 );
4882 }
4883 else
4884 {
4885 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4886 "qpl_questions.points " .
4887 "FROM tst_test_question, tst_active, qpl_questions " .
4888 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4889 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4890 array('integer'),
4891 array($active_id)
4892 );
4893 }
4894 $qpass = array();
4895 if ($result->numRows())
4896 {
4897 while ($row = $ilDB->fetchAssoc($result))
4898 {
4899 array_push($qpass, $row);
4900 }
4901 }
4902 return $qpass;
4903 }
4904
4905 function getUnfilteredEvaluationData()
4906 {
4908 global $DIC;
4909
4910 $ilDB = $DIC->database();
4911
4912 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
4913 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
4914 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
4915
4916 $data = new ilTestEvaluationData($this);
4917
4918 $query = "
4919 SELECT tst_test_result.*,
4920 qpl_questions.original_id,
4921 qpl_questions.title questiontitle,
4922 qpl_questions.points maxpoints
4923
4924 FROM tst_test_result, qpl_questions, tst_active
4925
4926 WHERE tst_active.active_id = tst_test_result.active_fi
4927 AND qpl_questions.question_id = tst_test_result.question_fi
4928 AND tst_active.test_fi = %s
4929
4930 ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
4931 ";
4932
4933 $result = $ilDB->queryF(
4934 $query, array('integer'), array($this->getTestId())
4935 );
4936
4937 $pass = NULL;
4938 $checked = array();
4939 $datasets = 0;
4940 $questionData = [];
4941
4942 while( $row = $ilDB->fetchAssoc($result) )
4943 {
4944 $participantObject = $data->getParticipant($row["active_fi"]);
4945
4946 if( !($participantObject instanceof ilTestEvaluationUserData) )
4947 {
4948 continue;
4949 }
4950
4951 $passObject = $participantObject->getPass($row["pass"]);
4952
4953 if( !($passObject instanceof ilTestEvaluationPassData) )
4954 {
4955 continue;
4956 }
4957
4958 $passObject->addAnsweredQuestion(
4959 $row["question_fi"], $row["maxpoints"], $row["points"], $row['answered'], null, $row['manual']
4960 );
4961 }
4962
4963 foreach( array_keys($data->getParticipants()) as $active_id )
4964 {
4965 if( $this->isRandomTest() )
4966 {
4967 for( $testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++ )
4968 {
4969 $ilDB->setLimit($this->getQuestionCount(), 0);
4970 $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id, " .
4971 "tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title " .
4972 "FROM tst_test_rnd_qst, qpl_questions " .
4973 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4974 "AND tst_test_rnd_qst.pass = %s " .
4975 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4976 array('integer','integer'),
4977 array($testpass, $active_id)
4978 );
4979 if ($result->numRows())
4980 {
4981 while ($row = $ilDB->fetchAssoc($result))
4982 {
4983 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
4984 $data->getParticipant($active_id)->addQuestion($row["original_id"], $row["question_fi"], $row["points"], $row["sequence"], $tpass);
4985 $data->addQuestionTitle($row["question_fi"], $row["title"]);
4986 }
4987 }
4988 }
4989 }
4990 else if($this->isDynamicTest())
4991 {
4992 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4993 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4994 require_once 'Modules/Test/classes/class.ilTestDynamicQuestionSetFilterSelection.php';
4995
4996 $lastPass = $data->getParticipant($active_id)->getLastPass();
4997 for($testpass = 0; $testpass <= $lastPass; $testpass++)
4998 {
4999 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
5000 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig(
5001 $DIC->repositoryTree(), $DIC->database(), $DIC['ilPluginAdmin'], $this
5002 );
5003 $dynamicQuestionSetConfig->loadFromDb();
5004
5005 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
5006 $testSequenceFactory = new ilTestSequenceFactory($DIC->database(), $DIC->language(), $DIC['ilPluginAdmin'], $this);
5007 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $testpass);
5008
5009 $testSequence->loadFromDb($dynamicQuestionSetConfig);
5010 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
5011
5012 $sequence = (array)$testSequence->getUserSequenceQuestions();
5013
5014 $questionsIdsToRequest = array_diff(array_values($sequence), array_values($questionData));
5015 if(count($questionsIdsToRequest) > 0)
5016 {
5017 $questionIdsCondition = ' ' . $DIC->database()->in('question_id', array_values($questionsIdsToRequest), false, 'integer') . ' ';
5018
5019 $res = $DIC->database()->queryF("
5020 SELECT *
5021 FROM qpl_questions
5022 WHERE {$questionIdsCondition}",
5023 array('integer'),
5024 array($active_id)
5025 );
5026 while($row = $DIC->database()->fetchAssoc($res))
5027 {
5028 $questionData[$row['question_id']] = $row;
5029 $data->addQuestionTitle($row['question_id'], $row['title']);
5030 }
5031 }
5032
5033 foreach($sequence as $questionId)
5034 {
5035 if(!isset($questionData[$questionId]))
5036 {
5037 continue;
5038 }
5039
5040 $row = $questionData[$questionId];
5041
5042 $data->getParticipant(
5043 $active_id)->addQuestion($row['original_id'], $row['question_id'], $row['points'],
5044 NULL, $testpass
5045 );
5046 }
5047 }
5048 }
5049 else
5050 {
5051 $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
5052 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
5053 "FROM tst_test_question, tst_active, qpl_questions " .
5054 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
5055 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
5056 array('integer'),
5057 array($active_id)
5058 );
5059 if ($result->numRows())
5060 {
5061 $questionsbysequence = array();
5062
5063 while ($row = $ilDB->fetchAssoc($result))
5064 {
5065 $questionsbysequence[$row["sequence"]] = $row;
5066 }
5067
5068 $seqresult = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s",
5069 array('integer'),
5070 array($active_id)
5071 );
5072
5073 while ($seqrow = $ilDB->fetchAssoc($seqresult))
5074 {
5075 $questionsequence = unserialize($seqrow["sequence"]);
5076 foreach ($questionsequence as $sidx => $seq)
5077 {
5078 $data->getParticipant($active_id)->addQuestion($questionsbysequence[$seq]["original_id"], $questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
5079 $data->addQuestionTitle($questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["title"]);
5080 }
5081 }
5082 }
5083 }
5084 }
5085
5086 if($this->getECTSOutput())
5087 {
5088 $passed_array =& $this->getTotalPointsPassedArray();
5089 }
5090
5091 foreach( array_keys($data->getParticipants()) as $active_id )
5092 {
5093 $tstUserData = $data->getParticipant($active_id);
5094
5095 $percentage = $tstUserData->getReachedPointsInPercent();
5096
5097 $obligationsAnswered = $tstUserData->areObligationsAnswered();
5098
5099 $mark = $this->mark_schema->getMatchingMark($percentage);
5100
5101 if (is_object($mark))
5102 {
5103 $tstUserData->setMark($mark->getShortName());
5104 $tstUserData->setMarkOfficial($mark->getOfficialName());
5105
5106 $tstUserData->setPassed(
5107 $mark->getPassed() && $tstUserData->areObligationsAnswered()
5108 );
5109 }
5110
5111 if($this->getECTSOutput())
5112 {
5113 $ects_mark = $this->getECTSGrade(
5114 $passed_array, $tstUserData->getReached(), $tstUserData->getMaxPoints()
5115 );
5116
5117 $tstUserData->setECTSMark($ects_mark);
5118 }
5119
5120 $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
5121
5122 $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
5123 $tstUserData->setLastVisit($visitingTime["lastvisit"]);
5124 }
5125
5126 return $data;
5127 }
5128
5129 public static function _getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
5130 {
5131 global $ilDB;
5132
5134
5135 switch( $questionSetType )
5136 {
5138
5139 $res = $ilDB->queryF("
5140 SELECT COUNT(qpl_questions.question_id) qcount,
5141 SUM(qpl_questions.points) qsum
5142 FROM tst_active
5143 INNER JOIN tst_tests
5144 ON tst_tests.test_id = tst_active.test_fi
5145 INNER JOIN tst_dyn_quest_set_cfg
5146 ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
5147 INNER JOIN qpl_questions
5148 ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
5149 AND qpl_questions.original_id IS NULL
5150 AND qpl_questions.complete = %s
5151 WHERE tst_active.active_id = %s
5152 ",
5153 array('integer', 'integer'),
5154 array(1, $active_id)
5155 );
5156
5157 break;
5158
5160
5161 $res = $ilDB->queryF("
5162 SELECT tst_test_rnd_qst.pass,
5163 COUNT(tst_test_rnd_qst.question_fi) qcount,
5164 SUM(qpl_questions.points) qsum
5165
5166 FROM tst_test_rnd_qst,
5167 qpl_questions
5168
5169 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
5170 AND tst_test_rnd_qst.active_fi = %s
5171 AND pass = %s
5172
5173 GROUP BY tst_test_rnd_qst.active_fi,
5174 tst_test_rnd_qst.pass
5175 ",
5176 array('integer', 'integer'),
5177 array($active_id, $pass)
5178 );
5179
5180 break;
5181
5183
5184 $res = $ilDB->queryF("
5185 SELECT COUNT(tst_test_question.question_fi) qcount,
5186 SUM(qpl_questions.points) qsum
5187
5188 FROM tst_test_question,
5189 qpl_questions,
5190 tst_active
5191
5192 WHERE tst_test_question.question_fi = qpl_questions.question_id
5193 AND tst_test_question.test_fi = tst_active.test_fi
5194 AND tst_active.active_id = %s
5195
5196 GROUP BY tst_test_question.test_fi
5197 ",
5198 array('integer'),
5199 array($active_id)
5200 );
5201
5202 break;
5203
5204 default:
5205
5206 throw new ilTestException("not supported question set type: $questionSetType");
5207 }
5208
5209 $row = $ilDB->fetchAssoc($res);
5210
5211 if( is_array($row) )
5212 {
5213 return array("count" => $row["qcount"], "points" => $row["qsum"]);
5214 }
5215
5216 return array("count" => 0, "points" => 0);
5217 }
5218
5219 function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
5220 {
5221 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5222 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5223 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5224 $data = $this->getUnfilteredEvaluationData();
5225 if ($withStatistics)
5226 {
5227 $data->calculateStatistics();
5228 }
5229 $data->setFilter($filterby, $filtertext);
5230 return $data;
5231 }
5232
5240 {
5241 return $this->_evalResultsOverview($this->getTestId());
5242 }
5243
5250 function &_evalResultsOverview($test_id)
5251 {
5252 global $ilDB;
5253
5254 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5255 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5256 "qpl_questions.points maxpoints " .
5257 "FROM tst_test_result, qpl_questions, tst_active " .
5258 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5259 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5260 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5261 "AND tst_active.test_fi = %s " .
5262 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5263 array('integer'),
5264 array($test_id)
5265 );
5266 $overview = array();
5267 while ($row = $ilDB->fetchAssoc($result))
5268 {
5269 if (!array_key_exists($row["active_fi"], $overview))
5270 {
5271 $overview[$row["active_fi"]] = array();
5272 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5273 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5274 $overview[$row["active_fi"]]["title"] = $row["title"];
5275 $overview[$row["active_fi"]]["login"] = $row["login"];
5276 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5277 $overview[$row["active_fi"]]["started"] = $row["started"];
5278 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5279 }
5280 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5281 {
5282 $overview[$row["active_fi"]][$row["pass"]] = array();
5283 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5284 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5285 }
5286 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5287 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5288 }
5289 return $overview;
5290 }
5291
5300 {
5301 global $ilDB;
5302
5303 $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5304 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5305 "qpl_questions.points maxpoints " .
5306 "FROM tst_test_result, qpl_questions, tst_active " .
5307 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5308 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5309 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5310 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5311 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5312 array('integer', 'integer'),
5313 array($this->getTestId(), $active_id)
5314 );
5315 $overview = array();
5316 while ($row = $ilDB->fetchAssoc($result))
5317 {
5318 if (!array_key_exists($row["active_fi"], $overview))
5319 {
5320 $overview[$row["active_fi"]] = array();
5321 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5322 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5323 $overview[$row["active_fi"]]["title"] = $row["title"];
5324 $overview[$row["active_fi"]]["login"] = $row["login"];
5325 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5326 $overview[$row["active_fi"]]["started"] = $row["started"];
5327 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5328 }
5329 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5330 {
5331 $overview[$row["active_fi"]][$row["pass"]] = array();
5332 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5333 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5334 }
5335 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5336 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5337 }
5338 return $overview;
5339 }
5340
5352 function buildName($user_id, $firstname, $lastname, $title)
5353 {
5354 $name = "";
5355 if (strlen($firstname.$lastname.$title) == 0)
5356 {
5357 $name = $this->lng->txt("deleted_user");
5358 }
5359 else
5360 {
5361 if ($user_id == ANONYMOUS_USER_ID)
5362 {
5363 $name = $lastname;
5364 }
5365 else
5366 {
5367 $name = trim($lastname . ", " . $firstname . " " . $title);
5368 }
5369 if ($this->getAnonymity())
5370 {
5371 $name = $this->lng->txt("anonymous");
5372 }
5373 }
5374 return $name;
5375 }
5376
5389 function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5390 {
5391 global $lng;
5392 $name = "";
5393 if (strlen($firstname.$lastname.$title) == 0)
5394 {
5395 $name = $lng->txt("deleted_user");
5396 }
5397 else
5398 {
5399 if ($user_id == ANONYMOUS_USER_ID)
5400 {
5401 $name = $lastname;
5402 }
5403 else
5404 {
5405 $name = trim($lastname . ", " . $firstname . " " . $title);
5406 }
5407 if ($is_anonymous)
5408 {
5409 $name = $lng->txt("anonymous");
5410 }
5411 }
5412 return $name;
5413 }
5414
5422 {
5423 global $ilDB;
5424
5425 $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",
5426 array('integer'),
5427 array($this->getTestId())
5428 );
5429 $times = array();
5430 while ($row = $ilDB->fetchObject($result))
5431 {
5432 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5433 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5434 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5435 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5436 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5437 }
5438 $max_time = 0;
5439 $counter = 0;
5440 foreach ($times as $key => $value)
5441 {
5442 $max_time += $value;
5443 $counter++;
5444 }
5445 if ($counter)
5446 {
5447 $average_time = round($max_time / $counter);
5448 }
5449 else
5450 {
5451 $average_time = 0;
5452 }
5453 return $average_time;
5454 }
5455
5462 function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
5463 {
5464 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5465 return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5466 }
5467
5475 {
5476 $time_in_seconds = 0;
5477 foreach ($this->questions as $question_id)
5478 {
5479 $question =& ilObjTest::_instanciateQuestion($question_id);
5480 $est_time = $question->getEstimatedWorkingTime();
5481 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5482 }
5483 $hours = (int)($time_in_seconds / 3600) ;
5484 $time_in_seconds = $time_in_seconds - ($hours * 3600);
5485 $minutes = (int)($time_in_seconds / 60);
5486 $time_in_seconds = $time_in_seconds - ($minutes * 60);
5487 $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5488 return $result;
5489 }
5490
5497 function getImagePath()
5498 {
5499 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5500 }
5501
5509 {
5510 include_once "./Services/Utilities/classes/class.ilUtil.php";
5511 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5512 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
5513 }
5514
5523 function &createQuestionGUI($question_type, $question_id = -1)
5524 {
5525 if ((!$question_type) and ($question_id > 0))
5526 {
5527 $question_type = $this->getQuestionType($question_id);
5528 }
5529
5530 if (!strlen($question_type)) return null;
5531
5532 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5533 assQuestion::_includeClass($question_type, 1);
5534
5535 $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5536 $question = new $question_type_gui();
5537
5538 if ($question_id > 0)
5539 {
5540 $question->object->loadFromDb($question_id);
5541
5542 global $ilCtrl, $ilDB, $ilUser, $lng;
5543
5544 $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5545 $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5546
5547 $assSettings = new ilSetting('assessment');
5548 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5549 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5550 $processLockerFactory->setQuestionId($question->object->getId());
5551 $processLockerFactory->setUserId($ilUser->getId());
5552 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5553 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5554 $question->object->setProcessLocker($processLockerFactory->getLocker());
5555 }
5556
5557 return $question;
5558 }
5559
5569 public static function _instanciateQuestion($question_id)
5570 {
5571 if (strcmp($question_id, "") != 0)
5572 {
5573 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5574 return assQuestion::_instanciateQuestion($question_id);
5575 }
5576 }
5577
5586 function moveQuestions($move_questions, $target_index, $insert_mode)
5587 {
5588 $this->questions = array_values($this->questions);
5589 $array_pos = array_search($target_index, $this->questions);
5590 if ($insert_mode == 0)
5591 {
5592 $part1 = array_slice($this->questions, 0, $array_pos);
5593 $part2 = array_slice($this->questions, $array_pos);
5594 }
5595 else if ($insert_mode == 1)
5596 {
5597 $part1 = array_slice($this->questions, 0, $array_pos + 1);
5598 $part2 = array_slice($this->questions, $array_pos + 1);
5599 }
5600 foreach ($move_questions as $question_id)
5601 {
5602 if (!(array_search($question_id, $part1) === FALSE))
5603 {
5604 unset($part1[array_search($question_id, $part1)]);
5605 }
5606 if (!(array_search($question_id, $part2) === FALSE))
5607 {
5608 unset($part2[array_search($question_id, $part2)]);
5609 }
5610 }
5611 $part1 = array_values($part1);
5612 $part2 = array_values($part2);
5613 $new_array = array_values(array_merge($part1, $move_questions, $part2));
5614 $this->questions = array();
5615 $counter = 1;
5616 foreach ($new_array as $question_id)
5617 {
5618 $this->questions[$counter] = $question_id;
5619 $counter++;
5620 }
5621 $this->saveQuestionsToDb();
5622 }
5623
5624
5633 {
5634 if( $this->isStartingTimeEnabled() && $this->getStartingTime() != 0 )
5635 {
5636 $now = time();
5637 if ($now < $this->getStartingTime())
5638 {
5639 return false;
5640 }
5641 }
5642 return true;
5643 }
5644
5653 {
5654 if( $this->isEndingTimeEnabled() && $this->getEndingTime() != 0 )
5655 {
5656 $now = time();
5657 if ($now > $this->getEndingTime())
5658 {
5659 return true;
5660 }
5661 }
5662 return false;
5663 }
5664
5670 function getAvailableQuestions($arrFilter, $completeonly = 0)
5671 {
5672 $pluginAdmin = $GLOBALS['DIC'] ? $GLOBALS['DIC']['ilPluginAdmin'] : $GLOBALS['ilPluginAdmin'];
5673 $lng = $GLOBALS['DIC'] ? $GLOBALS['DIC']['lng'] : $GLOBALS['lng'];
5674 global $ilUser;
5675 global $ilDB;
5676
5677 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5678 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
5679 $available = "";
5680 if (count($available_pools))
5681 {
5682 $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5683 }
5684 else
5685 {
5686 return array();
5687 }
5688 if ($completeonly)
5689 {
5690 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5691 }
5692
5693 $where = "";
5694 if (is_array($arrFilter))
5695 {
5696 if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
5697 {
5698 $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5699 }
5700 if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
5701 {
5702 $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5703 }
5704 if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
5705 {
5706 $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5707 }
5708 if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
5709 {
5710 $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5711 }
5712 if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl']))
5713 {
5714 $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5715 }
5716 }
5717
5718 $original_ids =& $this->getExistingQuestions();
5719 $original_clause = " qpl_questions.original_id IS NULL";
5720 if (count($original_ids))
5721 {
5722 $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5723 }
5724
5725 $query_result = $ilDB->query("
5726 SELECT qpl_questions.*, qpl_questions.tstamp,
5727 qpl_qst_type.type_tag, qpl_qst_type.plugin, qpl_qst_type.plugin_name,
5728 object_data.title parent_title
5729 FROM qpl_questions, qpl_qst_type, object_data
5730 WHERE $original_clause $available
5731 AND object_data.obj_id = qpl_questions.obj_fi
5732 AND qpl_questions.tstamp > 0
5733 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
5734 $where
5735 ");
5736 $rows = array();
5737 $types = $this->getQuestionTypeTranslations();
5738 if ($query_result->numRows())
5739 {
5740 while ($row = $ilDB->fetchAssoc($query_result))
5741 {
5743
5744 if( !$row['plugin'] )
5745 {
5746 $row[ 'ttype' ] = $lng->txt($row[ "type_tag" ]);
5747
5748 $rows[] = $row;
5749 continue;
5750 }
5751
5752 if( !$pluginAdmin->isActive(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $row['plugin_name']) )
5753 {
5754 continue;
5755 }
5756
5757 $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $row['plugin_name']);
5758 $row[ 'ttype' ] = $pl->getQuestionTypeTranslation();
5759
5760 $rows[] = $row;
5761 }
5762 }
5763 return $rows;
5764 }
5765
5770 public function fromXML(ilQTIAssessment $assessment)
5771 {
5772 unset($_SESSION["import_mob_xhtml"]);
5773
5774 $this->setDescription($assessment->getComment());
5775 $this->setTitle($assessment->getTitle());
5776
5777 $this->setIntroductionEnabled(false);
5778 foreach ($assessment->objectives as $objectives)
5779 {
5780 foreach ($objectives->materials as $material)
5781 {
5782 $intro = $this->QTIMaterialToString($material);
5783 $this->setIntroduction($intro);
5784 $this->setIntroductionEnabled(strlen($intro) > 0);
5785 }
5786 }
5787
5788 if(
5789 $assessment->getPresentationMaterial() &&
5790 $assessment->getPresentationMaterial()->getFlowMat(0) &&
5791 $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5792 )
5793 {
5794 $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5795 }
5796
5797 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
5798 {
5799 switch ($assessmentcontrol->getSolutionswitch())
5800 {
5801 case "Yes":
5803 break;
5804 default:
5806 break;
5807 }
5808 }
5809
5810 $this->setStartingTimeEnabled(false);
5811 $this->setEndingTimeEnabled(false);
5812 $this->setPasswordEnabled(false);
5813 $this->setLimitUsersEnabled(false);
5814
5815 foreach ($assessment->qtimetadata as $metadata)
5816 {
5817 switch ($metadata["label"])
5818 {
5819 case "test_type":
5820 // for old tests with a test type
5821 $type = $metadata["entry"];
5822 switch ($type)
5823 {
5824 case 1:
5825 // assessment
5826 $this->setAnonymity(1);
5827 break;
5828 case 2:
5829 // self assessment
5830 break;
5831 case 4:
5832 // online exam
5833 $this->setFixedParticipants(1);
5835 $this->setShowSolutionPrintview(1);
5836 break;
5837 case 5:
5838 // varying random test
5839 break;
5840 }
5841 break;
5842 case "sequence_settings":
5843 $this->setSequenceSettings($metadata["entry"]);
5844 break;
5845 case "solution_details":
5846 $this->setShowSolutionDetails((int)$metadata["entry"]);
5847 break;
5848 case "print_bs_with_res":
5849 $this->setPrintBestSolutionWithResult((int)$metadata["entry"]);
5850 break;
5851 case "author":
5852 $this->setAuthor($metadata["entry"]);
5853 break;
5854 case "nr_of_tries":
5855 $this->setNrOfTries($metadata["entry"]);
5856 break;
5857 case "pass_waiting":
5858 $this->setPassWaiting($metadata["entry"]);
5859 break;
5860 case "kiosk":
5861 $this->setKiosk($metadata["entry"]);
5862 break;
5863 case "showfinalstatement":
5864 $this->setShowFinalStatement($metadata["entry"]);
5865 break;
5866 case "showinfo":
5867 $this->setShowInfo($metadata["entry"]);
5868 break;
5869 case "forcejs":
5870 $this->setForceJS($metadata["entry"]);
5871 break;
5872 case "customstyle":
5873 $this->setCustomStyle($metadata["entry"]);
5874 break;
5875
5876 case "highscore_enabled":
5877 $this->setHighscoreEnabled($metadata["entry"]);
5878 break;
5879
5880 case "highscore_anon":
5881 $this->setHighscoreAnon($metadata["entry"]);
5882 break;
5883
5884 case "highscore_achieved_ts":
5885 $this->setHighscoreAchievedTS($metadata["entry"]);
5886 break;
5887
5888 case "highscore_score":
5889 $this->setHighscoreScore($metadata["entry"]);
5890 break;
5891
5892 case "highscore_percentage":
5893 $this->setHighscorePercentage($metadata["entry"]);
5894 break;
5895
5896 case "highscore_hints":
5897 $this->setHighscoreHints($metadata["entry"]);
5898 break;
5899
5900 case "highscore_wtime":
5901 $this->setHighscoreWTime($metadata["entry"]);
5902 break;
5903
5904 case "highscore_own_table":
5905 $this->setHighscoreOwnTable($metadata["entry"]);
5906 break;
5907
5908 case "highscore_top_table":
5909 $this->setHighscoreTopTable($metadata["entry"]);
5910 break;
5911
5912 case "highscore_top_num":
5913 $this->setHighscoreTopNum($metadata["entry"]);
5914 break;
5915
5916 case "hide_previous_results":
5917 if ($metadata["entry"] == 0)
5918 {
5919 $this->setUsePreviousAnswers(1);
5920 }
5921 else
5922 {
5923 $this->setUsePreviousAnswers(0);
5924 }
5925 break;
5926 case "use_previous_answers":
5927 $this->setUsePreviousAnswers($metadata["entry"]);
5928 break;
5929 case "answer_feedback":
5930 $this->setAnswerFeedback($metadata["entry"]);
5931 break;
5932 case "hide_title_points":
5933 $this->setTitleOutput($metadata["entry"]);
5934 break;
5935 case "title_output":
5936 $this->setTitleOutput($metadata["entry"]);
5937 break;
5938 case "question_set_type":
5939 $this->setQuestionSetType($metadata["entry"]);
5940 break;
5941 case "random_test":
5942 if( $metadata["entry"] )
5943 {
5944 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
5945 }
5946 else
5947 {
5948 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
5949 }
5950 break;
5951 case "results_presentation":
5952 $this->setResultsPresentation($metadata["entry"]);
5953 break;
5954 case "reset_processing_time":
5955 $this->setResetProcessingTime($metadata["entry"]);
5956 break;
5957 case "instant_verification":
5958 $this->setInstantFeedbackSolution($metadata["entry"]);
5959 break;
5960 case "instant_feedback_answer_fixation":
5961 $this->setInstantFeedbackAnswerFixationEnabled((bool)$metadata["entry"]);
5962 break;
5963 case "force_instant_feedback":
5964 $this->setForceInstantFeedbackEnabled((bool)$metadata["entry"]);
5965 break;
5966 case "answer_feedback_points":
5967 $this->setAnswerFeedbackPoints($metadata["entry"]);
5968 break;
5969 case "anonymity":
5970 $this->setAnonymity($metadata["entry"]);
5971 break;
5972 case "use_pool":
5973 $this->setPoolUsage((int)$metadata["entry"]);
5974 break;
5975 case "show_cancel":
5976 $this->setShowCancel($metadata["entry"]);
5977 break;
5978 case "show_marker":
5979 $this->setShowMarker($metadata["entry"]);
5980 break;
5981 case "fixed_participants":
5982 $this->setFixedParticipants($metadata["entry"]);
5983 break;
5984 case "score_reporting":
5985 $this->setScoreReporting($metadata["entry"]);
5986 break;
5987 case "shuffle_questions":
5988 $this->setShuffleQuestions($metadata["entry"]);
5989 break;
5990 case "count_system":
5991 $this->setCountSystem($metadata["entry"]);
5992 break;
5993 case "mc_scoring":
5994 $this->setMCScoring($metadata["entry"]);
5995 break;
5996 case "mailnotification":
5997 $this->setMailNotification($metadata["entry"]);
5998 break;
5999 case "mailnottype":
6000 $this->setMailNotificationType($metadata["entry"]);
6001 break;
6002 case "exportsettings":
6003 $this->setExportSettings($metadata['entry']);
6004 break;
6005 case "score_cutting":
6006 $this->setScoreCutting($metadata["entry"]);
6007 break;
6008 case "password":
6009 $this->setPassword($metadata["entry"]);
6010 $this->setPasswordEnabled(strlen($metadata["entry"]) > 0);
6011 break;
6012 case "allowedUsers":
6013 $this->setAllowedUsers($metadata["entry"]);
6014 $this->setLimitUsersEnabled((int)$metadata["entry"] > 0);
6015 break;
6016 case "allowedUsersTimeGap":
6017 $this->setAllowedUsersTimeGap($metadata["entry"]);
6018 break;
6019 case "pass_scoring":
6020 $this->setPassScoring($metadata["entry"]);
6021 break;
6022 case 'pass_deletion_allowed':
6023 $this->setPassDeletionAllowed((int)$metadata['entry']);
6024 break;
6025 case "show_summary":
6026 $this->setListOfQuestionsSettings($metadata["entry"]);
6027 break;
6028 case "reporting_date":
6029 $iso8601period = $metadata["entry"];
6030 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6031 {
6032 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6033 }
6034 break;
6035 case 'enable_processing_time':
6036 $this->setEnableProcessingTime($metadata['entry']);
6037 break;
6038 case "processing_time":
6039 $this->setProcessingTime($metadata['entry']);
6040 break;
6041 case "starting_time":
6042 $iso8601period = $metadata["entry"];
6043 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6044 {
6045 $date_time = new ilDateTime(sprintf("%02d-%02d-%02d %02d:%02d:%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]), IL_CAL_DATETIME);
6046 $this->setStartingTime($date_time->get(IL_CAL_UNIX));
6047 $this->setStartingTimeEnabled(true);
6048 }
6049 break;
6050 case "ending_time":
6051 $iso8601period = $metadata["entry"];
6052 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6053 {
6054 $date_time = new ilDateTime(sprintf("%02d-%02d-%02d %02d:%02d:%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]), IL_CAL_DATETIME);
6055 $this->setEndingTime($date_time->get(IL_CAL_UNIX));
6056 $this->setEndingTimeEnabled(true);
6057 }
6058 break;
6059 case "enable_examview":
6060 $this->setEnableExamview($metadata["entry"]);
6061 break;
6062 case 'show_examview_html':
6063 $this->setShowExamviewHtml($metadata['entry']);
6064 break;
6065 case 'show_examview_pdf':
6066 $this->setShowExamviewPdf($metadata['entry']);
6067 break;
6068 case 'redirection_mode':
6069 $this->setRedirectionMode($metadata['entry']);
6070 break;
6071 case 'redirection_url':
6072 $this->setRedirectionUrl($metadata['entry']);
6073 break;
6074 case 'examid_in_kiosk':
6075 case 'examid_in_test_pass':
6076 $this->setShowExamIdInTestPassEnabled($metadata['entry']);
6077 break;
6078 case 'show_exam_id':
6079 case 'examid_in_test_res':
6080 $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
6081 break;
6082 case 'enable_archiving':
6083 $this->setEnableArchiving($metadata['entry']);
6084 break;
6085 case 'sign_submission':
6086 $this->setSignSubmission($metadata['entry']);
6087 break;
6088 case 'char_selector_availability':
6089 $this->setCharSelectorAvailability($metadata['entry']);
6090 break;
6091 case 'char_selector_definition':
6092 $this->setCharSelectorDefinition($metadata['entry']);
6093 break;
6094 case 'skill_service':
6095 $this->setSkillServiceEnabled((bool)$metadata['entry']);
6096 break;
6097 case 'result_tax_filters':
6098 $this->setResultFilterTaxIds(strlen($metadata['entry']) ? unserialize($metadata['entry']) : array());
6099 break;
6100 case 'show_grading_status':
6101 $this->setShowGradingStatusEnabled((bool)$metadata['entry']);
6102 break;
6103 case 'show_grading_mark':
6104 $this->setShowGradingMarkEnabled((bool)$metadata['entry']);
6105 break;
6106 case 'activation_limited':
6107 $this->setActivationLimited($metadata['entry']);
6108 break;
6109 case 'activation_start_time':
6110 $this->setActivationStartingTime($metadata['entry']);
6111 break;
6112 case 'activation_end_time':
6113 $this->setActivationEndingTime($metadata['entry']);
6114 break;
6115 case 'activation_visibility':
6116 $this->setActivationVisibility($metadata['entry']);
6117 break;
6118 case 'autosave':
6119 $this->setAutosave($metadata['entry']);
6120 break;
6121 case 'autosave_ival':
6122 $this->setAutosaveIval($metadata['entry']);
6123 break;
6124 case 'offer_question_hints':
6125 $this->setOfferingQuestionHintsEnabled($metadata['entry']);
6126 break;
6127 case 'instant_feedback_specific':
6128 $this->setSpecificAnswerFeedback($metadata['entry']);
6129 break;
6130 case 'obligations_enabled':
6131 $this->setObligationsEnabled($metadata['entry']);
6132 break;
6133 }
6134 if (preg_match("/mark_step_\d+/", $metadata["label"]))
6135 {
6136 $xmlmark = $metadata["entry"];
6137 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
6138 $mark_short = $matches[1];
6139 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
6140 $mark_official = $matches[1];
6141 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
6142 $mark_percentage = $matches[1];
6143 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
6144 $mark_passed = $matches[1];
6145 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
6146 }
6147 }
6148 // handle the import of media objects in XHTML code
6149 if (is_array($_SESSION["import_mob_xhtml"]))
6150 {
6151 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6152 include_once "./Services/RTE/classes/class.ilRTE.php";
6153 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
6154 foreach ($_SESSION["import_mob_xhtml"] as $mob)
6155 {
6156 $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
6157 if (file_exists($importfile))
6158 {
6159 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
6160 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
6161 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
6162 $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
6163 }
6164 else
6165 {
6166 global $ilLog;
6167 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
6168 }
6169 }
6170 $this->saveToDb();
6171 }
6172 }
6173
6179 public function toXML()
6180 {
6181 include_once("./Services/Xml/classes/class.ilXmlWriter.php");
6182 $a_xml_writer = new ilXmlWriter;
6183 // set xml header
6184 $a_xml_writer->xmlHeader();
6185 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
6186 $a_xml_writer->xmlStartTag("questestinterop");
6187
6188 $attrs = array(
6189 "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
6190 "title" => $this->getTitle()
6191 );
6192 $a_xml_writer->xmlStartTag("assessment", $attrs);
6193 // add qti comment
6194 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
6195
6196 // add qti duration
6197 if ($this->enable_processing_time)
6198 {
6199 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
6200 $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
6201 }
6202
6203 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
6204 $a_xml_writer->xmlStartTag("qtimetadata");
6205 $a_xml_writer->xmlStartTag("qtimetadatafield");
6206 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
6207 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
6208 $a_xml_writer->xmlEndTag("qtimetadatafield");
6209
6210 // anonymity
6211 $a_xml_writer->xmlStartTag("qtimetadatafield");
6212 $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
6213 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
6214 $a_xml_writer->xmlEndTag("qtimetadatafield");
6215
6216 $a_xml_writer->xmlStartTag("qtimetadatafield");
6217 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_pool");
6218 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPoolUsage() ? 1 : 0);
6219 $a_xml_writer->xmlEndTag("qtimetadatafield");
6220
6221 // question set type (fixed, random, dynamic, ...)
6222 $a_xml_writer->xmlStartTag("qtimetadatafield");
6223 $a_xml_writer->xmlElement("fieldlabel", NULL, "question_set_type");
6224 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getQuestionSetType());
6225 $a_xml_writer->xmlEndTag("qtimetadatafield");
6226
6227 // sequence settings
6228 $a_xml_writer->xmlStartTag("qtimetadatafield");
6229 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
6230 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
6231 $a_xml_writer->xmlEndTag("qtimetadatafield");
6232
6233 // author
6234 $a_xml_writer->xmlStartTag("qtimetadatafield");
6235 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
6236 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
6237 $a_xml_writer->xmlEndTag("qtimetadatafield");
6238
6239 // reset processing time
6240 $a_xml_writer->xmlStartTag("qtimetadatafield");
6241 $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
6242 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
6243 $a_xml_writer->xmlEndTag("qtimetadatafield");
6244
6245 // count system
6246 $a_xml_writer->xmlStartTag("qtimetadatafield");
6247 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
6248 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
6249 $a_xml_writer->xmlEndTag("qtimetadatafield");
6250
6251 // multiple choice scoring
6252 $a_xml_writer->xmlStartTag("qtimetadatafield");
6253 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
6254 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
6255 $a_xml_writer->xmlEndTag("qtimetadatafield");
6256
6257 // multiple choice scoring
6258 $a_xml_writer->xmlStartTag("qtimetadatafield");
6259 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
6260 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
6261 $a_xml_writer->xmlEndTag("qtimetadatafield");
6262
6263 // multiple choice scoring
6264 $a_xml_writer->xmlStartTag("qtimetadatafield");
6265 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
6266 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
6267 $a_xml_writer->xmlEndTag("qtimetadatafield");
6268
6269 // allowed users
6270 $a_xml_writer->xmlStartTag("qtimetadatafield");
6271 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
6272 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
6273 $a_xml_writer->xmlEndTag("qtimetadatafield");
6274
6275 // allowed users time gap
6276 $a_xml_writer->xmlStartTag("qtimetadatafield");
6277 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
6278 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
6279 $a_xml_writer->xmlEndTag("qtimetadatafield");
6280
6281 // pass scoring
6282 $a_xml_writer->xmlStartTag("qtimetadatafield");
6283 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
6284 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
6285 $a_xml_writer->xmlEndTag("qtimetadatafield");
6286
6287 $a_xml_writer->xmlStartTag('qtimetadatafield');
6288 $a_xml_writer->xmlElement('fieldlabel', NULL, 'pass_deletion_allowed');
6289 $a_xml_writer->xmlElement('fieldentry', NULL, (int)$this->isPassDeletionAllowed());
6290 $a_xml_writer->xmlEndTag('qtimetadatafield');
6291
6292 // score reporting date
6293 if ($this->getReportingDate())
6294 {
6295 $a_xml_writer->xmlStartTag("qtimetadatafield");
6296 $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
6297 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6298 $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]));
6299 $a_xml_writer->xmlEndTag("qtimetadatafield");
6300 }
6301 // number of tries
6302 $a_xml_writer->xmlStartTag("qtimetadatafield");
6303 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
6304 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
6305 $a_xml_writer->xmlEndTag("qtimetadatafield");
6306
6307 // pass_waiting
6308 $a_xml_writer->xmlStartTag("qtimetadatafield");
6309 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_waiting");
6310 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassWaiting());
6311 $a_xml_writer->xmlEndTag("qtimetadatafield");
6312
6313 // kiosk
6314 $a_xml_writer->xmlStartTag("qtimetadatafield");
6315 $a_xml_writer->xmlElement("fieldlabel", NULL, "kiosk");
6316 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getKiosk()));
6317 $a_xml_writer->xmlEndTag("qtimetadatafield");
6318
6319
6320 //redirection_mode
6321 $a_xml_writer->xmlStartTag('qtimetadatafield');
6322 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_mode");
6323 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionMode());
6324 $a_xml_writer->xmlEndTag("qtimetadatafield");
6325
6326 //redirection_url
6327 $a_xml_writer->xmlStartTag('qtimetadatafield');
6328 $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_url");
6329 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionUrl());
6330 $a_xml_writer->xmlEndTag("qtimetadatafield");
6331
6332 // use previous answers
6333 $a_xml_writer->xmlStartTag("qtimetadatafield");
6334 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
6335 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
6336 $a_xml_writer->xmlEndTag("qtimetadatafield");
6337
6338 // hide title points
6339 $a_xml_writer->xmlStartTag("qtimetadatafield");
6340 $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
6341 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
6342 $a_xml_writer->xmlEndTag("qtimetadatafield");
6343
6344 // results presentation
6345 $a_xml_writer->xmlStartTag("qtimetadatafield");
6346 $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
6347 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
6348 $a_xml_writer->xmlEndTag("qtimetadatafield");
6349
6350 // examid in test pass
6351 $a_xml_writer->xmlStartTag("qtimetadatafield");
6352 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_pass");
6353 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6354 $a_xml_writer->xmlEndTag("qtimetadatafield");
6355
6356 // examid in kiosk
6357 $a_xml_writer->xmlStartTag("qtimetadatafield");
6358 $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_res");
6359 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6360 $a_xml_writer->xmlEndTag("qtimetadatafield");
6361
6362 // solution details
6363 $a_xml_writer->xmlStartTag("qtimetadatafield");
6364 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
6365 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
6366 $a_xml_writer->xmlEndTag("qtimetadatafield");
6367
6368 // solution details
6369 $a_xml_writer->xmlStartTag("qtimetadatafield");
6370 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
6371 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
6372 $a_xml_writer->xmlEndTag("qtimetadatafield");
6373
6374 $a_xml_writer->xmlStartTag("qtimetadatafield");
6375 $a_xml_writer->xmlElement("fieldlabel", NULL, "solution_details");
6376 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails());
6377 $a_xml_writer->xmlEndTag("qtimetadatafield");
6378 $a_xml_writer->xmlStartTag("qtimetadatafield");
6379 $a_xml_writer->xmlElement("fieldlabel", NULL, "print_bs_with_res");
6380 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails() ? (int)$this->isBestSolutionPrintedWithResult() : 0);
6381 $a_xml_writer->xmlEndTag("qtimetadatafield");
6382
6383 // solution details
6384 $a_xml_writer->xmlStartTag("qtimetadatafield");
6385 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
6386 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
6387 $a_xml_writer->xmlEndTag("qtimetadatafield");
6388
6389 // answer specific feedback
6390 $a_xml_writer->xmlStartTag("qtimetadatafield");
6391 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
6392 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
6393 $a_xml_writer->xmlEndTag("qtimetadatafield");
6394
6395 // answer specific feedback of reached points
6396 $a_xml_writer->xmlStartTag("qtimetadatafield");
6397 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
6398 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
6399 $a_xml_writer->xmlEndTag("qtimetadatafield");
6400
6401 // instant response answer freezing
6402 $a_xml_writer->xmlStartTag("qtimetadatafield");
6403 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6404 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6405 $a_xml_writer->xmlEndTag("qtimetadatafield");
6406
6407 // instant response forced
6408 $a_xml_writer->xmlStartTag("qtimetadatafield");
6409 $a_xml_writer->xmlElement("fieldlabel", NULL, "force_instant_feedback");
6410 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isForceInstantFeedbackEnabled());
6411 $a_xml_writer->xmlEndTag("qtimetadatafield");
6412
6413
6414 // highscore
6415 $highscore_metadata = array(
6416 'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6417 'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6418 'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6419 'highscore_score' => array('value' => $this->getHighscoreScore()),
6420 'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6421 'highscore_hints' => array('value' => $this->getHighscoreHints()),
6422 'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6423 'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6424 'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6425 'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6426 );
6427 foreach($highscore_metadata as $label => $data)
6428 {
6429 $a_xml_writer->xmlStartTag("qtimetadatafield");
6430 $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
6431 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $data['value']));
6432 $a_xml_writer->xmlEndTag("qtimetadatafield");
6433 }
6434
6435 // show cancel
6436 $a_xml_writer->xmlStartTag("qtimetadatafield");
6437 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
6438 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
6439 $a_xml_writer->xmlEndTag("qtimetadatafield");
6440
6441 // show marker
6442 $a_xml_writer->xmlStartTag("qtimetadatafield");
6443 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
6444 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
6445 $a_xml_writer->xmlEndTag("qtimetadatafield");
6446
6447 // fixed participants
6448 $a_xml_writer->xmlStartTag("qtimetadatafield");
6449 $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
6450 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
6451 $a_xml_writer->xmlEndTag("qtimetadatafield");
6452
6453 // show final statement
6454 $a_xml_writer->xmlStartTag("qtimetadatafield");
6455 $a_xml_writer->xmlElement("fieldlabel", NULL, "showfinalstatement");
6456 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6457 $a_xml_writer->xmlEndTag("qtimetadatafield");
6458
6459 // show introduction only
6460 $a_xml_writer->xmlStartTag("qtimetadatafield");
6461 $a_xml_writer->xmlElement("fieldlabel", NULL, "showinfo");
6462 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6463 $a_xml_writer->xmlEndTag("qtimetadatafield");
6464
6465 // mail notification
6466 $a_xml_writer->xmlStartTag("qtimetadatafield");
6467 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnotification");
6468 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotification());
6469 $a_xml_writer->xmlEndTag("qtimetadatafield");
6470
6471 // mail notification type
6472 $a_xml_writer->xmlStartTag("qtimetadatafield");
6473 $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnottype");
6474 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotificationType());
6475 $a_xml_writer->xmlEndTag("qtimetadatafield");
6476
6477 // export settings
6478 $a_xml_writer->xmlStartTag("qtimetadatafield");
6479 $a_xml_writer->xmlElement("fieldlabel", NULL, "exportsettings");
6480 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getExportSettings());
6481 $a_xml_writer->xmlEndTag("qtimetadatafield");
6482
6483 // force JavaScript
6484 $a_xml_writer->xmlStartTag("qtimetadatafield");
6485 $a_xml_writer->xmlElement("fieldlabel", NULL, "forcejs");
6486 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6487 $a_xml_writer->xmlEndTag("qtimetadatafield");
6488
6489 // custom style
6490 $a_xml_writer->xmlStartTag("qtimetadatafield");
6491 $a_xml_writer->xmlElement("fieldlabel", NULL, "customstyle");
6492 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCustomStyle());
6493 $a_xml_writer->xmlEndTag("qtimetadatafield");
6494
6495 // shuffle questions
6496 $a_xml_writer->xmlStartTag("qtimetadatafield");
6497 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
6498 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
6499 $a_xml_writer->xmlEndTag("qtimetadatafield");
6500
6501 // processing time
6502 $a_xml_writer->xmlStartTag("qtimetadatafield");
6503 $a_xml_writer->xmlElement("fieldlabel", NULL, "processing_time");
6504 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getProcessingTime());
6505 $a_xml_writer->xmlEndTag("qtimetadatafield");
6506
6507 // enable_examview
6508 $a_xml_writer->xmlStartTag("qtimetadatafield");
6509 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_examview");
6510 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableExamview());
6511 $a_xml_writer->xmlEndTag("qtimetadatafield");
6512
6513 // show_examview_html
6514 $a_xml_writer->xmlStartTag("qtimetadatafield");
6515 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_html");
6516 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewHtml());
6517 $a_xml_writer->xmlEndTag("qtimetadatafield");
6518
6519 // show_examview_pdf
6520 $a_xml_writer->xmlStartTag("qtimetadatafield");
6521 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_pdf");
6522 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewPdf());
6523 $a_xml_writer->xmlEndTag("qtimetadatafield");
6524
6525 // enable_archiving
6526 $a_xml_writer->xmlStartTag("qtimetadatafield");
6527 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_archiving");
6528 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableArchiving());
6529 $a_xml_writer->xmlEndTag("qtimetadatafield");
6530
6531 // sign_submission
6532 $a_xml_writer->xmlStartTag("qtimetadatafield");
6533 $a_xml_writer->xmlElement("fieldlabel", NULL, "sign_submission");
6534 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSignSubmission());
6535 $a_xml_writer->xmlEndTag("qtimetadatafield");
6536
6537 // char_selector_availability
6538 $a_xml_writer->xmlStartTag("qtimetadatafield");
6539 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_availability");
6540 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getCharSelectorAvailability()));
6541 $a_xml_writer->xmlEndTag("qtimetadatafield");
6542
6543 // char_selector_definition
6544 $a_xml_writer->xmlStartTag("qtimetadatafield");
6545 $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_definition");
6546 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCharSelectorDefinition());
6547 $a_xml_writer->xmlEndTag("qtimetadatafield");
6548
6549 // skill_service
6550 $a_xml_writer->xmlStartTag("qtimetadatafield");
6551 $a_xml_writer->xmlElement("fieldlabel", NULL, "skill_service");
6552 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isSkillServiceEnabled());
6553 $a_xml_writer->xmlEndTag("qtimetadatafield");
6554
6555 // result_tax_filters
6556 $a_xml_writer->xmlStartTag("qtimetadatafield");
6557 $a_xml_writer->xmlElement("fieldlabel", NULL, "result_tax_filters");
6558 $a_xml_writer->xmlElement("fieldentry", NULL, serialize((array)$this->getResultFilterTaxIds()));
6559 $a_xml_writer->xmlEndTag("qtimetadatafield");
6560
6561 // show_grading_status
6562 $a_xml_writer->xmlStartTag("qtimetadatafield");
6563 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_status");
6564 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingStatusEnabled());
6565 $a_xml_writer->xmlEndTag("qtimetadatafield");
6566
6567 // show_grading_mark
6568 $a_xml_writer->xmlStartTag("qtimetadatafield");
6569 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_mark");
6570 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingMarkEnabled());
6571 $a_xml_writer->xmlEndTag("qtimetadatafield");
6572
6573
6574 // starting time
6575 if ($this->getStartingTime())
6576 {
6577 $a_xml_writer->xmlStartTag("qtimetadatafield");
6578 $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
6579 $backward_compatibility_format = $this->buildIso8601PeriodFromUnixtimeForExportCompatibility($this->starting_time);
6580 $a_xml_writer->xmlElement("fieldentry", NULL, $backward_compatibility_format);
6581 $a_xml_writer->xmlEndTag("qtimetadatafield");
6582 }
6583 // ending time
6584 if ($this->getEndingTime())
6585 {
6586 $a_xml_writer->xmlStartTag("qtimetadatafield");
6587 $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
6588 $backward_compatibility_format = $this->buildIso8601PeriodFromUnixtimeForExportCompatibility($this->ending_time);
6589 $a_xml_writer->xmlElement("fieldentry", NULL, $backward_compatibility_format);
6590 $a_xml_writer->xmlEndTag("qtimetadatafield");
6591 }
6592
6593
6594 //activation_limited
6595 $a_xml_writer->xmlStartTag("qtimetadatafield");
6596 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_limited");
6597 $a_xml_writer->xmlElement("fieldentry", NULL,(int)$this->isActivationLimited());
6598 $a_xml_writer->xmlEndTag("qtimetadatafield");
6599
6600 //activation_start_time
6601 $a_xml_writer->xmlStartTag("qtimetadatafield");
6602 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_start_time");
6603 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationStartingTime());
6604 $a_xml_writer->xmlEndTag("qtimetadatafield");
6605
6606 //activation_end_time
6607 $a_xml_writer->xmlStartTag("qtimetadatafield");
6608 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_end_time");
6609 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationEndingTime());
6610 $a_xml_writer->xmlEndTag("qtimetadatafield");
6611
6612 //activation_visibility
6613 $a_xml_writer->xmlStartTag("qtimetadatafield");
6614 $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_visibility");
6615 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationVisibility());
6616 $a_xml_writer->xmlEndTag("qtimetadatafield");
6617
6618 // autosave
6619 $a_xml_writer->xmlStartTag("qtimetadatafield");
6620 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave");
6621 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosave());
6622 $a_xml_writer->xmlEndTag("qtimetadatafield");
6623
6624 // autosave_ival
6625 $a_xml_writer->xmlStartTag("qtimetadatafield");
6626 $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave_ival");
6627 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosaveIval());
6628 $a_xml_writer->xmlEndTag("qtimetadatafield");
6629
6630 //offer_question_hints
6631 $a_xml_writer->xmlStartTag("qtimetadatafield");
6632 $a_xml_writer->xmlElement("fieldlabel", NULL, "offer_question_hints");
6633 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isOfferingQuestionHintsEnabled());
6634 $a_xml_writer->xmlEndTag("qtimetadatafield");
6635
6636 //instant_feedback_specific
6637 $a_xml_writer->xmlStartTag("qtimetadatafield");
6638 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_specific");
6639 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSpecificAnswerFeedback());
6640 $a_xml_writer->xmlEndTag("qtimetadatafield");
6641
6642 //instant_feedback_answer_fixation
6643 $a_xml_writer->xmlStartTag("qtimetadatafield");
6644 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6645 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6646 $a_xml_writer->xmlEndTag("qtimetadatafield");
6647
6648 //obligations_enabled
6649 $a_xml_writer->xmlStartTag("qtimetadatafield");
6650 $a_xml_writer->xmlElement("fieldlabel", NULL, "obligations_enabled");
6651 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->areObligationsEnabled());
6652 $a_xml_writer->xmlEndTag("qtimetadatafield");
6653
6654 //enable_processing_time
6655 $a_xml_writer->xmlStartTag("qtimetadatafield");
6656 $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_processing_time");
6657 $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableProcessingTime());
6658 $a_xml_writer->xmlEndTag("qtimetadatafield");
6659
6660 foreach ($this->mark_schema->mark_steps as $index => $mark)
6661 {
6662 // mark steps
6663 $a_xml_writer->xmlStartTag("qtimetadatafield");
6664 $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
6665 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf(
6666 "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6667 $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()
6668 ));
6669 $a_xml_writer->xmlEndTag("qtimetadatafield");
6670 }
6671 $a_xml_writer->xmlEndTag("qtimetadata");
6672
6673 // add qti objectives
6674 $a_xml_writer->xmlStartTag("objectives");
6675 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6676 $a_xml_writer->xmlEndTag("objectives");
6677
6678 // add qti assessmentcontrol
6679 if ($this->getInstantFeedbackSolution() == 1)
6680 {
6681 $attrs = array(
6682 "solutionswitch" => "Yes"
6683 );
6684 }
6685 else
6686 {
6687 $attrs = NULL;
6688 }
6689 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
6690
6691 if (strlen($this->getFinalStatement()))
6692 {
6693 // add qti presentation_material
6694 $a_xml_writer->xmlStartTag("presentation_material");
6695 $a_xml_writer->xmlStartTag("flow_mat");
6696 $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6697 $a_xml_writer->xmlEndTag("flow_mat");
6698 $a_xml_writer->xmlEndTag("presentation_material");
6699 }
6700
6701 $attrs = array(
6702 "ident" => "1"
6703 );
6704 $a_xml_writer->xmlElement("section", $attrs, NULL);
6705 $a_xml_writer->xmlEndTag("assessment");
6706 $a_xml_writer->xmlEndTag("questestinterop");
6707
6708 $xml = $a_xml_writer->xmlDumpMem(FALSE);
6709 return $xml;
6710 }
6711
6717 {
6718 $date_time_unix = new ilDateTime($unix_timestamp, IL_CAL_UNIX);
6719 $date_time = $date_time_unix->get(IL_CAL_DATETIME);
6720 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $date_time, $matches);
6721 $iso8601_period = sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]);
6722 return $iso8601_period;
6723 }
6724
6731 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6732 {
6733 global $ilBench;
6734
6735 $this->mob_ids = array();
6736 $this->file_ids = array();
6737
6738 // MetaData
6739 $this->exportXMLMetaData($a_xml_writer);
6740
6741 // PageObjects
6742 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
6743 $ilBench->start("ContentObjectExport", "exportPageObjects");
6744 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6745 $ilBench->stop("ContentObjectExport", "exportPageObjects");
6746 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
6747
6748 // MediaObjects
6749 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
6750 $ilBench->start("ContentObjectExport", "exportMediaObjects");
6751 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6752 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6753 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
6754
6755 // FileItems
6756 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
6757 $ilBench->start("ContentObjectExport", "exportFileItems");
6758 $this->exportFileItems($a_target_dir, $expLog);
6759 $ilBench->stop("ContentObjectExport", "exportFileItems");
6760 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
6761 }
6762
6769 function exportXMLMetaData(&$a_xml_writer)
6770 {
6771 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6772 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6773 $md2xml->setExportMode(true);
6774 $md2xml->startExport();
6775 $a_xml_writer->appendXML($md2xml->getXML());
6776 }
6777
6783 function modifyExportIdentifier($a_tag, $a_param, $a_value)
6784 {
6785 if ($a_tag == "Identifier" && $a_param == "Entry")
6786 {
6787 include_once "./Services/Utilities/classes/class.ilUtil.php";
6788 $a_value = ilUtil::insertInstIntoID($a_value);
6789 }
6790
6791 return $a_value;
6792 }
6793
6794
6801 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6802 {
6803 global $ilBench;
6804
6805 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6806
6807 foreach ($this->questions as $question_id)
6808 {
6809 $ilBench->start("ContentObjectExport", "exportPageObject");
6810 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
6811
6812 $attrs = array();
6813 $a_xml_writer->xmlStartTag("PageObject", $attrs);
6814
6815
6816 // export xml to writer object
6817 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6818 include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6819 $page_object = new ilAssQuestionPage($question_id);
6820 $page_object->buildDom();
6821 $page_object->insertInstIntoIDs($a_inst);
6822 $mob_ids = $page_object->collectMediaObjects(false);
6823 require_once 'Services/COPage/classes/class.ilPCFileList.php';
6824 $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6825 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6826 $xml = str_replace("&","&amp;", $xml);
6827 $a_xml_writer->appendXML($xml);
6828 $page_object->freeDom();
6829 unset ($page_object);
6830
6831 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6832
6833 // collect media objects
6834 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6835 //$mob_ids = $page_obj->getMediaObjectIDs();
6836 foreach($mob_ids as $mob_id)
6837 {
6838 $this->mob_ids[$mob_id] = $mob_id;
6839 }
6840 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6841
6842 // collect all file items
6843 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6844 //$file_ids = $page_obj->getFileItemIds();
6845 foreach($file_ids as $file_id)
6846 {
6847 $this->file_ids[$file_id] = $file_id;
6848 }
6849 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6850
6851 $a_xml_writer->xmlEndTag("PageObject");
6852 //unset($page_obj);
6853
6854 $ilBench->stop("ContentObjectExport", "exportPageObject");
6855
6856
6857 }
6858 }
6859
6866 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6867 {
6868 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6869
6870 foreach ($this->mob_ids as $mob_id)
6871 {
6872 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
6873 if (ilObjMediaObject::_exists($mob_id))
6874 {
6875 $media_obj = new ilObjMediaObject($mob_id);
6876 $media_obj->exportXML($a_xml_writer, $a_inst);
6877 $media_obj->exportFiles($a_target_dir);
6878 unset($media_obj);
6879 }
6880 }
6881 }
6882
6887 function exportFileItems($a_target_dir, &$expLog)
6888 {
6889 include_once "./Modules/File/classes/class.ilObjFile.php";
6890
6891 foreach ($this->file_ids as $file_id)
6892 {
6893 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
6894 $file_obj = new ilObjFile($file_id, false);
6895 $file_obj->export($a_target_dir);
6896 unset($file_obj);
6897 }
6898 }
6899
6905 {
6906 if (!is_array($this->import_mapping))
6907 {
6908 return array();
6909 }
6910 else
6911 {
6912 return $this->import_mapping;
6913 }
6914 }
6915
6919 public function canEditEctsGrades()
6920 {
6921 return $this->canShowEctsGrades() && $this->canEditMarks();
6922 }
6923
6927 public function canShowEctsGrades()
6928 {
6929 return $this->getReportingDate();
6930 }
6931
6935 public function getECTSGrade($passed_array, $reached_points, $max_points)
6936 {
6937 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);
6938 }
6939
6943 public static function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
6944 {
6945 include_once "./Modules/Test/classes/class.ilStatistics.php";
6946 // calculate the median
6947 $passed_statistics = new ilStatistics();
6948 $passed_statistics->setData($points_passed);
6949 $ects_percentiles = array
6950 (
6951 "A" => $passed_statistics->quantile($a),
6952 "B" => $passed_statistics->quantile($b),
6953 "C" => $passed_statistics->quantile($c),
6954 "D" => $passed_statistics->quantile($d),
6955 "E" => $passed_statistics->quantile($e)
6956 );
6957 if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
6958 {
6959 return "A";
6960 }
6961 else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
6962 {
6963 return "B";
6964 }
6965 else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
6966 {
6967 return "C";
6968 }
6969 else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
6970 {
6971 return "D";
6972 }
6973 else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
6974 {
6975 return "E";
6976 }
6977 else if (strcmp($fx, "") != 0)
6978 {
6979 if ($max_points > 0)
6980 {
6981 $percentage = ($reached_points / $max_points) * 100.0;
6982 if ($percentage < 0) $percentage = 0.0;
6983 }
6984 else
6985 {
6986 $percentage = 0.0;
6987 }
6988 if ($percentage >= $fx)
6989 {
6990 return "FX";
6991 }
6992 else
6993 {
6994 return "F";
6995 }
6996 }
6997 else
6998 {
6999 return "F";
7000 }
7001 }
7002
7006 public function checkMarks()
7007 {
7008 return $this->mark_schema->checkMarks();
7009 }
7010
7014 public function getMarkSchema()
7015 {
7016 return $this->mark_schema;
7017 }
7018
7022 public function getMarkSchemaForeignId()
7023 {
7024 return $this->getTestId();
7025 }
7026
7029 public function onMarkSchemaSaved()
7030 {
7036 global $ilDB, $ilPluginAdmin, $tree;
7037
7038 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7039 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7040 $this->saveCompleteStatus($testQuestionSetConfigFactory->getQuestionSetConfig());
7041
7042 if( $this->participantDataExist() )
7043 {
7044 $this->recalculateScores(true);
7045 }
7046 }
7047
7051 public function canEditMarks()
7052 {
7053 $total = $this->evalTotalPersons();
7054 if($total > 0)
7055 {
7056 if($this->getReportingDate())
7057 {
7058 if(preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
7059 {
7060 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
7061 $now = time();
7062 if($now < $epoch_time)
7063 {
7064 return true;
7065 }
7066 }
7067 }
7068 return false;
7069 }
7070 else
7071 {
7072 return true;
7073 }
7074 }
7075
7083 function setAuthor($author = "")
7084 {
7085 $this->author = $author;
7086 }
7087
7097 function saveAuthorToMetadata($a_author = "")
7098 {
7099 $md = new ilMD($this->getId(), 0, $this->getType());
7100 $md_life =& $md->getLifecycle();
7101 if (!$md_life)
7102 {
7103 if (strlen($a_author) == 0)
7104 {
7105 global $ilUser;
7106 $a_author = $ilUser->getFullname();
7107 }
7108
7109 $md_life =& $md->addLifecycle();
7110 $md_life->save();
7111 $con =& $md_life->addContribute();
7112 $con->setRole("Author");
7113 $con->save();
7114 $ent =& $con->addEntity();
7115 $ent->setEntity($a_author);
7116 $ent->save();
7117 }
7118 }
7119
7126 {
7127 parent::createMetaData();
7128 $this->saveAuthorToMetadata();
7129 }
7130
7138 function getAuthor()
7139 {
7140 $author = array();
7141 include_once "./Services/MetaData/classes/class.ilMD.php";
7142 $md = new ilMD($this->getId(), 0, $this->getType());
7143 $md_life =& $md->getLifecycle();
7144 if ($md_life)
7145 {
7146 $ids =& $md_life->getContributeIds();
7147 foreach ($ids as $id)
7148 {
7149 $md_cont =& $md_life->getContribute($id);
7150 if (strcmp($md_cont->getRole(), "Author") == 0)
7151 {
7152 $entids =& $md_cont->getEntityIds();
7153 foreach ($entids as $entid)
7154 {
7155 $md_ent =& $md_cont->getEntity($entid);
7156 array_push($author, $md_ent->getEntity());
7157 }
7158 }
7159 }
7160 }
7161 return join($author, ",");
7162 }
7163
7171 public static function _lookupAuthor($obj_id)
7172 {
7173 $author = array();
7174 include_once "./Services/MetaData/classes/class.ilMD.php";
7175 $md = new ilMD($obj_id, 0, "tst");
7176 $md_life =& $md->getLifecycle();
7177 if ($md_life)
7178 {
7179 $ids =& $md_life->getContributeIds();
7180 foreach ($ids as $id)
7181 {
7182 $md_cont =& $md_life->getContribute($id);
7183 if (strcmp($md_cont->getRole(), "Author") == 0)
7184 {
7185 $entids =& $md_cont->getEntityIds();
7186 foreach ($entids as $entid)
7187 {
7188 $md_ent =& $md_cont->getEntity($entid);
7189 array_push($author, $md_ent->getEntity());
7190 }
7191 }
7192 }
7193 }
7194 return join($author, ",");
7195 }
7196
7203 public static function _getAvailableTests($use_object_id = FALSE)
7204 {
7205 global $ilUser;
7206 global $ilDB;
7207
7208 $result_array = array();
7209 $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
7210 if (count($tests))
7211 {
7212 $titles = ilObject::_prepareCloneSelection($tests, "tst");
7213 foreach ($tests as $ref_id)
7214 {
7215 if ($use_object_id)
7216 {
7218 $result_array[$obj_id] = $titles[$ref_id];
7219 }
7220 else
7221 {
7222 $result_array[$ref_id] = $titles[$ref_id];
7223 }
7224 }
7225 }
7226 return $result_array;
7227 }
7228
7237 public function cloneObject($a_target_id,$a_copy_id = 0, $a_omit_tree = false)
7238 {
7239 global $ilLog, $tree, $ilDB, $ilPluginAdmin;
7240
7241 $this->loadFromDb();
7242
7243 // Copy settings
7245 $newObj = parent::cloneObject($a_target_id,$a_copy_id, $a_omit_tree);
7246 $newObj->setTmpCopyWizardCopyId($a_copy_id);
7247 $this->cloneMetaData($newObj);
7248
7249 //copy online status if object is not the root copy object
7250 $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
7251
7252 if(!$cp_options->isRootNode($this->getRefId()))
7253 {
7254 $newObj->setOnline($this->isOnline());
7255 }
7256
7257 $newObj->setAnonymity($this->getAnonymity());
7258 $newObj->setAnswerFeedback($this->getAnswerFeedback());
7259 $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
7260 $newObj->setAuthor($this->getAuthor());
7261 $newObj->setLimitUsersEnabled($this->isLimitUsersEnabled());
7262 $newObj->setAllowedUsers($this->getAllowedUsers());
7263 $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
7264 $newObj->setCountSystem($this->getCountSystem());
7265 $newObj->setECTSFX($this->getECTSFX());
7266 $newObj->setECTSGrades($this->getECTSGrades());
7267 $newObj->setECTSOutput($this->getECTSOutput());
7268 $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
7269 $newObj->setEndingTimeEnabled($this->isEndingTimeEnabled());
7270 $newObj->setEndingTime($this->getEndingTime());
7271 $newObj->setFixedParticipants($this->getFixedParticipants());
7272 $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
7273 $newObj->setIntroductionEnabled($this->isIntroductionEnabled());
7274 $newObj->setIntroduction($this->getIntroduction());
7275 $newObj->setFinalStatement($this->getFinalStatement());
7276 $newObj->setShowInfo($this->getShowInfo());
7277 $newObj->setForceJS($this->getForceJS());
7278 $newObj->setCustomStyle($this->getCustomStyle());
7279 $newObj->setKiosk($this->getKiosk());
7280 $newObj->setShowFinalStatement($this->getShowFinalStatement());
7281 $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
7282 $newObj->setMCScoring($this->getMCScoring());
7283 $newObj->setMailNotification($this->getMailNotification());
7284 $newObj->setMailNotificationType($this->getMailNotificationType());
7285 $newObj->setNrOfTries($this->getNrOfTries());
7286 $newObj->setPassScoring($this->getPassScoring());
7287 $newObj->setPasswordEnabled($this->isPasswordEnabled());
7288 $newObj->setPassword($this->getPassword());
7289 $newObj->setProcessingTime($this->getProcessingTime());
7290 $newObj->setQuestionSetType($this->getQuestionSetType());
7291 $newObj->setReportingDate($this->getReportingDate());
7292 $newObj->setResetProcessingTime($this->getResetProcessingTime());
7293 $newObj->setResultsPresentation($this->getResultsPresentation());
7294 $newObj->setScoreCutting($this->getScoreCutting());
7295 $newObj->setScoreReporting($this->getScoreReporting());
7296 $newObj->setSequenceSettings($this->getSequenceSettings());
7297 $newObj->setShowCancel($this->getShowCancel());
7298 $newObj->setShowMarker($this->getShowMarker());
7299 $newObj->setShuffleQuestions($this->getShuffleQuestions());
7300 $newObj->setStartingTimeEnabled($this->isStartingTimeEnabled());
7301 $newObj->setStartingTime($this->getStartingTime());
7302 $newObj->setTitleOutput($this->getTitleOutput());
7303 $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
7304 $newObj->setRedirectionMode($this->getRedirectionMode());
7305 $newObj->setRedirectionUrl($this->getRedirectionUrl());
7306 $newObj->setCertificateVisibility($this->getCertificateVisibility());
7307 $newObj->mark_schema = clone $this->mark_schema;
7308 $newObj->setEnabledViewMode($this->getEnabledViewMode());
7309 $newObj->setTemplate($this->getTemplate());
7310 $newObj->setPoolUsage($this->getPoolUsage());
7311 $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
7312 $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
7313 $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
7314 $newObj->setEnableExamView($this->getEnableExamview());
7315 $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7316 $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7317 $newObj->setEnableArchiving($this->getEnableArchiving());
7318 $newObj->setSignSubmission($this->getSignSubmission());
7319 $newObj->setCharSelectorAvailability((int)$this->getCharSelectorAvailability());
7320 $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7321 $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
7322 $newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
7323 $newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
7324 $newObj->setForceInstantFeedbackEnabled($this->isForceInstantFeedbackEnabled());
7325 $newObj->setAutosave($this->getAutosave());
7326 $newObj->setAutosaveIval($this->getAutosaveIval());
7327 $newObj->setOfferingQuestionHintsEnabled($this->isOfferingQuestionHintsEnabled());
7328 $newObj->setSpecificAnswerFeedback($this->getSpecificAnswerFeedback());
7329 $newObj->setObligationsEnabled($this->areObligationsEnabled());
7330 $newObj->saveToDb();
7331
7332 // clone certificate
7333 include_once "./Services/Certificate/classes/class.ilCertificate.php";
7334 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7335 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7336 $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7337 $cert->cloneCertificate($newcert);
7338
7339 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7340 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7341 $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7342
7343 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdList.php';
7344 $skillLevelThresholdList = new ilTestSkillLevelThresholdList($ilDB);
7345 $skillLevelThresholdList->setTestId($this->getTestId());
7346 $skillLevelThresholdList->loadFromDb();
7347 $skillLevelThresholdList->cloneListForTest($newObj->getTestId());
7348
7349 $newObj->saveToDb();
7350 $newObj->updateMetaData();// #14467
7351
7352 include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
7353 $obj_settings = new ilLPObjSettings($this->getId());
7354 $obj_settings->cloneSettings($newObj->getId());
7355
7356 return $newObj;
7357 }
7358
7366 {
7367 $num = 0;
7368
7369 if( $this->isRandomTest() )
7370 {
7371 global $tree, $ilDB, $ilPluginAdmin;
7372
7373 $questionSetConfig = new ilTestRandomQuestionSetConfig(
7374 $tree, $ilDB, $ilPluginAdmin, $this
7375 );
7376
7377 $questionSetConfig->loadFromDb();
7378
7379 if( $questionSetConfig->isQuestionAmountConfigurationModePerPool() )
7380 {
7381 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7382 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7383 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7384
7385 $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList(
7387 );
7388
7389 $sourcePoolDefinitionList->loadDefinitions();
7390
7391 $num = $sourcePoolDefinitionList->getQuestionAmount();
7392 }
7393 else
7394 {
7395 $num = $questionSetConfig->getQuestionAmountPerTest();
7396 }
7397 }
7398 else
7399 {
7400 $num = count($this->questions);
7401 }
7402
7403 return $num;
7404 }
7405
7413 function logAction($logtext = "", $question_id = "")
7414 {
7415 global $ilUser;
7416
7417 $original_id = "";
7418 if (strcmp($question_id, "") != 0)
7419 {
7420 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7421 $original_id = assQuestion::_getOriginalId($question_id);
7422 }
7423 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7424 ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
7425 }
7426
7434 public static function _getObjectIDFromTestID($test_id)
7435 {
7436 global $ilDB;
7437 $object_id = FALSE;
7438 $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7439 array('integer'),
7440 array($test_id)
7441 );
7442 if ($result->numRows())
7443 {
7444 $row = $ilDB->fetchAssoc($result);
7445 $object_id = $row["obj_fi"];
7446 }
7447 return $object_id;
7448 }
7449
7457 public static function _getObjectIDFromActiveID($active_id)
7458 {
7459 global $ilDB;
7460 $object_id = FALSE;
7461 $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",
7462 array('integer'),
7463 array($active_id)
7464 );
7465 if ($result->numRows())
7466 {
7467 $row = $ilDB->fetchAssoc($result);
7468 $object_id = $row["obj_fi"];
7469 }
7470 return $object_id;
7471 }
7472
7480 public static function _getTestIDFromObjectID($object_id)
7481 {
7482 global $ilDB;
7483 $test_id = FALSE;
7484 $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7485 array('integer'),
7486 array($object_id)
7487 );
7488 if ($result->numRows())
7489 {
7490 $row = $ilDB->fetchAssoc($result);
7491 $test_id = $row["test_id"];
7492 }
7493 return $test_id;
7494 }
7495
7504 function getTextAnswer($active_id, $question_id, $pass = NULL)
7505 {
7506 global $ilDB;
7507
7508 $res = "";
7509 if (($active_id) && ($question_id))
7510 {
7511 if (is_null($pass))
7512 {
7513 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7514 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7515 }
7516 $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7517 array('integer', 'integer', 'integer'),
7518 array($active_id, $question_id, $pass)
7519 );
7520 if ($result->numRows() == 1)
7521 {
7522 $row = $ilDB->fetchAssoc($result);
7523 $res = $row["value1"];
7524 }
7525 }
7526 return $res;
7527 }
7528
7536 function getQuestiontext($question_id)
7537 {
7538 global $ilDB;
7539
7540 $res = "";
7541 if ($question_id)
7542 {
7543 $result = $ilDB->queryF("SELECT question_text FROM qpl_questions WHERE question_id = %s",
7544 array('integer'),
7545 array($question_id)
7546 );
7547 if ($result->numRows() == 1)
7548 {
7549 $row = $ilDB->fetchAssoc($result);
7550 $res = $row["question_text"];
7551 }
7552 }
7553 return $res;
7554 }
7555
7562 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7563 {
7564 global $ilDB;
7565
7566 $result_array = array();
7567
7568 if ($this->getAnonymity())
7569 {
7570 if (is_numeric($user_id))
7571 {
7572 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7573 "tst_active.submitted test_finished, matriculation, COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes 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('text', 'text', 'text', 'integer', 'integer'),
7578 array("", $this->lng->txt("anonymous"), "", $this->getTestId(), $user_id)
7579 );
7580 }
7581 else
7582 {
7583 $result = $ilDB->queryF("SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7584 "tst_active.submitted test_finished, matriculation, COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes 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('text', 'text', 'text', 'integer'),
7589 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7590 );
7591 }
7592 }
7593 else
7594 {
7595 if (is_numeric($user_id))
7596 {
7597 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7598 "tst_active.submitted test_finished, matriculation, COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes FROM usr_data, tst_invited_user " .
7599 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7600 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7601 "ORDER BY $order",
7602 array('integer', 'integer'),
7603 array($this->getTestId(), $user_id)
7604 );
7605 }
7606 else
7607 {
7608 $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7609 "tst_active.submitted test_finished, matriculation, COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes FROM usr_data, tst_invited_user " .
7610 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7611 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7612 "ORDER BY $order",
7613 array('integer'),
7614 array($this->getTestId())
7615 );
7616 }
7617 }
7618 $result_array = array();
7619 while ($row = $ilDB->fetchAssoc($result))
7620 {
7621 $result_array[$row['usr_id']]= $row;
7622 }
7623 return $result_array;
7624 }
7625
7633 {
7634 global $ilDB;
7635
7636 if ($this->getAnonymity())
7637 {
7638 $query = "
7639 SELECT tst_active.active_id,
7640 tst_active.tries,
7641 tst_active.user_fi usr_id,
7642 %s login,
7643 %s lastname,
7644 %s firstname,
7645 tst_active.submitted test_finished,
7646 usr_data.matriculation,
7647 usr_data.active,
7648 tst_active.lastindex,
7649 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes
7650 FROM tst_active
7651 LEFT JOIN usr_data
7652 ON tst_active.user_fi = usr_data.usr_id
7653 WHERE tst_active.test_fi = %s
7654 ORDER BY usr_data.lastname
7655 ";
7656 $result = $ilDB->queryF($query,
7657 array('text', 'text', 'text', 'integer'),
7658 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7659 );
7660 }
7661 else
7662 {
7663 $query = "
7664 SELECT tst_active.active_id,
7665 tst_active.tries,
7666 tst_active.user_fi usr_id,
7667 usr_data.login,
7668 usr_data.lastname,
7669 usr_data.firstname,
7670 tst_active.submitted test_finished,
7671 usr_data.matriculation,
7672 usr_data.active,
7673 tst_active.lastindex,
7674 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes
7675 FROM tst_active
7676 LEFT JOIN usr_data
7677 ON tst_active.user_fi = usr_data.usr_id
7678 WHERE tst_active.test_fi = %s
7679 ORDER BY usr_data.lastname
7680 ";
7681 $result = $ilDB->queryF(
7682 $query, array('integer'), array($this->getTestId())
7683 );
7684 }
7685 $data = array();
7686 while ($row = $ilDB->fetchAssoc($result))
7687 {
7688 $data[$row['active_id']] = $row;
7689 }
7690 foreach ($data as $index => $participant)
7691 {
7692 if (strlen(trim($participant["firstname"].$participant["lastname"])) == 0)
7693 {
7694 $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7695 }
7696 }
7697 return $data;
7698 }
7699
7700 public function getTestParticipantsForManualScoring($filter = NULL)
7701 {
7702 global $ilDB;
7703
7704 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7706 if (count($scoring) == 0) return array();
7707
7708 $participants =& $this->getTestParticipants();
7709 $filtered_participants = array();
7710 foreach ($participants as $active_id => $participant)
7711 {
7712 $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7713
7714 $queryString = "
7715 SELECT tst_test_result.manual
7716
7717 FROM tst_test_result
7718
7719 INNER JOIN qpl_questions
7720 ON tst_test_result.question_fi = qpl_questions.question_id
7721
7722 WHERE tst_test_result.active_fi = %s
7723 AND $qstType_IN_manScoreableQstTypes
7724 ";
7725
7726 $result = $ilDB->queryF(
7727 $queryString, array("integer"), array($active_id)
7728 );
7729
7730 $count = $result->numRows();
7731
7732 if ($count > 0)
7733 {
7734 switch ($filter)
7735 {
7736 case 1: // only active users
7737 if ($participant->active) $filtered_participants[$active_id] = $participant;
7738 break;
7739 case 2: // only inactive users
7740 if (!$participant->active) $filtered_participants[$active_id] = $participant;
7741 break;
7742 case 3: // all users
7743 $filtered_participants[$active_id] = $participant;
7744 break;
7745 case 4:
7746 // already scored participants
7747 //$found = 0;
7748 //while ($row = $ilDB->fetchAssoc($result))
7749 //{
7750 // if ($row["manual"]) $found++;
7751 //}
7752 //if ($found == $count)
7753 //{
7754 //$filtered_participants[$active_id] = $participant;
7755 //}
7756 //else
7757 //{
7758 $assessmentSetting = new ilSetting("assessment");
7759 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7760 if ($manscoring_done) $filtered_participants[$active_id] = $participant;
7761 //}
7762 break;
7763 case 5:
7764 // unscored participants
7765 //$found = 0;
7766 //while ($row = $ilDB->fetchAssoc($result))
7767 //{
7768 // if ($row["manual"]) $found++;
7769 //}
7770 //if ($found == 0)
7771 //{
7772 $assessmentSetting = new ilSetting("assessment");
7773 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7774 if (!$manscoring_done) $filtered_participants[$active_id] = $participant;
7775 //}
7776 break;
7777 case 6:
7778 // partially scored participants
7779 $found = 0;
7780 while ($row = $ilDB->fetchAssoc($result))
7781 {
7782 if ($row["manual"]) $found++;
7783 }
7784 if (($found > 0) && ($found < $count)) $filtered_participants[$active_id] = $participant;
7785 break;
7786 default:
7787 $filtered_participants[$active_id] = $participant;
7788 break;
7789 }
7790 }
7791 }
7792 return $filtered_participants;
7793 }
7794
7802 function &getUserData($ids)
7803 {
7804 global $ilDB;
7805
7806 if (!is_array($ids) || count($ids) ==0) return array();
7807
7808 if ($this->getAnonymity())
7809 {
7810 $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",
7811 array('text', 'text', 'text'),
7812 array("", $this->lng->txt("anonymous"), "")
7813 );
7814 }
7815 else
7816 {
7817 $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");
7818 }
7819
7820 $result_array = array();
7821 while ($row = $ilDB->fetchAssoc($result))
7822 {
7823 $result_array[$row["usr_id"]]= $row;
7824 }
7825 return $result_array;
7826 }
7827
7828 function &getGroupData($ids)
7829 {
7830 if (!is_array($ids) || count($ids) ==0) return array();
7831 $result = array();
7832 foreach ($ids as $ref_id)
7833 {
7835 $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7836 }
7837 return $result;
7838 }
7839
7840 function &getRoleData($ids)
7841 {
7842 if (!is_array($ids) || count($ids) ==0) return array();
7843 $result = array();
7844 foreach ($ids as $obj_id)
7845 {
7846 $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7847 }
7848 return $result;
7849 }
7850
7851
7858 function inviteGroup($group_id)
7859 {
7860 include_once "./Modules/Group/classes/class.ilObjGroup.php";
7861 $group = new ilObjGroup($group_id);
7862 $members = $group->getGroupMemberIds();
7863 include_once './Services/User/classes/class.ilObjUser.php';
7864 foreach ($members as $user_id)
7865 {
7866 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7867 }
7868 }
7869
7876 function inviteRole($role_id)
7877 {
7878 global $rbacreview;
7879 $members = $rbacreview->assignedUsers($role_id);
7880 include_once './Services/User/classes/class.ilObjUser.php';
7881 foreach ($members as $user_id)
7882 {
7883 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7884 }
7885 }
7886
7887
7888
7895 function disinviteUser($user_id)
7896 {
7897 global $ilDB;
7898
7899 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7900 array('integer', 'integer'),
7901 array($this->getTestId(), $user_id)
7902 );
7903 }
7904
7911 function inviteUser($user_id, $client_ip="")
7912 {
7913 global $ilDB;
7914
7915 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7916 array('integer', 'integer'),
7917 array($this->getTestId(), $user_id)
7918 );
7919 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7920 array('integer', 'integer', 'text', 'integer'),
7921 array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : NULL, time())
7922 );
7923 }
7924
7925
7926 function setClientIP($user_id, $client_ip)
7927 {
7928 global $ilDB;
7929
7930 $affectedRows = $ilDB->manipulateF("UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7931 array('text', 'integer', 'integer', 'integer'),
7932 array((strlen($client_ip)) ? $client_ip : NULL, time(), $this->getTestId(), $user_id)
7933 );
7934 }
7935
7941 public static function _getSolvedQuestions($active_id, $question_fi = null)
7942 {
7943 global $ilDB;
7944 if (is_numeric($question_fi))
7945 {
7946 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7947 array('integer', 'integer'),
7948 array($active_id, $question_fi)
7949 );
7950 }
7951 else
7952 {
7953 $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7954 array('integer'),
7955 array($active_id)
7956 );
7957 }
7958 $result_array = array();
7959 while ($row = $ilDB->fetchAssoc($result))
7960 {
7961 $result_array[$row["question_fi"]]= $row;
7962 }
7963 return $result_array;
7964 }
7965
7966
7970 function setQuestionSetSolved($value, $question_id, $user_id)
7971 {
7972 global $ilDB;
7973
7974 $active_id = $this->getActiveIdOfUser($user_id);
7975 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
7976 array('integer', 'integer'),
7977 array($active_id, $question_id)
7978 );
7979 $affectedRows = $ilDB->manipulateF("INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
7980 array('integer', 'integer', 'integer'),
7981 array($value, $question_id, $active_id)
7982 );
7983 }
7984
7988 function isTestFinished($active_id)
7989 {
7990 global $ilDB;
7991
7992 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
7993 array('integer', 'integer'),
7994 array($active_id, 1)
7995 );
7996 return $result->numRows() == 1;
7997 }
7998
8002 function isActiveTestSubmitted($user_id = null)
8003 {
8004 global $ilUser;
8005 global $ilDB;
8006
8007 if (!is_numeric($user_id))
8008 $user_id = $ilUser->getId();
8009
8010 $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
8011 array('integer', 'integer', 'integer'),
8012 array($this->getTestId(), $user_id, 1)
8013 );
8014 return $result->numRows() == 1;
8015 }
8016
8021 {
8022 return $this->getNrOfTries() != 0;
8023 }
8024
8025
8031 function isNrOfTriesReached($tries)
8032 {
8033 return $tries >= (int) $this->getNrOfTries();
8034 }
8035
8036
8045 function getAllTestResults($participants, $prepareForCSV = true)
8046 {
8047 $results = array();
8048 $row = array(
8049 "user_id" => $this->lng->txt("user_id"),
8050 "matriculation" => $this->lng->txt("matriculation"),
8051 "lastname" => $this->lng->txt("lastname"),
8052 "firstname" => $this->lng->txt("firstname"),
8053 "login" =>$this->lng->txt("login"),
8054 "reached_points" => $this->lng->txt("tst_reached_points"),
8055 "max_points" => $this->lng->txt("tst_maximum_points"),
8056 "percent_value" => $this->lng->txt("tst_percent_solved"),
8057 "mark" => $this->lng->txt("tst_mark"),
8058 "ects" => $this->lng->txt("ects_grade")
8059 );
8060 $results[] = $row;
8061 if (count($participants))
8062 {
8063 if($this->getECTSOutput())
8064 {
8065 $passed_array =& $this->getTotalPointsPassedArray();
8066 }
8067 foreach ($participants as $active_id => $user_rec)
8068 {
8069 $mark = $ects_mark = '';
8070 $row = array();
8071 $reached_points = 0;
8072 $max_points = 0;
8073 foreach ($this->questions as $value)
8074 {
8075 $question =& ilObjTest::_instanciateQuestion($value);
8076 if (is_object($question))
8077 {
8078 $max_points += $question->getMaximumPoints();
8079 $reached_points += $question->getReachedPoints($active_id);
8080 }
8081 }
8082 if ($max_points > 0)
8083 {
8084 $percentvalue = $reached_points / $max_points;
8085 if ($percentvalue < 0) $percentvalue = 0.0;
8086 }
8087 else
8088 {
8089 $percentvalue = 0;
8090 }
8091 $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
8092 $passed = "";
8093 if ($mark_obj)
8094 {
8095 $mark = $mark_obj->getOfficialName();
8096 if($this->getECTSOutput())
8097 {
8098 $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
8099 }
8100 }
8101 if ($this->getAnonymity())
8102 {
8103 $user_rec['firstname'] = "";
8104 $user_rec['lastname'] = $this->lng->txt("anonymous");
8105 }
8106 $row = array(
8107 "user_id"=>$user_rec['usr_id'],
8108 "matriculation" => $user_rec['matriculation'],
8109 "lastname" => $user_rec['lastname'],
8110 "firstname" => $user_rec['firstname'],
8111 "login"=>$user_rec['login'],
8112 "reached_points" => $reached_points,
8113 "max_points" => $max_points,
8114 "percent_value" => $percentvalue,
8115 "mark" => $mark,
8116 "ects" => $ects_mark
8117 );
8118 $results[] = $prepareForCSV ? $this->processCSVRow ($row, true) : $row;
8119 }
8120 }
8121 return $results;
8122 }
8123
8134 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
8135 {
8136 $resultarray = array();
8137 foreach ($row as $rowindex => $entry)
8138 {
8139 $surround = FALSE;
8140 if ($quoteAll)
8141 {
8142 $surround = TRUE;
8143 }
8144 if (strpos($entry, "\"") !== FALSE)
8145 {
8146 $entry = str_replace("\"", "\"\"", $entry);
8147 $surround = TRUE;
8148 }
8149 if (strpos($entry, $separator) !== FALSE)
8150 {
8151 $surround = TRUE;
8152 }
8153 // replace all CR LF with LF (for Excel for Windows compatibility
8154 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
8155
8156 if ($surround)
8157 {
8158 $entry = "\"" . $entry . "\"";
8159 }
8160
8161 $resultarray[$rowindex] = $entry;
8162 }
8163 return $resultarray;
8164 }
8165
8174 public static function _getPass($active_id)
8175 {
8176 global $ilDB;
8177 $result = $ilDB->queryF("SELECT tries FROM tst_active WHERE active_id = %s",
8178 array('integer'),
8179 array($active_id)
8180 );
8181 if ($result->numRows())
8182 {
8183 $row = $ilDB->fetchAssoc($result);
8184 return $row["tries"];
8185 }
8186 else
8187 {
8188 return 0;
8189 }
8190 }
8191
8201 public static function _getMaxPass($active_id)
8202 {
8203 global $ilDB;
8204 $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
8205 array('integer'),
8206 array($active_id)
8207 );
8208 if ($result->numRows())
8209 {
8210 $row = $ilDB->fetchAssoc($result);
8211 $max = $row["maxpass"];
8212 }
8213 else
8214 {
8215 $max = NULL;
8216 }
8217 return $max;
8218 }
8219
8225 public static function _getBestPass($active_id)
8226 {
8227 global $ilDB;
8228
8229 $result = $ilDB->queryF("SELECT * FROM tst_pass_result WHERE active_fi = %s",
8230 array('integer'),
8231 array($active_id)
8232 );
8233 if ($result->numRows())
8234 {
8235 $bestrow = null;
8236 $bestfactor = 0;
8237 while ($row = $ilDB->fetchAssoc($result))
8238 {
8239 if($row["maxpoints"] > 0)
8240 {
8241 $factor = $row["points"] / $row["maxpoints"];
8242 }
8243 else
8244 {
8245 $factor = 0;
8246 }
8247
8248 if($factor > $bestfactor)
8249 {
8250 $bestrow = $row;
8251 $bestfactor = $factor;
8252 }
8253 }
8254 if (is_array($bestrow))
8255 {
8256 return $bestrow["pass"];
8257 }
8258 else
8259 {
8260 return 0;
8261 }
8262 }
8263 else
8264 {
8265 return 0;
8266 }
8267 }
8268
8277 public static function _getResultPass($active_id)
8278 {
8279 $counted_pass = NULL;
8281 {
8282 $counted_pass = ilObjTest::_getBestPass($active_id);
8283 }
8284 else
8285 {
8286 $counted_pass = ilObjTest::_getMaxPass($active_id);
8287 }
8288 return $counted_pass;
8289 }
8290
8300 function getAnsweredQuestionCount($active_id, $pass = NULL)
8301 {
8302 if( $this->isDynamicTest() )
8303 {
8304 global $tree, $ilDB, $lng, $ilPluginAdmin;
8305
8306 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
8307 $testSessionFactory = new ilTestSessionFactory($this);
8308 $testSession = $testSessionFactory->getSession($active_id);
8309
8310 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
8311 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
8312 $testSequence = $testSequenceFactory->getSequenceByTestSession($testSession);
8313
8314 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
8315 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
8316 $dynamicQuestionSetConfig->loadFromDb();
8317
8318 $testSequence->loadFromDb($dynamicQuestionSetConfig);
8319 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
8320
8321 return $testSequence->getTrackedQuestionCount();
8322 }
8323
8324 if ($this->isRandomTest())
8325 {
8326 $this->loadQuestions($active_id, $pass);
8327 }
8328 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
8329 $workedthrough = 0;
8330 foreach ($this->questions as $value)
8331 {
8332 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
8333 {
8334 $workedthrough += 1;
8335 }
8336 }
8337 return $workedthrough;
8338 }
8339
8349 function getPassFinishDate($active_id, $pass)
8350 {
8351 global $ilDB;
8352
8353 if (is_null($pass))
8354 {
8355 $pass = 0;
8356 }
8357
8358 $query = "
8359 SELECT tst_pass_result.tstamp pass_res_tstamp,
8360 tst_test_result.tstamp quest_res_tstamp
8361
8362 FROM tst_pass_result
8363
8364 LEFT JOIN tst_test_result
8365 ON tst_test_result.active_fi = tst_pass_result.active_fi
8366 AND tst_test_result.pass = tst_pass_result.pass
8367
8368 WHERE tst_pass_result.active_fi = %s
8369 AND tst_pass_result.pass = %s
8370
8371 ORDER BY tst_test_result.tstamp DESC
8372 ";
8373
8374 $result = $ilDB->queryF($query,
8375 array('integer', 'integer'),
8376 array($active_id, $pass)
8377 );
8378
8379 while( $row = $ilDB->fetchAssoc($result) )
8380 {
8381 if( $row['qres_tstamp'] )
8382 {
8383 return $row['quest_res_tstamp'];
8384 }
8385
8386 return $row['pass_res_tstamp'];
8387 }
8388
8389 return 0;
8390 }
8391
8400 function isExecutable($testSession, $user_id, $allowPassIncrease = FALSE)
8401 {
8402 $result = array(
8403 "executable" => true,
8404 "errormessage" => ""
8405 );
8406 if (!$this->startingTimeReached())
8407 {
8408 $result["executable"] = false;
8409 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getStartingTime(), IL_CAL_UNIX)));
8410 return $result;
8411 }
8412 if ($this->endingTimeReached())
8413 {
8414 $result["executable"] = false;
8415 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getEndingTime(), IL_CAL_UNIX)));
8416 return $result;
8417 }
8418
8419 $active_id = $this->getActiveIdOfUser($user_id);
8420
8421 if ($this->getEnableProcessingTime())
8422 {
8423 if ($active_id > 0)
8424 {
8425 $starting_time = $this->getStartingTimeOfUser($active_id);
8426 if ($starting_time !== FALSE)
8427 {
8428 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8429 {
8430 if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > (self::_getPass($active_id)+1))))
8431 {
8432 // a test pass was quitted because the maximum processing time was reached, but the time
8433 // will be resetted for future passes, so if there are more passes allowed, the participant may
8434 // start the test again.
8435 // This code block is only called when $allowPassIncrease is TRUE which only happens when
8436 // the test info page is opened. Otherwise this will lead to unexpected results!
8437 $testSession->increasePass();
8438 $testSession->setLastSequence(0);
8439 $testSession->saveToDb();
8440 }
8441 else
8442 {
8443 $result["executable"] = false;
8444 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8445 }
8446 return $result;
8447 }
8448 }
8449 }
8450 }
8451 require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8452 $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8453 $testPassesSelector->setActiveId($active_id);
8454 $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8455
8456 if ($this->hasNrOfTriesRestriction() && ($active_id > 0))
8457 {
8458 $closedPasses = $testPassesSelector->getClosedPasses();
8459
8460 if( count($closedPasses) >= $this->getNrOfTries() )
8461 {
8462 $result["executable"] = false;
8463 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8464 return $result;
8465 }
8466 }
8467 if($this->isPassWaitingEnabled() && $testPassesSelector->getLastFinishedPass() !== null)
8468 {
8469 $lastPass = $testPassesSelector->getLastFinishedPassTimestamp();
8470 if($lastPass && strlen($this->getPassWaiting()))
8471 {
8472 $pass_waiting_string = $this->getPassWaiting();
8473 $time_values = explode(":", $pass_waiting_string);
8474 $next_pass_allowed = strtotime('+ ' . $time_values[0] . ' Months + ' . $time_values[1] . ' Days + ' . $time_values[2] . ' Hours' . $time_values[3] . ' Minutes', $lastPass);
8475
8476 if(time() < $next_pass_allowed)
8477 {
8478 $date = ilDatePresentation::formatDate(new ilDateTime($next_pass_allowed, IL_CAL_UNIX));
8479
8480 $result["executable"] = false;
8481 $result["errormessage"] = sprintf($this->lng->txt('wait_for_next_pass_hint_msg'), $date);
8482 return $result;
8483 }
8484 }
8485 }
8486 return $result;
8487 }
8488
8497 {
8498 // this logic was implemented before, it got stabled only for now
8499 // this method is not as exact as it's required, it's to be replaced in the long time
8500
8501 switch( $this->getScoreReporting() )
8502 {
8504 case self::SCORE_REPORTING_FINISHED: // this isn't excact enough
8505
8506 return true;
8507
8509
8510 if (!$this->getReportingDate())
8511 {
8512 return false;
8513 }
8514
8515 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8516 {
8517 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8518 $now = time();
8519 if ($now < $epoch_time)
8520 {
8521 return false;
8522 }
8523 }
8524
8525 return true;
8526 }
8527
8528 return false;
8529 }
8530
8532 {
8533 $active_id = $testSession->getActiveId();
8534 if ($active_id > 0)
8535 {
8536 $starting_time = $this->getStartingTimeOfUser($active_id);
8537 }
8538 $notimeleft = FALSE;
8539 if ($starting_time !== FALSE)
8540 {
8541 if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8542 {
8543 $notimeleft = TRUE;
8544 }
8545 }
8546 $result = TRUE;
8547 if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
8548 {
8549 $result = FALSE;
8550 }
8551 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
8552 $result = $result & $this->canViewResults();
8553 return $result;
8554 }
8555
8563 function getStartingTimeOfUser($active_id, $pass = null)
8564 {
8565 global $ilDB;
8566
8567 if ($active_id < 1) return FALSE;
8568 if($pass === null)
8569 {
8570 $pass = ($this->getResetProcessingTime()) ? self::_getPass($active_id) : 0;
8571 }
8572 $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",
8573 array('integer', 'integer'),
8574 array($active_id, $pass)
8575 );
8576 if ($result->numRows())
8577 {
8578 $row = $ilDB->fetchAssoc($result);
8579 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
8580 {
8581 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8582 }
8583 else
8584 {
8585 return time();
8586 }
8587 }
8588 else
8589 {
8590 return time();
8591 }
8592 }
8593
8603 {
8604 if ($this->getEnableProcessingTime())
8605 {
8606 $processing_time = $this->getProcessingTimeInSeconds($active_id);
8607 $now = time();
8608 if ($now > ($starting_time + $processing_time))
8609 {
8610 return TRUE;
8611 }
8612 else
8613 {
8614 return FALSE;
8615 }
8616 }
8617 else
8618 {
8619 return FALSE;
8620 }
8621 }
8622
8624 {
8625 global $ilDB;
8626
8627 $query = "
8628 SELECT questions.*,
8629 questtypes.type_tag,
8630 tstquest.sequence,
8631 tstquest.obligatory,
8632 origquest.obj_fi orig_obj_fi
8633
8634 FROM qpl_questions questions
8635
8636 INNER JOIN qpl_qst_type questtypes
8637 ON questtypes.question_type_id = questions.question_type_fi
8638
8639 INNER JOIN tst_test_question tstquest
8640 ON tstquest.question_fi = questions.question_id
8641
8642 LEFT JOIN qpl_questions origquest
8643 ON origquest.question_id = questions.original_id
8644
8645 WHERE tstquest.test_fi = %s
8646
8647 ORDER BY tstquest.sequence
8648 ";
8649
8650 $query_result = $ilDB->queryF(
8651 $query, array('integer'), array($this->getTestId())
8652 );
8653
8654 $questions = array();
8655
8656 while ($row = $ilDB->fetchAssoc($query_result))
8657 {
8658 $question = $row;
8659
8660 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8661
8662 $questions[] = $question;
8663 }
8664
8665 return $questions;
8666 }
8667
8668 public function checkQuestionParent($questionId)
8669 {
8670 global $DIC; /* @var ILIAS\DI\Container $DIC */
8671
8672 $row = $DIC->database()->fetchAssoc($DIC->database()->queryF(
8673 "SELECT COUNT(question_id) cnt FROM qpl_questions WHERE question_id = %s AND obj_fi = %s",
8674 array('integer', 'integer'), array($questionId, $this->getId())
8675 ));
8676
8677 return (bool)$row['cnt'];
8678 }
8679
8683 public function getPotentialRandomTestQuestions()
8684 {
8688 global $ilDB;
8689
8690 $query = "
8691 SELECT questions.*,
8692 questtypes.type_tag,
8693 origquest.obj_fi orig_obj_fi
8694
8695 FROM qpl_questions questions
8696
8697 INNER JOIN qpl_qst_type questtypes
8698 ON questtypes.question_type_id = questions.question_type_fi
8699
8700 INNER JOIN tst_rnd_cpy tstquest
8701 ON tstquest.qst_fi = questions.question_id
8702
8703 LEFT JOIN qpl_questions origquest
8704 ON origquest.question_id = questions.original_id
8705
8706 WHERE tstquest.tst_fi = %s
8707 ";
8708
8709 $query_result = $ilDB->queryF(
8710 $query, array('integer'), array($this->getTestId())
8711 );
8712
8713 $questions = array();
8714
8715 while ($row = $ilDB->fetchAssoc($query_result))
8716 {
8717 $question = $row;
8718
8719 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8720
8721 $questions[] = $question;
8722 }
8723
8724 return $questions;
8725 }
8726
8734 {
8735 return ($this->shuffle_questions) ? 1 : 0;
8736 }
8737
8744 function setShuffleQuestions($a_shuffle)
8745 {
8746 $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8747 }
8748
8762 {
8763 return ($this->show_summary) ? $this->show_summary : 0;
8764 }
8765
8778 function setListOfQuestionsSettings($a_value = 0)
8779 {
8780 $this->show_summary = $a_value;
8781 }
8782
8790 {
8791 if (($this->show_summary & 1) > 0)
8792 {
8793 return TRUE;
8794 }
8795 else
8796 {
8797 return FALSE;
8798 }
8799 }
8800
8807 function setListOfQuestions($a_value = TRUE)
8808 {
8809 if ($a_value)
8810 {
8811 $this->show_summary = 1;
8812 }
8813 else
8814 {
8815 $this->show_summary = 0;
8816 }
8817 }
8818
8826 {
8827 if (($this->show_summary & 2) > 0)
8828 {
8829 return TRUE;
8830 }
8831 else
8832 {
8833 return FALSE;
8834 }
8835 }
8836
8843 function setListOfQuestionsStart($a_value = TRUE)
8844 {
8845 if ($a_value && $this->getListOfQuestions())
8846 {
8847 $this->show_summary = $this->show_summary | 2;
8848 }
8849 if (!$a_value && $this->getListOfQuestions())
8850 {
8851 if ($this->getListOfQuestionsStart())
8852 {
8853 $this->show_summary = $this->show_summary ^ 2;
8854 }
8855 }
8856 }
8857
8865 {
8866 if (($this->show_summary & 4) > 0)
8867 {
8868 return TRUE;
8869 }
8870 else
8871 {
8872 return FALSE;
8873 }
8874 }
8875
8882 function setListOfQuestionsEnd($a_value = TRUE)
8883 {
8884 if ($a_value && $this->getListOfQuestions())
8885 {
8886 $this->show_summary = $this->show_summary | 4;
8887 }
8888 if (!$a_value && $this->getListOfQuestions())
8889 {
8890 if ($this->getListOfQuestionsEnd())
8891 {
8892 $this->show_summary = $this->show_summary ^ 4;
8893 }
8894 }
8895 }
8896
8904 {
8905 if (($this->show_summary & 8) > 0)
8906 {
8907 return TRUE;
8908 }
8909 else
8910 {
8911 return FALSE;
8912 }
8913 }
8914
8921 function setListOfQuestionsDescription($a_value = TRUE)
8922 {
8923 if ($a_value && $this->getListOfQuestions())
8924 {
8925 $this->show_summary = $this->show_summary | 8;
8926 }
8927 if (!$a_value && $this->getListOfQuestions())
8928 {
8929 if ($this->getListOfQuestionsDescription())
8930 {
8931 $this->show_summary = $this->show_summary ^ 8;
8932 }
8933 }
8934 }
8935
8943 {
8944 return ($this->results_presentation) ? $this->results_presentation : 0;
8945 }
8946
8954 {
8955 if (($this->results_presentation & 1) > 0)
8956 {
8957 return TRUE;
8958 }
8959 else
8960 {
8961 return FALSE;
8962 }
8963 }
8964
8972 {
8973 if (($this->results_presentation & 2) > 0)
8974 {
8975 return TRUE;
8976 }
8977 else
8978 {
8979 return FALSE;
8980 }
8981 }
8982
8990 {
8991 if (($this->results_presentation & 4) > 0)
8992 {
8993 return TRUE;
8994 }
8995 else
8996 {
8997 return FALSE;
8998 }
8999 }
9000
9008 {
9009 if (($this->results_presentation & 8) > 0)
9010 {
9011 return TRUE;
9012 }
9013 else
9014 {
9015 return FALSE;
9016 }
9017 }
9018
9026 {
9027 if (($this->results_presentation & 16) > 0)
9028 {
9029 return TRUE;
9030 }
9031 else
9032 {
9033 return FALSE;
9034 }
9035 }
9036
9044 {
9045 if (($this->results_presentation & 32) > 0)
9046 {
9047 return TRUE;
9048 }
9049 else
9050 {
9051 return FALSE;
9052 }
9053 }
9054
9060 {
9061 if (($this->results_presentation & 64) > 0)
9062 {
9063 return TRUE;
9064 }
9065 else
9066 {
9067 return FALSE;
9068 }
9069 }
9070
9076 {
9077 if(($this->results_presentation & 128) > 0)
9078 {
9079 return TRUE;
9080 }
9081 else
9082 {
9083 return FALSE;
9084 }
9085 }
9086
9093 function setResultsPresentation($a_results_presentation = 3)
9094 {
9095 $this->results_presentation = $a_results_presentation;
9096 }
9097
9106 function setShowPassDetails($a_details = 1)
9107 {
9108 if ($a_details)
9109 {
9110 $this->results_presentation = $this->results_presentation | 1;
9111 }
9112 else
9113 {
9114 if ($this->getShowPassDetails())
9115 {
9116 $this->results_presentation = $this->results_presentation ^ 1;
9117 }
9118 }
9119 }
9120
9127 function setShowSolutionDetails($a_details = 1)
9128 {
9129 if ($a_details)
9130 {
9131 $this->results_presentation = $this->results_presentation | 2;
9132 }
9133 else
9134 {
9135 if ($this->getShowSolutionDetails())
9136 {
9137 $this->results_presentation = $this->results_presentation ^ 2;
9138 }
9139 }
9140 }
9141
9148 function canShowSolutionPrintview($user_id = NULL)
9149 {
9150 return $this->getShowSolutionPrintview();
9151 }
9152
9159 function setShowSolutionPrintview($a_printview = 1)
9160 {
9161 if ($a_printview)
9162 {
9163 $this->results_presentation = $this->results_presentation | 4;
9164 }
9165 else
9166 {
9167 if ($this->getShowSolutionPrintview())
9168 {
9169 $this->results_presentation = $this->results_presentation ^ 4;
9170 }
9171 }
9172 }
9173
9180 function setShowSolutionFeedback($a_feedback = TRUE)
9181 {
9182 if ($a_feedback)
9183 {
9184 $this->results_presentation = $this->results_presentation | 8;
9185 }
9186 else
9187 {
9188 if ($this->getShowSolutionFeedback())
9189 {
9190 $this->results_presentation = $this->results_presentation ^ 8;
9191 }
9192 }
9193 }
9194
9201 function setShowSolutionAnswersOnly($a_full = TRUE)
9202 {
9203 if ($a_full)
9204 {
9205 $this->results_presentation = $this->results_presentation | 16;
9206 }
9207 else
9208 {
9209 if ($this->getShowSolutionAnswersOnly())
9210 {
9211 $this->results_presentation = $this->results_presentation ^ 16;
9212 }
9213 }
9214 }
9215
9222 function setShowSolutionSignature($a_signature = FALSE)
9223 {
9224 if ($a_signature)
9225 {
9226 $this->results_presentation = $this->results_presentation | 32;
9227 }
9228 else
9229 {
9230 if ($this->getShowSolutionSignature())
9231 {
9232 $this->results_presentation = $this->results_presentation ^ 32;
9233 }
9234 }
9235 }
9236
9243 function setShowSolutionSuggested($a_solution = FALSE)
9244 {
9245 if ($a_solution)
9246 {
9247 $this->results_presentation = $this->results_presentation | 64;
9248 }
9249 else
9250 {
9251 if ($this->getShowSolutionSuggested())
9252 {
9253 $this->results_presentation = $this->results_presentation ^ 64;
9254 }
9255 }
9256 }
9257
9263 public function setShowSolutionListComparison($a_comparison = FALSE)
9264 {
9265 if($a_comparison)
9266 {
9267 $this->results_presentation = $this->results_presentation | 128;
9268 }
9269 else
9270 {
9272 {
9273 $this->results_presentation = $this->results_presentation ^ 128;
9274 }
9275 }
9276 }
9277
9281 public static function _getUserIdFromActiveId($active_id)
9282 {
9283 global $ilDB;
9284 $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
9285 array('integer'),
9286 array($active_id)
9287 );
9288 if ($result->numRows())
9289 {
9290 $row = $ilDB->fetchAssoc($result);
9291 return $row["user_fi"];
9292 }
9293 else
9294 {
9295 return -1;
9296 }
9297 }
9298
9302 public function isLimitUsersEnabled()
9303 {
9305 }
9306
9311 {
9312 $this->limitUsersEnabled = $limitUsersEnabled;
9313 }
9314
9315 public function getAllowedUsers()
9316 {
9317 return ($this->allowedUsers) ? $this->allowedUsers : 0;
9318 }
9319
9320 public function setAllowedUsers($a_allowed_users)
9321 {
9322 $this->allowedUsers = $a_allowed_users;
9323 }
9324
9325 public function getAllowedUsersTimeGap()
9326 {
9327 return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
9328 }
9329
9330 public function setAllowedUsersTimeGap($a_allowed_users_time_gap)
9331 {
9332 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
9333 }
9334
9336 {
9337 global $ilDB;
9338
9339 $nr_of_users = $this->getAllowedUsers();
9340 $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
9341 if (($nr_of_users > 0) && ($time_gap > 0))
9342 {
9343 $now = time();
9344 $time_border = $now - $time_gap;
9345 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
9346 $query = "
9347 SELECT DISTINCT tst_times.active_fi
9348 FROM tst_times
9349 INNER JOIN tst_active
9350 ON tst_times.active_fi = tst_active.active_id
9351 AND (
9352 tst_times.pass > tst_active.last_finished_pass OR tst_active.last_finished_pass IS NULL
9353 )
9354 WHERE tst_times.tstamp > %s
9355 AND tst_active.test_fi = %s
9356 ";
9357 $result = $ilDB->queryF($query, array('integer', 'integer'), array($time_border, $this->getTestId()));
9358 if ($result->numRows() >= $nr_of_users)
9359 {
9360 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
9362 {
9363 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
9364 }
9365 return FALSE;
9366 }
9367 else
9368 {
9369 return TRUE;
9370 }
9371 }
9372 return TRUE;
9373 }
9374
9375 function _getLastAccess($active_id)
9376 {
9377 global $ilDB;
9378
9379 $result = $ilDB->queryF("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
9380 array('integer'),
9381 array($active_id)
9382 );
9383 if ($result->numRows())
9384 {
9385 $row = $ilDB->fetchAssoc($result);
9386 return $row["finished"];
9387 }
9388 return "";
9389 }
9390
9398 function isHTML($a_text)
9399 {
9400 if (preg_match("/<[^>]*?>/", $a_text))
9401 {
9402 return TRUE;
9403 }
9404 else
9405 {
9406 return FALSE;
9407 }
9408 }
9409
9417 function QTIMaterialToString($a_material)
9418 {
9419 $result = "";
9420 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
9421 {
9422 $material = $a_material->getMaterial($i);
9423 if (strcmp($material["type"], "mattext") == 0)
9424 {
9425 $result .= $material["material"]->getContent();
9426 }
9427 if (strcmp($material["type"], "matimage") == 0)
9428 {
9429 $matimage = $material["material"];
9430 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
9431 {
9432 // import an mediaobject which was inserted using tiny mce
9433 if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
9434 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
9435 }
9436 }
9437 }
9438 global $ilLog;
9439 $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
9440 return $result;
9441 }
9442
9451 function addQTIMaterial(&$a_xml_writer, $a_material)
9452 {
9453 include_once "./Services/RTE/classes/class.ilRTE.php";
9454 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9455
9456 $a_xml_writer->xmlStartTag("material");
9457 $attrs = array(
9458 "texttype" => "text/plain"
9459 );
9460 if ($this->isHTML($a_material))
9461 {
9462 $attrs["texttype"] = "text/xhtml";
9463 }
9464 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9465
9466 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9467 foreach ($mobs as $mob)
9468 {
9469 $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9470 if (strpos($a_material, "mm_$mob") !== FALSE)
9471 {
9472 if (ilObjMediaObject::_exists($mob))
9473 {
9474 $mob_obj = new ilObjMediaObject($mob);
9475 $imgattrs = array(
9476 "label" => $moblabel,
9477 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9478 );
9479 }
9480 $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
9481 }
9482 }
9483 $a_xml_writer->xmlEndTag("material");
9484 }
9485
9492 function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE, $omitNl2BrWhenTextArea = false)
9493 {
9494 include_once "./Services/Utilities/classes/class.ilUtil.php";
9495 return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output, $omitNl2BrWhenTextArea);
9496 }
9497
9504 function saveCertificateVisibility($a_value)
9505 {
9506 global $ilDB;
9507
9508 $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9509 array('text', 'integer', 'integer'),
9510 array($a_value, time(), $this->getTestId())
9511 );
9512 }
9513
9521 {
9522 return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9523 }
9524
9531 function setCertificateVisibility($a_value)
9532 {
9533 $this->certificate_visibility = $a_value;
9534 }
9535
9542 function getAnonymity()
9543 {
9544 return ($this->anonymity) ? 1 : 0;
9545 }
9546
9553 function setAnonymity($a_value = 0)
9554 {
9555 switch ($a_value)
9556 {
9557 case 1:
9558 $this->anonymity = 1;
9559 break;
9560 default:
9561 $this->anonymity = 0;
9562 break;
9563 }
9564 }
9565
9572 function getShowCancel()
9573 {
9574 return ($this->show_cancel) ? 1 : 0;
9575 }
9576
9583 function setShowCancel($a_value = 1)
9584 {
9585 switch ($a_value)
9586 {
9587 case 1:
9588 $this->show_cancel = 1;
9589 break;
9590 default:
9591 $this->show_cancel = 0;
9592 break;
9593 }
9594 }
9595
9602 function getShowMarker()
9603 {
9604 return ($this->show_marker) ? 1 : 0;
9605 }
9606
9613 function setShowMarker($a_value = 1)
9614 {
9615 switch ($a_value)
9616 {
9617 case 1:
9618 $this->show_marker = 1;
9619 break;
9620 default:
9621 $this->show_marker = 0;
9622 break;
9623 }
9624 }
9625
9633 {
9634 return ($this->fixed_participants) ? 1 : 0;
9635 }
9636
9643 function setFixedParticipants($a_value = 1)
9644 {
9645 switch ($a_value)
9646 {
9647 case 1:
9648 $this->fixed_participants = 1;
9649 break;
9650 default:
9651 $this->fixed_participants = 0;
9652 break;
9653 }
9654 }
9655
9663 public static function _lookupAnonymity($a_obj_id)
9664 {
9665 global $ilDB;
9666
9667 $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9668 array('integer'),
9669 array($a_obj_id)
9670 );
9671 while($row = $ilDB->fetchAssoc($result))
9672 {
9673 return $row['anonymity'];
9674 }
9675 return 0;
9676 }
9677
9684 public static function lookupQuestionSetTypeByActiveId($active_id)
9685 {
9686 global $ilDB;
9687
9688 $query = "
9689 SELECT tst_tests.question_set_type
9690 FROM tst_active
9691 INNER JOIN tst_tests
9692 ON tst_active.test_fi = tst_tests.test_id
9693 WHERE tst_active.active_id = %s
9694 ";
9695
9696 $res = $ilDB->queryF( $query, array('integer'), array($active_id) );
9697
9698 while($row = $ilDB->fetchAssoc($res))
9699 {
9700 return $row['question_set_type'];
9701 }
9702
9703 return null;
9704 }
9705
9715 {
9716 throw new Exception(__METHOD__.' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9717
9718 global $ilDB;
9719
9720 $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",
9721 array('integer'),
9722 array($active_id)
9723 );
9724 while($row = $ilDB->fetchAssoc($result))
9725 {
9726 return $row['random_test'];
9727 }
9728 return 0;
9729 }
9730
9741 function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
9742 {
9743 if ($this->getAnonymity() && !$overwrite_anonymity)
9744 {
9745 return $this->lng->txt("anonymous") . $suffix;
9746 }
9747 else
9748 {
9749 include_once './Services/User/classes/class.ilObjUser.php';
9750 $uname = ilObjUser::_lookupName($user_id);
9751 if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
9752 if ($sorted_order)
9753 {
9754 return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9755 }
9756 else
9757 {
9758 return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9759 }
9760 }
9761 }
9762
9770 function getStartTestLabel($active_id)
9771 {
9772 if ($this->getNrOfTries() == 1)
9773 {
9774 return $this->lng->txt("tst_start_test");
9775 }
9776 $active_pass = self::_getPass($active_id);
9777 $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9778 if ($res == 0)
9779 {
9780 if ($active_pass == 0)
9781 {
9782 return $this->lng->txt("tst_start_test");
9783 }
9784 else
9785 {
9786 return $this->lng->txt("tst_start_new_test_pass");
9787 }
9788 }
9789 else
9790 {
9791 return $this->lng->txt("tst_resume_test");
9792 }
9793 }
9794
9800 public function getAvailableDefaults()
9801 {
9806 global $ilDB, $ilUser;
9807
9808 $result = $ilDB->queryF(
9809 "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9810 array('integer'),
9811 array($ilUser->getId())
9812 );
9813 $defaults = array();
9814 while($row = $ilDB->fetchAssoc($result))
9815 {
9816 $defaults[$row["test_defaults_id"]] = $row;
9817 }
9818 return $defaults;
9819 }
9820
9828 function &getTestDefaults($test_defaults_id)
9829 {
9830 return self::_getTestDefaults($test_defaults_id);
9831 }
9832
9833 public static function _getTestDefaults($test_defaults_id)
9834 {
9835 global $ilDB;
9836
9837 $result = $ilDB->queryF("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9838 array('integer'),
9839 array($test_defaults_id)
9840 );
9841 if ($result->numRows() == 1)
9842 {
9843 $row = $ilDB->fetchAssoc($result);
9844 return $row;
9845 }
9846 else
9847 {
9848 return NULL;
9849 }
9850 }
9851
9858 function deleteDefaults($test_default_id)
9859 {
9860 global $ilDB;
9861 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9862 array('integer'),
9863 array($test_default_id)
9864 );
9865 }
9866
9873 function addDefaults($a_name)
9874 {
9875 global $ilDB;
9876 global $ilUser;
9877 $testsettings = array(
9878 "TitleOutput" => $this->getTitleOutput(),
9879 "PassScoring" => $this->getPassScoring(),
9880 "IntroEnabled" => $this->isIntroductionEnabled(),
9881 "Introduction" => $this->getIntroduction(),
9882 "FinalStatement" => $this->getFinalStatement(),
9883 "ShowInfo" => $this->getShowInfo(),
9884 "ForceJS" => $this->getForceJS(),
9885 "CustomStyle" => $this->getCustomStyle(),
9886 "ShowFinalStatement" => $this->getShowFinalStatement(),
9887 "SequenceSettings" => $this->getSequenceSettings(),
9888 "ScoreReporting" => $this->getScoreReporting(),
9889 "ScoreCutting" => $this->getScoreCutting(),
9890 'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9891 'PrintBsWithRes' => (int)$this->isBestSolutionPrintedWithResult(),
9892 "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9893 "AnswerFeedback" => $this->getAnswerFeedback(),
9894 "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9895 "ResultsPresentation" => $this->getResultsPresentation(),
9896 "Anonymity" => $this->getAnonymity(),
9897 "ShowCancel" => $this->getShowCancel(),
9898 "ShowMarker" => $this->getShowMarker(),
9899 "ReportingDate" => $this->getReportingDate(),
9900 "NrOfTries" => $this->getNrOfTries(),
9901 "Shuffle" => $this->getShuffleQuestions(),
9902 "Kiosk" => $this->getKiosk(),
9903 "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9904 "ProcessingTime" => $this->getProcessingTime(),
9905 "EnableProcessingTime" => $this->getEnableProcessingTime(),
9906 "ResetProcessingTime" => $this->getResetProcessingTime(),
9907 "StartingTimeEnabled" => $this->isStartingTimeEnabled(),
9908 "StartingTime" => $this->getStartingTime(),
9909 "EndingTimeEnabled" => $this->isEndingTimeEnabled(),
9910 "EndingTime" => $this->getEndingTime(),
9911 "ECTSOutput" => $this->getECTSOutput(),
9912 "ECTSFX" => $this->getECTSFX(),
9913 "ECTSGrades" => $this->getECTSGrades(),
9914 "questionSetType" => $this->getQuestionSetType(),
9915 "CountSystem" => $this->getCountSystem(),
9916 "MCScoring" => $this->getMCScoring(),
9917 "mailnotification" => $this->getMailNotification(),
9918 "mailnottype" => $this->getMailNotificationType(),
9919 "exportsettings" => $this->getExportSettings(),
9920 "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9921 'obligations_enabled' => (int)$this->areObligationsEnabled(),
9922 'offer_question_hints' => (int)$this->isOfferingQuestionHintsEnabled(),
9923 'pass_deletion_allowed' => (int)$this->isPassDeletionAllowed(),
9924 'enable_examview' => $this->getEnableExamview(),
9925 'show_examview_html' => $this->getShowExamviewHtml(),
9926 'show_examview_pdf' => $this->getShowExamviewPdf(),
9927 'char_selector_availability' => $this->getCharSelectorAvailability(),
9928 'char_selector_definition' => $this->getCharSelectorDefinition(),
9929 'skill_service' => (int)$this->isSkillServiceEnabled(),
9930 'result_tax_filters' => (array)$this->getResultFilterTaxIds(),
9931 'show_grading_status' => (int)$this->isShowGradingStatusEnabled(),
9932 'show_grading_mark' => (int)$this->isShowGradingMarkEnabled(),
9933
9934 'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
9935 'force_inst_fb' => $this->isForceInstantFeedbackEnabled(),
9936 'redirection_mode' => $this->getRedirectionMode(),
9937 'redirection_url' => $this->getRedirectionUrl(),
9938 'sign_submission' => $this->getSignSubmission(),
9939 'autosave' => (int)$this->getAutosave(),
9940 'autosave_ival' => (int)$this->getAutosaveIval(),
9941 'examid_in_test_pass' => (int)$this->isShowExamIdInTestPassEnabled(),
9942 'examid_in_test_res' => (int)$this->isShowExamIdInTestResultsEnabled(),
9943
9944 'enable_archiving' => (int)$this->getEnableArchiving(),
9945 'password_enabled' => (int)$this->isPasswordEnabled(),
9946 'password' => (string)$this->getPassword(),
9947 'fixed_participants' => $this->getFixedParticipants(),
9948 'limit_users_enabled' => $this->isLimitUsersEnabled(),
9949 'allowedusers' => $this->getAllowedUsers(),
9950 'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9951 'pool_usage' => $this->getPoolUsage(),
9952 'activation_limited' => $this->isActivationLimited(),
9953 'activation_start_time' => $this->getActivationStartingTime(),
9954 'activation_end_time' => $this->getActivationEndingTime(),
9955 'activation_visibility' => $this->getActivationVisibility(),
9956 'highscore_enabled' => $this->getHighscoreEnabled(),
9957 'highscore_anon' => $this->getHighscoreAnon(),
9958 'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9959 'highscore_score' => $this->getHighscoreScore(),
9960 'highscore_percentage' => $this->getHighscorePercentage(),
9961 'highscore_hints' => $this->getHighscoreHints(),
9962 'highscore_wtime' => $this->getHighscoreWTime(),
9963 'highscore_own_table' => $this->getHighscoreOwnTable(),
9964 'highscore_top_table' => $this->getHighscoreTopTable(),
9965 'highscore_top_num' => $this->getHighscoreTopNum(),
9966 'use_previous_answers' => (string)$this->getUsePreviousAnswers(),
9967 'pass_waiting' => $this->getPassWaiting()
9968 );
9969
9970 $next_id = $ilDB->nextId('tst_test_defaults');
9971 $ilDB->insert(
9972 'tst_test_defaults',
9973 array(
9974 'test_defaults_id' => array('integer', $next_id),
9975 'name' => array('text', $a_name),
9976 'user_fi' => array('integer', $ilUser->getId()),
9977 'defaults' => array('clob', serialize($testsettings)),
9978 'marks' => array('clob', serialize($this->mark_schema)),
9979 'tstamp' => array('integer', time())
9980 )
9981 );
9982 }
9983
9991 public function applyDefaults($test_defaults)
9992 {
9993 $testsettings = unserialize($test_defaults["defaults"]);
9994 include_once "./Modules/Test/classes/class.assMarkSchema.php";
9995 $this->mark_schema = unserialize($test_defaults["marks"]);
9996
9997 $this->setTitleOutput($testsettings["TitleOutput"]);
9998 $this->setPassScoring($testsettings["PassScoring"]);
9999 $this->setIntroductionEnabled($testsettings["IntroEnabled"]);
10000 $this->setIntroduction($testsettings["Introduction"]);
10001 $this->setFinalStatement($testsettings["FinalStatement"]);
10002 $this->setShowInfo($testsettings["ShowInfo"]);
10003 $this->setForceJS($testsettings["ForceJS"]);
10004 $this->setCustomStyle($testsettings["CustomStyle"]);
10005 $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
10006 $this->setSequenceSettings($testsettings["SequenceSettings"]);
10007 $this->setScoreReporting($testsettings["ScoreReporting"]);
10008 $this->setScoreCutting($testsettings['ScoreCutting']);
10009 $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
10010 $this->setPrintBestSolutionWithResult((bool)$testsettings['PrintBsWithRes']);
10011 $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
10012 $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
10013 $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
10014 $this->setResultsPresentation($testsettings["ResultsPresentation"]);
10015 $this->setAnonymity($testsettings["Anonymity"]);
10016 $this->setShowCancel($testsettings["ShowCancel"]);
10017 $this->setShuffleQuestions($testsettings["Shuffle"]);
10018 $this->setShowMarker($testsettings["ShowMarker"]);
10019 $this->setReportingDate($testsettings["ReportingDate"]);
10020 $this->setNrOfTries($testsettings["NrOfTries"]);
10021 $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
10022 $this->setRedirectionMode($testsettings['redirection_mode']);
10023 $this->setRedirectionUrl($testsettings['redirection_url']);
10024 $this->setProcessingTime($testsettings["ProcessingTime"]);
10025 $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
10026 $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
10027 $this->setStartingTimeEnabled($testsettings["StartingTimeEnabled"]);
10028 $this->setStartingTime($testsettings["StartingTime"]);
10029 $this->setKiosk($testsettings["Kiosk"]);
10030 $this->setEndingTimeEnabled($testsettings["EndingTimeEnabled"]);
10031 $this->setEndingTime($testsettings["EndingTime"]);
10032 $this->setECTSOutput($testsettings["ECTSOutput"]);
10033 $this->setECTSFX($testsettings["ECTSFX"]);
10034 $this->setECTSGrades($testsettings["ECTSGrades"]);
10035 if( isset($testsettings["isRandomTest"]) )
10036 {
10037 if( $testsettings["isRandomTest"] )
10038 {
10039 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
10040 }
10041 else
10042 {
10043 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
10044 }
10045 }
10046 elseif( isset($testsettings["questionSetType"]) )
10047 {
10048 $this->setQuestionSetType($testsettings["questionSetType"]);
10049 }
10050 $this->setCountSystem($testsettings["CountSystem"]);
10051 $this->setMCScoring($testsettings["MCScoring"]);
10052 $this->setMailNotification($testsettings["mailnotification"]);
10053 $this->setMailNotificationType($testsettings["mailnottype"]);
10054 $this->setExportSettings($testsettings['exportsettings']);
10055 $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
10056 $this->setObligationsEnabled($testsettings["obligations_enabled"]);
10057 $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
10058 $this->setHighscoreEnabled($testsettings['highscore_enabled']);
10059 $this->setHighscoreAnon($testsettings['highscore_anon']);
10060 $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
10061 $this->setHighscoreScore($testsettings['highscore_score']);
10062 $this->setHighscorePercentage($testsettings['highscore_percentage']);
10063 $this->setHighscoreHints($testsettings['highscore_hints']);
10064 $this->setHighscoreWTime($testsettings['highscore_wtime']);
10065 $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
10066 $this->setHighscoreTopTable($testsettings['highscore_top_table']);
10067 $this->setHighscoreTopNum($testsettings['highscore_top_num']);
10068 $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
10069 if( isset($testsettings['examid_in_kiosk']) )
10070 {
10071 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
10072 }
10073 else
10074 {
10075 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
10076 }
10077 if( isset($testsettings['show_exam_id']) )
10078 {
10079 $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
10080 }
10081 else
10082 {
10083 $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
10084 }
10085 $this->setEnableExamview($testsettings['enable_examview']);
10086 $this->setShowExamviewHtml($testsettings['show_examview_html']);
10087 $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
10088 $this->setEnableArchiving($testsettings['enable_archiving']);
10089 $this->setSignSubmission($testsettings['sign_submission']);
10090 $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
10091 $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
10092 $this->setSkillServiceEnabled((bool)$testsettings['skill_service']);
10093 $this->setResultFilterTaxIds((array)$testsettings['result_tax_filters']);
10094 $this->setShowGradingStatusEnabled((bool)$testsettings['show_grading_status']);
10095 $this->setShowGradingMarkEnabled((bool)$testsettings['show_grading_mark']);
10096
10097 $this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
10098 $this->setForceInstantFeedbackEnabled($testsettings['force_inst_fb']);
10099 $this->setRedirectionMode($testsettings['redirection_mode']);
10100 $this->setRedirectionUrl($testsettings['redirection_url']);
10101
10102 $this->setAutosave($testsettings['autosave']);
10103 $this->setAutosaveIval($testsettings['autosave_ival']);
10104 $this->setShowExamIdInTestResultsEnabled((int)$testsettings['examid_in_test_res']);
10105 $this->setPasswordEnabled($testsettings['password_enabled']);
10106 $this->setPassword($testsettings['password']);
10107 $this->setFixedParticipants($testsettings['fixed_participants'] );
10108 $this->setLimitUsersEnabled($testsettings['limit_users_enabled']);
10109 $this->setAllowedUsers($testsettings['allowedusers']);
10110 $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
10111 $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
10112 $this->setPoolUsage($testsettings['pool_usage']);
10113 $this->setActivationLimited($testsettings['activation_limited']);
10114 $this->setActivationStartingTime($testsettings['activation_start_time']);
10115 $this->setActivationEndingTime($testsettings['activation_end_time']);
10116 $this->setActivationVisibility($testsettings['activation_visibility']);
10117 $this->setPassWaiting($testsettings['pass_waiting']);
10118
10119 $this->saveToDb();
10120
10121 return true;
10122 }
10123
10131 function processPrintoutput2FO($print_output)
10132 {
10133 if (extension_loaded("tidy"))
10134 {
10135 $config = array(
10136 "indent" => false,
10137 "output-xml" => true,
10138 "numeric-entities" => true
10139 );
10140 $tidy = new tidy();
10141 $tidy->parseString($print_output, $config, 'utf8');
10142 $tidy->cleanRepair();
10143 $print_output = tidy_get_output($tidy);
10144 $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
10145 }
10146 else
10147 {
10148 $print_output = str_replace("&nbsp;", "&#160;", $print_output);
10149 $print_output = str_replace("&otimes;", "X", $print_output);
10150 }
10151 $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
10152
10153 // additional font support
10154 $xsl = str_replace(
10155 'font-family="Helvetica, unifont"',
10156 'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
10157 $xsl
10158 );
10159
10160 $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
10161 $xh = xslt_create();
10162 $params = array();
10163 $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
10164 xslt_error($xh);
10165 xslt_free($xh);
10166 return $output;
10167 }
10168
10175 public function deliverPDFfromHTML($content, $title = NULL)
10176 {
10177 $content = preg_replace("/href=\".*?\"/", "", $content);
10178 $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", TRUE, TRUE, "Modules/Test");
10179 $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
10180 $printbody->setVariable("ADM_CONTENT", $content);
10181 $printbody->setCurrentBlock("css_file");
10182 $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
10183 $printbody->parseCurrentBlock();
10184 $printbody->setCurrentBlock("css_file");
10185 $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
10186 $printbody->parseCurrentBlock();
10187 $printoutput = $printbody->get();
10188 $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
10189 $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
10190 if (extension_loaded("tidy"))
10191 {
10192 $config = array(
10193 "indent" => false,
10194 "output-xml" => true,
10195 "numeric-entities" => true
10196 );
10197 $tidy = new tidy();
10198 $tidy->parseString($html, $config, 'utf8');
10199 $tidy->cleanRepair();
10200 $html = tidy_get_output($tidy);
10201 $html = preg_replace("/^.*?(<html)/", "\\1", $html);
10202 }
10203 else
10204 {
10205 $html = str_replace("&nbsp;", "&#160;", $html);
10206 $html = str_replace("&otimes;", "X", $html);
10207 }
10208 $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
10210 }
10211
10218 public function deliverPDFfromFO($fo, $title = null)
10219 {
10220 global $ilLog;
10221
10222 include_once "./Services/Utilities/classes/class.ilUtil.php";
10223 $fo_file = ilUtil::ilTempnam() . ".fo";
10224 $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
10225
10226 include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
10227 try
10228 {
10229 $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
10230 $filename = (strlen($title)) ? $title : $this->getTitle();
10231 ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10232 return true;
10233 }
10234 catch(Exception $e)
10235 {
10236 $ilLog->write(__METHOD__.': '.$e->getMessage());
10237 return false;
10238 }
10239 }
10240
10250 static function getManualFeedback($active_id, $question_id, $pass)
10251 {
10252 global $ilDB;
10253 $feedback = "";
10254 $result = $ilDB->queryF("SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10255 array('integer', 'integer', 'integer'),
10256 array($active_id, $question_id, $pass)
10257 );
10258 if ($result->numRows())
10259 {
10260 $row = $ilDB->fetchAssoc($result);
10261 include_once("./Services/RTE/classes/class.ilRTE.php");
10262 $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
10263 }
10264 return $feedback;
10265 }
10266
10277 function saveManualFeedback($active_id, $question_id, $pass, $feedback)
10278 {
10279 global $ilDB;
10280
10281 $affectedRows = $ilDB->manipulateF("DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10282 array('integer', 'integer', 'integer'),
10283 array($active_id, $question_id, $pass)
10284 );
10285
10286 if (strlen($feedback))
10287 {
10288 $next_id = $ilDB->nextId('tst_manual_fb');
10290 $result = $ilDB->insert('tst_manual_fb', array(
10291 'manual_feedback_id' => array( 'integer', $next_id ),
10292 'active_fi' => array( 'integer', $active_id ),
10293 'question_fi' => array( 'integer', $question_id ),
10294 'pass' => array( 'integer', $pass),
10295 'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0) ),
10296 'tstamp' => array( 'integer', time() ),
10297 )
10298 );
10299 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10301 {
10302 global $lng, $ilUser;
10303 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
10304 $username = ilObjTestAccess::_getParticipantData($active_id);
10305 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10306 $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
10307 }
10308 }
10309 return TRUE;
10310 }
10311
10320 {
10321 return TRUE;
10322
10323// global $ilUser;
10324// if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
10325// if ($this->getForceJS()) return TRUE;
10326// $assessmentSetting = new ilSetting("assessment");
10327// return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
10328 }
10329
10330 function &createTestSequence($active_id, $pass, $shuffle)
10331 {
10332 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10333 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10334 }
10335
10341 public function setTestId($a_id)
10342 {
10343 $this->test_id = $a_id;
10344 }
10345
10354 function getDetailedTestResults($participants)
10355 {
10356 $results = array();
10357 if (count($participants))
10358 {
10359 foreach ($participants as $active_id => $user_rec)
10360 {
10361 $row = array();
10362 $reached_points = 0;
10363 $max_points = 0;
10364 foreach ($this->questions as $value)
10365 {
10366 $question =& ilObjTest::_instanciateQuestion($value);
10367 if (is_object($question))
10368 {
10369 $max_points += $question->getMaximumPoints();
10370 $reached_points += $question->getReachedPoints($active_id);
10371 if ($max_points > 0)
10372 {
10373 $percentvalue = $reached_points / $max_points;
10374 if ($percentvalue < 0) $percentvalue = 0.0;
10375 }
10376 else
10377 {
10378 $percentvalue = 0;
10379 }
10380 if ($this->getAnonymity())
10381 {
10382 $user_rec['firstname'] = "";
10383 $user_rec['lastname'] = $this->lng->txt("anonymous");
10384 }
10385 $row = array(
10386 "user_id"=>$user_rec['usr_id'],
10387 "matriculation" => $user_rec['matriculation'],
10388 "lastname" => $user_rec['lastname'],
10389 "firstname" => $user_rec['firstname'],
10390 "login"=>$user_rec['login'],
10391 "question_id" => $question->getId(),
10392 "question_title" => $question->getTitle(),
10393 "reached_points" => $reached_points,
10394 "max_points" => $max_points
10395 );
10396 $results[] = $row;
10397 }
10398 }
10399 }
10400 }
10401 return $results;
10402 }
10403
10407 public static function _lookupTestObjIdForQuestionId($a_q_id)
10408 {
10409 global $ilDB;
10410
10411 $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",
10412 array('integer'),
10413 array($a_q_id)
10414 );
10415 $rec = $ilDB->fetchAssoc($result);
10416 return $rec["obj_id"];
10417 }
10418
10425 function isPluginActive($a_pname)
10426 {
10427 global $ilPluginAdmin;
10428 if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname))
10429 {
10430 return TRUE;
10431 }
10432 else
10433 {
10434 return FALSE;
10435 }
10436 }
10437
10438 public function getPassed($active_id)
10439 {
10440 global $ilDB;
10441
10442 $result = $ilDB->queryF("SELECT passed FROM tst_result_cache WHERE active_fi = %s",
10443 array('integer'),
10444 array($active_id)
10445 );
10446 if ($result->numRows())
10447 {
10448 $row = $ilDB->fetchAssoc($result);
10449 return $row['passed'];
10450 }
10451 else
10452 {
10453 $counted_pass = ilObjTest::_getResultPass($active_id);
10454 $result_array =& $this->getTestResult($active_id, $counted_pass);
10455 return $result_array["test"]["passed"];
10456 }
10457 }
10458
10464 function canShowCertificate($testSession, $user_id, $active_id)
10465 {
10466 if ($this->canShowTestResults($testSession))
10467 {
10468 include_once "./Services/Certificate/classes/class.ilCertificate.php";
10469 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
10470 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
10471 if ($cert->isComplete())
10472 {
10473 $vis = $this->getCertificateVisibility();
10474 $showcert = FALSE;
10475 switch ($vis)
10476 {
10477 case 0:
10478 $showcert = TRUE;
10479 break;
10480 case 1:
10481 if ($this->getPassed($active_id))
10482 {
10483 $showcert = TRUE;
10484 }
10485 break;
10486 case 2:
10487 $showcert = FALSE;
10488 break;
10489 }
10490 if ($showcert)
10491 {
10492 return TRUE;
10493 }
10494 else
10495 {
10496 return FALSE;
10497 }
10498 }
10499 else
10500 {
10501 return FALSE;
10502 }
10503 }
10504 else
10505 {
10506 return FALSE;
10507 }
10508 }
10509
10513 public function getParticipantsForTestAndQuestion($test_id, $question_id)
10514 {
10516 global $ilDB;
10517
10518 $query = "
10519 SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10520 FROM tst_test_result
10521 INNER JOIN tst_active ON tst_active.active_id = tst_test_result.active_fi AND tst_active.test_fi = %s
10522 INNER JOIN qpl_questions ON qpl_questions.question_id = tst_test_result.question_fi
10523 LEFT JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
10524 WHERE tst_test_result.question_fi = %s
10525 ORDER BY usr_data.lastname ASC, usr_data.firstname ASC
10526 ";
10527
10528 $result = $ilDB->queryF($query,
10529 array('integer', 'integer'),
10530 array($test_id, $question_id)
10531 );
10532 $foundusers = array();
10534 while ($row = $ilDB->fetchAssoc($result))
10535 {
10536 if (!array_key_exists($row["active_fi"], $foundusers))
10537 {
10538 $foundusers[$row["active_fi"]] = array();
10539 }
10540 array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10541 }
10542 return $foundusers;
10543 }
10544
10551 {
10552 $data =& $this->getCompleteEvaluationData();
10553 $foundParticipants =& $data->getParticipants();
10554 $results = array("overview" => array(), "questions" => array());
10555 if (count($foundParticipants))
10556 {
10557 $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10558 $total_finished = $this->evalTotalFinished();
10559 $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10560 $average_time = $this->evalTotalStartedAverageTime();
10561 $diff_seconds = $average_time;
10562 $diff_hours = floor($diff_seconds/3600);
10563 $diff_seconds -= $diff_hours * 3600;
10564 $diff_minutes = floor($diff_seconds/60);
10565 $diff_seconds -= $diff_minutes * 60;
10566 $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10567 $total_passed = 0;
10568 $total_passed_reached = 0;
10569 $total_passed_max = 0;
10570 $total_passed_time = 0;
10571 foreach ($foundParticipants as $userdata)
10572 {
10573 if ($userdata->getPassed())
10574 {
10575 $total_passed++;
10576 $total_passed_reached += $userdata->getReached();
10577 $total_passed_max += $userdata->getMaxpoints();
10578 $total_passed_time += $userdata->getTimeOfWork();
10579 }
10580 }
10581 $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10582 $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10583 $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10584 $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10585 $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);
10586 $average_time = $average_passed_time;
10587 $diff_seconds = $average_time;
10588 $diff_hours = floor($diff_seconds/3600);
10589 $diff_seconds -= $diff_hours * 3600;
10590 $diff_minutes = floor($diff_seconds/60);
10591 $diff_seconds -= $diff_minutes * 60;
10592 $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10593 }
10594
10595 foreach ($data->getQuestionTitles() as $question_id => $question_title)
10596 {
10597 $answered = 0;
10598 $reached = 0;
10599 $max = 0;
10600 foreach ($foundParticipants as $userdata)
10601 {
10602 for ($i = 0; $i <= $userdata->getLastPass(); $i++)
10603 {
10604 if (is_object($userdata->getPass($i)))
10605 {
10606 $question =& $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10607 if (is_array($question))
10608 {
10609 $answered++;
10610 $reached += $question["reached"];
10611 $max += $question["points"];
10612 }
10613 }
10614 }
10615 }
10616 $percent = $max ? $reached/$max * 100.0 : 0;
10617 $counter++;
10618 $results["questions"][$question_id] = array(
10619 $question_title,
10620 sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10621 sprintf("%.2f", $percent) . "%",
10622 $answered,
10623 sprintf("%.2f", $answered ? $reached / $answered : 0),
10624 sprintf("%.2f", $answered ? $max / $answered : 0),
10625 $percent / 100.0
10626 );
10627 }
10628 return $results;
10629 }
10630
10634 function getXMLZip()
10635 {
10636 require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
10637 $expFactory = new ilTestExportFactory($this);
10638 $test_exp = $expFactory->getExporter('xml');
10639 return $test_exp->buildExportFile();
10640 }
10641
10645 public function getMailNotification()
10646 {
10648 }
10649
10655 public function setMailNotification($a_notification)
10656 {
10657 $this->mailnotification = $a_notification;
10658 }
10659
10660 public function sendSimpleNotification($active_id)
10661 {
10662 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10663
10664 $mail = new ilTestMailNotification();
10665 $owner_id = $this->getOwner();
10666 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10667 $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10668 }
10669
10676 {
10677 include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10678 include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10679 $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(''), 'outEvaluation', $this->getAnonymity());
10680 return $table_gui->getSelectedColumns();
10681 }
10682
10683 public function sendAdvancedNotification($active_id)
10684 {
10685 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10686
10687 $mail = new ilTestMailNotification();
10688 $owner_id = $this->getOwner();
10689 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10690
10691 require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
10692 $expFactory = new ilTestExportFactory($this);
10693 $exportObj = $expFactory->getExporter('results');
10694 $file = $exportObj->exportToExcel($deliver = FALSE, 'active_id', $active_id, $passedonly = FALSE);
10695 include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10696 $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10697 $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10698 $file_names[] = "result_" . $active_id . ".xls";
10699
10700 $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10701
10702 if(count($file_names))
10703 {
10704 $fd->unlinkFiles($file_names);
10705 unset($fd);
10706 @unlink($file);
10707 }
10708 }
10709
10710 function createRandomSolutions($number)
10711 {
10712 global $ilDB;
10713
10714 // 1. get a user
10715 $query = "SELECT usr_id FROM usr_data";
10716 $result = $ilDB->query($query);
10717 while ($data = $ilDB->fetchAssoc($result))
10718 {
10719 $activequery = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10720 $ilDB->quote($this->getTestId()),
10721 $ilDB->quote($data['usr_id'])
10722 );
10723 $activeresult = $ilDB->query($activequery);
10724 if ($activeresult->numRows() == 0)
10725 {
10726 $user_id = $data['usr_id'];
10727 if ($user_id != 13)
10728 {
10729 include_once "./Modules/Test/classes/class.ilTestSession.php";
10731 $testSession->setRefId($this->getRefId());
10732 $testSession->setTestId($this->getTestId());
10733 $testSession->setUserId($user_id);
10734 $testSession->saveToDb();
10735 $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10736 $nr_of_passes = rand(1, $passes);
10737 $active_id = $testSession->getActiveId();
10738 for ($pass = 0; $pass < $nr_of_passes; $pass++)
10739 {
10740 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10741 $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10742 $testSequence->loadFromDb();
10743 $testSequence->loadQuestions();
10744 if (!$testSequence->hasSequence())
10745 {
10746 $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10747 $testSequence->saveToDb();
10748 }
10749 for ($seq = 1; $seq <= count($this->questions); $seq++)
10750 {
10751 $question_id = $testSequence->getQuestionForSequence($seq);
10752 $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10753 $assSettings = new ilSetting('assessment');
10754 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
10755 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
10756 $processLockerFactory->setQuestionId($objQuestion->getId());
10757 $processLockerFactory->setUserId($testSession->getUserId());
10758 include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10759 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
10760 $objQuestion->setProcessLocker($processLockerFactory->getLocker());
10761 $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10762 }
10763 $testSession->increasePass();
10764 $testSession->setLastSequence(0);
10765 $testSession->setLastFinishedPass($pass);
10766 $testSession->setSubmitted(1);
10767 $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10768 $testSession->saveToDb();
10769 }
10770 $number--;
10771 if ($number == 0) return;
10772 }
10773 }
10774 }
10775 }
10776
10777 public function getResultsForActiveId($active_id)
10778 {
10779 global $ilDB;
10780
10781 $query = "
10782 SELECT *
10783 FROM tst_result_cache
10784 WHERE active_fi = %s
10785 ";
10786
10787 $result = $ilDB->queryF(
10788 $query, array('integer'), array($active_id)
10789 );
10790
10791 if( !$result->numRows() )
10792 {
10793 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10794
10796
10797 $query = "
10798 SELECT *
10799 FROM tst_result_cache
10800 WHERE active_fi = %s
10801 ";
10802
10803 $result = $ilDB->queryF(
10804 $query, array('integer'), array($active_id)
10805 );
10806 }
10807
10808 $row = $ilDB->fetchAssoc($result);
10809
10810 return $row;
10811
10812 }
10813
10814 public function getMailNotificationType()
10815 {
10816 if ($this->mailnottype == 1)
10817 {
10818 return $this->mailnottype;
10819 }
10820 else
10821 {
10822 return 0;
10823 }
10824 }
10825
10827 {
10828 if ($a_type == 1)
10829 {
10830 $this->mailnottype = 1;
10831 }
10832 else
10833 {
10834 $this->mailnottype = 0;
10835 }
10836 }
10837
10838 public function getExportSettings()
10839 {
10840 if ($this->exportsettings)
10841 {
10842 return $this->exportsettings;
10843 }
10844 else
10845 {
10846 return 0;
10847 }
10848 }
10849
10850 public function setExportSettings($a_settings)
10851 {
10852 if ($a_settings)
10853 {
10854 $this->exportsettings = $a_settings;
10855 }
10856 else
10857 {
10858 $this->exportsettings = 0;
10859 }
10860 }
10861
10863 {
10864 if (($this->exportsettings & 1) > 0)
10865 {
10866 return true;
10867 }
10868 else
10869 {
10870 return false;
10871 }
10872 }
10873
10874 public function setExportSettingsSingleChoiceShort($a_settings)
10875 {
10876 if ($a_settings)
10877 {
10878 $this->exportsettings = $this->exportsettings | 1;
10879 }
10880 else
10881 {
10883 {
10884 $this->exportsettings = $this->exportsettings ^ 1;
10885 }
10886 }
10887 }
10888
10889 public function getEnabledViewMode() {
10890 return $this->enabled_view_mode;
10891 }
10892
10893 public function setEnabledViewMode($mode) {
10894 $this->enabled_view_mode = $mode;
10895 }
10896
10898 $this->template_id = (int)$template_id;
10899 }
10900
10901 function getTemplate() {
10902 return $this->template_id;
10903 }
10904
10905 public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
10906 $new_array = array();
10907 $position = 1;
10908
10909 $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10910 $types = array('integer');
10911 $values = array($this->getTestId());
10912
10913 $new_question_id += 1;
10914
10915 global $ilDB;
10916 $inserted = false;
10917 $res = $ilDB->queryF($query, $types, $values);
10918 while($row = $ilDB->fetchAssoc($res)) {
10919
10920 $qid = $row['question_fi'];
10921
10922 if ($qid == $new_question_id) {
10923 continue;
10924 }
10925 else if ($qid == $previous_question_id) {
10926 $new_array[$position++] = $qid;
10927 $new_array[$position++] = $new_question_id;
10928 $inserted = true;
10929 }
10930 else {
10931 $new_array[$position++] = $qid;
10932 }
10933 }
10934
10935 $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10936 $update_types = array('integer', 'integer', 'integer');
10937
10938 foreach($new_array as $position => $qid) {
10939 $ilDB->manipulateF(
10940 $update_query,
10941 $update_types,
10942 $vals = array(
10943 $position,
10944 $this->getTestId(),
10945 $qid
10946 )
10947 );
10948 }
10949 }
10950
10952 {
10953 if (is_array($options))
10954 {
10955 $this->setGenericAnswerFeedback( in_array('instant_feedback_generic', $options) ? 1 : 0);
10956 $this->setSpecificAnswerFeedback( in_array('instant_feedback_specific', $options) ? 1 : 0);
10957 $this->setAnswerFeedbackPoints( in_array('instant_feedback_points', $options) ? 1 : 0);
10958 $this->setInstantFeedbackSolution( in_array('instant_feedback_solution', $options) ? 1 : 0);
10959 }
10960 else
10961 {
10962 $this->setGenericAnswerFeedback(0);
10963 $this->setSpecificAnswerFeedback(0);
10964 $this->setAnswerFeedbackPoints(0);
10966 }
10967 }
10968
10970 $setter = array(
10971 'pass_details' => 'setShowPassDetails',
10972 'solution_details' => 'setShowSolutionDetails',
10973 'solution_printview' => 'setShowSolutionPrintview',
10974 'solution_feedback' => 'setShowSolutionFeedback',
10975 'solution_answers_only' => 'setShowSolutionAnswersOnly',
10976 'solution_signature' => 'setShowSolutionSignature',
10977 'solution_suggested' => 'setShowSolutionSuggested',
10978 );
10979 foreach($setter as $key => $setter) {
10980 if (in_array($key, $options)) {
10981 $this->$setter(1);
10982 }
10983 else {
10984 $this->$setter(0);
10985 }
10986 }
10987 }
10988
10989 public function getPoolUsage() {
10990 return (boolean) $this->poolUsage;
10991 }
10992
10993 public function setPoolUsage($usage) {
10994 $this->poolUsage = (boolean)$usage;
10995 }
10996
10998 {
10999 $tree = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tree'] : $GLOBALS['tree'];
11000 $db = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
11001 $pluginAdmin = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilPluginAdmin'] : $GLOBALS['ilPluginAdmin'];
11002
11003 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
11004 $qscFactory = new ilTestQuestionSetConfigFactory($tree, $db, $pluginAdmin, $this);
11005 $questionSetConfig = $qscFactory->getQuestionSetConfig();
11006
11007 /* @var ilTestFixedQuestionSetConfig $questionSetConfig */
11008 $questionSetConfig->reindexQuestionOrdering();
11009
11010 $this->loadQuestions();
11011 }
11012
11013 public function setQuestionOrderAndObligations($orders, $obligations)
11014 {
11015 global $ilDB;
11016
11017 asort($orders);
11018
11019 $i = 0;
11020
11021 foreach($orders as $id => $position)
11022 {
11023 $i++;
11024
11025 $obligatory = (
11026 isset($obligations[$id]) && $obligations[$id] ? 1 : 0
11027 );
11028
11029 $query = "
11030 UPDATE tst_test_question
11031 SET sequence = %s,
11032 obligatory = %s
11033 WHERE question_fi = %s
11034 ";
11035
11036 $ilDB->manipulateF(
11037 $query, array('integer', 'integer', 'integer'), array($i, $obligatory, $id)
11038 );
11039 }
11040
11041 $this->loadQuestions();
11042 }
11043
11044 public function moveQuestionAfter($question_to_move, $question_before) {
11045 global $ilDB;
11046 //var_dump(func_get_args());
11047 if ($question_before) {
11048 $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
11049 $types = array('integer');
11050 $values = array($question_before);
11051 $rset = $ilDB->queryF($query, $types, $values);
11052 }
11053
11054 if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
11055 $row = array(
11056 'sequence' => 0,
11057 'test_fi' => $this->getTestId(),
11058 );
11059 }
11060
11061 $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
11062 $types = array('integer', 'integer');
11063 $values = array($row['sequence'], $row['test_fi']);
11064 $ilDB->manipulateF($update, $types, $values);
11065
11066 $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
11067 $types = array('integer', 'integer');
11068 $values = array($row['sequence'] + 1, $question_to_move);
11069 $ilDB->manipulateF($update, $types, $values);
11070
11072 }
11073
11075 {
11076 global $ilDB;
11077
11079
11080 $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
11081
11082 $query = "
11083 SELECT count(q1.question_id) cnt
11084
11085 FROM qpl_questions q1
11086
11087 INNER JOIN qpl_questions q2
11088 ON q2.question_id = q1.original_id
11089
11090 WHERE $IN_questions
11091 AND q1.obj_fi = q2.obj_fi
11092 ";
11093
11094 $rset = $ilDB->query($query);
11095
11096 $row = $ilDB->fetchAssoc($rset);
11097
11098 return $row['cnt'] > 0;
11099 }
11100
11107 public static function _lookupFinishedUserTests($a_user_id)
11108 {
11109 global $ilDB;
11110
11111 $result = $ilDB->queryF("SELECT test_fi,MAX(pass) AS pass FROM tst_active".
11112 " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)".
11113 " WHERE user_fi=%s".
11114 " GROUP BY test_fi",
11115 array('integer', 'integer'),
11116 array($a_user_id, 1)
11117 );
11118 $all = array();
11119 while($row = $ilDB->fetchAssoc($result))
11120 {
11121 $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
11122 $all[$obj_id] = (bool)$row["pass"];
11123 }
11124 return $all;
11125 }
11126 public function getQuestions()
11127 {
11128 return $this->questions;
11129 }
11130
11131 public function isOnline()
11132 {
11133 return $this->online;
11134 }
11135
11136 public function setOnline($a_online = true)
11137 {
11138 $this->online = (bool)$a_online;
11139 }
11140
11144 public function getOldOnlineStatus()
11145 {
11147 }
11148
11153 {
11154 $this->oldOnlineStatus = $oldOnlineStatus;
11155 }
11156
11157 public function setPrintBestSolutionWithResult($status)
11158 {
11159 $this->print_best_solution_with_result = (bool) $status;
11160 }
11161
11163 {
11165 }
11166
11173 {
11175 }
11176
11183 {
11184 $this->offeringQuestionHintsEnabled = (bool)$offeringQuestionHintsEnabled;
11185 }
11186
11187 function setActivationVisibility($a_value)
11188 {
11189 $this->activation_visibility = (bool) $a_value;
11190 }
11191
11193 {
11195 }
11196
11198 {
11199 return (bool)$this->activation_limited;
11200 }
11201
11202 function setActivationLimited($a_value)
11203 {
11204 $this->activation_limited = (bool)$a_value;
11205 }
11206
11207 /* GET/SET for highscore feature */
11208
11214 public function setHighscoreEnabled($a_enabled)
11215 {
11216 $this->_highscore_enabled = (bool)$a_enabled;
11217 }
11218
11224 public function getHighscoreEnabled()
11225 {
11226 return (bool) $this->_highscore_enabled;
11227 }
11228
11236 public function setHighscoreAnon($a_anon)
11237 {
11238 $this->_highscore_anon = (bool)$a_anon;
11239 }
11240
11250 public function getHighscoreAnon()
11251 {
11252 return (bool) $this->_highscore_anon;
11253 }
11254
11263 public function isHighscoreAnon()
11264 {
11265 if ($this->getAnonymity() == 1)
11266 {
11267 return true;
11268 }
11269 else
11270 {
11271 return (bool)$this->getHighscoreAnon();
11272 }
11273 }
11274
11280 public function setHighscoreAchievedTS($a_achieved_ts)
11281 {
11282 $this->_highscore_achieved_ts = (bool)$a_achieved_ts;
11283 }
11284
11290 public function getHighscoreAchievedTS()
11291 {
11292 return (bool) $this->_highscore_achieved_ts;
11293 }
11294
11300 public function setHighscoreScore($a_score)
11301 {
11302 $this->_highscore_score = (bool)$a_score;
11303 }
11304
11310 public function getHighscoreScore()
11311 {
11312 return (bool) $this->_highscore_score;
11313 }
11314
11320 public function setHighscorePercentage($a_percentage)
11321 {
11322 $this->_highscore_percentage = (bool)$a_percentage;
11323 }
11324
11330 public function getHighscorePercentage()
11331 {
11332 return (bool) $this->_highscore_percentage;
11333 }
11334
11340 public function setHighscoreHints($a_hints)
11341 {
11342 $this->_highscore_hints = (bool)$a_hints;
11343 }
11344
11350 public function getHighscoreHints()
11351 {
11352 return (bool) $this->_highscore_hints;
11353 }
11354
11360 public function setHighscoreWTime($a_wtime)
11361 {
11362 $this->_highscore_wtime = (bool)$a_wtime;
11363 }
11364
11370 public function getHighscoreWTime()
11371 {
11372 return (bool) $this->_highscore_wtime;
11373 }
11374
11380 public function setHighscoreOwnTable($a_own_table)
11381 {
11382 $this->_highscore_own_table = (bool)$a_own_table;
11383 }
11384
11390 public function getHighscoreOwnTable()
11391 {
11392 return (bool) $this->_highscore_own_table;
11393 }
11394
11400 public function setHighscoreTopTable($a_top_table)
11401 {
11402 $this->_highscore_top_table = (bool)$a_top_table;
11403 }
11404
11410 public function getHighscoreTopTable()
11411 {
11412 return (bool) $this->_highscore_top_table;
11413 }
11414
11421 public function setHighscoreTopNum($a_top_num)
11422 {
11423 $this->_highscore_top_num = (int)$a_top_num;
11424 }
11425
11434 public function getHighscoreTopNum($a_retval = 10)
11435 {
11436 $retval = $a_retval;
11437 if ( (int) $this->_highscore_top_num != 0)
11438 {
11439 $retval = $this->_highscore_top_num;
11440 }
11441
11442 return $retval;
11443 }
11444
11448 public function getHighscoreMode()
11449 {
11450 switch(true)
11451 {
11452 case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
11454 break;
11455
11456 case $this->getHighscoreTopTable():
11458 break;
11459
11460 case $this->getHighscoreOwnTable():
11461 default:
11463 break;
11464 }
11465 }
11466
11470 public function setHighscoreMode($mode)
11471 {
11472 switch($mode)
11473 {
11475 $this->setHighscoreTopTable(1);
11476 $this->setHighscoreOwnTable(1);
11477 break;
11478
11480 $this->setHighscoreTopTable(1);
11481 $this->setHighscoreOwnTable(0);
11482 break;
11483
11485 default:
11486 $this->setHighscoreTopTable(0);
11487 $this->setHighscoreOwnTable(1);
11488 break;
11489 }
11490 }
11491 /* End GET/SET for highscore feature*/
11492
11493 public function setSpecificAnswerFeedback($specific_answer_feedback)
11494 {
11495 switch ($specific_answer_feedback)
11496 {
11497 case 1:
11498 $this->specific_answer_feedback = 1;
11499 break;
11500 default:
11501 $this->specific_answer_feedback = 0;
11502 break;
11503 }
11504 }
11505
11507 {
11508 switch ($this->specific_answer_feedback)
11509 {
11510 case 1:
11511 return 1;
11512 default:
11513 return 0;
11514 }
11515 }
11516
11523 {
11524 $this->obligationsEnabled = (bool)$obligationsEnabled;
11525 }
11526
11532 public function areObligationsEnabled()
11533 {
11534 return (bool)$this->obligationsEnabled;
11535 }
11536
11543 public static function isQuestionObligationPossible($questionId)
11544 {
11545 require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11546
11547 $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11548
11549 assQuestion::_includeClass($classConcreteQuestion, 0);
11550
11551 // static binder is not at work yet (in PHP < 5.3)
11552 //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11553 $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11554
11555 return $obligationPossible;
11556 }
11557
11564 public static function isQuestionObligatory($question_id)
11565 {
11566 global $ilDB;
11567
11568 $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11569
11570 if( $row = $ilDB->fetchAssoc($rset) )
11571 {
11572 return (bool) $row['obligatory'];
11573 }
11574
11575 return false;
11576 }
11577
11590 public static function allObligationsAnswered($test_id, $active_id, $pass)
11591 {
11592 global $ilDB;
11593
11594 $rset = $ilDB->queryF(
11595 'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11596 array('integer', 'integer'),
11597 array($active_id, $pass)
11598 );
11599
11600 if( $row = $ilDB->fetchAssoc($rset) )
11601 {
11602 return (bool)$row['obligations_answered'];
11603 }
11604
11606 }
11607
11616 public static function hasObligations($test_id)
11617 {
11618 global $ilDB;
11619
11620 $rset = $ilDB->queryF(
11621 'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11622 array('integer'), array($test_id)
11623 );
11624
11625 $row = $ilDB->fetchAssoc($rset);
11626
11627 return (bool)$row['cnt'] > 0;
11628 }
11629
11630 public function setAutosave($autosave)
11631 {
11632 $this->autosave = $autosave;
11633 }
11634
11635 public function getAutosave()
11636 {
11637 return $this->autosave;
11638 }
11639
11641 {
11642 $this->autosave_ival = $autosave_ival;
11643 }
11644
11645 public function getAutosaveIval()
11646 {
11647 return $this->autosave_ival;
11648 }
11649
11655 public function isPassDeletionAllowed()
11656 {
11658 }
11659
11666 {
11667 $this->passDeletionAllowed = (bool)$passDeletionAllowed;
11668 }
11669
11670 #region Examview / PDF Examview
11675 {
11676 $this->show_examview_html = $show_examview_html;
11677 }
11678
11682 public function getShowExamviewHtml()
11683 {
11685 }
11686
11691 {
11692 $this->show_examview_pdf = $show_examview_pdf;
11693 }
11694
11698 public function getShowExamviewPdf()
11699 {
11701 }
11702
11707 {
11708 $this->enable_examview = $enable_examview;
11709 }
11710
11714 public function getEnableExamview()
11715 {
11717 }
11718
11719 #endregion
11720
11722 {
11723 $this->activation_starting_time = $starting_time;
11724 }
11725
11727 {
11728 $this->activation_ending_time = $ending_time;
11729 }
11730
11732 {
11733 return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
11734 }
11735
11737 {
11738 return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
11739 }
11740
11742 {
11743 global $ilDB;
11744
11745 $times = array();
11746 $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");
11747 while ($row = $ilDB->fetchAssoc($result))
11748 {
11749 $times[$row['active_fi']] = $row['started'];
11750 }
11751 return $times;
11752 }
11753
11755 {
11756 global $ilDB;
11757
11758 $times = array();
11759 $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",
11760 array('integer'),
11761 array($this->getTestId())
11762 );
11763 while ($row = $ilDB->fetchAssoc($result))
11764 {
11765 $times[$row['active_fi']] = $row['additionaltime'];
11766 }
11767 return $times;
11768 }
11769
11770 public function getExtraTime($active_id)
11771 {
11772 global $ilDB;
11773
11774 $result = $ilDB->queryF("SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11775 array('integer'),
11776 array($active_id)
11777 );
11778 if ($result->numRows() > 0)
11779 {
11780 $row = $ilDB->fetchAssoc($result);
11781 return $row['additionaltime'];
11782 }
11783 return 0;
11784 }
11785
11786 public function addExtraTime($active_id, $minutes)
11787 {
11788 global $ilDB;
11789
11790 $participants = array();
11791 if ($active_id == 0)
11792 {
11793 $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
11794 array('integer'),
11795 array($this->getTestId())
11796 );
11797 while ($row = $ilDB->fetchAssoc($result))
11798 {
11799 array_push($participants, $row['active_id']);
11800 }
11801 }
11802 else
11803 {
11804 array_push($participants, $active_id);
11805 }
11806 foreach ($participants as $active_id)
11807 {
11808 $result = $ilDB->queryF("SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11809 array('integer'),
11810 array($active_id)
11811 );
11812 if ($result->numRows() > 0)
11813 {
11814 $ilDB->manipulateF("DELETE FROM tst_addtime WHERE active_fi = %s",
11815 array('integer'),
11816 array($active_id)
11817 );
11818 }
11819
11820 $ilDB->manipulateF("UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11821 array('integer','integer','timestamp','integer'),
11822 array(0, 0, NULL, $active_id)
11823 );
11824
11825 $ilDB->manipulateF("INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11826 array('integer','integer','integer'),
11827 array($active_id, $minutes, time())
11828 );
11829
11830 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11832 {
11833 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11834 }
11835 }
11836 }
11837
11844 {
11845 $this->enable_archiving = $enable_archiving;
11846 return $this;
11847 }
11848
11852 public function getEnableArchiving()
11853 {
11855 }
11856
11857 public function getMaxPassOfTest()
11858 {
11862 global $ilDB;
11863
11864 $query = '
11865 SELECT MAX(tst_pass_result.pass) + 1 max_res
11866 FROM tst_pass_result
11867 INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11868 WHERE test_fi = '.$ilDB->quote($this->getTestId(), 'integer').'
11869 ';
11870 $res = $ilDB->query($query);
11871 $data = $ilDB->fetchAssoc($res);
11872 return (int)$data['max_res'];
11873 }
11874
11880 public static function lookupExamId($active_id, $pass)
11881 {
11882 global $ilDB;
11883
11884 $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11885 $exam_id_result = $ilDB->queryF( $exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ) );
11886 if ($ilDB->numRows( $exam_id_result ) == 1)
11887 {
11888 $exam_id_row = $ilDB->fetchAssoc( $exam_id_result );
11889
11890 if ($exam_id_row['exam_id'] != null)
11891 {
11892 return $exam_id_row['exam_id'];
11893 }
11894 }
11895
11896 return null;
11897 }
11898
11905 public static function buildExamId($active_id, $pass, $test_obj_id = null)
11906 {
11907 global $ilSetting;
11908
11909 $inst_id = $ilSetting->get( 'inst_id', null );
11910
11911 if($test_obj_id === null)
11912 {
11913 $obj_id = self::_getObjectIDFromActiveID($active_id);
11914 }
11915 else
11916 {
11917 $obj_id = $test_obj_id;
11918 }
11919
11920 $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11921
11922 return $examId;
11923 }
11924
11926 {
11927 $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11928 }
11929
11931 {
11933 }
11934
11939 {
11940 $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11941 }
11942
11947 {
11949 }
11950
11955 {
11956 $this->sign_submission = $sign_submission;
11957 }
11958
11962 public function getSignSubmission()
11963 {
11965 }
11966
11970 public function setCharSelectorAvailability($availability)
11971 {
11972 $this->char_selector_availability = (int) $availability;
11973 }
11974
11979 {
11981 }
11982
11986 public function setCharSelectorDefinition($definition = '')
11987 {
11988 $this->char_selector_definition = $definition;
11989 }
11990
11995 {
11997 }
11998
11999
12006 {
12007 $this->questionSetType = $questionSetType;
12008 }
12009
12015 public function getQuestionSetType()
12016 {
12018 }
12019
12027 public static function lookupQuestionSetType($objId)
12028 {
12029 global $ilDB;
12030
12031 $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
12032
12033 $res = $ilDB->queryF($query, array('integer'), array($objId));
12034
12035 $questionSetType = null;
12036
12037 while( $row = $ilDB->fetchAssoc($res) )
12038 {
12039 $questionSetType = $row['question_set_type'];
12040 }
12041
12042 return $questionSetType;
12043 }
12044
12050 public function isFixedTest()
12051 {
12053 }
12054
12060 public function isRandomTest()
12061 {
12063 }
12064
12070 public function isDynamicTest()
12071 {
12073 }
12074
12082 public static function _lookupRandomTest($a_obj_id)
12083 {
12085 }
12086
12088 {
12089 switch( $questionSetType )
12090 {
12092 return $lng->txt('tst_question_set_type_fixed');
12093
12095 return $lng->txt('tst_question_set_type_random');
12096
12098 return $lng->txt('tst_question_set_type_dynamic');
12099 }
12100
12101 throw new ilTestException('invalid question set type value given: '.$questionSetType);
12102 }
12103
12104 public function participantDataExist()
12105 {
12106 if( $this->participantDataExist === null )
12107 {
12108 $this->participantDataExist = (bool)$this->evalTotalPersons();
12109 }
12110
12112 }
12113
12115 {
12116 if ($this->getScoreReporting() == 4)
12117 {
12118 return false;
12119 }
12120
12121 if ($this->getScoreReporting() == 3 && $this->getReportingDate() > time())
12122 {
12123 return false;
12124 }
12125
12126 return true;
12127 }
12128
12129 public function recalculateScores($preserve_manscoring = false)
12130 {
12131 require_once 'class.ilTestScoring.php';
12132 $scoring = new ilTestScoring($this);
12133 $scoring->setPreserveManualScores($preserve_manscoring);
12134 $scoring->recalculateSolutions();
12135 }
12136
12137 public static function getPoolQuestionChangeListeners(ilDBInterface $db, $poolObjId)
12138 {
12139 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
12140
12141 $questionChangeListeners = array(
12143 );
12144
12145 return $questionChangeListeners;
12146 }
12147
12148 public static function getTestObjIdsWithActiveForUserId($userId)
12149 {
12150 global $ilDB;
12151
12152 $query = "
12153 SELECT obj_fi
12154 FROM tst_active
12155 INNER JOIN tst_tests
12156 ON test_id = test_fi
12157 WHERE user_fi = %s
12158 ";
12159
12160 $res = $ilDB->queryF($query, array('integer'), array($userId));
12161
12162 $objIds = array();
12163
12164 while( $row = $ilDB->fetchAssoc($res) )
12165 {
12166 $objIds[] = (int)$row['obj_fi'];
12167 }
12168
12169 return $objIds;
12170 }
12171
12173 {
12174 $this->skillServiceEnabled = $skillServiceEnabled;
12175 }
12176
12177 public function isSkillServiceEnabled()
12178 {
12180 }
12181
12183 {
12184 $this->resultFilterTaxIds = $resultFilterTaxIds;
12185 }
12186
12187 public function getResultFilterTaxIds()
12188 {
12190 }
12191
12193 {
12194 if( !$this->isSkillServiceEnabled() )
12195 {
12196 return false;
12197 }
12198
12199 if( !self::isSkillManagementGloballyActivated() )
12200 {
12201 return false;
12202 }
12203
12204 return true;
12205 }
12206
12208
12209 public static function isSkillManagementGloballyActivated()
12210 {
12211 if( self::$isSkillManagementGloballyActivated === null )
12212 {
12213 include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
12214 $skmgSet = new ilSkillManagementSettings();
12215
12216 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
12217 }
12218
12220 }
12221
12223 {
12224 $this->showGradingStatusEnabled = $showGradingStatusEnabled;
12225 }
12226
12228 {
12230 }
12231
12233 {
12234 $this->showGradingMarkEnabled = $showGradingMarkEnabled;
12235 }
12236
12237
12239 {
12241 }
12242
12244 {
12245 $this->instantFeedbackAnswerFixationEnabled = $instantFeedbackAnswerFixationEnabled;
12246 }
12247
12249 {
12251 }
12252
12257 {
12259 }
12260
12265 {
12266 $this->forceInstantFeedbackEnabled = $forceInstantFeedbackEnabled;
12267 }
12268
12269 public static function ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run = FALSE)
12270 {
12271 global $ilDB, $lng, $ilPluginAdmin;
12272
12273 /* @var ilObjTest $testOBJ */
12274
12275 $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12276
12277 $activeId = $testOBJ->getActiveIdOfUser($userId);
12278
12279 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12280 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12281
12282 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12283 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12284
12285 $testSession = $testSessionFactory->getSession($activeId);
12286 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
12287 $testSequence->loadFromDb();
12288
12289 // begin-patch lok changed smeyer
12290 if($a_force_new_run)
12291 {
12292 if( $testSequence->hasSequence() )
12293 {
12294 $testSession->increasePass();
12295 }
12296 $testSession->setLastSequence(0);
12297 $testSession->saveToDb();
12298 }
12299 // end-patch lok
12300 }
12301
12302 public static function isParticipantsLastPassActive($testRefId, $userId)
12303 {
12304 global $ilDB, $lng, $ilPluginAdmin;
12305
12306 /* @var ilObjTest $testOBJ */
12307
12308 $testOBJ = ilObjectFactory::getInstanceByRefId($testRefId,false);
12309
12310
12311 $activeId = $testOBJ->getActiveIdOfUser($userId);
12312
12313 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12314 $testSessionFactory = new ilTestSessionFactory($testOBJ);
12315 // Added temporarily bugfix smeyer
12316 $testSessionFactory->reset();
12317
12318 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12319 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12320
12321 $testSession = $testSessionFactory->getSession($activeId);
12322 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
12323 $testSequence->loadFromDb();
12324
12325 return $testSequence->hasSequence();
12326 }
12327
12331 public function isTestFinalBroken()
12332 {
12334 }
12335
12340 {
12341 $this->testFinalBroken = $testFinalBroken;
12342 }
12343}
sprintf('%.4f', $callTime)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
for($col=0; $col< 50; $col++) $d
$result
$total
Definition: Utf8Test.php:87
$test
Definition: Utf8Test.php:84
$files
Definition: add-vimline.php:18
$_SESSION["AccountId"]
A class defining mark schemas for assessment test objects.
An exception for terminatinating execution or to throw for unit testing.
const IL_COMP_MODULE
const IL_CAL_UNIX
const IL_CAL_DATETIME
const NEWS_USERS
const NEWS_NOTICE
static getFeedbackClassNameByQuestionType($questionType)
static _getOriginalId($question_id)
Returns the original id of a question.
static _getSolutionMaxPass($question_id, $active_id)
Returns the maximum pass a users question solution.
static _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.
static _getQuestionTitle($question_id)
Returns the question title of a question with a given id.
static _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.
static deleteRequestsByActiveIds($activeIds)
Deletes all hint requests relating to a testactive included in given active ids.
Question page object.
static completeMissingPluginName($questionTypeData)
Create PDF certificates.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
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.
static recursive_dirscan($dir, &$arr)
Recursively scans a given directory and writes path and filename into referenced array.
language handling
static getFirstNewsIdForContext($a_context_obj_id, $a_context_obj_type, $a_context_sub_obj_id="", $a_context_sub_obj_type="")
Get first new id of news set related to a certain context.
static deleteNewsOfContext($a_context_obj_id, $a_context_obj_type, $a_context_sub_obj_id=0, $a_context_sub_obj_type="")
Delete all news of a context.
static _addLog($user_id, $object_id, $logtext, $question_id="", $original_id="", $test_only=FALSE, $test_ref_id=NULL)
Add an assessment log entry.
static _getLogLanguage()
retrieve the log language for assessment logging
static _getManualScoring()
Retrieve the manual scoring settings.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
Class ilObjFile.
Class ilObjGroup.
Class ilObjMediaObject.
static _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 _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
static _removeUsage($a_mob_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
Remove usage of mob in another container.
static _exists($a_id, $a_reference=false, $a_type=NULL)
checks wether a lm content object with specified id exists or not
static _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
static _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.
static _getParticipantData($active_id)
Retrieves a participant name from active id.
static getPoolQuestionChangeListener(ilDBInterface $db, $poolObjId)
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.
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given 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.
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)
{}
static _getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
getProcessingTimeAsMinutes()
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
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
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.
getQuestionTitle($title, $nr=null)
Returns the title of a test question and checks if the title output is allowed.
canShowEctsGrades()
{boolean}
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)
getListOfQuestionsStart()
Returns if the list of questions should be presented as the first page of the test.
& getCompleteEvaluationData($withStatistics=TRUE, $filterby="", $filtertext="")
static _getTestIDFromObjectID($object_id)
Returns the ILIAS test id for a given object id.
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)
& 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
setActivationEndingTime($ending_time=NULL)
setAllowedUsers($a_allowed_users)
isNrOfTriesReached($tries)
returns if number of tries are reached
reindexFixedQuestionOrdering()
static getTestObjIdsWithActiveForUserId($userId)
setTemplate($template_id)
setShowExamviewPdf($show_examview_pdf)
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.
static _getCountSystem($active_id)
Gets the count system for the calculation of points.
getQuestionCount()
Returns the number of questions in the test.
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...
setOldOnlineStatus($oldOnlineStatus)
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()
static lookupExamId($active_id, $pass)
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)
static _getActiveIdOfUser($user_id="", $test_id="")
Gets the active id of the tst_active table for the active user.
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.
isPreviousSolutionReuseEnabled($activeId)
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.
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.
buildIso8601PeriodFromUnixtimeForExportCompatibility($unix_timestamp)
$instantFeedbackAnswerFixationEnabled
static _getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
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.
static _getAvailableTests($use_object_id=FALSE)
Returns the available tests for the active user.
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.
& 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 ...
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
static _lookupAuthor($obj_id)
Gets the authors name of the ilObjTest object.
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...
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.
static _getPassScoring($active_id)
Gets the pass scoring type.
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.
static _getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
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.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
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.
read()
read object data from db into object
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.
static _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.
static _getObjectIDFromTestID($test_id)
Returns the ILIAS test object id for a given test id.
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.
static _setImportDirectory($a_import_dir=null)
set import directory
static _getMaxPass($active_id)
Retrieves the maximum pass of a given user for a given test in which the user answered at least one q...
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.
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)
static _getImportDirectory()
Get the import directory location of the test.
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 _getBestPass($active_id)
Retrieves the best pass of a given user for a given test.
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)
checkQuestionParent($questionId)
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.
setPassWaiting($pass_waiting)
removeQuestions($removeQuestionIds)
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.
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 _getWorkingTimeOfParticipantForPass($active_id, $pass)
Returns the complete working time in seconds for a test participant.
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
static _createImportDirectory()
creates data directory for import files (data_dir/tst_data/tst_<id>/import, depending on data directo...
create()
create test object
getEndingTime()
Returns the ending time of the test.
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)
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)
static $isSkillManagementGloballyActivated
getScoreReporting()
Gets the score reporting of the ilObjTest object.
getMailNotification()
Get mail notification settings.
setSignSubmission($sign_submission)
setEndingTime($ending_time=NULL)
Sets the ending time in database timestamp format for the test.
setEnableArchiving($enable_archiving)
& _evalResultsOverview($test_id)
Creates an associated array with the results of all participants of a test.
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 _getScoreCutting($active_id)
Determines if the score of a question should be cut at 0 points or the score of the whole test.
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.
$online
the object's online status
setExportSettingsSingleChoiceShort($a_settings)
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.
setShowExamviewHtml($show_examview_html)
const SCORE_REPORTING_DATE
setMCScoring($a_mc_scoring=SCORE_ZERO_POINTS_WHEN_UNANSWERED)
Sets the multiple choice scoring.
static _getSolvedQuestions($active_id, $question_fi=null)
get solved questions
static _lookupAnonymity($a_obj_id)
Returns the anonymity status of a test with a given object id.
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.
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)
static getPoolQuestionChangeListeners(ilDBInterface $db, $poolObjId)
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
static _lookupTestObjIdForQuestionId($a_q_id)
Get test Object ID for question ID.
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.
getTitleFilenameCompliant()
returns the object title prepared to be used as a filename
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.
getIntroduction()
Gets the introduction text of the ilObjTest object.
getAnswerFeedback()
Returns 1 if generic answer feedback is activated.
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
static _lookupClientIP($a_user_id)
Lookup client ip.
Class ilObjectActivation.
setTimingType($a_type)
Set timing type.
static getItem($a_ref_id)
Get item data.
static 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
deleteMetaData()
delete meta data entry
static _lookupDescription($a_id)
lookup object description
updateMetaData()
update meta data entry
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.
static _lookupOwner($a_id)
lookup object owner
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...
static _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, $a_timeout=0)
Creates an ilRpcClient instance to our ilServer.
ILIAS Setting Class.
special template class to simplify handling of ITX/PEAR
Base Exception for all Exceptions relating to Modules/Test.
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.
$counter
$html
Definition: example_001.php:87
$params
Definition: example_049.php:96
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\s+" &#(? foreach( $entity_files as $file) $output
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
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
xslt_error(&$proc)
xslt_free(&$proc)
xslt_create()
Interface ilDBInterface.
redirection script todo: (a better solution should control the processing via a xml file)
global $ilSetting
Definition: privfeed.php:17
if(!file_exists("$old.txt")) if( $old===$new) if(file_exists("$new.txt")) $file
$results
global $ilDB
if(!is_array($argv)) $options
global $DIC
$mobs
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:93