ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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
87 public $test_id;
88
95
102 public $author;
103
109 public $metadata;
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 public function create()
739 {
740 parent::create();
741
742 // meta data will be created by
743 // import parser
744 if (!$a_upload) {
745 $this->createMetaData();
746 }
747 }
748
755 public function update()
756 {
757 if (!parent::update()) {
758 return false;
759 }
760
761 // put here object specific stuff
762 $this->updateMetaData();
763 return true;
764 }
765
771 public function read()
772 {
773 parent::read();
774 $this->loadFromDb();
775 }
776
777
784 public function delete()
785 {
786 // always call parent delete function first!!
787 if (!parent::delete()) {
788 return false;
789 }
790
791 // delet meta data
792 $this->deleteMetaData();
793
794 //put here your module specific stuff
795 $this->deleteTest();
796
797 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentImportFails.php';
798 $qsaImportFails = new ilAssQuestionSkillAssignmentImportFails($this->getId());
799 $qsaImportFails->deleteRegisteredImportFails();
800 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdImportFails.php';
801 $sltImportFails = new ilTestSkillLevelThresholdImportFails($this->getId());
802 $sltImportFails->deleteRegisteredImportFails();
803
804 return true;
805 }
806
812 public function deleteTest()
813 {
814 global $tree, $ilDB, $ilPluginAdmin, $lng;
815
816 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
817 $participantData = new ilTestParticipantData($ilDB, $lng);
818 $participantData->load($this->getTestId());
819 $this->removeTestResults($participantData);
820
821 $affectedRows = $ilDB->manipulateF(
822 "DELETE FROM tst_mark WHERE test_fi = %s",
823 array('integer'),
824 array($this->getTestId())
825 );
826
827 $affectedRows = $ilDB->manipulateF(
828 "DELETE FROM tst_tests WHERE test_id = %s",
829 array('integer'),
830 array($this->getTestId())
831 );
832
833 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
834 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
835 $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
836
837 // delete export files
838 include_once "./Services/Utilities/classes/class.ilUtil.php";
839 $tst_data_dir = ilUtil::getDataDir() . "/tst_data";
840 $directory = $tst_data_dir . "/tst_" . $this->getId();
841 if (is_dir($directory)) {
842 include_once "./Services/Utilities/classes/class.ilUtil.php";
843 ilUtil::delDir($directory);
844 }
845 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
846 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
847 // remaining usages are not in text anymore -> delete them
848 // and media objects (note: delete method of ilObjMediaObject
849 // checks whether object is used in another context; if yes,
850 // the object is not deleted!)
851 foreach ($mobs as $mob) {
852 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
853 if (ilObjMediaObject::_exists($mob)) {
854 $mob_obj = new ilObjMediaObject($mob);
855 $mob_obj->delete();
856 }
857 }
858 }
859
865 public function createExportDirectory()
866 {
867 include_once "./Services/Utilities/classes/class.ilUtil.php";
868 $tst_data_dir = ilUtil::getDataDir() . "/tst_data";
869 ilUtil::makeDir($tst_data_dir);
870 if (!is_writable($tst_data_dir)) {
871 $this->ilias->raiseError("Test Data Directory (" . $tst_data_dir
872 . ") not writeable.", $this->ilias->error_obj->MESSAGE);
873 }
874
875 // create learning module directory (data_dir/lm_data/lm_<id>)
876 $tst_dir = $tst_data_dir . "/tst_" . $this->getId();
877 ilUtil::makeDir($tst_dir);
878 if (!@is_dir($tst_dir)) {
879 $this->ilias->raiseError("Creation of Test Directory failed.", $this->ilias->error_obj->MESSAGE);
880 }
881 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
882 $export_dir = $tst_dir . "/export";
883 ilUtil::makeDir($export_dir);
884 if (!@is_dir($export_dir)) {
885 $this->ilias->raiseError("Creation of Export Directory failed.", $this->ilias->error_obj->MESSAGE);
886 }
887 }
888
894 public function getExportDirectory()
895 {
896 include_once "./Services/Utilities/classes/class.ilUtil.php";
897 $export_dir = ilUtil::getDataDir() . "/tst_data" . "/tst_" . $this->getId() . "/export";
898 return $export_dir;
899 }
900
907 public function getExportFiles($dir)
908 {
909 // quit if import dir not available
910 if (!@is_dir($dir) || !is_writeable($dir)) {
911 return array();
912 }
913
914 $files = array();
915 foreach (new DirectoryIterator($dir) as $file) {
919 if ($file->isDir()) {
920 continue;
921 }
922
923 $files[] = $file->getBasename();
924 }
925
926 sort($files);
927
928 return $files;
929 }
930
934 public static function _setImportDirectory($a_import_dir = null)
935 {
936 if (strlen($a_import_dir)) {
937 $_SESSION["tst_import_dir"] = $a_import_dir;
938 } else {
939 unset($_SESSION["tst_import_dir"]);
940 }
941 }
942
949 public static function _getImportDirectory()
950 {
951 if (strlen($_SESSION["tst_import_dir"])) {
952 return $_SESSION["tst_import_dir"];
953 }
954 return null;
955 }
956
957 public function getImportDirectory()
958 {
960 }
961
967 public static function _createImportDirectory()
968 {
969 global $ilias;
970 include_once "./Services/Utilities/classes/class.ilUtil.php";
971 $tst_data_dir = ilUtil::getDataDir() . "/tst_data";
972 ilUtil::makeDir($tst_data_dir);
973
974 if (!is_writable($tst_data_dir)) {
975 $ilias->raiseError("Test Data Directory (" . $tst_data_dir
976 . ") not writeable.", $ilias->error_obj->FATAL);
977 }
978
979 // create test directory (data_dir/tst_data/tst_import)
980 $tst_dir = $tst_data_dir . "/tst_import";
981 ilUtil::makeDir($tst_dir);
982 if (!@is_dir($tst_dir)) {
983 $ilias->raiseError("Creation of test import directory failed.", $ilias->error_obj->FATAL);
984 }
985
986 // assert that this is empty and does not contain old data
987 ilUtil::delDir($tst_dir, true);
988
989 return $tst_dir;
990 }
991
998 public function hasSingleChoiceQuestions()
999 {
1000 global $ilDB;
1001
1002 $result = $ilDB->queryF(
1003 "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",
1004 array('integer'),
1005 array($this->getTestId())
1006 );
1007 $hasSC = false;
1008 while ($row = $ilDB->fetchAssoc($result)) {
1009 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0) {
1010 $hasSC = true;
1011 }
1012 }
1013 return $hasSC;
1014 }
1015
1022 public function isSingleChoiceTest()
1023 {
1024 global $ilDB;
1025
1026 $result = $ilDB->queryF(
1027 "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",
1028 array('integer'),
1029 array($this->getTestId())
1030 );
1031 if ($result->numRows() == 1) {
1032 $row = $ilDB->fetchAssoc($result);
1033 if (strcmp($row['foundtypes'], 'assSingleChoice') == 0) {
1034 return true;
1035 } else {
1036 return false;
1037 }
1038 }
1039 return false;
1040 }
1041
1049 {
1050 global $ilDB;
1051
1052 if (!$this->hasSingleChoiceQuestions()) {
1053 return false;
1054 }
1055
1056 $result = $ilDB->queryF(
1057 "
1058 SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1059 FROM qpl_questions,
1060 qpl_qst_sc,
1061 tst_test_result,
1062 qpl_qst_type,
1063 tst_active
1064 WHERE tst_test_result.question_fi = qpl_questions.question_id
1065 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1066 AND tst_test_result.active_fi = tst_active.active_id
1067 AND qpl_questions.question_id = qpl_qst_sc.question_fi
1068 AND tst_active.test_fi = %s
1069 AND qpl_qst_type.type_tag = %s
1070 ",
1071 array('integer', 'text'),
1072 array($this->getTestId(), 'assSingleChoice')
1073 );
1074 if ($result->numRows() == 1) {
1075 $row = $ilDB->fetchAssoc($result);
1076 return ($row['foundshuffles'] == 0);
1077 }
1078 return false;
1079 }
1080
1087 final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1088 {
1089 if (!count($this->mark_schema->mark_steps)) {
1090 return false;
1091 }
1092
1093 if (!$testQuestionSetConfig->isQuestionSetConfigured()) {
1094 return false;
1095 }
1096
1097 return true;
1098 }
1099
1106 public function _isComplete($obj_id)
1107 {
1108 global $tree, $ilDB, $ilPluginAdmin;
1109
1110 $test = new ilObjTest($obj_id, false);
1111 $test->loadFromDb();
1112
1113 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1114 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1115
1116 return $test->isComplete($testQuestionSetConfigFactory->getQuestionSetConfig());
1117 }
1118
1122 public function saveECTSStatus()
1123 {
1127 global $ilDB;
1128
1129 if ($this->getTestId() > 0) {
1130 $this->setECTSFX(preg_replace('/,/', '.', $this->getECTSFX()));
1131 if (!preg_match('/\d+/', $this->getECTSFX())) {
1132 $this->setECTSFX(null);
1133 }
1134
1135 $grades = $this->getECTSGrades();
1136 $ilDB->manipulateF(
1137 "UPDATE tst_tests
1138 SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s
1139 WHERE test_id = %s",
1140 array('text', 'float', 'float', 'float', 'float', 'float', 'float', 'integer'),
1141 array(
1142 (int) $this->getECTSOutput(),
1143 $grades['A'], $grades['B'], $grades['C'], $grades['D'], $grades['E'],
1144 $this->getECTSFX(),
1145 $this->getTestId()
1146 )
1147 );
1148 }
1149 }
1150
1155 public function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1156 {
1157 global $ilDB;
1158
1159 $complete = 0;
1160 if ($this->isComplete($testQuestionSetConfig)) {
1161 $complete = 1;
1162 }
1163 if ($this->getTestId() > 0) {
1164 $ilDB->manipulateF(
1165 "UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1166 array('text', 'integer'),
1167 array($complete, $this->test_id)
1168 );
1169 }
1170 }
1171
1177 public function getAllRTEContent()
1178 {
1179 $result = array();
1180 array_push($result, $this->getIntroduction());
1181 array_push($result, $this->getFinalStatement());
1182 return $result;
1183 }
1184
1190 public function cleanupMediaobjectUsage()
1191 {
1192 include_once("./Services/RTE/classes/class.ilRTE.php");
1193 $completecontent = "";
1194 foreach ($this->getAllRTEContent() as $content) {
1195 $completecontent .= $content;
1196 }
1198 $completecontent,
1199 $this->getType() . ":html",
1200 $this->getId()
1201 );
1202 }
1203
1209 public function saveToDb($properties_only = false)
1210 {
1211 global $tree, $ilDB, $ilPluginAdmin;
1212
1213 // moved online_status to ilObjectActivation (see below)
1214
1215 // cleanup RTE images
1216 $this->cleanupMediaobjectUsage();
1217
1218 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1219 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1220 $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1221
1222 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1223 if ($this->test_id == -1) {
1224 // Create new dataset
1225 $next_id = $ilDB->nextId('tst_tests');
1226
1227 $ilDB->insert('tst_tests', array(
1228 'test_id' => array('integer', $next_id),
1229 'obj_fi' => array('integer', $this->getId()),
1230 'author' => array('text', $this->getAuthor()),
1231 'intro_enabled' => array('integer', (int) $this->isIntroductionEnabled()),
1232 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1233 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1234 'showinfo' => array('integer', $this->getShowInfo()),
1235 'forcejs' => array('integer', $this->getForceJS()),
1236 'customstyle' => array('text', $this->getCustomStyle()),
1237 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1238 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1239 'score_reporting' => array('integer', $this->getScoreReporting()),
1240 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1241 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1242 'answer_feedback' => array('text', $this->getAnswerFeedback()),
1243 'anonymity' => array('text', $this->getAnonymity()),
1244 'show_cancel' => array('text', $this->getShowCancel()),
1245 'show_marker' => array('integer', $this->getShowMarker()),
1246 'fixed_participants' => array('text', $this->getFixedParticipants()),
1247 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1248 'kiosk' => array('integer', $this->getKiosk()),
1249 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1250 'title_output' => array('text', $this->getTitleOutput()),
1251 'processing_time' => array('text', $this->getProcessingTime()),
1252 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1253 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1254 'reporting_date' => array('text', $this->getReportingDate()),
1255 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1256 'starting_time' => array('integer', $this->getStartingTime()),
1257 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1258 'ending_time' => array('integer', $this->getEndingTime()),
1259 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1260 'ects_output' => array('text', $this->getECTSOutput()),
1261 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : null),
1262 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : null),
1263 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : null),
1264 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : null),
1265 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : null),
1266 'ects_fx' => array('float', $this->getECTSFX()),
1267 'count_system' => array('text', $this->getCountSystem()),
1268 'mc_scoring' => array('text', $this->getMCScoring()),
1269 'score_cutting' => array('text', $this->getScoreCutting()),
1270 'pass_scoring' => array('text', $this->getPassScoring()),
1271 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1272 'results_presentation' => array('integer', $this->getResultsPresentation()),
1273 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1274 'password_enabled' => array('integer', (int) $this->isPasswordEnabled()),
1275 'password' => array('text', $this->getPassword()),
1276 'limit_users_enabled' => array('integer', (int) $this->isLimitUsersEnabled()),
1277 'allowedusers' => array('integer', $this->getAllowedUsers()),
1278 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1279 'mailnottype' => array('integer', $this->getMailNotificationType()),
1280 'exportsettings' => array('integer', $this->getExportSettings()),
1281 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1282 'mailnotification' => array('integer', $this->getMailNotification()),
1283 'created' => array('integer', time()),
1284 'tstamp' => array('integer', time()),
1285 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1286 'template_id' => array('integer', $this->getTemplate()),
1287 'pool_usage' => array('integer', $this->getPoolUsage()),
1288 'print_bs_with_res' => array('integer', (int) $this->isBestSolutionPrintedWithResult()),
1289 'obligations_enabled' => array('integer', (int) $this->areObligationsEnabled()),
1290 'offer_question_hints' => array('integer', (int) $this->isOfferingQuestionHintsEnabled()),
1291 'highscore_enabled' => array('integer', (int) $this->getHighscoreEnabled()),
1292 'highscore_anon' => array('integer', (int) $this->getHighscoreAnon()),
1293 'highscore_achieved_ts' => array('integer', (int) $this->getHighscoreAchievedTS()),
1294 'highscore_score' => array('integer', (int) $this->getHighscoreScore()),
1295 'highscore_percentage' => array('integer', (int) $this->getHighscorePercentage()),
1296 'highscore_hints' => array('integer', (int) $this->getHighscoreHints()),
1297 'highscore_wtime' => array('integer', (int) $this->getHighscoreWTime()),
1298 'highscore_own_table' => array('integer', (int) $this->getHighscoreOwnTable()),
1299 'highscore_top_table' => array('integer', (int) $this->getHighscoreTopTable()),
1300 'highscore_top_num' => array('integer', (int) $this->getHighscoreTopNum()),
1301 'online_status' => array('integer', (int) $this->isOnline()),
1302 'specific_feedback' => array('integer', (int) $this->getSpecificAnswerFeedback()),
1303 'autosave' => array('integer', (int) $this->getAutosave()),
1304 'autosave_ival' => array('integer', (int) $this->getAutosaveIval()),
1305 'pass_deletion_allowed' => array('integer', (int) $this->isPassDeletionAllowed()),
1306 'enable_examview' => array('integer', (int) $this->getEnableExamview()),
1307 'show_examview_html' => array('integer', (int) $this->getShowExamviewHtml()),
1308 'show_examview_pdf' => array('integer', (int) $this->getShowExamviewPdf()),
1309 'redirection_mode' => array('integer', (int) $this->getRedirectionMode()),
1310 'redirection_url' => array('text', (string) $this->getRedirectionUrl()),
1311 'enable_archiving' => array('integer', (int) $this->getEnableArchiving()),
1312 'examid_in_test_pass' => array('integer', (int) $this->isShowExamIdInTestPassEnabled()),
1313 'examid_in_test_res' => array('integer', (int) $this->isShowExamIdInTestResultsEnabled()),
1314 'sign_submission' => array('integer', (int) $this->getSignSubmission()),
1315 'question_set_type' => array('text', $this->getQuestionSetType()),
1316 'char_selector_availability' => array('integer', (int) $this->getCharSelectorAvailability()),
1317 'char_selector_definition' => array('text', (string) $this->getCharSelectorDefinition()),
1318 'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
1319 'result_tax_filters' => array('text', serialize((array) $this->getResultFilterTaxIds())),
1320 'show_grading_status' => array('integer', (int) $this->isShowGradingStatusEnabled()),
1321 'show_grading_mark' => array('integer', (int) $this->isShowGradingMarkEnabled()),
1322 'inst_fb_answer_fixation' => array('integer', (int) $this->isInstantFeedbackAnswerFixationEnabled()),
1323 'force_inst_fb' => array('integer', (int) $this->isForceInstantFeedbackEnabled()),
1324 'broken' => array('integer', (int) $this->isTestFinalBroken()),
1325 'pass_waiting' => array('text', (string) $this->getPassWaiting())
1326 ));
1327
1328 $this->test_id = $next_id;
1329
1331 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1332 }
1333 } else {
1334 // Modify existing dataset
1335 $oldrow = array();
1337 $result = $ilDB->queryF(
1338 "SELECT * FROM tst_tests WHERE test_id = %s",
1339 array('integer'),
1340 array($this->test_id)
1341 );
1342 if ($result->numRows() == 1) {
1343 $oldrow = $ilDB->fetchAssoc($result);
1344 }
1345 }
1346
1347 $ilDB->update(
1348 'tst_tests',
1349 array(
1350 'author' => array('text', $this->getAuthor()),
1351 'intro_enabled' => array('integer', (int) $this->isIntroductionEnabled()),
1352 'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1353 'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1354 'showinfo' => array('integer', $this->getShowInfo()),
1355 'forcejs' => array('integer', $this->getForceJS()),
1356 'customstyle' => array('text', $this->getCustomStyle()),
1357 'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1358 'sequence_settings' => array('integer', $this->getSequenceSettings()),
1359 'score_reporting' => array('integer', $this->getScoreReporting()),
1360 'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1361 'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1362 'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1363 'anonymity' => array('text', $this->getAnonymity()),
1364 'show_cancel' => array('text', $this->getShowCancel()),
1365 'show_marker' => array('integer', $this->getShowMarker()),
1366 'fixed_participants' => array('text', $this->getFixedParticipants()),
1367 'nr_of_tries' => array('integer', $this->getNrOfTries()),
1368 'kiosk' => array('integer', $this->getKiosk()),
1369 'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1370 'title_output' => array('text', $this->getTitleOutput()),
1371 'processing_time' => array('text', $this->getProcessingTime()),
1372 'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1373 'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1374 'reporting_date' => array('text', $this->getReportingDate()),
1375 'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1376 'starting_time' => array('integer', $this->getStartingTime()),
1377 'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1378 'ending_time' => array('integer', $this->getEndingTime()),
1379 'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1380 'ects_output' => array('text', $this->getECTSOutput()),
1381 'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : null),
1382 'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : null),
1383 'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : null),
1384 'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : null),
1385 'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : null),
1386 'ects_fx' => array('float', $this->getECTSFX()),
1387 'count_system' => array('text', $this->getCountSystem()),
1388 'mc_scoring' => array('text', $this->getMCScoring()),
1389 'score_cutting' => array('text', $this->getScoreCutting()),
1390 'pass_scoring' => array('text', $this->getPassScoring()),
1391 'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1392 'results_presentation' => array('integer', $this->getResultsPresentation()),
1393 'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1394 'password_enabled' => array('integer', (int) $this->isPasswordEnabled()),
1395 'password' => array('text', $this->getPassword()),
1396 'limit_users_enabled' => array('integer', (int) $this->isLimitUsersEnabled()),
1397 'allowedusers' => array('integer', $this->getAllowedUsers()),
1398 'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1399 'mailnottype' => array('integer', $this->getMailNotificationType()),
1400 'exportsettings' => array('integer', $this->getExportSettings()),
1401 'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1402 'mailnotification' => array('integer', $this->getMailNotification()),
1403 'tstamp' => array('integer', time()),
1404 'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1405 'template_id' => array('integer', $this->getTemplate()),
1406 'pool_usage' => array('integer', $this->getPoolUsage()),
1407 'print_bs_with_res' => array('integer', (int) $this->isBestSolutionPrintedWithResult()),
1408 'obligations_enabled' => array('integer', (int) $this->areObligationsEnabled()),
1409 'offer_question_hints' => array('integer', (int) $this->isOfferingQuestionHintsEnabled()),
1410 'highscore_enabled' => array('integer', (int) $this->getHighscoreEnabled()),
1411 'highscore_anon' => array('integer', (int) $this->getHighscoreAnon()),
1412 'highscore_achieved_ts' => array('integer', (int) $this->getHighscoreAchievedTS()),
1413 'highscore_score' => array('integer', (int) $this->getHighscoreScore()),
1414 'highscore_percentage' => array('integer', (int) $this->getHighscorePercentage()),
1415 'highscore_hints' => array('integer', (int) $this->getHighscoreHints()),
1416 'highscore_wtime' => array('integer', (int) $this->getHighscoreWTime()),
1417 'highscore_own_table' => array('integer', (int) $this->getHighscoreOwnTable()),
1418 'highscore_top_table' => array('integer', (int) $this->getHighscoreTopTable()),
1419 'highscore_top_num' => array('integer', (int) $this->getHighscoreTopNum()),
1420 'online_status' => array('integer', (int) $this->isOnline()),
1421 'specific_feedback' => array('integer', (int) $this->getSpecificAnswerFeedback()),
1422 'autosave' => array('integer', (int) $this->getAutosave()),
1423 'autosave_ival' => array('integer', (int) $this->getAutosaveIval()),
1424 'pass_deletion_allowed' => array('integer', (int) $this->isPassDeletionAllowed()),
1425 'enable_examview' => array('integer', (int) $this->getEnableExamview()),
1426 'show_examview_html' => array('integer', (int) $this->getShowExamviewHtml()),
1427 'show_examview_pdf' => array('integer', (int) $this->getShowExamviewPdf()),
1428 'redirection_mode' => array('integer', (int) $this->getRedirectionMode()),
1429 'redirection_url' => array('text', (string) $this->getRedirectionUrl()),
1430 'enable_archiving' => array('integer', (int) $this->getEnableArchiving()),
1431 'examid_in_test_pass' => array('integer', (int) $this->isShowExamIdInTestPassEnabled()),
1432 'examid_in_test_res' => array('integer', (int) $this->isShowExamIdInTestResultsEnabled()),
1433 'sign_submission' => array('integer', (int) $this->getSignSubmission()),
1434 'question_set_type' => array('text', $this->getQuestionSetType()),
1435 'char_selector_availability' => array('integer', (int) $this->getCharSelectorAvailability()),
1436 'char_selector_definition' => array('text', (string) $this->getCharSelectorDefinition()),
1437 'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
1438 'result_tax_filters' => array('text', serialize((array) $this->getResultFilterTaxIds())),
1439 'show_grading_status' => array('integer', (int) $this->isShowGradingStatusEnabled()),
1440 'show_grading_mark' => array('integer', (int) $this->isShowGradingMarkEnabled()),
1441 'inst_fb_answer_fixation' => array('integer', (int) $this->isInstantFeedbackAnswerFixationEnabled()),
1442 'force_inst_fb' => array('integer', (int) $this->isForceInstantFeedbackEnabled()),
1443 'broken' => array('integer', (int) $this->isTestFinalBroken()),
1444 'pass_waiting' => array('text', (string) $this->getPassWaiting())
1445 ),
1446 array(
1447 'test_id' => array('integer', (int) $this->getTestId())
1448 )
1449 );
1450
1451 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1453 $logresult = $ilDB->queryF(
1454 "SELECT * FROM tst_tests WHERE test_id = %s",
1455 array('integer'),
1456 array($this->getTestId())
1457 );
1458 $newrow = array();
1459 if ($logresult->numRows() == 1) {
1460 $newrow = $ilDB->fetchAssoc($logresult);
1461 }
1462 $changed_fields = array();
1463 foreach ($oldrow as $key => $value) {
1464 if (strcmp($oldrow[$key], $newrow[$key]) != 0) {
1465 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
1466 }
1467 }
1468 $changes = join($changed_fields, ", ");
1469 if (count($changed_fields) > 0) {
1470 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [" . $changes . "]");
1471 }
1472 }
1473 if ($this->evalTotalPersons() > 0) {
1474 // reset the finished status of participants if the nr of test passes did change
1475 if ($this->getNrOfTries() > 0) {
1476 // set all unfinished tests with nr of passes >= allowed passes finished
1477 $aresult = $ilDB->queryF(
1478 "SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = %s",
1479 array('integer', 'integer', 'integer'),
1480 array($this->getTestId(), $this->getNrOfTries(), 0)
1481 );
1482 while ($row = $ilDB->fetchAssoc($aresult)) {
1483 $ilDB->manipulateF(
1484 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1485 array('integer', 'timestamp', 'integer'),
1486 array(1, date('Y-m-d H:i:s'), $row["active_id"])
1487 );
1488 }
1489
1490 // set all finished tests with nr of passes < allowed passes not finished
1491 $aresult = $ilDB->queryF(
1492 "SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = %s",
1493 array('integer', 'integer', 'integer'),
1494 array($this->getTestId(), $this->getNrOfTries()-1, 1)
1495 );
1496 while ($row = $ilDB->fetchAssoc($aresult)) {
1497 $ilDB->manipulateF(
1498 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1499 array('integer', 'timestamp', 'integer'),
1500 array(0, null, $row["active_id"])
1501 );
1502 }
1503 } else {
1504 // set all finished tests with nr of passes >= allowed passes not finished
1505 $aresult = $ilDB->queryF(
1506 "SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = %s",
1507 array('integer', 'integer'),
1508 array($this->getTestId(), 1)
1509 );
1510 while ($row = $ilDB->fetchAssoc($aresult)) {
1511 $ilDB->manipulateF(
1512 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1513 array('integer', 'timestamp', 'integer'),
1514 array(0, null, $row["active_id"])
1515 );
1516 }
1517 }
1518 }
1519 }
1520
1521 // news item creation/update/deletion
1522 include_once 'Services/News/classes/class.ilNewsItem.php';
1523 if (!$this->getOldOnlineStatus() && $this->isOnline()) {
1524 global $ilUser;
1525 $newsItem = new ilNewsItem();
1526 $newsItem->setContext($this->getId(), 'tst');
1527 $newsItem->setPriority(NEWS_NOTICE);
1528 $newsItem->setTitle('new_test_online');
1529 $newsItem->setContentIsLangVar(true);
1530 $newsItem->setContent('');
1531 $newsItem->setUserId($ilUser->getId());
1532 $newsItem->setVisibility(NEWS_USERS);
1533 $newsItem->create();
1534 } elseif ($this->getOldOnlineStatus() && !$this->isOnline()) {
1535 ilNewsItem::deleteNewsOfContext($this->getId(), 'tst');
1536 } elseif ($this->isOnline()) {
1537 $newsId = ilNewsItem::getFirstNewsIdForContext($this->getId(), 'tst');
1538 if ($newsId > 0) {
1539 $newsItem = new ilNewsItem($newsId);
1540 $newsItem->setTitle('new_test_online');
1541 $newsItem->setContentIsLangVar(true);
1542 $newsItem->setContent('');
1543 $newsItem->update();
1544 }
1545 }
1546
1547 // moved activation to ilObjectActivation
1548 if ($this->ref_id) {
1549 include_once "./Services/Object/classes/class.ilObjectActivation.php";
1550 ilObjectActivation::getItem($this->ref_id);
1551
1552 $item = new ilObjectActivation;
1553 if (!$this->isActivationLimited()) {
1555 } else {
1556 $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1557 $item->setTimingStart($this->getActivationStartingTime());
1558 $item->setTimingEnd($this->getActivationEndingTime());
1559 $item->toggleVisible($this->getActivationVisibility());
1560 }
1561
1562 $item->update($this->ref_id);
1563 }
1564
1565 if (!$properties_only) {
1566 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED) {
1567 $this->saveQuestionsToDb();
1568 }
1569
1570 $this->mark_schema->saveToDb($this->test_id);
1571 }
1572 }
1573
1580 public function saveQuestionsToDb()
1581 {
1582 global $ilDB;
1583
1584 $oldquestions = array();
1585 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1587 $result = $ilDB->queryF(
1588 "SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1589 array('integer'),
1590 array($this->getTestId())
1591 );
1592 if ($result->numRows() > 0) {
1593 while ($row = $ilDB->fetchAssoc($result)) {
1594 array_push($oldquestions, $row["question_fi"]);
1595 }
1596 }
1597 }
1598 // workaround for lost obligations
1599 // this method is called if a question is removed
1600 $currentQuestionsObligationsQuery = 'SELECT question_fi, obligatory FROM tst_test_question WHERE test_fi = %s';
1601 $rset = $ilDB->queryF($currentQuestionsObligationsQuery, array('integer'), array($this->getTestId()));
1602 while ($row = $ilDB->fetchAssoc($rset)) {
1603 $obligatoryQuestionState[$row['question_fi']] = $row['obligatory'];
1604 }
1605 // delete existing category relations
1606 $affectedRows = $ilDB->manipulateF(
1607 "DELETE FROM tst_test_question WHERE test_fi = %s",
1608 array('integer'),
1609 array($this->getTestId())
1610 );
1611 // create new category relations
1612 foreach ($this->questions as $key => $value) {
1613 // workaround for import witout obligations information
1614 if (!isset($obligatoryQuestionState[$value]) || is_null($obligatoryQuestionState[$value])) {
1615 $obligatoryQuestionState[$value] = 0;
1616 }
1617
1618 // insert question
1619 $next_id = $ilDB->nextId('tst_test_question');
1620 $ilDB->insert('tst_test_question', array(
1621 'test_question_id' => array('integer', $next_id),
1622 'test_fi' => array('integer', $this->getTestId()),
1623 'question_fi' => array('integer', $value),
1624 'sequence' => array('integer', $key),
1625 'obligatory' => array('integer', $obligatoryQuestionState[$value]),
1626 'tstamp' => array('integer', time())
1627 ));
1628 }
1629 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1631 $result = $ilDB->queryF(
1632 "SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1633 array('integer'),
1634 array($this->getTestId())
1635 );
1636 $newquestions = array();
1637 if ($result->numRows() > 0) {
1638 while ($row = $ilDB->fetchAssoc($result)) {
1639 array_push($newquestions, $row["question_fi"]);
1640 }
1641 }
1642 foreach ($oldquestions as $index => $question_id) {
1643 if (strcmp($newquestions[$index], $question_id) != 0) {
1644 $pos = array_search($question_id, $newquestions);
1645 if ($pos === false) {
1646 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
1647 } else {
1648 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
1649 }
1650 }
1651 }
1652 foreach ($newquestions as $index => $question_id) {
1653 if (array_search($question_id, $oldquestions) === false) {
1654 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
1655 }
1656 }
1657 }
1658 }
1659
1665 protected function isNewRandomTest()
1666 {
1667 global $ilDB;
1668 $result = $ilDB->queryF(
1669 'SELECT copy_id FROM tst_rnd_cpy WHERE tst_fi = %s',
1670 array('integer'),
1671 array($this->getTestId())
1672 );
1673 return $result->numRows() > 0;
1674 }
1675
1688 public function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = null)
1689 {
1690 global $rbacsystem;
1691 global $ilDB;
1692
1693 // retrieve object id instead of ref id if necessary
1694 if (($questionpool != 0) && (!$use_obj_id)) {
1695 $questionpool = ilObject::_lookupObjId($questionpool);
1696 }
1697
1698 // get original ids of all existing questions in the test
1699 $result = $ilDB->queryF(
1700 "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",
1701 array("integer"),
1702 array($this->getTestId())
1703 );
1704 $original_ids = array();
1705 $paramtypes = array();
1706 $paramvalues = array();
1707 while ($row = $ilDB->fetchAssoc($result)) {
1708 array_push($original_ids, $row['original_id']);
1709 }
1710
1711 $available = "";
1712 // get a list of all available questionpools
1713 if (($questionpool == 0) && (!is_array($qpls))) {
1714 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1715 $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())));
1716 if (count($available_pools)) {
1717 $available = " AND " . $ilDB->in('obj_fi', $available_pools, false, 'integer');
1718 } else {
1719 return array();
1720 }
1721 }
1722
1723 $constraint_qpls = "";
1724 $result_array = array();
1725 if ($questionpool == 0) {
1726 if (is_array($qpls)) {
1727 if (count($qpls) > 0) {
1728 $constraint_qpls = " AND " . $ilDB->in('obj_fi', $qpls, false, 'integer');
1729 }
1730 }
1731 }
1732
1733 $original_clause = "";
1734 if (count($original_ids)) {
1735 $original_clause = " AND " . $ilDB->in('question_id', $original_ids, true, 'integer');
1736 }
1737
1738 if ($questionpool == 0) {
1739 $result = $ilDB->queryF(
1740 "SELECT question_id FROM qpl_questions WHERE original_id IS NULL $available $constraint_qpls AND owner > %s AND complete = %s $original_clause",
1741 array('integer', 'text'),
1742 array(0, "1")
1743 );
1744 } else {
1745 $result = $ilDB->queryF(
1746 "SELECT question_id FROM qpl_questions WHERE original_id IS NULL AND obj_fi = %s AND owner > %s AND complete = %s $original_clause",
1747 array('integer','integer', 'text'),
1748 array($questionpool, 0, "1")
1749 );
1750 }
1751 $found_ids = array();
1752 while ($row = $ilDB->fetchAssoc($result)) {
1753 array_push($found_ids, $row['question_id']);
1754 }
1755 $nr_of_questions = ($nr_of_questions > count($found_ids)) ? count($found_ids) : $nr_of_questions;
1756 if ($nr_of_questions == 0) {
1757 return array();
1758 }
1759 $rand_keys = array_rand($found_ids, $nr_of_questions);
1760 $result = array();
1761 if (is_array($rand_keys)) {
1762 foreach ($rand_keys as $key) {
1763 $result[$found_ids[$key]] = $found_ids[$key];
1764 }
1765 } else {
1766 $result[$found_ids[$rand_keys]] = $found_ids[$rand_keys];
1767 }
1768 return $result;
1769 }
1770
1778 public function getNrOfResultsForPass($active_id, $pass)
1779 {
1780 global $ilDB;
1781
1782 $result = $ilDB->queryF(
1783 "SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
1784 array('integer','integer'),
1785 array($active_id, $pass)
1786 );
1787 return $result->numRows();
1788 }
1789
1800 public function hasRandomQuestionsForPass($active_id, $pass)
1801 {
1802 global $ilDB;
1803 $result = $ilDB->queryF(
1804 "SELECT test_random_question_id FROM tst_test_rnd_qst WHERE active_fi = %s AND pass = %s",
1805 array('integer','integer'),
1806 array($active_id, $pass)
1807 );
1808 return ($result->numRows() > 0) ? true : false;
1809 }
1810
1814 public function loadFromDb()
1815 {
1816 global $ilDB;
1817
1818 $result = $ilDB->queryF(
1819 "SELECT * FROM tst_tests WHERE obj_fi = %s",
1820 array('integer'),
1821 array($this->getId())
1822 );
1823 if ($result->numRows() == 1) {
1824 $data = $ilDB->fetchObject($result);
1825 $this->setTestId($data->test_id);
1826 if (strlen($this->getAuthor()) == 0) {
1827 $this->saveAuthorToMetadata($data->author);
1828 }
1829 $this->setAuthor($data->author);
1830 include_once("./Services/RTE/classes/class.ilRTE.php");
1831 $this->setIntroductionEnabled($data->intro_enabled);
1833 $this->setShowInfo($data->showinfo);
1835 $this->setForceJS($data->forcejs);
1836 $this->setCustomStyle($data->customstyle);
1837 $this->setShowFinalStatement($data->showfinalstatement);
1838 $this->setSequenceSettings($data->sequence_settings);
1839 $this->setScoreReporting($data->score_reporting);
1840 $this->setInstantFeedbackSolution($data->instant_verification);
1841 $this->setAnswerFeedbackPoints($data->answer_feedback_points);
1842 $this->setAnswerFeedback($data->answer_feedback);
1843 $this->setAnonymity($data->anonymity);
1844 $this->setShowCancel($data->show_cancel);
1845 $this->setShowMarker($data->show_marker);
1846 $this->setFixedParticipants($data->fixed_participants);
1847 $this->setNrOfTries($data->nr_of_tries);
1848 $this->setKiosk($data->kiosk);
1849 $this->setUsePreviousAnswers($data->use_previous_answers);
1850 $this->setRedirectionMode($data->redirection_mode);
1851 $this->setRedirectionUrl($data->redirection_url);
1852 $this->setTitleOutput($data->title_output);
1853 $this->setProcessingTime($data->processing_time);
1854 $this->setEnableProcessingTime($data->enable_processing_time);
1855 $this->setResetProcessingTime($data->reset_processing_time);
1856 $this->setReportingDate($data->reporting_date);
1857 $this->setShuffleQuestions($data->shuffle_questions);
1858 $this->setResultsPresentation($data->results_presentation);
1859 $this->setStartingTimeEnabled($data->starting_time_enabled);
1860 $this->setStartingTime($data->starting_time);
1861 $this->setEndingTimeEnabled($data->ending_time_enabled);
1862 $this->setEndingTime($data->ending_time);
1863 $this->setListOfQuestionsSettings($data->show_summary);
1864 $this->setECTSOutput($data->ects_output);
1865 $this->setECTSGrades(
1866 array(
1867 "A" => $data->ects_a,
1868 "B" => $data->ects_b,
1869 "C" => $data->ects_c,
1870 "D" => $data->ects_d,
1871 "E" => $data->ects_e
1872 )
1873 );
1874 $this->setECTSFX($data->ects_fx);
1875 $this->mark_schema->flush();
1876 $this->mark_schema->loadFromDb($this->getTestId());
1877 $this->setCountSystem($data->count_system);
1878 $this->setMCScoring($data->mc_scoring);
1879 $this->setMailNotification($data->mailnotification);
1880 $this->setMailNotificationType($data->mailnottype);
1881 $this->setExportSettings($data->exportsettings);
1882 $this->setScoreCutting($data->score_cutting);
1883 $this->setPasswordEnabled($data->password_enabled);
1884 $this->setPassword($data->password);
1885 $this->setLimitUsersEnabled($data->limit_users_enabled);
1886 $this->setAllowedUsers($data->allowedusers);
1887 $this->setAllowedUsersTimeGap($data->alloweduserstimegap);
1888 $this->setPassScoring($data->pass_scoring);
1889 $this->setObligationsEnabled($data->obligations_enabled);
1890 $this->setOfferingQuestionHintsEnabled($data->offer_question_hints);
1891 $this->setCertificateVisibility($data->certificate_visibility);
1892 $this->setEnabledViewMode($data->enabled_view_mode);
1893 $this->setTemplate($data->template_id);
1894 $this->setPoolUsage($data->pool_usage);
1895 $this->setPrintBestSolutionWithResult((bool) $data->print_bs_with_res);
1896 $this->setHighscoreEnabled((bool) $data->highscore_enabled);
1897 $this->setHighscoreAnon((bool) $data->highscore_anon);
1898 $this->setHighscoreAchievedTS((bool) $data->highscore_achieved_ts);
1899 $this->setHighscoreScore((bool) $data->highscore_score);
1900 $this->setHighscorePercentage((bool) $data->highscore_percentage);
1901 $this->setHighscoreHints((bool) $data->highscore_hints);
1902 $this->setHighscoreWTime((bool) $data->highscore_wtime);
1903 $this->setHighscoreOwnTable((bool) $data->highscore_own_table);
1904 $this->setHighscoreTopTable((bool) $data->highscore_top_table);
1905 $this->setHighscoreTopNum((int) $data->highscore_top_num);
1906 $this->setOnline((bool) $data->online_status);
1907 $this->setOldOnlineStatus((bool) $data->online_status);
1908 $this->setSpecificAnswerFeedback((int) $data->specific_feedback);
1909 $this->setAutosave((bool) $data->autosave);
1910 $this->setAutosaveIval((int) $data->autosave_ival);
1911 $this->setPassDeletionAllowed($data->pass_deletion_allowed);
1912 $this->setEnableExamview((bool) $data->enable_examview);
1913 $this->setShowExamviewHtml((bool) $data->show_examview_html);
1914 $this->setShowExamviewPdf((bool) $data->show_examview_pdf);
1915 $this->setEnableArchiving((bool) $data->enable_archiving);
1916 $this->setShowExamIdInTestPassEnabled((bool) $data->examid_in_test_pass);
1917 $this->setShowExamIdInTestResultsEnabled((bool) $data->examid_in_test_res);
1918 $this->setSignSubmission((bool) $data->sign_submission);
1919 $this->setQuestionSetType($data->question_set_type);
1920 $this->setCharSelectorAvailability((int) $data->char_selector_availability);
1921 $this->setCharSelectorDefinition($data->char_selector_definition);
1922 $this->setSkillServiceEnabled((bool) $data->skill_service);
1923 $this->setResultFilterTaxIds(strlen($data->result_tax_filters) ? unserialize($data->result_tax_filters) : array());
1924 $this->setShowGradingStatusEnabled((bool) $data->show_grading_status);
1925 $this->setShowGradingMarkEnabled((bool) $data->show_grading_mark);
1926 $this->setInstantFeedbackAnswerFixationEnabled((bool) $data->inst_fb_answer_fixation);
1927 $this->setForceInstantFeedbackEnabled((bool) $data->force_inst_fb);
1928 $this->setTestFinalBroken((bool) $data->broken);
1929 $this->setPassWaiting($data->pass_waiting);
1930 $this->loadQuestions();
1931 }
1932
1933 // moved activation to ilObjectActivation
1934 if ($this->ref_id) {
1935 include_once "./Services/Object/classes/class.ilObjectActivation.php";
1936 $activation = ilObjectActivation::getItem($this->ref_id);
1937 switch ($activation["timing_type"]) {
1939 $this->setActivationLimited(true);
1940 $this->setActivationStartingTime($activation["timing_start"]);
1941 $this->setActivationEndingTime($activation["timing_end"]);
1942 $this->setActivationVisibility($activation["visible"]);
1943 break;
1944
1945 default:
1946 $this->setActivationLimited(false);
1947 break;
1948 }
1949 }
1950 }
1951
1958 public function loadQuestions($active_id = "", $pass = null)
1959 {
1960 global $ilUser;
1961 global $ilDB;
1962
1963 $this->questions = array();
1964 if ($this->isRandomTest()) {
1965 if (strcmp($active_id, "") == 0) {
1966 $active_id = $this->getActiveIdOfUser($ilUser->getId());
1967 }
1968 if (is_null($pass)) {
1969 $pass = self::_getPass($active_id);
1970 }
1971 $result = $ilDB->queryF(
1972 "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",
1973 array('integer', 'integer'),
1974 array($active_id, $pass)
1975 );
1976 // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
1977 // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
1978 // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
1979 // no questions are present for a newer pass.
1980 if ($result->numRows() == 0) {
1981 $result = $ilDB->queryF(
1982 "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",
1983 array('integer'),
1984 array($active_id)
1985 );
1986 }
1987 } else {
1988 $result = $ilDB->queryF(
1989 "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",
1990 array('integer'),
1991 array($this->test_id)
1992 );
1993 }
1994 $index = 1;
1995 while ($data = $ilDB->fetchAssoc($result)) {
1996 $this->questions[$index++] = $data["question_fi"];
1997 }
1998 }
1999
2003 public function isIntroductionEnabled()
2004 {
2006 }
2007
2012 {
2013 $this->introductionEnabled = $introductionEnabled;
2014 }
2015
2022 public function getIntroduction()
2023 {
2024 return (strlen($this->introduction)) ? $this->introduction : null;
2025 }
2026
2034 public function setIntroduction($introduction = "")
2035 {
2036 $this->introduction = $introduction;
2037 }
2038
2039
2047 public function setFinalStatement($a_statement = "")
2048 {
2049 $this->_finalstatement = $a_statement;
2050 }
2051
2059 public function setShowInfo($a_info = 1)
2060 {
2061 $this->_showinfo = ($a_info) ? 1 : 0;
2062 }
2063
2071 public function setForceJS($a_js = 1)
2072 {
2073 $this->_forcejs = ($a_js) ? 1 : 0;
2074 }
2075
2083 public function setCustomStyle($a_customStyle = null)
2084 {
2085 $this->_customStyle = $a_customStyle;
2086 }
2087
2095 public function getCustomStyle()
2096 {
2097 return (strlen($this->_customStyle)) ? $this->_customStyle : null;
2098 }
2099
2107 public function getCustomStyles()
2108 {
2109 $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2110 $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2111 $customstyles = array();
2112 if (is_dir($css_path)) {
2113 $results = array();
2114 include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2116 if (is_array($results["file"])) {
2117 foreach ($results["file"] as $filename) {
2118 if (strpos($filename, ".css")) {
2119 array_push($customstyles, $filename);
2120 }
2121 }
2122 }
2123 }
2124 return $customstyles;
2125 }
2126
2134 public function getTestStyleLocation($mode = "output")
2135 {
2136 if (strlen($this->getCustomStyle())) {
2137 $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2138 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2139 if (file_exists($custom)) {
2140 $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2141 $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2142 return $custom;
2143 } else {
2144 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2145 }
2146 } else {
2147 return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2148 }
2149 }
2150
2158 public function setShowFinalStatement($show = 0)
2159 {
2160 $this->_showfinalstatement = ($show) ? 1 : 0;
2161 }
2162
2169 public function getFinalStatement()
2170 {
2171 return (strlen($this->_finalstatement)) ? $this->_finalstatement : null;
2172 }
2173
2181 public function getShowInfo()
2182 {
2183 return ($this->_showinfo) ? 1 : 0;
2184 }
2185
2193 public function getForceJS()
2194 {
2195 return ($this->_forcejs) ? 1 : 0;
2196 }
2197
2205 public function getShowFinalStatement()
2206 {
2207 return ($this->_showfinalstatement) ? 1 : 0;
2208 }
2209
2217 public function getTestId()
2218 {
2219 return $this->test_id;
2220 }
2221
2225 public function getECTSOutput()
2226 {
2227 return ($this->ects_output) ? 1 : 0;
2228 }
2229
2233 public function setECTSOutput($a_ects_output)
2234 {
2235 $this->ects_output = $a_ects_output ? 1 : 0;
2236 }
2237
2241 public function getECTSFX()
2242 {
2243 return (strlen($this->ects_fx)) ? $this->ects_fx : null;
2244 }
2245
2249 public function setECTSFX($a_ects_fx)
2250 {
2251 $this->ects_fx = $a_ects_fx;
2252 }
2253
2257 public function getECTSGrades()
2258 {
2259 return $this->ects_grades;
2260 }
2261
2265 public function setECTSGrades(array $a_ects_grades)
2266 {
2267 $this->ects_grades = $a_ects_grades;
2268 }
2269
2275 public function getSequenceSettings()
2276 {
2277 return ($this->sequence_settings) ? $this->sequence_settings : 0;
2278 }
2279
2286 {
2287 $this->sequence_settings = $sequence_settings;
2288 }
2289
2293 public function isPostponingEnabled()
2294 {
2295 return (bool) $this->getSequenceSettings();
2296 }
2297
2301 public function setPostponingEnabled($postponingEnabled)
2302 {
2303 $this->setSequenceSettings((int) $postponingEnabled);
2304 }
2305
2314 {
2315 $this->score_reporting = $score_reporting;
2316 }
2317
2325 public function setInstantFeedbackSolution($instant_feedback = 0)
2326 {
2327 switch ($instant_feedback) {
2328 case 1:
2329 $this->instant_verification = 1;
2330 break;
2331 default:
2332 $this->instant_verification = 0;
2333 break;
2334 }
2335 }
2336
2345 {
2346 switch ($answer_feedback) {
2347 case 1:
2348 $this->answer_feedback = 1;
2349 break;
2350 default:
2351 $this->answer_feedback = 0;
2352 break;
2353 }
2354 }
2355
2361 public function setGenericAnswerFeedback($generic_answer_feedback = 0)
2362 {
2363 switch ($generic_answer_feedback) {
2364 case 1:
2365 $this->answer_feedback = 1;
2366 break;
2367 default:
2368 $this->answer_feedback = 0;
2369 break;
2370 }
2371 }
2372
2381 {
2382 switch ($answer_feedback_points) {
2383 case 1:
2384 $this->answer_feedback_points = 1;
2385 break;
2386 default:
2387 $this->answer_feedback_points = 0;
2388 break;
2389 }
2390 }
2391
2397 {
2398 if (!$reporting_date) {
2399 $this->reporting_date = '';
2400 $this->setECTSOutput(false);
2401 } else {
2402 $this->reporting_date = $reporting_date;
2403 }
2404 }
2405
2410
2418 public function getScoreReporting()
2419 {
2420 return ($this->score_reporting) ? $this->score_reporting : 0;
2421 }
2422
2423 public function isScoreReportingEnabled()
2424 {
2425 return $this->getScoreReporting() > 0 && $this->getScoreReporting() < 4;
2426 }
2427
2436 {
2437 return ($this->instant_verification) ? $this->instant_verification : 0;
2438 }
2439
2448 public function getAnswerFeedback()
2449 {
2450 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2451 }
2452
2460 {
2461 return ($this->answer_feedback) ? $this->answer_feedback : 0;
2462 }
2463
2471 public function getAnswerFeedbackPoints()
2472 {
2473 return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2474 }
2475
2483 public function getCountSystem()
2484 {
2485 return ($this->count_system) ? $this->count_system : 0;
2486 }
2487
2495 public static function _getCountSystem($active_id)
2496 {
2497 global $ilDB;
2498 $result = $ilDB->queryF(
2499 "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",
2500 array('integer'),
2501 array($active_id)
2502 );
2503 if ($result->numRows()) {
2504 $row = $ilDB->fetchAssoc($result);
2505 return $row["count_system"];
2506 }
2507 return false;
2508 }
2509
2517 public function getMCScoring()
2518 {
2519 return ($this->mc_scoring) ? $this->mc_scoring : 0;
2520 }
2521
2529 public function getScoreCutting()
2530 {
2531 return ($this->score_cutting) ? $this->score_cutting : 0;
2532 }
2533
2541 public function getPassScoring()
2542 {
2543 return ($this->pass_scoring) ? $this->pass_scoring : 0;
2544 }
2545
2553 public static function _getPassScoring($active_id)
2554 {
2555 global $ilDB;
2556 $result = $ilDB->queryF(
2557 "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",
2558 array('integer'),
2559 array($active_id)
2560 );
2561 if ($result->numRows()) {
2562 $row = $ilDB->fetchAssoc($result);
2563 return $row["pass_scoring"];
2564 }
2565 return 0;
2566 }
2567
2575 public static function _getMCScoring($active_id)
2576 {
2577 global $ilDB;
2578 $result = $ilDB->queryF(
2579 "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",
2580 array('integer'),
2581 array($active_id)
2582 );
2583 if ($result->numRows()) {
2584 $row = $ilDB->fetchAssoc($result);
2585 return $row["mc_scoring"];
2586 }
2587 return false;
2588 }
2589
2597 public static function _getScoreCutting($active_id)
2598 {
2599 global $ilDB;
2600 $result = $ilDB->queryF(
2601 "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",
2602 array('integer'),
2603 array($active_id)
2604 );
2605 if ($result->numRows()) {
2606 $row = $ilDB->fetchAssoc($result);
2607 return $row["score_cutting"];
2608 }
2609 return false;
2610 }
2611
2619 public function getReportingDate()
2620 {
2621 return (strlen($this->reporting_date)) ? $this->reporting_date : null;
2622 }
2623
2631 public function getNrOfTries()
2632 {
2633 return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2634 }
2635
2643 public function getKiosk()
2644 {
2645 return ($this->_kiosk) ? $this->_kiosk : 0;
2646 }
2647
2648
2656 public function setKiosk($kiosk = 0)
2657 {
2658 $this->_kiosk = $kiosk;
2659 }
2660
2668 public function getKioskMode()
2669 {
2670 if (($this->_kiosk & 1) > 0) {
2671 return true;
2672 } else {
2673 return false;
2674 }
2675 }
2676
2684 public function setKioskMode($a_kiosk = false)
2685 {
2686 if ($a_kiosk) {
2687 $this->_kiosk = $this->_kiosk | 1;
2688 } else {
2689 if ($this->getKioskMode()) {
2690 $this->_kiosk = $this->_kiosk ^ 1;
2691 }
2692 }
2693 }
2694
2702 public function getShowKioskModeTitle()
2703 {
2704 if (($this->_kiosk & 2) > 0) {
2705 return true;
2706 } else {
2707 return false;
2708 }
2709 }
2710
2717 public function setShowKioskModeTitle($a_title = false)
2718 {
2719 if ($a_title) {
2720 $this->_kiosk = $this->_kiosk | 2;
2721 } else {
2722 if ($this->getShowKioskModeTitle()) {
2723 $this->_kiosk = $this->_kiosk ^ 2;
2724 }
2725 }
2726 }
2727
2736 {
2737 if (($this->_kiosk & 4) > 0) {
2738 return true;
2739 } else {
2740 return false;
2741 }
2742 }
2743
2750 public function setShowKioskModeParticipant($a_participant = false)
2751 {
2752 if ($a_participant) {
2753 $this->_kiosk = $this->_kiosk | 4;
2754 } else {
2755 if ($this->getShowKioskModeParticipant()) {
2756 $this->_kiosk = $this->_kiosk ^ 4;
2757 }
2758 }
2759 }
2760
2768 public function getUsePreviousAnswers()
2769 {
2770 return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2771 }
2772
2780 public function getTitleOutput()
2781 {
2782 return ($this->title_output) ? $this->title_output : 0;
2783 }
2784
2793 public function _getTitleOutput($active_id)
2794 {
2795 global $ilDB;
2796
2797 $result = $ilDB->queryF(
2798 "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",
2799 array('integer'),
2800 array($active_id)
2801 );
2802 if ($result->numRows()) {
2803 $row = $ilDB->fetchAssoc($result);
2804 return $row["title_output"];
2805 }
2806 return 0;
2807 }
2808
2809 // hey: prevPassSolutions - serious (nonstatic) identifier, for use in high level controller gui
2810 public function isPreviousSolutionReuseEnabled($activeId)
2811 {
2812 // checks if allowed in general and if enabled by participant
2813 return self::_getUsePreviousAnswers($activeId, true);
2814 }
2815 // hey.
2816
2826 public static function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2827 {
2828 global $ilDB;
2829 global $ilUser;
2830
2832
2833 $result = $ilDB->queryF(
2834 "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",
2835 array("integer"),
2836 array($active_id)
2837 );
2838 if ($result->numRows()) {
2839 $row = $ilDB->fetchAssoc($result);
2840 $use_previous_answers = $row["use_previous_answers"];
2841 }
2842
2843 if ($use_previous_answers == 1) {
2844 if ($user_active_user_setting) {
2845 $res = $ilUser->getPref("tst_use_previous_answers");
2846 if ($res !== false) {
2848 }
2849 }
2850 }
2851 return $use_previous_answers;
2852 }
2853
2861 public function getProcessingTime()
2862 {
2863 return (strlen($this->processing_time)) ? $this->processing_time : null;
2864 }
2865
2873 {
2874 if (strlen($this->processing_time)) {
2875 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches)) {
2876 if ((int) $matches[1]+(int) $matches[2]+(int) $matches[3] == 0) {
2877 return $this->getEstimatedWorkingTime();
2878 } else {
2879 return array(
2880 'hh' => $matches[1],
2881 'mm' => $matches[2],
2882 'ss' => $matches[3],
2883 );
2884 }
2885 }
2886 }
2887 return $this->getEstimatedWorkingTime();
2888 }
2889
2891 {
2892 if (strlen($this->processing_time)) {
2893 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches)) {
2894 return ($matches[1] * 60) + $matches[2];
2895 }
2896 }
2897
2899 }
2900
2908 public function getProcessingTimeInSeconds($active_id = "")
2909 {
2910 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches)) {
2911 $extratime = $this->getExtraTime($active_id) * 60;
2912 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
2913 } else {
2914 return 0;
2915 }
2916 }
2917
2926 {
2927 if ($this->getEndingTime() != 0) {
2928 $ending = $this->getEndingTime();
2929 $now = time();
2930 return $ending - $now;
2931 } else {
2932 return 0;
2933 }
2934 }
2935
2943 public function getEnableProcessingTime()
2944 {
2945 return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
2946 }
2947
2955 public function getResetProcessingTime()
2956 {
2957 return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
2958 }
2959
2963 public function isStartingTimeEnabled()
2964 {
2966 }
2967
2972 {
2973 $this->starting_time_enabled = $starting_time_enabled;
2974 }
2975
2983 public function getStartingTime()
2984 {
2985 return ($this->starting_time != 0) ? $this->starting_time : 0;
2986 }
2987
2995 public function setStartingTime($starting_time = null)
2996 {
2997 $this->starting_time = $starting_time;
2998 }
2999
3003 public function isEndingTimeEnabled()
3004 {
3006 }
3007
3012 {
3013 $this->ending_time_enabled = $ending_time_enabled;
3014 }
3015
3023 public function getEndingTime()
3024 {
3025 return ($this->ending_time != 0) ? $this->ending_time : 0;
3026 }
3027
3035 public function setEndingTime($ending_time = null)
3036 {
3037 $this->ending_time = $ending_time;
3038 }
3039
3047 public function setNrOfTries($nr_of_tries = 0)
3048 {
3049 $this->nr_of_tries = $nr_of_tries;
3050 }
3051
3060 {
3062 $this->use_previous_answers = 1;
3063 } else {
3064 $this->use_previous_answers = 0;
3065 }
3066 }
3067
3069 {
3070 $this->redirection_mode = $redirection_mode;
3071 }
3072 public function getRedirectionMode()
3073 {
3075 }
3076 public function setRedirectionUrl($redirection_url = null)
3077 {
3078 $this->redirection_url = $redirection_url;
3079 }
3080 public function getRedirectionUrl()
3081 {
3083 }
3084
3092 public function setTitleOutput($title_output = 0)
3093 {
3094 switch ($title_output) {
3095 case 1:
3096 $this->title_output = 1;
3097 break;
3098 case 2:
3099 $this->title_output = 2;
3100 break;
3101 default:
3102 $this->title_output = 0;
3103 break;
3104 }
3105 }
3106
3114 public function setProcessingTime($processing_time = "00:00:00")
3115 {
3116 $this->processing_time = $processing_time;
3117 }
3118
3119 public function setProcessingTimeByMinutes($minutes)
3120 {
3121 $this->processing_time = sprintf("%02d:%02d:00", floor($minutes/60), $minutes%60);
3122 }
3123
3131 public function setEnableProcessingTime($enable = 0)
3132 {
3133 if ($enable) {
3134 $this->enable_processing_time = "1";
3135 } else {
3136 $this->enable_processing_time = "0";
3137 }
3138 }
3139
3147 public function setResetProcessingTime($reset = 0)
3148 {
3149 if ($reset) {
3150 $this->reset_processing_time = 1;
3151 } else {
3152 $this->reset_processing_time = 0;
3153 }
3154 }
3155
3163 public function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3164 {
3165 $this->count_system = $a_count_system;
3166 }
3167
3171 public function isPasswordEnabled()
3172 {
3174 }
3175
3180 {
3181 $this->passwordEnabled = $passwordEnabled;
3182 }
3183
3191 public function getPassword()
3192 {
3193 return (strlen($this->password)) ? $this->password : null;
3194 }
3195
3203 public function setPassword($a_password = null)
3204 {
3205 $this->password = $a_password;
3206 }
3207
3215 public function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3216 {
3217 $this->score_cutting = $a_score_cutting;
3218 }
3219
3227 public function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED)
3228 {
3229 $this->mc_scoring = $a_mc_scoring;
3230 }
3231
3239 public function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3240 {
3241 switch ($a_pass_scoring) {
3242 case SCORE_BEST_PASS:
3243 $this->pass_scoring = SCORE_BEST_PASS;
3244 break;
3245 default:
3246 $this->pass_scoring = SCORE_LAST_PASS;
3247 break;
3248 }
3249 }
3250
3254 public function getPassWaiting()
3255 {
3256 return $this->pass_waiting;
3257 }
3258
3263 {
3264 $this->pass_waiting = $pass_waiting;
3265 }
3269 public function isPassWaitingEnabled()
3270 {
3271 if (array_sum(explode(':', $this->getPassWaiting())) > 0) {
3272 return true;
3273 }
3274 return false;
3275 }
3276
3280 public function removeQuestions($removeQuestionIds)
3281 {
3282 foreach ($removeQuestionIds as $value) {
3283 $this->removeQuestion($value);
3284 }
3285
3287 }
3288
3296 public function removeQuestion($question_id)
3297 {
3298 $question =&ilObjTest::_instanciateQuestion($question_id);
3299 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3301 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3302 }
3303 $question->delete($question_id);
3304 }
3305
3315 {
3316 $this->removeTestResultsByUserIds($userIds);
3317
3318 $ilDB = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
3319 $lng = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['lng'] : $GLOBALS['lng'];
3320
3321 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3322 $participantData = new ilTestParticipantData($ilDB, $lng);
3323 $participantData->setUserIds($userIds);
3324 $participantData->load($this->getTestId());
3325
3326 $this->removeTestActives($participantData->getActiveIds());
3327 }
3328
3329 public function removeTestResults(ilTestParticipantData $participantData)
3330 {
3331 if (count($participantData->getAnonymousActiveIds())) {
3332 $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3333 }
3334
3335 if (count($participantData->getUserIds())) {
3336 /* @var ilTestLP $testLP */
3337 require_once 'Services/Object/classes/class.ilObjectLP.php';
3338 $testLP = ilObjectLP::getInstance($this->getId());
3339 $testLP->setTestObject($this);
3340 $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3341 }
3342
3343 if (count($participantData->getActiveIds())) {
3344 $this->removeTestActives($participantData->getActiveIds());
3345 }
3346 }
3347
3348 public function removeTestResultsByUserIds($userIds)
3349 {
3350 global $ilDB, $lng;
3351
3352 require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3353 $participantData = new ilTestParticipantData($ilDB, $lng);
3354 $participantData->setUserIds($userIds);
3355 $participantData->load($this->getTestId());
3356
3357 $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3358 $ilDB->manipulateF(
3359 "DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3360 array('text'),
3361 array("tst_password_" . $this->getTestId())
3362 );
3363
3364 if (count($participantData->getActiveIds())) {
3365 $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3366 }
3367 }
3368
3369 public function removeTestResultsByActiveIds($activeIds)
3370 {
3371 global $ilDB;
3372
3373 $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3374
3375 $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3376 $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3377 $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3378 $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3379 $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3380 $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3381 $ilDB->manipulate("DELETE FROM tst_times WHERE $IN_activeIds");
3382
3383 if ($this->isRandomTest()) {
3384 $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3385 } elseif ($this->isDynamicTest()) {
3386 $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3387 $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3388 $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3389 $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3390 }
3391
3392 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3393
3394 foreach ($activeIds as $active_id) {
3395 // remove file uploads
3396 if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id")) {
3397 ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3398 }
3399
3401 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3402 }
3403 }
3404
3405 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3407 }
3408
3409 public function removeTestActives($activeIds)
3410 {
3411 global $ilDB;
3412
3413 $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3414 $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3415 }
3416
3424 public function questionMoveUp($question_id)
3425 {
3426 global $ilDB;
3427
3428 // Move a question up in sequence
3429 $result = $ilDB->queryF(
3430 "SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3431 array('integer', 'integer'),
3432 array($this->getTestId(), $question_id)
3433 );
3434 $data = $ilDB->fetchObject($result);
3435 if ($data->sequence > 1) {
3436 // OK, it's not the top question, so move it up
3437 $result = $ilDB->queryF(
3438 "SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3439 array('integer','integer'),
3440 array($this->getTestId(), $data->sequence - 1)
3441 );
3442 $data_previous = $ilDB->fetchObject($result);
3443 // change previous dataset
3444 $affectedRows = $ilDB->manipulateF(
3445 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3446 array('integer','integer'),
3447 array($data->sequence, $data_previous->test_question_id)
3448 );
3449 // move actual dataset up
3450 $affectedRows = $ilDB->manipulateF(
3451 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3452 array('integer','integer'),
3453 array($data->sequence - 1, $data->test_question_id)
3454 );
3455 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3457 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3458 }
3459 }
3460 $this->loadQuestions();
3461 }
3462
3470 public function questionMoveDown($question_id)
3471 {
3472 global $ilDB;
3473
3474 // Move a question down in sequence
3475 $result = $ilDB->queryF(
3476 "SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3477 array('integer','integer'),
3478 array($this->getTestId(), $question_id)
3479 );
3480 $data = $ilDB->fetchObject($result);
3481 $result = $ilDB->queryF(
3482 "SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3483 array('integer','integer'),
3484 array($this->getTestId(), $data->sequence + 1)
3485 );
3486 if ($result->numRows() == 1) {
3487 // OK, it's not the last question, so move it down
3488 $data_next = $ilDB->fetchObject($result);
3489 // change next dataset
3490 $affectedRows = $ilDB->manipulateF(
3491 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3492 array('integer','integer'),
3493 array($data->sequence, $data_next->test_question_id)
3494 );
3495 // move actual dataset down
3496 $affectedRows = $ilDB->manipulateF(
3497 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3498 array('integer','integer'),
3499 array($data->sequence + 1, $data->test_question_id)
3500 );
3501 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3503 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3504 }
3505 }
3506 $this->loadQuestions();
3507 }
3508
3516 public function duplicateQuestionForTest($question_id)
3517 {
3518 global $ilUser;
3519 $question =&ilObjTest::_instanciateQuestion($question_id);
3520 $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3521
3522 return $duplicate_id;
3523 }
3524
3533 public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3534 {
3535 global $ilDB;
3536 #var_dump($question_id);
3537 if ($linkOnly) {
3538 $duplicate_id = $question_id;
3539 } else {
3540 $duplicate_id = $this->duplicateQuestionForTest($question_id);
3541 }
3542
3543 // get maximum sequence index in test
3544 $result = $ilDB->queryF(
3545 "SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3546 array('integer'),
3547 array($this->getTestId())
3548 );
3549 $sequence = 1;
3550
3551 if ($result->numRows() == 1) {
3552 $data = $ilDB->fetchObject($result);
3553 $sequence = $data->seq + 1;
3554 }
3555
3556 $next_id = $ilDB->nextId('tst_test_question');
3557 $affectedRows = $ilDB->manipulateF(
3558 "INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3559 array('integer', 'integer','integer','integer','integer'),
3560 array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3561 );
3562 if ($affectedRows == 1) {
3563 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3565 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3566 }
3567 }
3568 // remove test_active entries, because test has changed
3569 $affectedRows = $ilDB->manipulateF(
3570 "DELETE FROM tst_active WHERE test_fi = %s",
3571 array('integer'),
3572 array($this->getTestId())
3573 );
3574 $this->loadQuestions();
3575 $this->saveCompleteStatus($testQuestionSetConfig);
3576 return $duplicate_id;
3577 }
3578
3586 public function &getQuestionTitles()
3587 {
3588 $titles = array();
3589 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED) {
3590 global $ilDB;
3591 $result = $ilDB->queryF(
3592 "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",
3593 array('integer'),
3594 array($this->getTestId())
3595 );
3596 while ($row = $ilDB->fetchAssoc($result)) {
3597 array_push($titles, $row["title"]);
3598 }
3599 }
3600 return $titles;
3601 }
3602
3611 {
3612 $titles = array();
3613 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED) {
3614 global $ilDB;
3615 $result = $ilDB->queryF(
3616 "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",
3617 array('integer'),
3618 array($this->getTestId())
3619 );
3620 while ($row = $ilDB->fetchAssoc($result)) {
3621 $titles[$row['question_id']] = $row["title"];
3622 }
3623 }
3624 return $titles;
3625 }
3626
3627 // fau: testNav - add number parameter (to show if title should not be shown)
3637 public function getQuestionTitle($title, $nr = null)
3638 {
3639 if ($this->getTitleOutput() == 2) {
3640 if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_DYNAMIC) {
3641 // avoid legacy setting combination: ctm without question titles
3642 return $title;
3643 } elseif (isset($nr)) {
3644 return $this->lng->txt("ass_question") . ' ' . $nr;
3645 } else {
3646 return $this->lng->txt("ass_question");
3647 }
3648 } else {
3649 return $title;
3650 }
3651 }
3652 // fau.
3653
3662 public function getQuestionDataset($question_id)
3663 {
3664 global $ilDB;
3665
3666 $result = $ilDB->queryF(
3667 "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",
3668 array('integer'),
3669 array($question_id)
3670 );
3671 $row = $ilDB->fetchObject($result);
3672 return $row;
3673 }
3674
3681 public function &getExistingQuestions($pass = null)
3682 {
3683 global $ilUser;
3684 global $ilDB;
3685
3686 $existing_questions = array();
3687 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3688 if ($this->isRandomTest()) {
3689 if (is_null($pass)) {
3690 $pass = 0;
3691 }
3692 $result = $ilDB->queryF(
3693 "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",
3694 array('integer','integer'),
3695 array($active_id, $pass)
3696 );
3697 } else {
3698 $result = $ilDB->queryF(
3699 "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",
3700 array('integer'),
3701 array($this->getTestId())
3702 );
3703 }
3704 while ($data = $ilDB->fetchObject($result)) {
3705 if ($data->original_id === null) {
3706 continue;
3707 }
3708
3709 array_push($existing_questions, $data->original_id);
3710 }
3711 return $existing_questions;
3712 }
3713
3721 public function getQuestionType($question_id)
3722 {
3723 global $ilDB;
3724
3725 if ($question_id < 1) {
3726 return -1;
3727 }
3728 $result = $ilDB->queryF(
3729 "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",
3730 array('integer'),
3731 array($question_id)
3732 );
3733 if ($result->numRows() == 1) {
3734 $data = $ilDB->fetchObject($result);
3735 return $data->type_tag;
3736 } else {
3737 return "";
3738 }
3739 }
3740
3747 public function startWorkingTime($active_id, $pass)
3748 {
3749 global $ilDB;
3750
3751 $next_id = $ilDB->nextId('tst_times');
3752 $affectedRows = $ilDB->manipulateF(
3753 "INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
3754 array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
3755 array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
3756 );
3757 return $next_id;
3758 }
3759
3766 public function updateWorkingTime($times_id)
3767 {
3768 global $ilDB;
3769
3770 $affectedRows = $ilDB->manipulateF(
3771 "UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
3772 array('timestamp', 'integer', 'integer'),
3773 array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
3774 );
3775 }
3776
3783 public function &getWorkedQuestions($active_id, $pass = null)
3784 {
3785 global $ilUser;
3786 global $ilDB;
3787
3788 if (is_null($pass)) {
3789 $result = $ilDB->queryF(
3790 "SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3791 array('integer','integer'),
3792 array($active_id, 0)
3793 );
3794 } else {
3795 $result = $ilDB->queryF(
3796 "SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3797 array('integer','integer'),
3798 array($active_id, $pass)
3799 );
3800 }
3801 $result_array = array();
3802 while ($row = $ilDB->fetchAssoc($result)) {
3803 array_push($result_array, $row["question_fi"]);
3804 }
3805 return $result_array;
3806 }
3807
3816 public function isTestFinishedToViewResults($active_id, $currentpass)
3817 {
3818 $num = ilObjTest::lookupPassResultsUpdateTimestamp($active_id, $currentpass);
3819 return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
3820 }
3821
3828 public function &getAllQuestions($pass = null)
3829 {
3830 global $ilUser;
3831 global $ilDB;
3832
3833 $result_array = array();
3834 if ($this->isRandomTest()) {
3835 $active_id = $this->getActiveIdOfUser($ilUser->getId());
3836 $this->loadQuestions($active_id, $pass);
3837 if (count($this->questions) == 0) {
3838 return $result_array;
3839 }
3840 if (is_null($pass)) {
3841 $pass = self::_getPass($active_id);
3842 }
3843 $result = $ilDB->queryF(
3844 "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'),
3845 array('integer','integer'),
3846 array($active_id, $pass)
3847 );
3848 } else {
3849 if (count($this->questions) == 0) {
3850 return $result_array;
3851 }
3852 $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'));
3853 }
3854 while ($row = $ilDB->fetchAssoc($result)) {
3855 $result_array[$row["question_id"]] = $row;
3856 }
3857 return $result_array;
3858 }
3859
3868 public function getActiveIdOfUser($user_id = "", $anonymous_id = "")
3869 {
3870 global $ilDB;
3871 global $ilUser;
3872
3873 if (!$user_id) {
3874 $user_id = $ilUser->getId();
3875 }
3876 if (($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()]))) {
3877 $result = $ilDB->queryF(
3878 "SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3879 array('integer','integer','text'),
3880 array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
3881 );
3882 } elseif (strlen($anonymous_id)) {
3883 $result = $ilDB->queryF(
3884 "SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3885 array('integer','integer','text'),
3886 array($user_id, $this->test_id, $anonymous_id)
3887 );
3888 } else {
3889 if ($GLOBALS['DIC']['ilUser']->getId() == ANONYMOUS_USER_ID) {
3890 return null;
3891 }
3892 $result = $ilDB->queryF(
3893 "SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
3894 array('integer','integer'),
3895 array($user_id, $this->test_id)
3896 );
3897 }
3898 if ($result->numRows()) {
3899 $row = $ilDB->fetchAssoc($result);
3900 return $row["active_id"];
3901 } else {
3902 return 0;
3903 }
3904 }
3905
3914 public static function _getActiveIdOfUser($user_id = "", $test_id = "")
3915 {
3916 global $ilDB;
3917 global $ilUser;
3918
3919 if (!$user_id) {
3920 $user_id = $ilUser->id;
3921 }
3922 if (!$test_id) {
3923 return "";
3924 }
3925 $result = $ilDB->queryF(
3926 "SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
3927 array('integer', 'integer'),
3928 array($user_id, $test_id)
3929 );
3930 if ($result->numRows()) {
3931 $row = $ilDB->fetchAssoc($result);
3932 return $row["active_id"];
3933 } else {
3934 return "";
3935 }
3936 }
3937
3944 public function pcArrayShuffle($array)
3945 {
3946 $keys = array_keys($array);
3947 shuffle($keys);
3948 $result = array();
3949 foreach ($keys as $key) {
3950 $result[$key] = $array[$key];
3951 }
3952 return $result;
3953 }
3954
3962 public function &getTestResult($active_id, $pass = null, $ordered_sequence = false, $considerHiddenQuestions = true, $considerOptionalQuestions = true)
3963 {
3964 global $tree, $ilDB, $lng, $ilPluginAdmin;
3965
3966 $results = $this->getResultsForActiveId($active_id);
3967
3968 if (is_null($pass)) {
3969 $pass = $results['pass'];
3970 }
3971
3972 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
3973 $testSessionFactory = new ilTestSessionFactory($this);
3974 $testSession = $testSessionFactory->getSession($active_id);
3975
3976 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
3977 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
3978 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass);
3979
3980 if ($this->isDynamicTest()) {
3981 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
3982 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
3983 $dynamicQuestionSetConfig->loadFromDb();
3984
3985 $testSequence->loadFromDb($dynamicQuestionSetConfig);
3986 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
3987
3988 $sequence = $testSequence->getUserSequenceQuestions();
3989 } else {
3990 $testSequence->setConsiderHiddenQuestionsEnabled($considerHiddenQuestions);
3991 $testSequence->setConsiderOptionalQuestionsEnabled($considerOptionalQuestions);
3992
3993 $testSequence->loadFromDb();
3994 $testSequence->loadQuestions();
3995
3996 if ($ordered_sequence) {
3997 $sequence = $testSequence->getOrderedSequenceQuestions();
3998 } else {
3999 $sequence = $testSequence->getUserSequenceQuestions();
4000 }
4001 }
4002
4003 $arrResults = array();
4004
4005 $query = "
4006 SELECT tst_test_result.question_fi,
4007 tst_test_result.points reached,
4008 tst_test_result.hint_count requested_hints,
4009 tst_test_result.hint_points hint_points,
4010 tst_test_result.answered answered
4011
4012 FROM tst_test_result
4013
4014 LEFT JOIN tst_solutions
4015 ON tst_solutions.active_fi = tst_test_result.active_fi
4016 AND tst_solutions.question_fi = tst_test_result.question_fi
4017
4018 WHERE tst_test_result.active_fi = %s
4019 AND tst_test_result.pass = %s
4020 ";
4021
4022 $solutionresult = $ilDB->queryF(
4023 $query,
4024 array('integer', 'integer'),
4025 array($active_id, $pass)
4026 );
4027
4028 while ($row = $ilDB->fetchAssoc($solutionresult)) {
4029 $arrResults[ $row['question_fi'] ] = $row;
4030 }
4031
4032 $numWorkedThrough = count($arrResults);
4033
4034 require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4035
4036 $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4037
4038 $query = "
4039 SELECT qpl_questions.*,
4040 qpl_qst_type.type_tag,
4041 qpl_sol_sug.question_fi has_sug_sol
4042
4043 FROM qpl_qst_type,
4044 qpl_questions
4045
4046 LEFT JOIN qpl_sol_sug
4047 ON qpl_sol_sug.question_fi = qpl_questions.question_id
4048
4049 WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4050 AND $IN_question_ids
4051 ";
4052
4053 $result = $ilDB->query($query);
4054
4055 $unordered = array();
4056
4057 $key = 1;
4058
4059 $obligationsAnswered = true;
4060
4061 while ($row = $ilDB->fetchAssoc($result)) {
4062 $percentvalue = (
4063 $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4064 );
4065
4066 if ($percentvalue < 0) {
4067 $percentvalue = 0.0;
4068 }
4069
4070 $data = array(
4071 "nr" => "$key",
4072 "title" => ilUtil::prepareFormOutput($row['title']),
4073 "max" => round($row['points'], 2),
4074 "reached" => round($arrResults[$row['question_id']]['reached'], 2),
4075 'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4076 'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4077 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4078 "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4079 "type" => $row["type_tag"],
4080 "qid" => $row['question_id'],
4081 "original_id" => $row["original_id"],
4082 "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4083 'answered' => $arrResults[$row['question_id']]['answered']
4084 );
4085
4086 if (!$arrResults[ $row['question_id'] ]['answered']) {
4087 $obligationsAnswered = false;
4088 }
4089
4090 $unordered[ $row['question_id'] ] = $data;
4091
4092 $key++;
4093 }
4094
4095 $numQuestionsTotal = count($unordered);
4096
4097 $pass_max = 0;
4098 $pass_reached = 0;
4099 $pass_requested_hints = 0;
4100 $pass_hint_points = 0;
4101 $key = 1;
4102
4103 $found = array();
4104
4105 foreach ($sequence as $qid) {
4106 // building pass point sums based on prepared data
4107 // for question that exists in users qst sequence
4108 $pass_max += round($unordered[$qid]['max'], 2);
4109 $pass_reached += round($unordered[$qid]['reached'], 2);
4110 $pass_requested_hints += $unordered[$qid]['requested_hints'];
4111 $pass_hint_points += $unordered[$qid]['hint_points'];
4112
4113 // pickup prepared data for question
4114 // that exists in users qst sequence
4115 $unordered[$qid]['nr'] = $key;
4116 array_push($found, $unordered[$qid]);
4117
4118 // increment key counter
4119 $key++;
4120 }
4121
4122 $unordered = null;
4123
4124 if ($this->getScoreCutting() == 1) {
4125 if ($results['reached_points'] < 0) {
4126 $results['reached_points'] = 0;
4127 }
4128
4129 if ($pass_reached < 0) {
4130 $pass_reached = 0;
4131 }
4132 }
4133
4134 $found['pass']['total_max_points'] = $pass_max;
4135 $found['pass']['total_reached_points'] = $pass_reached;
4136 $found['pass']['total_requested_hints'] = $pass_requested_hints;
4137 $found['pass']['total_hint_points'] = $pass_hint_points;
4138 $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4139 $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4140 $found['pass']['num_workedthrough'] = $numWorkedThrough;
4141 $found['pass']['num_questions_total'] = $numQuestionsTotal;
4142
4143 $found["test"]["total_max_points"] = $results['max_points'];
4144 $found["test"]["total_reached_points"] = $results['reached_points'];
4145 $found["test"]["total_requested_hints"] = $results['hint_count'];
4146 $found["test"]["total_hint_points"] = $results['hint_points'];
4147 $found["test"]["result_pass"] = $results['pass'];
4148 $found['test']['result_tstamp'] = $results['tstamp'];
4149 $found['test']['obligations_answered'] = $results['obligations_answered'];
4150
4151 if ((!$total_reached_points) or (!$total_max_points)) {
4152 $percentage = 0.0;
4153 } else {
4154 $percentage = ($total_reached_points / $total_max_points) * 100.0;
4155
4156 if ($percentage < 0) {
4157 $percentage = 0.0;
4158 }
4159 }
4160
4161 $found["test"]["passed"] = $results['passed'];
4162
4163 return $found;
4164 }
4165
4172 public function evalTotalPersons()
4173 {
4174 global $ilDB;
4175
4176 $result = $ilDB->queryF(
4177 "SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4178 array('integer'),
4179 array($this->getTestId())
4180 );
4181 $row = $ilDB->fetchAssoc($result);
4182 return $row["total"];
4183 }
4184
4191 public function getCompleteWorkingTime($user_id)
4192 {
4193 global $ilDB;
4194
4195 $result = $ilDB->queryF(
4196 "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",
4197 array('integer','integer'),
4198 array($this->getTestId(), $user_id)
4199 );
4200 $time = 0;
4201 while ($row = $ilDB->fetchAssoc($result)) {
4202 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4203 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4204 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4205 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4206 $time += ($epoch_2 - $epoch_1);
4207 }
4208 return $time;
4209 }
4210
4218 {
4219 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4220 }
4221
4230 {
4231 global $ilDB;
4232
4233 $result = $ilDB->queryF(
4234 "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",
4235 array('integer'),
4236 array($test_id)
4237 );
4238 $time = 0;
4239 $times = array();
4240 while ($row = $ilDB->fetchAssoc($result)) {
4241 if (!array_key_exists($row["active_fi"], $times)) {
4242 $times[$row["active_fi"]] = 0;
4243 }
4244 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4245 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4246 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4247 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4248 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4249 }
4250 return $times;
4251 }
4252
4259 public function getCompleteWorkingTimeOfParticipant($active_id)
4260 {
4261 global $ilDB;
4262
4263 $result = $ilDB->queryF(
4264 "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",
4265 array('integer','integer'),
4266 array($this->getTestId(), $active_id)
4267 );
4268 $time = 0;
4269 while ($row = $ilDB->fetchAssoc($result)) {
4270 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4271 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4272 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4273 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4274 $time += ($epoch_2 - $epoch_1);
4275 }
4276 return $time;
4277 }
4278
4285 public static function _getWorkingTimeOfParticipantForPass($active_id, $pass)
4286 {
4287 global $ilDB;
4288
4289 $result = $ilDB->queryF(
4290 "SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4291 array('integer','integer'),
4292 array($active_id, $pass)
4293 );
4294 $time = 0;
4295 while ($row = $ilDB->fetchAssoc($result)) {
4296 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4297 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4298 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4299 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4300 $time += ($epoch_2 - $epoch_1);
4301 }
4302 return $time;
4303 }
4304
4312 public function getVisitTimeOfParticipant($active_id)
4313 {
4314 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4315 }
4316
4325 public function _getVisitTimeOfParticipant($test_id, $active_id)
4326 {
4327 global $ilDB;
4328
4329 $result = $ilDB->queryF(
4330 "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",
4331 array('integer','integer'),
4332 array($test_id, $active_id)
4333 );
4334 $firstvisit = 0;
4335 $lastvisit = 0;
4336 while ($row = $ilDB->fetchAssoc($result)) {
4337 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4338 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4339 if ($firstvisit == 0 || $epoch_1 < $firstvisit) {
4340 $firstvisit = $epoch_1;
4341 }
4342 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4343 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4344 if ($epoch_2 > $lastvisit) {
4345 $lastvisit = $epoch_2;
4346 }
4347 }
4348 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4349 }
4350
4357 public function &evalStatistical($active_id)
4358 {
4359 global $ilDB;
4360 // global $ilBench;
4361 $pass = ilObjTest::_getResultPass($active_id);
4362 $test_result =&$this->getTestResult($active_id, $pass);
4363 $result = $ilDB->queryF(
4364 "SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
4365 array('integer'),
4366 array($active_id)
4367 );
4368 $times = array();
4369 $first_visit = 0;
4370 $last_visit = 0;
4371 while ($row = $ilDB->fetchObject($result)) {
4372 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4373 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4374 if (!$first_visit) {
4375 $first_visit = $epoch_1;
4376 }
4377 if ($epoch_1 < $first_visit) {
4378 $first_visit = $epoch_1;
4379 }
4380 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4381 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4382 if (!$last_visit) {
4383 $last_visit = $epoch_2;
4384 }
4385 if ($epoch_2 > $last_visit) {
4386 $last_visit = $epoch_2;
4387 }
4388 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4389 }
4390 $max_time = 0;
4391 foreach ($times as $key => $value) {
4392 $max_time += $value;
4393 }
4394 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"])) {
4395 $percentage = 0.0;
4396 } else {
4397 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4398 if ($percentage < 0) {
4399 $percentage = 0.0;
4400 }
4401 }
4402 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4403 $first_date = getdate($first_visit);
4404 $last_date = getdate($last_visit);
4405 $qworkedthrough = 0;
4406 foreach ($test_result as $key => $value) {
4407 if (preg_match("/\d+/", $key)) {
4408 $qworkedthrough += $value["workedthrough"];
4409 }
4410 }
4411 if (!$qworkedthrough) {
4412 $atimeofwork = 0;
4413 } else {
4414 $atimeofwork = $max_time / $qworkedthrough;
4415 }
4416
4417 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4418
4419 $result_mark = "";
4420 $passed = "";
4421
4422 if ($mark_obj) {
4423 $result_mark = $mark_obj->getShortName();
4424
4425 if ($mark_obj->getPassed() && $obligationsAnswered) {
4426 $passed = 1;
4427 } else {
4428 $passed = 0;
4429 }
4430 }
4431 $percent_worked_through = 0;
4432 if (count($this->questions)) {
4433 $percent_worked_through = $qworkedthrough / count($this->questions);
4434 }
4435 $result_array = array(
4436 "qworkedthrough" => $qworkedthrough,
4437 "qmax" => count($this->questions),
4438 "pworkedthrough" => $percent_worked_through,
4439 "timeofwork" => $max_time,
4440 "atimeofwork" => $atimeofwork,
4441 "firstvisit" => $first_date,
4442 "lastvisit" => $last_date,
4443 "resultspoints" => $test_result["test"]["total_reached_points"],
4444 "maxpoints" => $test_result["test"]["total_max_points"],
4445 "resultsmarks" => $result_mark,
4446 "passed" => $passed,
4447 "distancemedian" => "0"
4448 );
4449 foreach ($test_result as $key => $value) {
4450 if (preg_match("/\d+/", $key)) {
4451 $result_array[$key] = $value;
4452 }
4453 }
4454 return $result_array;
4455 }
4456
4464 public function &getTotalPointsPassedArray()
4465 {
4466 $totalpoints_array = array();
4467 $all_users =&$this->evalTotalParticipantsArray();
4468 foreach ($all_users as $active_id => $user_name) {
4469 $test_result =&$this->getTestResult($active_id);
4470 $reached = $test_result["test"]["total_reached_points"];
4471 $total = $test_result["test"]["total_max_points"];
4472 $percentage = $total != 0 ? $reached/$total : 0;
4473 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4474
4475 $obligationsAnswered = $test_result["test"]["obligations_answered"];
4476
4477 if ($mark) {
4478 if ($mark->getPassed() && $obligationsAnswered) {
4479 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4480 }
4481 }
4482 }
4483 return $totalpoints_array;
4484 }
4485
4491 public function &getParticipants()
4492 {
4493 global $ilDB;
4494 $result = $ilDB->queryF(
4495 "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",
4496 array('integer'),
4497 array($this->getTestId())
4498 );
4499 $persons_array = array();
4500 while ($row = $ilDB->fetchAssoc($result)) {
4501 $name = $this->lng->txt("anonymous");
4502 $fullname = $this->lng->txt("anonymous");
4503 $login = "";
4504 if (!$this->getAnonymity()) {
4505 if (strlen($row["firstname"] . $row["lastname"] . $row["title"]) == 0) {
4506 $name = $this->lng->txt("deleted_user");
4507 $fullname = $this->lng->txt("deleted_user");
4508 $login = $this->lng->txt("unknown");
4509 } else {
4510 $login = $row["login"];
4511 if ($row["user_fi"] == ANONYMOUS_USER_ID) {
4512 $name = $this->lng->txt("anonymous");
4513 $fullname = $this->lng->txt("anonymous");
4514 } else {
4515 $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4516 $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4517 }
4518 }
4519 }
4520 $persons_array[$row["active_id"]] = array(
4521 "name" => $name,
4522 "fullname" => $fullname,
4523 "login" => $login
4524 );
4525 }
4526 return $persons_array;
4527 }
4528
4535 public function &evalTotalPersonsArray($name_sort_order = "asc")
4536 {
4537 global $ilDB;
4538 $result = $ilDB->queryF(
4539 "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),
4540 array('integer'),
4541 array($this->getTestId())
4542 );
4543 $persons_array = array();
4544 while ($row = $ilDB->fetchAssoc($result)) {
4545 if ($this->getAnonymity()) {
4546 $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
4547 } else {
4548 if (strlen($row["firstname"] . $row["lastname"] . $row["title"]) == 0) {
4549 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4550 } else {
4551 if ($row["user_fi"] == ANONYMOUS_USER_ID) {
4552 $persons_array[$row["active_id"]] = $row["lastname"];
4553 } else {
4554 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4555 }
4556 }
4557 }
4558 }
4559 return $persons_array;
4560 }
4561
4568 public function &evalTotalParticipantsArray($name_sort_order = "asc")
4569 {
4570 global $ilDB;
4571 $result = $ilDB->queryF(
4572 "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),
4573 array('integer'),
4574 array($this->getTestId())
4575 );
4576 $persons_array = array();
4577 while ($row = $ilDB->fetchAssoc($result)) {
4578 if ($this->getAnonymity()) {
4579 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
4580 } else {
4581 if (strlen($row["firstname"] . $row["lastname"] . $row["title"]) == 0) {
4582 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4583 } else {
4584 if ($row["user_fi"] == ANONYMOUS_USER_ID) {
4585 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4586 } else {
4587 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4588 }
4589 }
4590 }
4591 }
4592 return $persons_array;
4593 }
4594
4601 public function evalTotalFinished()
4602 {
4603 global $ilDB;
4604
4605 $result = $ilDB->queryF(
4606 "SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4607 array('integer', 'integer'),
4608 array($this->getTestId(), 1)
4609 );
4610 $row = $ilDB->fetchAssoc($result);
4611 return $row["total"];
4612 }
4613
4620 public function &getQuestionsOfTest($active_id)
4621 {
4622 global $ilDB;
4623 if ($this->isRandomTest()) {
4624 $ilDB->setLimit($this->getQuestionCount(), 0);
4625 $result = $ilDB->queryF(
4626 "SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4627 "tst_test_rnd_qst.pass, qpl_questions.points " .
4628 "FROM tst_test_rnd_qst, qpl_questions " .
4629 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4630 "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4631 array('integer'),
4632 array($active_id)
4633 );
4634 } else {
4635 $result = $ilDB->queryF(
4636 "SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4637 "qpl_questions.points " .
4638 "FROM tst_test_question, tst_active, qpl_questions " .
4639 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4640 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4641 array('integer'),
4642 array($active_id)
4643 );
4644 }
4645 $qtest = array();
4646 if ($result->numRows()) {
4647 while ($row = $ilDB->fetchAssoc($result)) {
4648 array_push($qtest, $row);
4649 }
4650 }
4651 return $qtest;
4652 }
4653
4660 public function &getQuestionsOfPass($active_id, $pass)
4661 {
4662 global $ilDB;
4663 if ($this->isRandomTest()) {
4664 $ilDB->setLimit($this->getQuestionCount(), 0);
4665 $result = $ilDB->queryF(
4666 "SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4667 "qpl_questions.points " .
4668 "FROM tst_test_rnd_qst, qpl_questions " .
4669 "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4670 "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4671 "ORDER BY tst_test_rnd_qst.sequence",
4672 array('integer', 'integer'),
4673 array($active_id, $pass)
4674 );
4675 } else {
4676 $result = $ilDB->queryF(
4677 "SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4678 "qpl_questions.points " .
4679 "FROM tst_test_question, tst_active, qpl_questions " .
4680 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4681 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4682 array('integer'),
4683 array($active_id)
4684 );
4685 }
4686 $qpass = array();
4687 if ($result->numRows()) {
4688 while ($row = $ilDB->fetchAssoc($result)) {
4689 array_push($qpass, $row);
4690 }
4691 }
4692 return $qpass;
4693 }
4694
4695 public function getUnfilteredEvaluationData()
4696 {
4698 global $DIC;
4699
4700 $ilDB = $DIC->database();
4701
4702 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
4703 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
4704 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
4705
4706 $data = new ilTestEvaluationData($this);
4707
4708 $query = "
4709 SELECT tst_test_result.*,
4710 qpl_questions.original_id,
4711 qpl_questions.title questiontitle,
4712 qpl_questions.points maxpoints
4713
4714 FROM tst_test_result, qpl_questions, tst_active
4715
4716 WHERE tst_active.active_id = tst_test_result.active_fi
4717 AND qpl_questions.question_id = tst_test_result.question_fi
4718 AND tst_active.test_fi = %s
4719
4720 ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
4721 ";
4722
4723 $result = $ilDB->queryF(
4724 $query,
4725 array('integer'),
4726 array($this->getTestId())
4727 );
4728
4729 $pass = null;
4730 $checked = array();
4731 $datasets = 0;
4732 $questionData = [];
4733
4734 while ($row = $ilDB->fetchAssoc($result)) {
4735 $participantObject = $data->getParticipant($row["active_fi"]);
4736
4737 if (!($participantObject instanceof ilTestEvaluationUserData)) {
4738 continue;
4739 }
4740
4741 $passObject = $participantObject->getPass($row["pass"]);
4742
4743 if (!($passObject instanceof ilTestEvaluationPassData)) {
4744 continue;
4745 }
4746
4747 $passObject->addAnsweredQuestion(
4748 $row["question_fi"],
4749 $row["maxpoints"],
4750 $row["points"],
4751 $row['answered'],
4752 null,
4753 $row['manual']
4754 );
4755 }
4756
4757 foreach (array_keys($data->getParticipants()) as $active_id) {
4758 if ($this->isRandomTest()) {
4759 for ($testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++) {
4760 $ilDB->setLimit($this->getQuestionCount(), 0);
4761
4762 $query = "
4763 SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id,
4764 tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title
4765 FROM tst_test_rnd_qst, qpl_questions
4766 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
4767 AND tst_test_rnd_qst.pass = %s
4768 AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence
4769 ";
4770
4771 $result = $ilDB->queryF(
4772 $query,
4773 array('integer','integer'),
4774 array($testpass, $active_id)
4775 );
4776
4777 if ($result->numRows()) {
4778 while ($row = $ilDB->fetchAssoc($result)) {
4779 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
4780
4781 $data->getParticipant($active_id)->addQuestion(
4782 $row["original_id"],
4783 $row["question_fi"],
4784 $row["points"],
4785 $row["sequence"],
4786 $tpass
4787 );
4788
4789 $data->addQuestionTitle($row["question_fi"], $row["title"]);
4790 }
4791 }
4792 }
4793 } elseif ($this->isDynamicTest()) {
4794 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4795 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4796 require_once 'Modules/Test/classes/class.ilTestDynamicQuestionSetFilterSelection.php';
4797
4798 $lastPass = $data->getParticipant($active_id)->getLastPass();
4799 for ($testpass = 0; $testpass <= $lastPass; $testpass++) {
4800 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4801 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig(
4802 $DIC->repositoryTree(),
4803 $DIC->database(),
4804 $DIC['ilPluginAdmin'],
4805 $this
4806 );
4807 $dynamicQuestionSetConfig->loadFromDb();
4808
4809 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4810 $testSequenceFactory = new ilTestSequenceFactory($DIC->database(), $DIC->language(), $DIC['ilPluginAdmin'], $this);
4811 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $testpass);
4812
4813 $testSequence->loadFromDb($dynamicQuestionSetConfig);
4814 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4815
4816 $sequence = (array) $testSequence->getUserSequenceQuestions();
4817
4818 $questionsIdsToRequest = array_diff(array_values($sequence), array_values($questionData));
4819 if (count($questionsIdsToRequest) > 0) {
4820 $questionIdsCondition = ' ' . $DIC->database()->in('question_id', array_values($questionsIdsToRequest), false, 'integer') . ' ';
4821
4822 $res = $DIC->database()->queryF(
4823 "
4824 SELECT *
4825 FROM qpl_questions
4826 WHERE {$questionIdsCondition}",
4827 array('integer'),
4828 array($active_id)
4829 );
4830 while ($row = $DIC->database()->fetchAssoc($res)) {
4831 $questionData[$row['question_id']] = $row;
4832 $data->addQuestionTitle($row['question_id'], $row['title']);
4833 }
4834 }
4835
4836 foreach ($sequence as $questionId) {
4837 if (!isset($questionData[$questionId])) {
4838 continue;
4839 }
4840
4841 $row = $questionData[$questionId];
4842
4843 $data->getParticipant(
4844 $active_id
4845 )->addQuestion(
4846 $row['original_id'],
4847 $row['question_id'],
4848 $row['points'],
4849 null,
4850 $testpass
4851 );
4852 }
4853 }
4854 } else {
4855 $query = "
4856 SELECT tst_test_question.sequence, tst_test_question.question_fi,
4857 qpl_questions.points, qpl_questions.title, qpl_questions.original_id
4858 FROM tst_test_question, tst_active, qpl_questions
4859 WHERE tst_test_question.question_fi = qpl_questions.question_id
4860 AND tst_active.active_id = %s
4861 AND tst_active.test_fi = tst_test_question.test_fi
4862 ORDER BY tst_test_question.sequence
4863 ";
4864
4865 $result = $ilDB->queryF(
4866 $query,
4867 array('integer'),
4868 array($active_id)
4869 );
4870
4871 if ($result->numRows()) {
4872 $questionsbysequence = array();
4873
4874 while ($row = $ilDB->fetchAssoc($result)) {
4875 $questionsbysequence[$row["sequence"]] = $row;
4876 }
4877
4878 $seqresult = $ilDB->queryF(
4879 "SELECT * FROM tst_sequence WHERE active_fi = %s",
4880 array('integer'),
4881 array($active_id)
4882 );
4883
4884 while ($seqrow = $ilDB->fetchAssoc($seqresult)) {
4885 $questionsequence = unserialize($seqrow["sequence"]);
4886
4887 foreach ($questionsequence as $sidx => $seq) {
4888 $data->getParticipant($active_id)->addQuestion(
4889 $questionsbysequence[$seq]["original_id"],
4890 $questionsbysequence[$seq]["question_fi"],
4891 $questionsbysequence[$seq]["points"],
4892 $sidx + 1,
4893 $seqrow["pass"]
4894 );
4895
4896 $data->addQuestionTitle(
4897 $questionsbysequence[$seq]["question_fi"],
4898 $questionsbysequence[$seq]["title"]
4899 );
4900 }
4901 }
4902 }
4903 }
4904 }
4905
4906 if ($this->getECTSOutput()) {
4907 $passed_array =&$this->getTotalPointsPassedArray();
4908 }
4909
4910 foreach (array_keys($data->getParticipants()) as $active_id) {
4911 $tstUserData = $data->getParticipant($active_id);
4912
4913 $percentage = $tstUserData->getReachedPointsInPercent();
4914
4915 $obligationsAnswered = $tstUserData->areObligationsAnswered();
4916
4917 $mark = $this->mark_schema->getMatchingMark($percentage);
4918
4919 if (is_object($mark)) {
4920 $tstUserData->setMark($mark->getShortName());
4921 $tstUserData->setMarkOfficial($mark->getOfficialName());
4922
4923 $tstUserData->setPassed(
4924 $mark->getPassed() && $tstUserData->areObligationsAnswered()
4925 );
4926 }
4927
4928 if ($this->getECTSOutput()) {
4929 $ects_mark = $this->getECTSGrade(
4930 $passed_array,
4931 $tstUserData->getReached(),
4932 $tstUserData->getMaxPoints()
4933 );
4934
4935 $tstUserData->setECTSMark($ects_mark);
4936 }
4937
4938 $visitingTime =&$this->getVisitTimeOfParticipant($active_id);
4939
4940 $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
4941 $tstUserData->setLastVisit($visitingTime["lastvisit"]);
4942 }
4943
4944 return $data;
4945 }
4946
4947 public static function _getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
4948 {
4949 global $ilDB;
4950
4952
4953 switch ($questionSetType) {
4955
4956 $res = $ilDB->queryF(
4957 "
4958 SELECT COUNT(qpl_questions.question_id) qcount,
4959 SUM(qpl_questions.points) qsum
4960 FROM tst_active
4961 INNER JOIN tst_tests
4962 ON tst_tests.test_id = tst_active.test_fi
4963 INNER JOIN tst_dyn_quest_set_cfg
4964 ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
4965 INNER JOIN qpl_questions
4966 ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
4967 AND qpl_questions.original_id IS NULL
4968 AND qpl_questions.complete = %s
4969 WHERE tst_active.active_id = %s
4970 ",
4971 array('integer', 'integer'),
4972 array(1, $active_id)
4973 );
4974
4975 break;
4976
4978
4979 $res = $ilDB->queryF(
4980 "
4981 SELECT tst_test_rnd_qst.pass,
4982 COUNT(tst_test_rnd_qst.question_fi) qcount,
4983 SUM(qpl_questions.points) qsum
4984
4985 FROM tst_test_rnd_qst,
4986 qpl_questions
4987
4988 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
4989 AND tst_test_rnd_qst.active_fi = %s
4990 AND pass = %s
4991
4992 GROUP BY tst_test_rnd_qst.active_fi,
4993 tst_test_rnd_qst.pass
4994 ",
4995 array('integer', 'integer'),
4996 array($active_id, $pass)
4997 );
4998
4999 break;
5000
5002
5003 $res = $ilDB->queryF(
5004 "
5005 SELECT COUNT(tst_test_question.question_fi) qcount,
5006 SUM(qpl_questions.points) qsum
5007
5008 FROM tst_test_question,
5009 qpl_questions,
5010 tst_active
5011
5012 WHERE tst_test_question.question_fi = qpl_questions.question_id
5013 AND tst_test_question.test_fi = tst_active.test_fi
5014 AND tst_active.active_id = %s
5015
5016 GROUP BY tst_test_question.test_fi
5017 ",
5018 array('integer'),
5019 array($active_id)
5020 );
5021
5022 break;
5023
5024 default:
5025
5026 throw new ilTestException("not supported question set type: $questionSetType");
5027 }
5028
5029 $row = $ilDB->fetchAssoc($res);
5030
5031 if (is_array($row)) {
5032 return array("count" => $row["qcount"], "points" => $row["qsum"]);
5033 }
5034
5035 return array("count" => 0, "points" => 0);
5036 }
5037
5038 public function &getCompleteEvaluationData($withStatistics = true, $filterby = "", $filtertext = "")
5039 {
5040 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5041 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5042 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5043 $data = $this->getUnfilteredEvaluationData();
5044 if ($withStatistics) {
5045 $data->calculateStatistics();
5046 }
5047 $data->setFilter($filterby, $filtertext);
5048 return $data;
5049 }
5050
5057 public function &evalResultsOverview()
5058 {
5059 return $this->_evalResultsOverview($this->getTestId());
5060 }
5061
5069 {
5070 global $ilDB;
5071
5072 $result = $ilDB->queryF(
5073 "SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5074 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5075 "qpl_questions.points maxpoints " .
5076 "FROM tst_test_result, qpl_questions, tst_active " .
5077 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5078 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5079 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5080 "AND tst_active.test_fi = %s " .
5081 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5082 array('integer'),
5083 array($test_id)
5084 );
5085 $overview = array();
5086 while ($row = $ilDB->fetchAssoc($result)) {
5087 if (!array_key_exists($row["active_fi"], $overview)) {
5088 $overview[$row["active_fi"]] = array();
5089 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5090 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5091 $overview[$row["active_fi"]]["title"] = $row["title"];
5092 $overview[$row["active_fi"]]["login"] = $row["login"];
5093 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5094 $overview[$row["active_fi"]]["started"] = $row["started"];
5095 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5096 }
5097 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]])) {
5098 $overview[$row["active_fi"]][$row["pass"]] = array();
5099 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5100 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5101 }
5102 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5103 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5104 }
5105 return $overview;
5106 }
5107
5115 public function &evalResultsOverviewOfParticipant($active_id)
5116 {
5117 global $ilDB;
5118
5119 $result = $ilDB->queryF(
5120 "SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5121 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5122 "qpl_questions.points maxpoints " .
5123 "FROM tst_test_result, qpl_questions, tst_active " .
5124 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5125 "WHERE tst_active.active_id = tst_test_result.active_fi " .
5126 "AND qpl_questions.question_id = tst_test_result.question_fi " .
5127 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5128 "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5129 array('integer', 'integer'),
5130 array($this->getTestId(), $active_id)
5131 );
5132 $overview = array();
5133 while ($row = $ilDB->fetchAssoc($result)) {
5134 if (!array_key_exists($row["active_fi"], $overview)) {
5135 $overview[$row["active_fi"]] = array();
5136 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5137 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5138 $overview[$row["active_fi"]]["title"] = $row["title"];
5139 $overview[$row["active_fi"]]["login"] = $row["login"];
5140 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5141 $overview[$row["active_fi"]]["started"] = $row["started"];
5142 $overview[$row["active_fi"]]["finished"] = $row["finished"];
5143 }
5144 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]])) {
5145 $overview[$row["active_fi"]][$row["pass"]] = array();
5146 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5147 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5148 }
5149 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5150 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5151 }
5152 return $overview;
5153 }
5154
5166 public function buildName($user_id, $firstname, $lastname, $title)
5167 {
5168 $name = "";
5169 if (strlen($firstname . $lastname . $title) == 0) {
5170 $name = $this->lng->txt("deleted_user");
5171 } else {
5172 if ($user_id == ANONYMOUS_USER_ID) {
5173 $name = $lastname;
5174 } else {
5175 $name = trim($lastname . ", " . $firstname . " " . $title);
5176 }
5177 if ($this->getAnonymity()) {
5178 $name = $this->lng->txt("anonymous");
5179 }
5180 }
5181 return $name;
5182 }
5183
5196 public function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5197 {
5198 global $lng;
5199 $name = "";
5200 if (strlen($firstname . $lastname . $title) == 0) {
5201 $name = $lng->txt("deleted_user");
5202 } else {
5203 if ($user_id == ANONYMOUS_USER_ID) {
5204 $name = $lastname;
5205 } else {
5206 $name = trim($lastname . ", " . $firstname . " " . $title);
5207 }
5208 if ($is_anonymous) {
5209 $name = $lng->txt("anonymous");
5210 }
5211 }
5212 return $name;
5213 }
5214
5222 {
5223 global $ilDB;
5224
5225 $result = $ilDB->queryF(
5226 "SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
5227 array('integer'),
5228 array($this->getTestId())
5229 );
5230 $times = array();
5231 while ($row = $ilDB->fetchObject($result)) {
5232 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5233 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5234 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5235 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5236 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5237 }
5238 $max_time = 0;
5239 $counter = 0;
5240 foreach ($times as $key => $value) {
5241 $max_time += $value;
5242 $counter++;
5243 }
5244 if ($counter) {
5245 $average_time = round($max_time / $counter);
5246 } else {
5247 $average_time = 0;
5248 }
5249 return $average_time;
5250 }
5251
5258 public function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = false, $with_questioncount = false, $permission = "read")
5259 {
5260 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5261 return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5262 }
5263
5270 public function getEstimatedWorkingTime()
5271 {
5272 $time_in_seconds = 0;
5273 foreach ($this->questions as $question_id) {
5274 $question =&ilObjTest::_instanciateQuestion($question_id);
5275 $est_time = $question->getEstimatedWorkingTime();
5276 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5277 }
5278 $hours = (int) ($time_in_seconds / 3600) ;
5279 $time_in_seconds = $time_in_seconds - ($hours * 3600);
5280 $minutes = (int) ($time_in_seconds / 60);
5281 $time_in_seconds = $time_in_seconds - ($minutes * 60);
5282 $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5283 return $result;
5284 }
5285
5292 public function getImagePath()
5293 {
5294 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5295 }
5296
5303 public function getImagePathWeb()
5304 {
5305 include_once "./Services/Utilities/classes/class.ilUtil.php";
5306 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5307 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
5308 }
5309
5318 public function &createQuestionGUI($question_type, $question_id = -1)
5319 {
5320 if ((!$question_type) and ($question_id > 0)) {
5321 $question_type = $this->getQuestionType($question_id);
5322 }
5323
5324 if (!strlen($question_type)) {
5325 return null;
5326 }
5327
5328 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5329 assQuestion::_includeClass($question_type, 1);
5330
5331 $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5332 $question = new $question_type_gui();
5333
5334 if ($question_id > 0) {
5335 $question->object->loadFromDb($question_id);
5336
5337 global $ilCtrl, $ilDB, $ilUser, $lng;
5338
5339 $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5340 $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5341
5342 $assSettings = new ilSetting('assessment');
5343 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5344 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5345 $processLockerFactory->setQuestionId($question->object->getId());
5346 $processLockerFactory->setUserId($ilUser->getId());
5347 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5348 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5349 $question->object->setProcessLocker($processLockerFactory->getLocker());
5350 }
5351
5352 return $question;
5353 }
5354
5364 public static function _instanciateQuestion($question_id)
5365 {
5366 if (strcmp($question_id, "") != 0) {
5367 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5368 return assQuestion::_instanciateQuestion($question_id);
5369 }
5370 }
5371
5380 public function moveQuestions($move_questions, $target_index, $insert_mode)
5381 {
5382 $this->questions = array_values($this->questions);
5383 $array_pos = array_search($target_index, $this->questions);
5384 if ($insert_mode == 0) {
5385 $part1 = array_slice($this->questions, 0, $array_pos);
5386 $part2 = array_slice($this->questions, $array_pos);
5387 } elseif ($insert_mode == 1) {
5388 $part1 = array_slice($this->questions, 0, $array_pos + 1);
5389 $part2 = array_slice($this->questions, $array_pos + 1);
5390 }
5391 foreach ($move_questions as $question_id) {
5392 if (!(array_search($question_id, $part1) === false)) {
5393 unset($part1[array_search($question_id, $part1)]);
5394 }
5395 if (!(array_search($question_id, $part2) === false)) {
5396 unset($part2[array_search($question_id, $part2)]);
5397 }
5398 }
5399 $part1 = array_values($part1);
5400 $part2 = array_values($part2);
5401 $new_array = array_values(array_merge($part1, $move_questions, $part2));
5402 $this->questions = array();
5403 $counter = 1;
5404 foreach ($new_array as $question_id) {
5405 $this->questions[$counter] = $question_id;
5406 $counter++;
5407 }
5408 $this->saveQuestionsToDb();
5409 }
5410
5411
5419 public function startingTimeReached()
5420 {
5421 if ($this->isStartingTimeEnabled() && $this->getStartingTime() != 0) {
5422 $now = time();
5423 if ($now < $this->getStartingTime()) {
5424 return false;
5425 }
5426 }
5427 return true;
5428 }
5429
5437 public function endingTimeReached()
5438 {
5439 if ($this->isEndingTimeEnabled() && $this->getEndingTime() != 0) {
5440 $now = time();
5441 if ($now > $this->getEndingTime()) {
5442 return true;
5443 }
5444 }
5445 return false;
5446 }
5447
5453 public function getAvailableQuestions($arrFilter, $completeonly = 0)
5454 {
5455 $pluginAdmin = $GLOBALS['DIC'] ? $GLOBALS['DIC']['ilPluginAdmin'] : $GLOBALS['ilPluginAdmin'];
5456 $lng = $GLOBALS['DIC'] ? $GLOBALS['DIC']['lng'] : $GLOBALS['lng'];
5457 global $ilUser;
5458 global $ilDB;
5459
5460 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5461 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = true, $equal_points = false, $could_be_offline = false, $showPath = false, $with_questioncount = false));
5462 $available = "";
5463 if (count($available_pools)) {
5464 $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5465 } else {
5466 return array();
5467 }
5468 if ($completeonly) {
5469 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5470 }
5471
5472 $where = "";
5473 if (is_array($arrFilter)) {
5474 if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
5475 $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5476 }
5477 if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description'])) {
5478 $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5479 }
5480 if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author'])) {
5481 $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5482 }
5483 if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type'])) {
5484 $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5485 }
5486 if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl'])) {
5487 $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5488 }
5489 }
5490
5491 $original_ids =&$this->getExistingQuestions();
5492 $original_clause = " qpl_questions.original_id IS NULL";
5493 if (count($original_ids)) {
5494 $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5495 }
5496
5497 $query_result = $ilDB->query("
5498 SELECT qpl_questions.*, qpl_questions.tstamp,
5499 qpl_qst_type.type_tag, qpl_qst_type.plugin, qpl_qst_type.plugin_name,
5500 object_data.title parent_title
5501 FROM qpl_questions, qpl_qst_type, object_data
5502 WHERE $original_clause $available
5503 AND object_data.obj_id = qpl_questions.obj_fi
5504 AND qpl_questions.tstamp > 0
5505 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
5506 $where
5507 ");
5508 $rows = array();
5509 $types = $this->getQuestionTypeTranslations();
5510 if ($query_result->numRows()) {
5511 while ($row = $ilDB->fetchAssoc($query_result)) {
5513
5514 if (!$row['plugin']) {
5515 $row[ 'ttype' ] = $lng->txt($row[ "type_tag" ]);
5516
5517 $rows[] = $row;
5518 continue;
5519 }
5520
5521 if (!$pluginAdmin->isActive(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $row['plugin_name'])) {
5522 continue;
5523 }
5524
5525 $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $row['plugin_name']);
5526 $row[ 'ttype' ] = $pl->getQuestionTypeTranslation();
5527
5528 $rows[] = $row;
5529 }
5530 }
5531 return $rows;
5532 }
5533
5538 public function fromXML(ilQTIAssessment $assessment)
5539 {
5540 unset($_SESSION["import_mob_xhtml"]);
5541
5542 $this->setDescription($assessment->getComment());
5543 $this->setTitle($assessment->getTitle());
5544
5545 $this->setIntroductionEnabled(false);
5546 foreach ($assessment->objectives as $objectives) {
5547 foreach ($objectives->materials as $material) {
5548 $intro = $this->QTIMaterialToString($material);
5549 $this->setIntroduction($intro);
5550 $this->setIntroductionEnabled(strlen($intro) > 0);
5551 }
5552 }
5553
5554 if (
5555 $assessment->getPresentationMaterial() &&
5556 $assessment->getPresentationMaterial()->getFlowMat(0) &&
5557 $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5558 ) {
5559 $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5560 }
5561
5562 foreach ($assessment->assessmentcontrol as $assessmentcontrol) {
5563 switch ($assessmentcontrol->getSolutionswitch()) {
5564 case "Yes":
5566 break;
5567 default:
5569 break;
5570 }
5571 }
5572
5573 $this->setStartingTimeEnabled(false);
5574 $this->setEndingTimeEnabled(false);
5575 $this->setPasswordEnabled(false);
5576 $this->setLimitUsersEnabled(false);
5577
5578 foreach ($assessment->qtimetadata as $metadata) {
5579 switch ($metadata["label"]) {
5580 case "test_type":
5581 // for old tests with a test type
5582 $type = $metadata["entry"];
5583 switch ($type) {
5584 case 1:
5585 // assessment
5586 $this->setAnonymity(1);
5587 break;
5588 case 2:
5589 // self assessment
5590 break;
5591 case 4:
5592 // online exam
5593 $this->setFixedParticipants(1);
5595 $this->setShowSolutionPrintview(1);
5596 break;
5597 case 5:
5598 // varying random test
5599 break;
5600 }
5601 break;
5602 case "sequence_settings":
5603 $this->setSequenceSettings($metadata["entry"]);
5604 break;
5605 case "solution_details":
5606 $this->setShowSolutionDetails((int) $metadata["entry"]);
5607 break;
5608 case "print_bs_with_res":
5609 $this->setPrintBestSolutionWithResult((int) $metadata["entry"]);
5610 break;
5611 case "author":
5612 $this->setAuthor($metadata["entry"]);
5613 break;
5614 case "nr_of_tries":
5615 $this->setNrOfTries($metadata["entry"]);
5616 break;
5617 case "pass_waiting":
5618 $this->setPassWaiting($metadata["entry"]);
5619 break;
5620 case "kiosk":
5621 $this->setKiosk($metadata["entry"]);
5622 break;
5623 case "showfinalstatement":
5624 $this->setShowFinalStatement($metadata["entry"]);
5625 break;
5626 case "showinfo":
5627 $this->setShowInfo($metadata["entry"]);
5628 break;
5629 case "forcejs":
5630 $this->setForceJS($metadata["entry"]);
5631 break;
5632 case "customstyle":
5633 $this->setCustomStyle($metadata["entry"]);
5634 break;
5635
5636 case "highscore_enabled":
5637 $this->setHighscoreEnabled($metadata["entry"]);
5638 break;
5639
5640 case "highscore_anon":
5641 $this->setHighscoreAnon($metadata["entry"]);
5642 break;
5643
5644 case "highscore_achieved_ts":
5645 $this->setHighscoreAchievedTS($metadata["entry"]);
5646 break;
5647
5648 case "highscore_score":
5649 $this->setHighscoreScore($metadata["entry"]);
5650 break;
5651
5652 case "highscore_percentage":
5653 $this->setHighscorePercentage($metadata["entry"]);
5654 break;
5655
5656 case "highscore_hints":
5657 $this->setHighscoreHints($metadata["entry"]);
5658 break;
5659
5660 case "highscore_wtime":
5661 $this->setHighscoreWTime($metadata["entry"]);
5662 break;
5663
5664 case "highscore_own_table":
5665 $this->setHighscoreOwnTable($metadata["entry"]);
5666 break;
5667
5668 case "highscore_top_table":
5669 $this->setHighscoreTopTable($metadata["entry"]);
5670 break;
5671
5672 case "highscore_top_num":
5673 $this->setHighscoreTopNum($metadata["entry"]);
5674 break;
5675
5676 case "hide_previous_results":
5677 if ($metadata["entry"] == 0) {
5678 $this->setUsePreviousAnswers(1);
5679 } else {
5680 $this->setUsePreviousAnswers(0);
5681 }
5682 break;
5683 case "use_previous_answers":
5684 $this->setUsePreviousAnswers($metadata["entry"]);
5685 break;
5686 case "answer_feedback":
5687 $this->setAnswerFeedback($metadata["entry"]);
5688 break;
5689 case "hide_title_points":
5690 $this->setTitleOutput($metadata["entry"]);
5691 break;
5692 case "title_output":
5693 $this->setTitleOutput($metadata["entry"]);
5694 break;
5695 case "question_set_type":
5696 $this->setQuestionSetType($metadata["entry"]);
5697 break;
5698 case "random_test":
5699 if ($metadata["entry"]) {
5700 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
5701 } else {
5702 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
5703 }
5704 break;
5705 case "results_presentation":
5706 $this->setResultsPresentation($metadata["entry"]);
5707 break;
5708 case "reset_processing_time":
5709 $this->setResetProcessingTime($metadata["entry"]);
5710 break;
5711 case "instant_verification":
5712 $this->setInstantFeedbackSolution($metadata["entry"]);
5713 break;
5714 case "instant_feedback_answer_fixation":
5715 $this->setInstantFeedbackAnswerFixationEnabled((bool) $metadata["entry"]);
5716 break;
5717 case "force_instant_feedback":
5718 $this->setForceInstantFeedbackEnabled((bool) $metadata["entry"]);
5719 break;
5720 case "answer_feedback_points":
5721 $this->setAnswerFeedbackPoints($metadata["entry"]);
5722 break;
5723 case "anonymity":
5724 $this->setAnonymity($metadata["entry"]);
5725 break;
5726 case "use_pool":
5727 $this->setPoolUsage((int) $metadata["entry"]);
5728 break;
5729 case "show_cancel":
5730 $this->setShowCancel($metadata["entry"]);
5731 break;
5732 case "show_marker":
5733 $this->setShowMarker($metadata["entry"]);
5734 break;
5735 case "fixed_participants":
5736 $this->setFixedParticipants($metadata["entry"]);
5737 break;
5738 case "score_reporting":
5739 $this->setScoreReporting($metadata["entry"]);
5740 break;
5741 case "shuffle_questions":
5742 $this->setShuffleQuestions($metadata["entry"]);
5743 break;
5744 case "count_system":
5745 $this->setCountSystem($metadata["entry"]);
5746 break;
5747 case "mc_scoring":
5748 $this->setMCScoring($metadata["entry"]);
5749 break;
5750 case "mailnotification":
5751 $this->setMailNotification($metadata["entry"]);
5752 break;
5753 case "mailnottype":
5754 $this->setMailNotificationType($metadata["entry"]);
5755 break;
5756 case "exportsettings":
5757 $this->setExportSettings($metadata['entry']);
5758 break;
5759 case "score_cutting":
5760 $this->setScoreCutting($metadata["entry"]);
5761 break;
5762 case "password":
5763 $this->setPassword($metadata["entry"]);
5764 $this->setPasswordEnabled(strlen($metadata["entry"]) > 0);
5765 break;
5766 case "allowedUsers":
5767 $this->setAllowedUsers($metadata["entry"]);
5768 $this->setLimitUsersEnabled((int) $metadata["entry"] > 0);
5769 break;
5770 case "allowedUsersTimeGap":
5771 $this->setAllowedUsersTimeGap($metadata["entry"]);
5772 break;
5773 case "pass_scoring":
5774 $this->setPassScoring($metadata["entry"]);
5775 break;
5776 case 'pass_deletion_allowed':
5777 $this->setPassDeletionAllowed((int) $metadata['entry']);
5778 break;
5779 case "show_summary":
5780 $this->setListOfQuestionsSettings($metadata["entry"]);
5781 break;
5782 case "reporting_date":
5783 $iso8601period = $metadata["entry"];
5784 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches)) {
5785 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
5786 }
5787 break;
5788 case 'enable_processing_time':
5789 $this->setEnableProcessingTime($metadata['entry']);
5790 break;
5791 case "processing_time":
5792 $this->setProcessingTime($metadata['entry']);
5793 break;
5794 case "starting_time":
5795 $iso8601period = $metadata["entry"];
5796 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches)) {
5797 $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);
5798 $this->setStartingTime($date_time->get(IL_CAL_UNIX));
5799 $this->setStartingTimeEnabled(true);
5800 }
5801 break;
5802 case "ending_time":
5803 $iso8601period = $metadata["entry"];
5804 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches)) {
5805 $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);
5806 $this->setEndingTime($date_time->get(IL_CAL_UNIX));
5807 $this->setEndingTimeEnabled(true);
5808 }
5809 break;
5810 case "enable_examview":
5811 $this->setEnableExamview($metadata["entry"]);
5812 break;
5813 case 'show_examview_html':
5814 $this->setShowExamviewHtml($metadata['entry']);
5815 break;
5816 case 'show_examview_pdf':
5817 $this->setShowExamviewPdf($metadata['entry']);
5818 break;
5819 case 'redirection_mode':
5820 $this->setRedirectionMode($metadata['entry']);
5821 break;
5822 case 'redirection_url':
5823 $this->setRedirectionUrl($metadata['entry']);
5824 break;
5825 case 'examid_in_kiosk':
5826 case 'examid_in_test_pass':
5827 $this->setShowExamIdInTestPassEnabled($metadata['entry']);
5828 break;
5829 case 'show_exam_id':
5830 case 'examid_in_test_res':
5831 $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
5832 break;
5833 case 'enable_archiving':
5834 $this->setEnableArchiving($metadata['entry']);
5835 break;
5836 case 'sign_submission':
5837 $this->setSignSubmission($metadata['entry']);
5838 break;
5839 case 'char_selector_availability':
5840 $this->setCharSelectorAvailability($metadata['entry']);
5841 break;
5842 case 'char_selector_definition':
5843 $this->setCharSelectorDefinition($metadata['entry']);
5844 break;
5845 case 'skill_service':
5846 $this->setSkillServiceEnabled((bool) $metadata['entry']);
5847 break;
5848 case 'result_tax_filters':
5849 $this->setResultFilterTaxIds(strlen($metadata['entry']) ? unserialize($metadata['entry']) : array());
5850 break;
5851 case 'show_grading_status':
5852 $this->setShowGradingStatusEnabled((bool) $metadata['entry']);
5853 break;
5854 case 'show_grading_mark':
5855 $this->setShowGradingMarkEnabled((bool) $metadata['entry']);
5856 break;
5857 case 'activation_limited':
5858 $this->setActivationLimited($metadata['entry']);
5859 break;
5860 case 'activation_start_time':
5861 $this->setActivationStartingTime($metadata['entry']);
5862 break;
5863 case 'activation_end_time':
5864 $this->setActivationEndingTime($metadata['entry']);
5865 break;
5866 case 'activation_visibility':
5867 $this->setActivationVisibility($metadata['entry']);
5868 break;
5869 case 'autosave':
5870 $this->setAutosave($metadata['entry']);
5871 break;
5872 case 'autosave_ival':
5873 $this->setAutosaveIval($metadata['entry']);
5874 break;
5875 case 'offer_question_hints':
5876 $this->setOfferingQuestionHintsEnabled($metadata['entry']);
5877 break;
5878 case 'instant_feedback_specific':
5879 $this->setSpecificAnswerFeedback($metadata['entry']);
5880 break;
5881 case 'obligations_enabled':
5882 $this->setObligationsEnabled($metadata['entry']);
5883 break;
5884 }
5885 if (preg_match("/mark_step_\d+/", $metadata["label"])) {
5886 $xmlmark = $metadata["entry"];
5887 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
5888 $mark_short = $matches[1];
5889 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
5890 $mark_official = $matches[1];
5891 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
5892 $mark_percentage = $matches[1];
5893 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
5894 $mark_passed = $matches[1];
5895 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
5896 }
5897 }
5898 // handle the import of media objects in XHTML code
5899 if (is_array($_SESSION["import_mob_xhtml"])) {
5900 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
5901 include_once "./Services/RTE/classes/class.ilRTE.php";
5902 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5903 foreach ($_SESSION["import_mob_xhtml"] as $mob) {
5904 $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
5905 if (file_exists($importfile)) {
5906 $media_object =&ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
5907 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
5908 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
5909 $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
5910 } else {
5911 global $ilLog;
5912 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
5913 }
5914 }
5915 $this->saveToDb();
5916 }
5917 }
5918
5924 public function toXML()
5925 {
5926 include_once("./Services/Xml/classes/class.ilXmlWriter.php");
5927 $a_xml_writer = new ilXmlWriter;
5928 // set xml header
5929 $a_xml_writer->xmlHeader();
5930 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
5931 $a_xml_writer->xmlStartTag("questestinterop");
5932
5933 $attrs = array(
5934 "ident" => "il_" . IL_INST_ID . "_tst_" . $this->getTestId(),
5935 "title" => $this->getTitle()
5936 );
5937 $a_xml_writer->xmlStartTag("assessment", $attrs);
5938 // add qti comment
5939 $a_xml_writer->xmlElement("qticomment", null, $this->getDescription());
5940
5941 // add qti duration
5942 if ($this->enable_processing_time) {
5943 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
5944 $a_xml_writer->xmlElement("duration", null, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
5945 }
5946
5947 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
5948 $a_xml_writer->xmlStartTag("qtimetadata");
5949 $a_xml_writer->xmlStartTag("qtimetadatafield");
5950 $a_xml_writer->xmlElement("fieldlabel", null, "ILIAS_VERSION");
5951 $a_xml_writer->xmlElement("fieldentry", null, $this->ilias->getSetting("ilias_version"));
5952 $a_xml_writer->xmlEndTag("qtimetadatafield");
5953
5954 // anonymity
5955 $a_xml_writer->xmlStartTag("qtimetadatafield");
5956 $a_xml_writer->xmlElement("fieldlabel", null, "anonymity");
5957 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getAnonymity()));
5958 $a_xml_writer->xmlEndTag("qtimetadatafield");
5959
5960 $a_xml_writer->xmlStartTag("qtimetadatafield");
5961 $a_xml_writer->xmlElement("fieldlabel", null, "use_pool");
5962 $a_xml_writer->xmlElement("fieldentry", null, $this->getPoolUsage() ? 1 : 0);
5963 $a_xml_writer->xmlEndTag("qtimetadatafield");
5964
5965 // question set type (fixed, random, dynamic, ...)
5966 $a_xml_writer->xmlStartTag("qtimetadatafield");
5967 $a_xml_writer->xmlElement("fieldlabel", null, "question_set_type");
5968 $a_xml_writer->xmlElement("fieldentry", null, $this->getQuestionSetType());
5969 $a_xml_writer->xmlEndTag("qtimetadatafield");
5970
5971 // sequence settings
5972 $a_xml_writer->xmlStartTag("qtimetadatafield");
5973 $a_xml_writer->xmlElement("fieldlabel", null, "sequence_settings");
5974 $a_xml_writer->xmlElement("fieldentry", null, $this->getSequenceSettings());
5975 $a_xml_writer->xmlEndTag("qtimetadatafield");
5976
5977 // author
5978 $a_xml_writer->xmlStartTag("qtimetadatafield");
5979 $a_xml_writer->xmlElement("fieldlabel", null, "author");
5980 $a_xml_writer->xmlElement("fieldentry", null, $this->getAuthor());
5981 $a_xml_writer->xmlEndTag("qtimetadatafield");
5982
5983 // reset processing time
5984 $a_xml_writer->xmlStartTag("qtimetadatafield");
5985 $a_xml_writer->xmlElement("fieldlabel", null, "reset_processing_time");
5986 $a_xml_writer->xmlElement("fieldentry", null, $this->getResetProcessingTime());
5987 $a_xml_writer->xmlEndTag("qtimetadatafield");
5988
5989 // count system
5990 $a_xml_writer->xmlStartTag("qtimetadatafield");
5991 $a_xml_writer->xmlElement("fieldlabel", null, "count_system");
5992 $a_xml_writer->xmlElement("fieldentry", null, $this->getCountSystem());
5993 $a_xml_writer->xmlEndTag("qtimetadatafield");
5994
5995 // multiple choice scoring
5996 $a_xml_writer->xmlStartTag("qtimetadatafield");
5997 $a_xml_writer->xmlElement("fieldlabel", null, "mc_scoring");
5998 $a_xml_writer->xmlElement("fieldentry", null, $this->getMCScoring());
5999 $a_xml_writer->xmlEndTag("qtimetadatafield");
6000
6001 // multiple choice scoring
6002 $a_xml_writer->xmlStartTag("qtimetadatafield");
6003 $a_xml_writer->xmlElement("fieldlabel", null, "score_cutting");
6004 $a_xml_writer->xmlElement("fieldentry", null, $this->getScoreCutting());
6005 $a_xml_writer->xmlEndTag("qtimetadatafield");
6006
6007 // multiple choice scoring
6008 $a_xml_writer->xmlStartTag("qtimetadatafield");
6009 $a_xml_writer->xmlElement("fieldlabel", null, "password");
6010 $a_xml_writer->xmlElement("fieldentry", null, $this->getPassword());
6011 $a_xml_writer->xmlEndTag("qtimetadatafield");
6012
6013 // allowed users
6014 $a_xml_writer->xmlStartTag("qtimetadatafield");
6015 $a_xml_writer->xmlElement("fieldlabel", null, "allowedUsers");
6016 $a_xml_writer->xmlElement("fieldentry", null, $this->getAllowedUsers());
6017 $a_xml_writer->xmlEndTag("qtimetadatafield");
6018
6019 // allowed users time gap
6020 $a_xml_writer->xmlStartTag("qtimetadatafield");
6021 $a_xml_writer->xmlElement("fieldlabel", null, "allowedUsersTimeGap");
6022 $a_xml_writer->xmlElement("fieldentry", null, $this->getAllowedUsersTimeGap());
6023 $a_xml_writer->xmlEndTag("qtimetadatafield");
6024
6025 // pass scoring
6026 $a_xml_writer->xmlStartTag("qtimetadatafield");
6027 $a_xml_writer->xmlElement("fieldlabel", null, "pass_scoring");
6028 $a_xml_writer->xmlElement("fieldentry", null, $this->getPassScoring());
6029 $a_xml_writer->xmlEndTag("qtimetadatafield");
6030
6031 $a_xml_writer->xmlStartTag('qtimetadatafield');
6032 $a_xml_writer->xmlElement('fieldlabel', null, 'pass_deletion_allowed');
6033 $a_xml_writer->xmlElement('fieldentry', null, (int) $this->isPassDeletionAllowed());
6034 $a_xml_writer->xmlEndTag('qtimetadatafield');
6035
6036 // score reporting date
6037 if ($this->getReportingDate()) {
6038 $a_xml_writer->xmlStartTag("qtimetadatafield");
6039 $a_xml_writer->xmlElement("fieldlabel", null, "reporting_date");
6040 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6041 $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]));
6042 $a_xml_writer->xmlEndTag("qtimetadatafield");
6043 }
6044 // number of tries
6045 $a_xml_writer->xmlStartTag("qtimetadatafield");
6046 $a_xml_writer->xmlElement("fieldlabel", null, "nr_of_tries");
6047 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getNrOfTries()));
6048 $a_xml_writer->xmlEndTag("qtimetadatafield");
6049
6050 // pass_waiting
6051 $a_xml_writer->xmlStartTag("qtimetadatafield");
6052 $a_xml_writer->xmlElement("fieldlabel", null, "pass_waiting");
6053 $a_xml_writer->xmlElement("fieldentry", null, $this->getPassWaiting());
6054 $a_xml_writer->xmlEndTag("qtimetadatafield");
6055
6056 // kiosk
6057 $a_xml_writer->xmlStartTag("qtimetadatafield");
6058 $a_xml_writer->xmlElement("fieldlabel", null, "kiosk");
6059 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getKiosk()));
6060 $a_xml_writer->xmlEndTag("qtimetadatafield");
6061
6062
6063 //redirection_mode
6064 $a_xml_writer->xmlStartTag('qtimetadatafield');
6065 $a_xml_writer->xmlElement("fieldlabel", null, "redirection_mode");
6066 $a_xml_writer->xmlElement("fieldentry", null, $this->getRedirectionMode());
6067 $a_xml_writer->xmlEndTag("qtimetadatafield");
6068
6069 //redirection_url
6070 $a_xml_writer->xmlStartTag('qtimetadatafield');
6071 $a_xml_writer->xmlElement("fieldlabel", null, "redirection_url");
6072 $a_xml_writer->xmlElement("fieldentry", null, $this->getRedirectionUrl());
6073 $a_xml_writer->xmlEndTag("qtimetadatafield");
6074
6075 // use previous answers
6076 $a_xml_writer->xmlStartTag("qtimetadatafield");
6077 $a_xml_writer->xmlElement("fieldlabel", null, "use_previous_answers");
6078 $a_xml_writer->xmlElement("fieldentry", null, $this->getUsePreviousAnswers());
6079 $a_xml_writer->xmlEndTag("qtimetadatafield");
6080
6081 // hide title points
6082 $a_xml_writer->xmlStartTag("qtimetadatafield");
6083 $a_xml_writer->xmlElement("fieldlabel", null, "title_output");
6084 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getTitleOutput()));
6085 $a_xml_writer->xmlEndTag("qtimetadatafield");
6086
6087 // results presentation
6088 $a_xml_writer->xmlStartTag("qtimetadatafield");
6089 $a_xml_writer->xmlElement("fieldlabel", null, "results_presentation");
6090 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getResultsPresentation()));
6091 $a_xml_writer->xmlEndTag("qtimetadatafield");
6092
6093 // examid in test pass
6094 $a_xml_writer->xmlStartTag("qtimetadatafield");
6095 $a_xml_writer->xmlElement("fieldlabel", null, "examid_in_test_pass");
6096 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6097 $a_xml_writer->xmlEndTag("qtimetadatafield");
6098
6099 // examid in kiosk
6100 $a_xml_writer->xmlStartTag("qtimetadatafield");
6101 $a_xml_writer->xmlElement("fieldlabel", null, "examid_in_test_res");
6102 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6103 $a_xml_writer->xmlEndTag("qtimetadatafield");
6104
6105 // solution details
6106 $a_xml_writer->xmlStartTag("qtimetadatafield");
6107 $a_xml_writer->xmlElement("fieldlabel", null, "show_summary");
6108 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getListOfQuestionsSettings()));
6109 $a_xml_writer->xmlEndTag("qtimetadatafield");
6110
6111 // solution details
6112 $a_xml_writer->xmlStartTag("qtimetadatafield");
6113 $a_xml_writer->xmlElement("fieldlabel", null, "score_reporting");
6114 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getScoreReporting()));
6115 $a_xml_writer->xmlEndTag("qtimetadatafield");
6116
6117 $a_xml_writer->xmlStartTag("qtimetadatafield");
6118 $a_xml_writer->xmlElement("fieldlabel", null, "solution_details");
6119 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowSolutionDetails());
6120 $a_xml_writer->xmlEndTag("qtimetadatafield");
6121 $a_xml_writer->xmlStartTag("qtimetadatafield");
6122 $a_xml_writer->xmlElement("fieldlabel", null, "print_bs_with_res");
6123 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowSolutionDetails() ? (int) $this->isBestSolutionPrintedWithResult() : 0);
6124 $a_xml_writer->xmlEndTag("qtimetadatafield");
6125
6126 // solution details
6127 $a_xml_writer->xmlStartTag("qtimetadatafield");
6128 $a_xml_writer->xmlElement("fieldlabel", null, "instant_verification");
6129 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getInstantFeedbackSolution()));
6130 $a_xml_writer->xmlEndTag("qtimetadatafield");
6131
6132 // answer specific feedback
6133 $a_xml_writer->xmlStartTag("qtimetadatafield");
6134 $a_xml_writer->xmlElement("fieldlabel", null, "answer_feedback");
6135 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getAnswerFeedback()));
6136 $a_xml_writer->xmlEndTag("qtimetadatafield");
6137
6138 // answer specific feedback of reached points
6139 $a_xml_writer->xmlStartTag("qtimetadatafield");
6140 $a_xml_writer->xmlElement("fieldlabel", null, "answer_feedback_points");
6141 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getAnswerFeedbackPoints()));
6142 $a_xml_writer->xmlEndTag("qtimetadatafield");
6143
6144 // instant response answer freezing
6145 $a_xml_writer->xmlStartTag("qtimetadatafield");
6146 $a_xml_writer->xmlElement("fieldlabel", null, "instant_feedback_answer_fixation");
6147 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isInstantFeedbackAnswerFixationEnabled());
6148 $a_xml_writer->xmlEndTag("qtimetadatafield");
6149
6150 // instant response forced
6151 $a_xml_writer->xmlStartTag("qtimetadatafield");
6152 $a_xml_writer->xmlElement("fieldlabel", null, "force_instant_feedback");
6153 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isForceInstantFeedbackEnabled());
6154 $a_xml_writer->xmlEndTag("qtimetadatafield");
6155
6156
6157 // highscore
6158 $highscore_metadata = array(
6159 'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6160 'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6161 'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6162 'highscore_score' => array('value' => $this->getHighscoreScore()),
6163 'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6164 'highscore_hints' => array('value' => $this->getHighscoreHints()),
6165 'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6166 'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6167 'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6168 'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6169 );
6170 foreach ($highscore_metadata as $label => $data) {
6171 $a_xml_writer->xmlStartTag("qtimetadatafield");
6172 $a_xml_writer->xmlElement("fieldlabel", null, $label);
6173 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $data['value']));
6174 $a_xml_writer->xmlEndTag("qtimetadatafield");
6175 }
6176
6177 // show cancel
6178 $a_xml_writer->xmlStartTag("qtimetadatafield");
6179 $a_xml_writer->xmlElement("fieldlabel", null, "show_cancel");
6180 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getShowCancel()));
6181 $a_xml_writer->xmlEndTag("qtimetadatafield");
6182
6183 // show marker
6184 $a_xml_writer->xmlStartTag("qtimetadatafield");
6185 $a_xml_writer->xmlElement("fieldlabel", null, "show_marker");
6186 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getShowMarker()));
6187 $a_xml_writer->xmlEndTag("qtimetadatafield");
6188
6189 // fixed participants
6190 $a_xml_writer->xmlStartTag("qtimetadatafield");
6191 $a_xml_writer->xmlElement("fieldlabel", null, "fixed_participants");
6192 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getFixedParticipants()));
6193 $a_xml_writer->xmlEndTag("qtimetadatafield");
6194
6195 // show final statement
6196 $a_xml_writer->xmlStartTag("qtimetadatafield");
6197 $a_xml_writer->xmlElement("fieldlabel", null, "showfinalstatement");
6198 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6199 $a_xml_writer->xmlEndTag("qtimetadatafield");
6200
6201 // show introduction only
6202 $a_xml_writer->xmlStartTag("qtimetadatafield");
6203 $a_xml_writer->xmlElement("fieldlabel", null, "showinfo");
6204 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6205 $a_xml_writer->xmlEndTag("qtimetadatafield");
6206
6207 // mail notification
6208 $a_xml_writer->xmlStartTag("qtimetadatafield");
6209 $a_xml_writer->xmlElement("fieldlabel", null, "mailnotification");
6210 $a_xml_writer->xmlElement("fieldentry", null, $this->getMailNotification());
6211 $a_xml_writer->xmlEndTag("qtimetadatafield");
6212
6213 // mail notification type
6214 $a_xml_writer->xmlStartTag("qtimetadatafield");
6215 $a_xml_writer->xmlElement("fieldlabel", null, "mailnottype");
6216 $a_xml_writer->xmlElement("fieldentry", null, $this->getMailNotificationType());
6217 $a_xml_writer->xmlEndTag("qtimetadatafield");
6218
6219 // export settings
6220 $a_xml_writer->xmlStartTag("qtimetadatafield");
6221 $a_xml_writer->xmlElement("fieldlabel", null, "exportsettings");
6222 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getExportSettings());
6223 $a_xml_writer->xmlEndTag("qtimetadatafield");
6224
6225 // force JavaScript
6226 $a_xml_writer->xmlStartTag("qtimetadatafield");
6227 $a_xml_writer->xmlElement("fieldlabel", null, "forcejs");
6228 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6229 $a_xml_writer->xmlEndTag("qtimetadatafield");
6230
6231 // custom style
6232 $a_xml_writer->xmlStartTag("qtimetadatafield");
6233 $a_xml_writer->xmlElement("fieldlabel", null, "customstyle");
6234 $a_xml_writer->xmlElement("fieldentry", null, $this->getCustomStyle());
6235 $a_xml_writer->xmlEndTag("qtimetadatafield");
6236
6237 // shuffle questions
6238 $a_xml_writer->xmlStartTag("qtimetadatafield");
6239 $a_xml_writer->xmlElement("fieldlabel", null, "shuffle_questions");
6240 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getShuffleQuestions()));
6241 $a_xml_writer->xmlEndTag("qtimetadatafield");
6242
6243 // processing time
6244 $a_xml_writer->xmlStartTag("qtimetadatafield");
6245 $a_xml_writer->xmlElement("fieldlabel", null, "processing_time");
6246 $a_xml_writer->xmlElement("fieldentry", null, $this->getProcessingTime());
6247 $a_xml_writer->xmlEndTag("qtimetadatafield");
6248
6249 // enable_examview
6250 $a_xml_writer->xmlStartTag("qtimetadatafield");
6251 $a_xml_writer->xmlElement("fieldlabel", null, "enable_examview");
6252 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getEnableExamview());
6253 $a_xml_writer->xmlEndTag("qtimetadatafield");
6254
6255 // show_examview_html
6256 $a_xml_writer->xmlStartTag("qtimetadatafield");
6257 $a_xml_writer->xmlElement("fieldlabel", null, "show_examview_html");
6258 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowExamviewHtml());
6259 $a_xml_writer->xmlEndTag("qtimetadatafield");
6260
6261 // show_examview_pdf
6262 $a_xml_writer->xmlStartTag("qtimetadatafield");
6263 $a_xml_writer->xmlElement("fieldlabel", null, "show_examview_pdf");
6264 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getShowExamviewPdf());
6265 $a_xml_writer->xmlEndTag("qtimetadatafield");
6266
6267 // enable_archiving
6268 $a_xml_writer->xmlStartTag("qtimetadatafield");
6269 $a_xml_writer->xmlElement("fieldlabel", null, "enable_archiving");
6270 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getEnableArchiving());
6271 $a_xml_writer->xmlEndTag("qtimetadatafield");
6272
6273 // sign_submission
6274 $a_xml_writer->xmlStartTag("qtimetadatafield");
6275 $a_xml_writer->xmlElement("fieldlabel", null, "sign_submission");
6276 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getSignSubmission());
6277 $a_xml_writer->xmlEndTag("qtimetadatafield");
6278
6279 // char_selector_availability
6280 $a_xml_writer->xmlStartTag("qtimetadatafield");
6281 $a_xml_writer->xmlElement("fieldlabel", null, "char_selector_availability");
6282 $a_xml_writer->xmlElement("fieldentry", null, sprintf("%d", $this->getCharSelectorAvailability()));
6283 $a_xml_writer->xmlEndTag("qtimetadatafield");
6284
6285 // char_selector_definition
6286 $a_xml_writer->xmlStartTag("qtimetadatafield");
6287 $a_xml_writer->xmlElement("fieldlabel", null, "char_selector_definition");
6288 $a_xml_writer->xmlElement("fieldentry", null, $this->getCharSelectorDefinition());
6289 $a_xml_writer->xmlEndTag("qtimetadatafield");
6290
6291 // skill_service
6292 $a_xml_writer->xmlStartTag("qtimetadatafield");
6293 $a_xml_writer->xmlElement("fieldlabel", null, "skill_service");
6294 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isSkillServiceEnabled());
6295 $a_xml_writer->xmlEndTag("qtimetadatafield");
6296
6297 // result_tax_filters
6298 $a_xml_writer->xmlStartTag("qtimetadatafield");
6299 $a_xml_writer->xmlElement("fieldlabel", null, "result_tax_filters");
6300 $a_xml_writer->xmlElement("fieldentry", null, serialize((array) $this->getResultFilterTaxIds()));
6301 $a_xml_writer->xmlEndTag("qtimetadatafield");
6302
6303 // show_grading_status
6304 $a_xml_writer->xmlStartTag("qtimetadatafield");
6305 $a_xml_writer->xmlElement("fieldlabel", null, "show_grading_status");
6306 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isShowGradingStatusEnabled());
6307 $a_xml_writer->xmlEndTag("qtimetadatafield");
6308
6309 // show_grading_mark
6310 $a_xml_writer->xmlStartTag("qtimetadatafield");
6311 $a_xml_writer->xmlElement("fieldlabel", null, "show_grading_mark");
6312 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isShowGradingMarkEnabled());
6313 $a_xml_writer->xmlEndTag("qtimetadatafield");
6314
6315
6316 // starting time
6317 if ($this->getStartingTime()) {
6318 $a_xml_writer->xmlStartTag("qtimetadatafield");
6319 $a_xml_writer->xmlElement("fieldlabel", null, "starting_time");
6320 $backward_compatibility_format = $this->buildIso8601PeriodFromUnixtimeForExportCompatibility($this->starting_time);
6321 $a_xml_writer->xmlElement("fieldentry", null, $backward_compatibility_format);
6322 $a_xml_writer->xmlEndTag("qtimetadatafield");
6323 }
6324 // ending time
6325 if ($this->getEndingTime()) {
6326 $a_xml_writer->xmlStartTag("qtimetadatafield");
6327 $a_xml_writer->xmlElement("fieldlabel", null, "ending_time");
6328 $backward_compatibility_format = $this->buildIso8601PeriodFromUnixtimeForExportCompatibility($this->ending_time);
6329 $a_xml_writer->xmlElement("fieldentry", null, $backward_compatibility_format);
6330 $a_xml_writer->xmlEndTag("qtimetadatafield");
6331 }
6332
6333
6334 //activation_limited
6335 $a_xml_writer->xmlStartTag("qtimetadatafield");
6336 $a_xml_writer->xmlElement("fieldlabel", null, "activation_limited");
6337 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isActivationLimited());
6338 $a_xml_writer->xmlEndTag("qtimetadatafield");
6339
6340 //activation_start_time
6341 $a_xml_writer->xmlStartTag("qtimetadatafield");
6342 $a_xml_writer->xmlElement("fieldlabel", null, "activation_start_time");
6343 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getActivationStartingTime());
6344 $a_xml_writer->xmlEndTag("qtimetadatafield");
6345
6346 //activation_end_time
6347 $a_xml_writer->xmlStartTag("qtimetadatafield");
6348 $a_xml_writer->xmlElement("fieldlabel", null, "activation_end_time");
6349 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getActivationEndingTime());
6350 $a_xml_writer->xmlEndTag("qtimetadatafield");
6351
6352 //activation_visibility
6353 $a_xml_writer->xmlStartTag("qtimetadatafield");
6354 $a_xml_writer->xmlElement("fieldlabel", null, "activation_visibility");
6355 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getActivationVisibility());
6356 $a_xml_writer->xmlEndTag("qtimetadatafield");
6357
6358 // autosave
6359 $a_xml_writer->xmlStartTag("qtimetadatafield");
6360 $a_xml_writer->xmlElement("fieldlabel", null, "autosave");
6361 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getAutosave());
6362 $a_xml_writer->xmlEndTag("qtimetadatafield");
6363
6364 // autosave_ival
6365 $a_xml_writer->xmlStartTag("qtimetadatafield");
6366 $a_xml_writer->xmlElement("fieldlabel", null, "autosave_ival");
6367 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getAutosaveIval());
6368 $a_xml_writer->xmlEndTag("qtimetadatafield");
6369
6370 //offer_question_hints
6371 $a_xml_writer->xmlStartTag("qtimetadatafield");
6372 $a_xml_writer->xmlElement("fieldlabel", null, "offer_question_hints");
6373 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isOfferingQuestionHintsEnabled());
6374 $a_xml_writer->xmlEndTag("qtimetadatafield");
6375
6376 //instant_feedback_specific
6377 $a_xml_writer->xmlStartTag("qtimetadatafield");
6378 $a_xml_writer->xmlElement("fieldlabel", null, "instant_feedback_specific");
6379 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getSpecificAnswerFeedback());
6380 $a_xml_writer->xmlEndTag("qtimetadatafield");
6381
6382 //instant_feedback_answer_fixation
6383 $a_xml_writer->xmlStartTag("qtimetadatafield");
6384 $a_xml_writer->xmlElement("fieldlabel", null, "instant_feedback_answer_fixation");
6385 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->isInstantFeedbackAnswerFixationEnabled());
6386 $a_xml_writer->xmlEndTag("qtimetadatafield");
6387
6388 //obligations_enabled
6389 $a_xml_writer->xmlStartTag("qtimetadatafield");
6390 $a_xml_writer->xmlElement("fieldlabel", null, "obligations_enabled");
6391 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->areObligationsEnabled());
6392 $a_xml_writer->xmlEndTag("qtimetadatafield");
6393
6394 //enable_processing_time
6395 $a_xml_writer->xmlStartTag("qtimetadatafield");
6396 $a_xml_writer->xmlElement("fieldlabel", null, "enable_processing_time");
6397 $a_xml_writer->xmlElement("fieldentry", null, (int) $this->getEnableProcessingTime());
6398 $a_xml_writer->xmlEndTag("qtimetadatafield");
6399
6400 foreach ($this->mark_schema->mark_steps as $index => $mark) {
6401 // mark steps
6402 $a_xml_writer->xmlStartTag("qtimetadatafield");
6403 $a_xml_writer->xmlElement("fieldlabel", null, "mark_step_$index");
6404 $a_xml_writer->xmlElement("fieldentry", null, sprintf(
6405 "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6406 $mark->getShortName(),
6407 $mark->getOfficialName(),
6408 $mark->getMinimumLevel(),
6409 $mark->getPassed()
6410 ));
6411 $a_xml_writer->xmlEndTag("qtimetadatafield");
6412 }
6413 $a_xml_writer->xmlEndTag("qtimetadata");
6414
6415 // add qti objectives
6416 $a_xml_writer->xmlStartTag("objectives");
6417 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6418 $a_xml_writer->xmlEndTag("objectives");
6419
6420 // add qti assessmentcontrol
6421 if ($this->getInstantFeedbackSolution() == 1) {
6422 $attrs = array(
6423 "solutionswitch" => "Yes"
6424 );
6425 } else {
6426 $attrs = null;
6427 }
6428 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, null);
6429
6430 if (strlen($this->getFinalStatement())) {
6431 // add qti presentation_material
6432 $a_xml_writer->xmlStartTag("presentation_material");
6433 $a_xml_writer->xmlStartTag("flow_mat");
6434 $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6435 $a_xml_writer->xmlEndTag("flow_mat");
6436 $a_xml_writer->xmlEndTag("presentation_material");
6437 }
6438
6439 $attrs = array(
6440 "ident" => "1"
6441 );
6442 $a_xml_writer->xmlElement("section", $attrs, null);
6443 $a_xml_writer->xmlEndTag("assessment");
6444 $a_xml_writer->xmlEndTag("questestinterop");
6445
6446 $xml = $a_xml_writer->xmlDumpMem(false);
6447 return $xml;
6448 }
6449
6455 {
6456 $date_time_unix = new ilDateTime($unix_timestamp, IL_CAL_UNIX);
6457 $date_time = $date_time_unix->get(IL_CAL_DATETIME);
6458 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $date_time, $matches);
6459 $iso8601_period = sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]);
6460 return $iso8601_period;
6461 }
6462
6469 public function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6470 {
6471 global $ilBench;
6472
6473 $this->mob_ids = array();
6474 $this->file_ids = array();
6475
6476 // MetaData
6477 $this->exportXMLMetaData($a_xml_writer);
6478
6479 // PageObjects
6480 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Page Objects");
6481 $ilBench->start("ContentObjectExport", "exportPageObjects");
6482 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6483 $ilBench->stop("ContentObjectExport", "exportPageObjects");
6484 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Page Objects");
6485
6486 // MediaObjects
6487 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Media Objects");
6488 $ilBench->start("ContentObjectExport", "exportMediaObjects");
6489 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6490 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6491 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Media Objects");
6492
6493 // FileItems
6494 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export File Items");
6495 $ilBench->start("ContentObjectExport", "exportFileItems");
6496 $this->exportFileItems($a_target_dir, $expLog);
6497 $ilBench->stop("ContentObjectExport", "exportFileItems");
6498 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export File Items");
6499 }
6500
6507 public function exportXMLMetaData(&$a_xml_writer)
6508 {
6509 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6510 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6511 $md2xml->setExportMode(true);
6512 $md2xml->startExport();
6513 $a_xml_writer->appendXML($md2xml->getXML());
6514 }
6515
6521 public function modifyExportIdentifier($a_tag, $a_param, $a_value)
6522 {
6523 if ($a_tag == "Identifier" && $a_param == "Entry") {
6524 include_once "./Services/Utilities/classes/class.ilUtil.php";
6525 $a_value = ilUtil::insertInstIntoID($a_value);
6526 }
6527
6528 return $a_value;
6529 }
6530
6531
6538 public function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6539 {
6540 global $ilBench;
6541
6542 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6543
6544 foreach ($this->questions as $question_id) {
6545 $ilBench->start("ContentObjectExport", "exportPageObject");
6546 $expLog->write(date("[y-m-d H:i:s] ") . "Page Object " . $question_id);
6547
6548 $attrs = array();
6549 $a_xml_writer->xmlStartTag("PageObject", $attrs);
6550
6551
6552 // export xml to writer object
6553 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6554 include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6555 $page_object = new ilAssQuestionPage($question_id);
6556 $page_object->buildDom();
6557 $page_object->insertInstIntoIDs($a_inst);
6558 $mob_ids = $page_object->collectMediaObjects(false);
6559 require_once 'Services/COPage/classes/class.ilPCFileList.php';
6560 $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6561 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6562 $xml = str_replace("&", "&amp;", $xml);
6563 $a_xml_writer->appendXML($xml);
6564 $page_object->freeDom();
6565 unset($page_object);
6566
6567 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6568
6569 // collect media objects
6570 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6571 //$mob_ids = $page_obj->getMediaObjectIDs();
6572 foreach ($mob_ids as $mob_id) {
6573 $this->mob_ids[$mob_id] = $mob_id;
6574 }
6575 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6576
6577 // collect all file items
6578 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6579 //$file_ids = $page_obj->getFileItemIds();
6580 foreach ($file_ids as $file_id) {
6581 $this->file_ids[$file_id] = $file_id;
6582 }
6583 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6584
6585 $a_xml_writer->xmlEndTag("PageObject");
6586 //unset($page_obj);
6587
6588 $ilBench->stop("ContentObjectExport", "exportPageObject");
6589 }
6590 }
6591
6598 public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6599 {
6600 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6601
6602 foreach ($this->mob_ids as $mob_id) {
6603 $expLog->write(date("[y-m-d H:i:s] ") . "Media Object " . $mob_id);
6604 if (ilObjMediaObject::_exists($mob_id)) {
6605 $media_obj = new ilObjMediaObject($mob_id);
6606 $media_obj->exportXML($a_xml_writer, $a_inst);
6607 $media_obj->exportFiles($a_target_dir);
6608 unset($media_obj);
6609 }
6610 }
6611 }
6612
6617 public function exportFileItems($a_target_dir, &$expLog)
6618 {
6619 include_once "./Modules/File/classes/class.ilObjFile.php";
6620
6621 foreach ($this->file_ids as $file_id) {
6622 $expLog->write(date("[y-m-d H:i:s] ") . "File Item " . $file_id);
6623 $file_obj = new ilObjFile($file_id, false);
6624 $file_obj->export($a_target_dir);
6625 unset($file_obj);
6626 }
6627 }
6628
6633 public function getImportMapping()
6634 {
6635 if (!is_array($this->import_mapping)) {
6636 return array();
6637 } else {
6638 return $this->import_mapping;
6639 }
6640 }
6641
6645 public function canEditEctsGrades()
6646 {
6647 return $this->canShowEctsGrades() && $this->canEditMarks();
6648 }
6649
6653 public function canShowEctsGrades()
6654 {
6655 return $this->getReportingDate();
6656 }
6657
6661 public function getECTSGrade($passed_array, $reached_points, $max_points)
6662 {
6663 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);
6664 }
6665
6669 public static function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
6670 {
6671 include_once "./Modules/Test/classes/class.ilStatistics.php";
6672 // calculate the median
6673 $passed_statistics = new ilStatistics();
6674 $passed_statistics->setData($points_passed);
6675 $ects_percentiles = array(
6676 "A" => $passed_statistics->quantile($a),
6677 "B" => $passed_statistics->quantile($b),
6678 "C" => $passed_statistics->quantile($c),
6679 "D" => $passed_statistics->quantile($d),
6680 "E" => $passed_statistics->quantile($e)
6681 );
6682 if (count($points_passed) && ($reached_points >= $ects_percentiles["A"])) {
6683 return "A";
6684 } elseif (count($points_passed) && ($reached_points >= $ects_percentiles["B"])) {
6685 return "B";
6686 } elseif (count($points_passed) && ($reached_points >= $ects_percentiles["C"])) {
6687 return "C";
6688 } elseif (count($points_passed) && ($reached_points >= $ects_percentiles["D"])) {
6689 return "D";
6690 } elseif (count($points_passed) && ($reached_points >= $ects_percentiles["E"])) {
6691 return "E";
6692 } elseif (strcmp($fx, "") != 0) {
6693 if ($max_points > 0) {
6694 $percentage = ($reached_points / $max_points) * 100.0;
6695 if ($percentage < 0) {
6696 $percentage = 0.0;
6697 }
6698 } else {
6699 $percentage = 0.0;
6700 }
6701 if ($percentage >= $fx) {
6702 return "FX";
6703 } else {
6704 return "F";
6705 }
6706 } else {
6707 return "F";
6708 }
6709 }
6710
6714 public function checkMarks()
6715 {
6716 return $this->mark_schema->checkMarks();
6717 }
6718
6722 public function getMarkSchema()
6723 {
6724 return $this->mark_schema;
6725 }
6726
6730 public function getMarkSchemaForeignId()
6731 {
6732 return $this->getTestId();
6733 }
6734
6737 public function onMarkSchemaSaved()
6738 {
6744 global $ilDB, $ilPluginAdmin, $tree;
6745
6746 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
6747 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
6748 $this->saveCompleteStatus($testQuestionSetConfigFactory->getQuestionSetConfig());
6749
6750 if ($this->participantDataExist()) {
6751 $this->recalculateScores(true);
6752 }
6753 }
6754
6758 public function canEditMarks()
6759 {
6760 $total = $this->evalTotalPersons();
6761 if ($total > 0) {
6762 if ($this->getReportingDate()) {
6763 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches)) {
6764 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
6765 $now = time();
6766 if ($now < $epoch_time) {
6767 return true;
6768 }
6769 }
6770 }
6771 return false;
6772 } else {
6773 return true;
6774 }
6775 }
6776
6784 public function setAuthor($author = "")
6785 {
6786 $this->author = $author;
6787 }
6788
6798 public function saveAuthorToMetadata($a_author = "")
6799 {
6800 $md = new ilMD($this->getId(), 0, $this->getType());
6801 $md_life =&$md->getLifecycle();
6802 if (!$md_life) {
6803 if (strlen($a_author) == 0) {
6804 global $ilUser;
6805 $a_author = $ilUser->getFullname();
6806 }
6807
6808 $md_life =&$md->addLifecycle();
6809 $md_life->save();
6810 $con =&$md_life->addContribute();
6811 $con->setRole("Author");
6812 $con->save();
6813 $ent =&$con->addEntity();
6814 $ent->setEntity($a_author);
6815 $ent->save();
6816 }
6817 }
6818
6824 public function createMetaData()
6825 {
6826 parent::createMetaData();
6827 $this->saveAuthorToMetadata();
6828 }
6829
6837 public function getAuthor()
6838 {
6839 $author = array();
6840 include_once "./Services/MetaData/classes/class.ilMD.php";
6841 $md = new ilMD($this->getId(), 0, $this->getType());
6842 $md_life =&$md->getLifecycle();
6843 if ($md_life) {
6844 $ids =&$md_life->getContributeIds();
6845 foreach ($ids as $id) {
6846 $md_cont =&$md_life->getContribute($id);
6847 if (strcmp($md_cont->getRole(), "Author") == 0) {
6848 $entids =&$md_cont->getEntityIds();
6849 foreach ($entids as $entid) {
6850 $md_ent =&$md_cont->getEntity($entid);
6851 array_push($author, $md_ent->getEntity());
6852 }
6853 }
6854 }
6855 }
6856 return join($author, ",");
6857 }
6858
6866 public static function _lookupAuthor($obj_id)
6867 {
6868 $author = array();
6869 include_once "./Services/MetaData/classes/class.ilMD.php";
6870 $md = new ilMD($obj_id, 0, "tst");
6871 $md_life =&$md->getLifecycle();
6872 if ($md_life) {
6873 $ids =&$md_life->getContributeIds();
6874 foreach ($ids as $id) {
6875 $md_cont =&$md_life->getContribute($id);
6876 if (strcmp($md_cont->getRole(), "Author") == 0) {
6877 $entids =&$md_cont->getEntityIds();
6878 foreach ($entids as $entid) {
6879 $md_ent =&$md_cont->getEntity($entid);
6880 array_push($author, $md_ent->getEntity());
6881 }
6882 }
6883 }
6884 }
6885 return join($author, ",");
6886 }
6887
6894 public static function _getAvailableTests($use_object_id = false)
6895 {
6896 global $ilUser;
6897 global $ilDB;
6898
6899 $result_array = array();
6900 $tests = ilUtil::_getObjectsByOperations("tst", "write", $ilUser->getId(), -1);
6901 if (count($tests)) {
6902 $titles = ilObject::_prepareCloneSelection($tests, "tst");
6903 foreach ($tests as $ref_id) {
6904 if ($use_object_id) {
6906 $result_array[$obj_id] = $titles[$ref_id];
6907 } else {
6908 $result_array[$ref_id] = $titles[$ref_id];
6909 }
6910 }
6911 }
6912 return $result_array;
6913 }
6914
6923 public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
6924 {
6925 global $ilLog, $tree, $ilDB, $ilPluginAdmin;
6926
6927 $this->loadFromDb();
6928
6929 // Copy settings
6931 $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
6932 $newObj->setTmpCopyWizardCopyId($a_copy_id);
6933 $this->cloneMetaData($newObj);
6934
6935 //copy online status if object is not the root copy object
6936 $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
6937
6938 if (!$cp_options->isRootNode($this->getRefId())) {
6939 $newObj->setOnline($this->isOnline());
6940 }
6941
6942 $newObj->setAnonymity($this->getAnonymity());
6943 $newObj->setAnswerFeedback($this->getAnswerFeedback());
6944 $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
6945 $newObj->setAuthor($this->getAuthor());
6946 $newObj->setLimitUsersEnabled($this->isLimitUsersEnabled());
6947 $newObj->setAllowedUsers($this->getAllowedUsers());
6948 $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
6949 $newObj->setCountSystem($this->getCountSystem());
6950 $newObj->setECTSFX($this->getECTSFX());
6951 $newObj->setECTSGrades($this->getECTSGrades());
6952 $newObj->setECTSOutput($this->getECTSOutput());
6953 $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
6954 $newObj->setEndingTimeEnabled($this->isEndingTimeEnabled());
6955 $newObj->setEndingTime($this->getEndingTime());
6956 $newObj->setFixedParticipants($this->getFixedParticipants());
6957 $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
6958 $newObj->setIntroductionEnabled($this->isIntroductionEnabled());
6959 $newObj->setIntroduction($this->getIntroduction());
6960 $newObj->setFinalStatement($this->getFinalStatement());
6961 $newObj->setShowInfo($this->getShowInfo());
6962 $newObj->setForceJS($this->getForceJS());
6963 $newObj->setCustomStyle($this->getCustomStyle());
6964 $newObj->setKiosk($this->getKiosk());
6965 $newObj->setShowFinalStatement($this->getShowFinalStatement());
6966 $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
6967 $newObj->setMCScoring($this->getMCScoring());
6968 $newObj->setMailNotification($this->getMailNotification());
6969 $newObj->setMailNotificationType($this->getMailNotificationType());
6970 $newObj->setNrOfTries($this->getNrOfTries());
6971 $newObj->setPassScoring($this->getPassScoring());
6972 $newObj->setPasswordEnabled($this->isPasswordEnabled());
6973 $newObj->setPassword($this->getPassword());
6974 $newObj->setProcessingTime($this->getProcessingTime());
6975 $newObj->setQuestionSetType($this->getQuestionSetType());
6976 $newObj->setReportingDate($this->getReportingDate());
6977 $newObj->setResetProcessingTime($this->getResetProcessingTime());
6978 $newObj->setResultsPresentation($this->getResultsPresentation());
6979 $newObj->setScoreCutting($this->getScoreCutting());
6980 $newObj->setScoreReporting($this->getScoreReporting());
6981 $newObj->setSequenceSettings($this->getSequenceSettings());
6982 $newObj->setShowCancel($this->getShowCancel());
6983 $newObj->setShowMarker($this->getShowMarker());
6984 $newObj->setShuffleQuestions($this->getShuffleQuestions());
6985 $newObj->setStartingTimeEnabled($this->isStartingTimeEnabled());
6986 $newObj->setStartingTime($this->getStartingTime());
6987 $newObj->setTitleOutput($this->getTitleOutput());
6988 $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
6989 $newObj->setRedirectionMode($this->getRedirectionMode());
6990 $newObj->setRedirectionUrl($this->getRedirectionUrl());
6991 $newObj->setCertificateVisibility($this->getCertificateVisibility());
6992 $newObj->mark_schema = clone $this->mark_schema;
6993 $newObj->setEnabledViewMode($this->getEnabledViewMode());
6994 $newObj->setTemplate($this->getTemplate());
6995 $newObj->setPoolUsage($this->getPoolUsage());
6996 $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
6997 $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
6998 $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
6999 $newObj->setEnableExamView($this->getEnableExamview());
7000 $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7001 $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7002 $newObj->setEnableArchiving($this->getEnableArchiving());
7003 $newObj->setSignSubmission($this->getSignSubmission());
7004 $newObj->setCharSelectorAvailability((int) $this->getCharSelectorAvailability());
7005 $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7006 $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
7007 $newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
7008 $newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
7009 $newObj->setForceInstantFeedbackEnabled($this->isForceInstantFeedbackEnabled());
7010 $newObj->setAutosave($this->getAutosave());
7011 $newObj->setAutosaveIval($this->getAutosaveIval());
7012 $newObj->setOfferingQuestionHintsEnabled($this->isOfferingQuestionHintsEnabled());
7013 $newObj->setSpecificAnswerFeedback($this->getSpecificAnswerFeedback());
7014 if ($this->isPassWaitingEnabled()) {
7015 $newObj->setPassWaiting($this->getPassWaiting());
7016 }
7017 $newObj->setObligationsEnabled($this->areObligationsEnabled());
7018 $newObj->saveToDb();
7019
7020 // clone certificate
7021 include_once "./Services/Certificate/classes/class.ilCertificate.php";
7022 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7023 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7024 $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7025 $cert->cloneCertificate($newcert);
7026
7027 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7028 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7029 $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7030
7031 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdList.php';
7032 $skillLevelThresholdList = new ilTestSkillLevelThresholdList($ilDB);
7033 $skillLevelThresholdList->setTestId($this->getTestId());
7034 $skillLevelThresholdList->loadFromDb();
7035 $skillLevelThresholdList->cloneListForTest($newObj->getTestId());
7036
7037 $newObj->saveToDb();
7038 $newObj->updateMetaData();// #14467
7039
7040 include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
7041 $obj_settings = new ilLPObjSettings($this->getId());
7042 $obj_settings->cloneSettings($newObj->getId());
7043
7044 return $newObj;
7045 }
7046
7053 public function getQuestionCount()
7054 {
7055 $num = 0;
7056
7057 if ($this->isRandomTest()) {
7058 global $tree, $ilDB, $ilPluginAdmin;
7059
7060 $questionSetConfig = new ilTestRandomQuestionSetConfig(
7061 $tree,
7062 $ilDB,
7063 $ilPluginAdmin,
7064 $this
7065 );
7066
7067 $questionSetConfig->loadFromDb();
7068
7069 if ($questionSetConfig->isQuestionAmountConfigurationModePerPool()) {
7070 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7071 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7072 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7073
7074 $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList(
7075 $ilDB,
7076 $this,
7078 );
7079
7080 $sourcePoolDefinitionList->loadDefinitions();
7081
7082 $num = $sourcePoolDefinitionList->getQuestionAmount();
7083 } else {
7084 $num = $questionSetConfig->getQuestionAmountPerTest();
7085 }
7086 } else {
7087 $num = count($this->questions);
7088 }
7089
7090 return $num;
7091 }
7092
7100 public function logAction($logtext = "", $question_id = "")
7101 {
7102 global $ilUser;
7103
7104 $original_id = "";
7105 if (strcmp($question_id, "") != 0) {
7106 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7107 $original_id = assQuestion::_getOriginalId($question_id);
7108 }
7109 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7110 ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, true, $this->getRefId());
7111 }
7112
7120 public static function _getObjectIDFromTestID($test_id)
7121 {
7122 global $ilDB;
7123 $object_id = false;
7124 $result = $ilDB->queryF(
7125 "SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7126 array('integer'),
7127 array($test_id)
7128 );
7129 if ($result->numRows()) {
7130 $row = $ilDB->fetchAssoc($result);
7131 $object_id = $row["obj_fi"];
7132 }
7133 return $object_id;
7134 }
7135
7143 public static function _getObjectIDFromActiveID($active_id)
7144 {
7145 global $ilDB;
7146 $object_id = false;
7147 $result = $ilDB->queryF(
7148 "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",
7149 array('integer'),
7150 array($active_id)
7151 );
7152 if ($result->numRows()) {
7153 $row = $ilDB->fetchAssoc($result);
7154 $object_id = $row["obj_fi"];
7155 }
7156 return $object_id;
7157 }
7158
7166 public static function _getTestIDFromObjectID($object_id)
7167 {
7168 global $ilDB;
7169 $test_id = false;
7170 $result = $ilDB->queryF(
7171 "SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7172 array('integer'),
7173 array($object_id)
7174 );
7175 if ($result->numRows()) {
7176 $row = $ilDB->fetchAssoc($result);
7177 $test_id = $row["test_id"];
7178 }
7179 return $test_id;
7180 }
7181
7190 public function getTextAnswer($active_id, $question_id, $pass = null)
7191 {
7192 global $ilDB;
7193
7194 $res = "";
7195 if (($active_id) && ($question_id)) {
7196 if (is_null($pass)) {
7197 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7198 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7199 }
7200 $result = $ilDB->queryF(
7201 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7202 array('integer', 'integer', 'integer'),
7203 array($active_id, $question_id, $pass)
7204 );
7205 if ($result->numRows() == 1) {
7206 $row = $ilDB->fetchAssoc($result);
7207 $res = $row["value1"];
7208 }
7209 }
7210 return $res;
7211 }
7212
7220 public function getQuestiontext($question_id)
7221 {
7222 global $ilDB;
7223
7224 $res = "";
7225 if ($question_id) {
7226 $result = $ilDB->queryF(
7227 "SELECT question_text FROM qpl_questions WHERE question_id = %s",
7228 array('integer'),
7229 array($question_id)
7230 );
7231 if ($result->numRows() == 1) {
7232 $row = $ilDB->fetchAssoc($result);
7233 $res = $row["question_text"];
7234 }
7235 }
7236 return $res;
7237 }
7238
7245 public function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7246 {
7247 global $ilDB;
7248
7249 $result_array = array();
7250
7251 if ($this->getAnonymity()) {
7252 if (is_numeric($user_id)) {
7253 $result = $ilDB->queryF(
7254 "SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7255 "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 " .
7256 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7257 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7258 "ORDER BY $order",
7259 array('text', 'text', 'text', 'integer', 'integer'),
7260 array("", $this->lng->txt("anonymous"), "", $this->getTestId(), $user_id)
7261 );
7262 } else {
7263 $result = $ilDB->queryF(
7264 "SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7265 "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 " .
7266 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7267 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7268 "ORDER BY $order",
7269 array('text', 'text', 'text', 'integer'),
7270 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7271 );
7272 }
7273 } else {
7274 if (is_numeric($user_id)) {
7275 $result = $ilDB->queryF(
7276 "SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7277 "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 " .
7278 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7279 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7280 "ORDER BY $order",
7281 array('integer', 'integer'),
7282 array($this->getTestId(), $user_id)
7283 );
7284 } else {
7285 $result = $ilDB->queryF(
7286 "SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7287 "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 " .
7288 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7289 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7290 "ORDER BY $order",
7291 array('integer'),
7292 array($this->getTestId())
7293 );
7294 }
7295 }
7296 $result_array = array();
7297 while ($row = $ilDB->fetchAssoc($result)) {
7298 $result_array[$row['usr_id']]= $row;
7299 }
7300 return $result_array;
7301 }
7302
7309 public function &getTestParticipants()
7310 {
7311 global $ilDB;
7312
7313 if ($this->getAnonymity()) {
7314 $query = "
7315 SELECT tst_active.active_id,
7316 tst_active.tries,
7317 tst_active.user_fi usr_id,
7318 %s login,
7319 %s lastname,
7320 %s firstname,
7321 tst_active.submitted test_finished,
7322 usr_data.matriculation,
7323 usr_data.active,
7324 tst_active.lastindex,
7325 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes
7326 FROM tst_active
7327 LEFT JOIN usr_data
7328 ON tst_active.user_fi = usr_data.usr_id
7329 WHERE tst_active.test_fi = %s
7330 ORDER BY usr_data.lastname
7331 ";
7332 $result = $ilDB->queryF(
7333 $query,
7334 array('text', 'text', 'text', 'integer'),
7335 array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7336 );
7337 } else {
7338 $query = "
7339 SELECT tst_active.active_id,
7340 tst_active.tries,
7341 tst_active.user_fi usr_id,
7342 usr_data.login,
7343 usr_data.lastname,
7344 usr_data.firstname,
7345 tst_active.submitted test_finished,
7346 usr_data.matriculation,
7347 usr_data.active,
7348 tst_active.lastindex,
7349 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes
7350 FROM tst_active
7351 LEFT JOIN usr_data
7352 ON tst_active.user_fi = usr_data.usr_id
7353 WHERE tst_active.test_fi = %s
7354 ORDER BY usr_data.lastname
7355 ";
7356 $result = $ilDB->queryF(
7357 $query,
7358 array('integer'),
7359 array($this->getTestId())
7360 );
7361 }
7362 $data = array();
7363 while ($row = $ilDB->fetchAssoc($result)) {
7364 $data[$row['active_id']] = $row;
7365 }
7366 foreach ($data as $index => $participant) {
7367 if (strlen(trim($participant["firstname"] . $participant["lastname"])) == 0) {
7368 $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7369 }
7370 }
7371 return $data;
7372 }
7373
7374 public function getTestParticipantsForManualScoring($filter = null)
7375 {
7376 global $ilDB;
7377
7378 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7380 if (count($scoring) == 0) {
7381 return array();
7382 }
7383
7384 $participants =&$this->getTestParticipants();
7385 $filtered_participants = array();
7386 foreach ($participants as $active_id => $participant) {
7387 $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7388
7389 $queryString = "
7390 SELECT tst_test_result.manual
7391
7392 FROM tst_test_result
7393
7394 INNER JOIN qpl_questions
7395 ON tst_test_result.question_fi = qpl_questions.question_id
7396
7397 WHERE tst_test_result.active_fi = %s
7398 AND $qstType_IN_manScoreableQstTypes
7399 ";
7400
7401 $result = $ilDB->queryF(
7402 $queryString,
7403 array("integer"),
7404 array($active_id)
7405 );
7406
7407 $count = $result->numRows();
7408
7409 if ($count > 0) {
7410 switch ($filter) {
7411 case 1: // only active users
7412 if ($participant->active) {
7413 $filtered_participants[$active_id] = $participant;
7414 }
7415 break;
7416 case 2: // only inactive users
7417 if (!$participant->active) {
7418 $filtered_participants[$active_id] = $participant;
7419 }
7420 break;
7421 case 3: // all users
7422 $filtered_participants[$active_id] = $participant;
7423 break;
7424 case 4:
7425 // already scored participants
7426 //$found = 0;
7427 //while ($row = $ilDB->fetchAssoc($result))
7428 //{
7429 // if ($row["manual"]) $found++;
7430 //}
7431 //if ($found == $count)
7432 //{
7433 //$filtered_participants[$active_id] = $participant;
7434 //}
7435 //else
7436 //{
7437 $assessmentSetting = new ilSetting("assessment");
7438 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7439 if ($manscoring_done) {
7440 $filtered_participants[$active_id] = $participant;
7441 }
7442 //}
7443 break;
7444 case 5:
7445 // unscored participants
7446 //$found = 0;
7447 //while ($row = $ilDB->fetchAssoc($result))
7448 //{
7449 // if ($row["manual"]) $found++;
7450 //}
7451 //if ($found == 0)
7452 //{
7453 $assessmentSetting = new ilSetting("assessment");
7454 $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7455 if (!$manscoring_done) {
7456 $filtered_participants[$active_id] = $participant;
7457 }
7458 //}
7459 break;
7460 case 6:
7461 // partially scored participants
7462 $found = 0;
7463 while ($row = $ilDB->fetchAssoc($result)) {
7464 if ($row["manual"]) {
7465 $found++;
7466 }
7467 }
7468 if (($found > 0) && ($found < $count)) {
7469 $filtered_participants[$active_id] = $participant;
7470 }
7471 break;
7472 default:
7473 $filtered_participants[$active_id] = $participant;
7474 break;
7475 }
7476 }
7477 }
7478 return $filtered_participants;
7479 }
7480
7488 public function &getUserData($ids)
7489 {
7490 global $ilDB;
7491
7492 if (!is_array($ids) || count($ids) ==0) {
7493 return array();
7494 }
7495
7496 if ($this->getAnonymity()) {
7497 $result = $ilDB->queryF(
7498 "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",
7499 array('text', 'text', 'text'),
7500 array("", $this->lng->txt("anonymous"), "")
7501 );
7502 } else {
7503 $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");
7504 }
7505
7506 $result_array = array();
7507 while ($row = $ilDB->fetchAssoc($result)) {
7508 $result_array[$row["usr_id"]]= $row;
7509 }
7510 return $result_array;
7511 }
7512
7513 public function &getGroupData($ids)
7514 {
7515 if (!is_array($ids) || count($ids) ==0) {
7516 return array();
7517 }
7518 $result = array();
7519 foreach ($ids as $ref_id) {
7521 $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7522 }
7523 return $result;
7524 }
7525
7526 public function &getRoleData($ids)
7527 {
7528 if (!is_array($ids) || count($ids) ==0) {
7529 return array();
7530 }
7531 $result = array();
7532 foreach ($ids as $obj_id) {
7533 $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7534 }
7535 return $result;
7536 }
7537
7538
7545 public function inviteGroup($group_id)
7546 {
7547 include_once "./Modules/Group/classes/class.ilObjGroup.php";
7548 $group = new ilObjGroup($group_id);
7549 $members = $group->getGroupMemberIds();
7550 include_once './Services/User/classes/class.ilObjUser.php';
7551 foreach ($members as $user_id) {
7552 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7553 }
7554 }
7555
7562 public function inviteRole($role_id)
7563 {
7564 global $rbacreview;
7565 $members = $rbacreview->assignedUsers($role_id);
7566 include_once './Services/User/classes/class.ilObjUser.php';
7567 foreach ($members as $user_id) {
7568 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7569 }
7570 }
7571
7572
7573
7580 public function disinviteUser($user_id)
7581 {
7582 global $ilDB;
7583
7584 $affectedRows = $ilDB->manipulateF(
7585 "DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7586 array('integer', 'integer'),
7587 array($this->getTestId(), $user_id)
7588 );
7589 }
7590
7597 public function inviteUser($user_id, $client_ip="")
7598 {
7599 global $ilDB;
7600
7601 $affectedRows = $ilDB->manipulateF(
7602 "DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7603 array('integer', 'integer'),
7604 array($this->getTestId(), $user_id)
7605 );
7606 $affectedRows = $ilDB->manipulateF(
7607 "INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7608 array('integer', 'integer', 'text', 'integer'),
7609 array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : null, time())
7610 );
7611 }
7612
7613
7614 public function setClientIP($user_id, $client_ip)
7615 {
7616 global $ilDB;
7617
7618 $affectedRows = $ilDB->manipulateF(
7619 "UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7620 array('text', 'integer', 'integer', 'integer'),
7621 array((strlen($client_ip)) ? $client_ip : null, time(), $this->getTestId(), $user_id)
7622 );
7623 }
7624
7630 public static function _getSolvedQuestions($active_id, $question_fi = null)
7631 {
7632 global $ilDB;
7633 if (is_numeric($question_fi)) {
7634 $result = $ilDB->queryF(
7635 "SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7636 array('integer', 'integer'),
7637 array($active_id, $question_fi)
7638 );
7639 } else {
7640 $result = $ilDB->queryF(
7641 "SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7642 array('integer'),
7643 array($active_id)
7644 );
7645 }
7646 $result_array = array();
7647 while ($row = $ilDB->fetchAssoc($result)) {
7648 $result_array[$row["question_fi"]]= $row;
7649 }
7650 return $result_array;
7651 }
7652
7653
7657 public function setQuestionSetSolved($value, $question_id, $user_id)
7658 {
7659 global $ilDB;
7660
7661 $active_id = $this->getActiveIdOfUser($user_id);
7662 $affectedRows = $ilDB->manipulateF(
7663 "DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
7664 array('integer', 'integer'),
7665 array($active_id, $question_id)
7666 );
7667 $affectedRows = $ilDB->manipulateF(
7668 "INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
7669 array('integer', 'integer', 'integer'),
7670 array($value, $question_id, $active_id)
7671 );
7672 }
7673
7677 public function isTestFinished($active_id)
7678 {
7679 global $ilDB;
7680
7681 $result = $ilDB->queryF(
7682 "SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
7683 array('integer', 'integer'),
7684 array($active_id, 1)
7685 );
7686 return $result->numRows() == 1;
7687 }
7688
7692 public function isActiveTestSubmitted($user_id = null)
7693 {
7694 global $ilUser;
7695 global $ilDB;
7696
7697 if (!is_numeric($user_id)) {
7698 $user_id = $ilUser->getId();
7699 }
7700
7701 $result = $ilDB->queryF(
7702 "SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
7703 array('integer', 'integer', 'integer'),
7704 array($this->getTestId(), $user_id, 1)
7705 );
7706 return $result->numRows() == 1;
7707 }
7708
7712 public function hasNrOfTriesRestriction()
7713 {
7714 return $this->getNrOfTries() != 0;
7715 }
7716
7717
7723 public function isNrOfTriesReached($tries)
7724 {
7725 return $tries >= (int) $this->getNrOfTries();
7726 }
7727
7728
7737 public function getAllTestResults($participants, $prepareForCSV = true)
7738 {
7739 $results = array();
7740 $row = array(
7741 "user_id" => $this->lng->txt("user_id"),
7742 "matriculation" => $this->lng->txt("matriculation"),
7743 "lastname" => $this->lng->txt("lastname"),
7744 "firstname" => $this->lng->txt("firstname"),
7745 "login" =>$this->lng->txt("login"),
7746 "reached_points" => $this->lng->txt("tst_reached_points"),
7747 "max_points" => $this->lng->txt("tst_maximum_points"),
7748 "percent_value" => $this->lng->txt("tst_percent_solved"),
7749 "mark" => $this->lng->txt("tst_mark"),
7750 "ects" => $this->lng->txt("ects_grade")
7751 );
7752 $results[] = $row;
7753 if (count($participants)) {
7754 if ($this->getECTSOutput()) {
7755 $passed_array =&$this->getTotalPointsPassedArray();
7756 }
7757 foreach ($participants as $active_id => $user_rec) {
7758 $mark = $ects_mark = '';
7759 $row = array();
7760 $reached_points = 0;
7761 $max_points = 0;
7762 foreach ($this->questions as $value) {
7763 $question =&ilObjTest::_instanciateQuestion($value);
7764 if (is_object($question)) {
7765 $max_points += $question->getMaximumPoints();
7766 $reached_points += $question->getReachedPoints($active_id);
7767 }
7768 }
7769 if ($max_points > 0) {
7770 $percentvalue = $reached_points / $max_points;
7771 if ($percentvalue < 0) {
7772 $percentvalue = 0.0;
7773 }
7774 } else {
7775 $percentvalue = 0;
7776 }
7777 $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
7778 $passed = "";
7779 if ($mark_obj) {
7780 $mark = $mark_obj->getOfficialName();
7781 if ($this->getECTSOutput()) {
7782 $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
7783 }
7784 }
7785 if ($this->getAnonymity()) {
7786 $user_rec['firstname'] = "";
7787 $user_rec['lastname'] = $this->lng->txt("anonymous");
7788 }
7789 $row = array(
7790 "user_id"=>$user_rec['usr_id'],
7791 "matriculation" => $user_rec['matriculation'],
7792 "lastname" => $user_rec['lastname'],
7793 "firstname" => $user_rec['firstname'],
7794 "login"=>$user_rec['login'],
7795 "reached_points" => $reached_points,
7796 "max_points" => $max_points,
7797 "percent_value" => $percentvalue,
7798 "mark" => $mark,
7799 "ects" => $ects_mark
7800 );
7801 $results[] = $prepareForCSV ? $this->processCSVRow($row, true) : $row;
7802 }
7803 }
7804 return $results;
7805 }
7806
7817 public function &processCSVRow($row, $quoteAll = false, $separator = ";")
7818 {
7819 $resultarray = array();
7820 foreach ($row as $rowindex => $entry) {
7821 $surround = false;
7822 if ($quoteAll) {
7823 $surround = true;
7824 }
7825 if (strpos($entry, "\"") !== false) {
7826 $entry = str_replace("\"", "\"\"", $entry);
7827 $surround = true;
7828 }
7829 if (strpos($entry, $separator) !== false) {
7830 $surround = true;
7831 }
7832 // replace all CR LF with LF (for Excel for Windows compatibility
7833 $entry = str_replace(chr(13) . chr(10), chr(10), $entry);
7834
7835 if ($surround) {
7836 $entry = "\"" . $entry . "\"";
7837 }
7838
7839 $resultarray[$rowindex] = $entry;
7840 }
7841 return $resultarray;
7842 }
7843
7852 public static function _getPass($active_id)
7853 {
7854 global $ilDB;
7855 $result = $ilDB->queryF(
7856 "SELECT tries FROM tst_active WHERE active_id = %s",
7857 array('integer'),
7858 array($active_id)
7859 );
7860 if ($result->numRows()) {
7861 $row = $ilDB->fetchAssoc($result);
7862 return $row["tries"];
7863 } else {
7864 return 0;
7865 }
7866 }
7867
7877 public static function _getMaxPass($active_id)
7878 {
7879 global $ilDB;
7880 $result = $ilDB->queryF(
7881 "SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
7882 array('integer'),
7883 array($active_id)
7884 );
7885 if ($result->numRows()) {
7886 $row = $ilDB->fetchAssoc($result);
7887 $max = $row["maxpass"];
7888 } else {
7889 $max = null;
7890 }
7891 return $max;
7892 }
7893
7899 public static function _getBestPass($active_id)
7900 {
7901 global $ilDB;
7902
7903 $result = $ilDB->queryF(
7904 "SELECT * FROM tst_pass_result WHERE active_fi = %s",
7905 array('integer'),
7906 array($active_id)
7907 );
7908 if ($result->numRows()) {
7909 $bestrow = null;
7910 $bestfactor = 0;
7911 while ($row = $ilDB->fetchAssoc($result)) {
7912 if ($row["maxpoints"] > 0) {
7913 $factor = $row["points"] / $row["maxpoints"];
7914 } else {
7915 $factor = 0;
7916 }
7917
7918 if ($factor > $bestfactor) {
7919 $bestrow = $row;
7920 $bestfactor = $factor;
7921 }
7922 }
7923 if (is_array($bestrow)) {
7924 return $bestrow["pass"];
7925 } else {
7926 return 0;
7927 }
7928 } else {
7929 return 0;
7930 }
7931 }
7932
7941 public static function _getResultPass($active_id)
7942 {
7943 $counted_pass = null;
7944 if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS) {
7945 $counted_pass = ilObjTest::_getBestPass($active_id);
7946 } else {
7947 $counted_pass = ilObjTest::_getMaxPass($active_id);
7948 }
7949 return $counted_pass;
7950 }
7951
7961 public function getAnsweredQuestionCount($active_id, $pass = null)
7962 {
7963 if ($this->isDynamicTest()) {
7964 global $tree, $ilDB, $lng, $ilPluginAdmin;
7965
7966 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
7967 $testSessionFactory = new ilTestSessionFactory($this);
7968 $testSession = $testSessionFactory->getSession($active_id);
7969
7970 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
7971 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
7972 $testSequence = $testSequenceFactory->getSequenceByTestSession($testSession);
7973
7974 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
7975 $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
7976 $dynamicQuestionSetConfig->loadFromDb();
7977
7978 $testSequence->loadFromDb($dynamicQuestionSetConfig);
7979 $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
7980
7981 return $testSequence->getTrackedQuestionCount();
7982 }
7983
7984 if ($this->isRandomTest()) {
7985 $this->loadQuestions($active_id, $pass);
7986 }
7987 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7988 $workedthrough = 0;
7989 foreach ($this->questions as $value) {
7990 if (assQuestion::_isWorkedThrough($active_id, $value, $pass)) {
7991 $workedthrough += 1;
7992 }
7993 }
7994 return $workedthrough;
7995 }
7996
8003 public static function lookupPassResultsUpdateTimestamp($active_id, $pass)
8004 {
8005 global $ilDB;
8006
8007 if (is_null($pass)) {
8008 $pass = 0;
8009 }
8010
8011 $query = "
8012 SELECT tst_pass_result.tstamp pass_res_tstamp,
8013 tst_test_result.tstamp quest_res_tstamp
8014
8015 FROM tst_pass_result
8016
8017 LEFT JOIN tst_test_result
8018 ON tst_test_result.active_fi = tst_pass_result.active_fi
8019 AND tst_test_result.pass = tst_pass_result.pass
8020
8021 WHERE tst_pass_result.active_fi = %s
8022 AND tst_pass_result.pass = %s
8023
8024 ORDER BY tst_test_result.tstamp DESC
8025 ";
8026
8027 $result = $ilDB->queryF(
8028 $query,
8029 array('integer', 'integer'),
8030 array($active_id, $pass)
8031 );
8032
8033 while ($row = $ilDB->fetchAssoc($result)) {
8034 if ($row['qres_tstamp']) {
8035 return $row['quest_res_tstamp'];
8036 }
8037
8038 return $row['pass_res_tstamp'];
8039 }
8040
8041 return 0;
8042 }
8043
8052 public function isExecutable($testSession, $user_id, $allowPassIncrease = false)
8053 {
8054 $result = array(
8055 "executable" => true,
8056 "errormessage" => ""
8057 );
8058 if (!$this->startingTimeReached()) {
8059 $result["executable"] = false;
8060 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getStartingTime(), IL_CAL_UNIX)));
8061 return $result;
8062 }
8063 if ($this->endingTimeReached()) {
8064 $result["executable"] = false;
8065 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getEndingTime(), IL_CAL_UNIX)));
8066 return $result;
8067 }
8068
8069 $active_id = $this->getActiveIdOfUser($user_id);
8070
8071 if ($this->getEnableProcessingTime()) {
8072 if ($active_id > 0) {
8073 $starting_time = $this->getStartingTimeOfUser($active_id);
8074 if ($starting_time !== false) {
8075 if ($this->isMaxProcessingTimeReached($starting_time, $active_id)) {
8076 if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > (self::_getPass($active_id)+1)))) {
8077 // a test pass was quitted because the maximum processing time was reached, but the time
8078 // will be resetted for future passes, so if there are more passes allowed, the participant may
8079 // start the test again.
8080 // This code block is only called when $allowPassIncrease is TRUE which only happens when
8081 // the test info page is opened. Otherwise this will lead to unexpected results!
8082 $testSession->increasePass();
8083 $testSession->setLastSequence(0);
8084 $testSession->saveToDb();
8085 } else {
8086 $result["executable"] = false;
8087 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8088 }
8089 return $result;
8090 }
8091 }
8092 }
8093 }
8094 require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8095 $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8096 $testPassesSelector->setActiveId($active_id);
8097 $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8098
8099 if ($this->hasNrOfTriesRestriction() && ($active_id > 0)) {
8100 $closedPasses = $testPassesSelector->getClosedPasses();
8101
8102 if (count($closedPasses) >= $this->getNrOfTries()) {
8103 $result["executable"] = false;
8104 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8105 return $result;
8106 }
8107 }
8108 if ($this->isPassWaitingEnabled() && $testPassesSelector->getLastFinishedPass() !== null) {
8109 $lastPass = $testPassesSelector->getLastFinishedPassTimestamp();
8110 if ($lastPass && strlen($this->getPassWaiting())) {
8111 $pass_waiting_string = $this->getPassWaiting();
8112 $time_values = explode(":", $pass_waiting_string);
8113 $next_pass_allowed = strtotime('+ ' . $time_values[0] . ' Months + ' . $time_values[1] . ' Days + ' . $time_values[2] . ' Hours' . $time_values[3] . ' Minutes', $lastPass);
8114
8115 if (time() < $next_pass_allowed) {
8116 $date = ilDatePresentation::formatDate(new ilDateTime($next_pass_allowed, IL_CAL_UNIX));
8117
8118 $result["executable"] = false;
8119 $result["errormessage"] = sprintf($this->lng->txt('wait_for_next_pass_hint_msg'), $date);
8120 return $result;
8121 }
8122 }
8123 }
8124 return $result;
8125 }
8126
8134 public function canViewResults()
8135 {
8136 // this logic was implemented before, it got stabled only for now
8137 // this method is not as exact as it's required, it's to be replaced in the long time
8138
8139 switch ($this->getScoreReporting()) {
8141 case self::SCORE_REPORTING_FINISHED: // this isn't excact enough
8142
8143 return true;
8144
8146
8147 if (!$this->getReportingDate()) {
8148 return false;
8149 }
8150
8151 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches)) {
8152 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8153 $now = time();
8154 if ($now < $epoch_time) {
8155 return false;
8156 }
8157 }
8158
8159 return true;
8160 }
8161
8162 return false;
8163 }
8164
8166 {
8167 $active_id = $testSession->getActiveId();
8168 if ($active_id > 0) {
8169 $starting_time = $this->getStartingTimeOfUser($active_id);
8170 }
8171 $notimeleft = false;
8172 if ($starting_time !== false) {
8173 if ($this->isMaxProcessingTimeReached($starting_time, $active_id)) {
8174 $notimeleft = true;
8175 }
8176 }
8177 $result = true;
8178 if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST)) {
8179 $result = false;
8180 }
8181 if (($this->endingTimeReached()) || $notimeleft) {
8182 $result = true;
8183 }
8184 $result = $result & $this->canViewResults();
8185 return $result;
8186 }
8187
8195 public function getStartingTimeOfUser($active_id, $pass = null)
8196 {
8197 global $ilDB;
8198
8199 if ($active_id < 1) {
8200 return false;
8201 }
8202 if ($pass === null) {
8203 $pass = ($this->getResetProcessingTime()) ? self::_getPass($active_id) : 0;
8204 }
8205 $result = $ilDB->queryF(
8206 "SELECT tst_times.started FROM tst_times WHERE tst_times.active_fi = %s AND tst_times.pass = %s ORDER BY tst_times.started",
8207 array('integer', 'integer'),
8208 array($active_id, $pass)
8209 );
8210 if ($result->numRows()) {
8211 $row = $ilDB->fetchAssoc($result);
8212 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches)) {
8213 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8214 } else {
8215 return time();
8216 }
8217 } else {
8218 return time();
8219 }
8220 }
8221
8230 public function isMaxProcessingTimeReached($starting_time, $active_id)
8231 {
8232 if ($this->getEnableProcessingTime()) {
8233 $processing_time = $this->getProcessingTimeInSeconds($active_id);
8234 $now = time();
8235 if ($now > ($starting_time + $processing_time)) {
8236 return true;
8237 } else {
8238 return false;
8239 }
8240 } else {
8241 return false;
8242 }
8243 }
8244
8245 public function &getTestQuestions()
8246 {
8247 global $ilDB;
8248
8249 $query = "
8250 SELECT questions.*,
8251 questtypes.type_tag,
8252 tstquest.sequence,
8253 tstquest.obligatory,
8254 origquest.obj_fi orig_obj_fi
8255
8256 FROM qpl_questions questions
8257
8258 INNER JOIN qpl_qst_type questtypes
8259 ON questtypes.question_type_id = questions.question_type_fi
8260
8261 INNER JOIN tst_test_question tstquest
8262 ON tstquest.question_fi = questions.question_id
8263
8264 LEFT JOIN qpl_questions origquest
8265 ON origquest.question_id = questions.original_id
8266
8267 WHERE tstquest.test_fi = %s
8268
8269 ORDER BY tstquest.sequence
8270 ";
8271
8272 $query_result = $ilDB->queryF(
8273 $query,
8274 array('integer'),
8275 array($this->getTestId())
8276 );
8277
8278 $questions = array();
8279
8280 while ($row = $ilDB->fetchAssoc($query_result)) {
8281 $question = $row;
8282
8283 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8284
8285 $questions[] = $question;
8286 }
8287
8288 return $questions;
8289 }
8290
8291 public function checkQuestionParent($questionId)
8292 {
8293 global $DIC; /* @var ILIAS\DI\Container $DIC */
8294
8295 $row = $DIC->database()->fetchAssoc($DIC->database()->queryF(
8296 "SELECT COUNT(question_id) cnt FROM qpl_questions WHERE question_id = %s AND obj_fi = %s",
8297 array('integer', 'integer'),
8298 array($questionId, $this->getId())
8299 ));
8300
8301 return (bool) $row['cnt'];
8302 }
8303
8307 public function getPotentialRandomTestQuestions()
8308 {
8312 global $ilDB;
8313
8314 $query = "
8315 SELECT questions.*,
8316 questtypes.type_tag,
8317 origquest.obj_fi orig_obj_fi
8318
8319 FROM qpl_questions questions
8320
8321 INNER JOIN qpl_qst_type questtypes
8322 ON questtypes.question_type_id = questions.question_type_fi
8323
8324 INNER JOIN tst_rnd_cpy tstquest
8325 ON tstquest.qst_fi = questions.question_id
8326
8327 LEFT JOIN qpl_questions origquest
8328 ON origquest.question_id = questions.original_id
8329
8330 WHERE tstquest.tst_fi = %s
8331 ";
8332
8333 $query_result = $ilDB->queryF(
8334 $query,
8335 array('integer'),
8336 array($this->getTestId())
8337 );
8338
8339 $questions = array();
8340
8341 while ($row = $ilDB->fetchAssoc($query_result)) {
8342 $question = $row;
8343
8344 $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8345
8346 $questions[] = $question;
8347 }
8348
8349 return $questions;
8350 }
8351
8358 public function getShuffleQuestions()
8359 {
8360 return ($this->shuffle_questions) ? 1 : 0;
8361 }
8362
8369 public function setShuffleQuestions($a_shuffle)
8370 {
8371 $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8372 }
8373
8387 {
8388 return ($this->show_summary) ? $this->show_summary : 0;
8389 }
8390
8403 public function setListOfQuestionsSettings($a_value = 0)
8404 {
8405 $this->show_summary = $a_value;
8406 }
8407
8414 public function getListOfQuestions()
8415 {
8416 if (($this->show_summary & 1) > 0) {
8417 return true;
8418 } else {
8419 return false;
8420 }
8421 }
8422
8429 public function setListOfQuestions($a_value = true)
8430 {
8431 if ($a_value) {
8432 $this->show_summary = 1;
8433 } else {
8434 $this->show_summary = 0;
8435 }
8436 }
8437
8444 public function getListOfQuestionsStart()
8445 {
8446 if (($this->show_summary & 2) > 0) {
8447 return true;
8448 } else {
8449 return false;
8450 }
8451 }
8452
8459 public function setListOfQuestionsStart($a_value = true)
8460 {
8461 if ($a_value && $this->getListOfQuestions()) {
8462 $this->show_summary = $this->show_summary | 2;
8463 }
8464 if (!$a_value && $this->getListOfQuestions()) {
8465 if ($this->getListOfQuestionsStart()) {
8466 $this->show_summary = $this->show_summary ^ 2;
8467 }
8468 }
8469 }
8470
8477 public function getListOfQuestionsEnd()
8478 {
8479 if (($this->show_summary & 4) > 0) {
8480 return true;
8481 } else {
8482 return false;
8483 }
8484 }
8485
8492 public function setListOfQuestionsEnd($a_value = true)
8493 {
8494 if ($a_value && $this->getListOfQuestions()) {
8495 $this->show_summary = $this->show_summary | 4;
8496 }
8497 if (!$a_value && $this->getListOfQuestions()) {
8498 if ($this->getListOfQuestionsEnd()) {
8499 $this->show_summary = $this->show_summary ^ 4;
8500 }
8501 }
8502 }
8503
8511 {
8512 if (($this->show_summary & 8) > 0) {
8513 return true;
8514 } else {
8515 return false;
8516 }
8517 }
8518
8525 public function setListOfQuestionsDescription($a_value = true)
8526 {
8527 if ($a_value && $this->getListOfQuestions()) {
8528 $this->show_summary = $this->show_summary | 8;
8529 }
8530 if (!$a_value && $this->getListOfQuestions()) {
8531 if ($this->getListOfQuestionsDescription()) {
8532 $this->show_summary = $this->show_summary ^ 8;
8533 }
8534 }
8535 }
8536
8543 public function getResultsPresentation()
8544 {
8545 return ($this->results_presentation) ? $this->results_presentation : 0;
8546 }
8547
8554 public function getShowPassDetails()
8555 {
8556 if (($this->results_presentation & 1) > 0) {
8557 return true;
8558 } else {
8559 return false;
8560 }
8561 }
8562
8569 public function getShowSolutionDetails()
8570 {
8571 if (($this->results_presentation & 2) > 0) {
8572 return true;
8573 } else {
8574 return false;
8575 }
8576 }
8577
8585 {
8586 if (($this->results_presentation & 4) > 0) {
8587 return true;
8588 } else {
8589 return false;
8590 }
8591 }
8592
8599 public function getShowSolutionFeedback()
8600 {
8601 if (($this->results_presentation & 8) > 0) {
8602 return true;
8603 } else {
8604 return false;
8605 }
8606 }
8607
8615 {
8616 if (($this->results_presentation & 16) > 0) {
8617 return true;
8618 } else {
8619 return false;
8620 }
8621 }
8622
8630 {
8631 if (($this->results_presentation & 32) > 0) {
8632 return true;
8633 } else {
8634 return false;
8635 }
8636 }
8637
8643 {
8644 if (($this->results_presentation & 64) > 0) {
8645 return true;
8646 } else {
8647 return false;
8648 }
8649 }
8650
8656 {
8657 if (($this->results_presentation & 128) > 0) {
8658 return true;
8659 } else {
8660 return false;
8661 }
8662 }
8663
8670 public function setResultsPresentation($a_results_presentation = 3)
8671 {
8672 $this->results_presentation = $a_results_presentation;
8673 }
8674
8683 public function setShowPassDetails($a_details = 1)
8684 {
8685 if ($a_details) {
8686 $this->results_presentation = $this->results_presentation | 1;
8687 } else {
8688 if ($this->getShowPassDetails()) {
8689 $this->results_presentation = $this->results_presentation ^ 1;
8690 }
8691 }
8692 }
8693
8700 public function setShowSolutionDetails($a_details = 1)
8701 {
8702 if ($a_details) {
8703 $this->results_presentation = $this->results_presentation | 2;
8704 } else {
8705 if ($this->getShowSolutionDetails()) {
8706 $this->results_presentation = $this->results_presentation ^ 2;
8707 }
8708 }
8709 }
8710
8717 public function canShowSolutionPrintview($user_id = null)
8718 {
8719 return $this->getShowSolutionPrintview();
8720 }
8721
8728 public function setShowSolutionPrintview($a_printview = 1)
8729 {
8730 if ($a_printview) {
8731 $this->results_presentation = $this->results_presentation | 4;
8732 } else {
8733 if ($this->getShowSolutionPrintview()) {
8734 $this->results_presentation = $this->results_presentation ^ 4;
8735 }
8736 }
8737 }
8738
8745 public function setShowSolutionFeedback($a_feedback = true)
8746 {
8747 if ($a_feedback) {
8748 $this->results_presentation = $this->results_presentation | 8;
8749 } else {
8750 if ($this->getShowSolutionFeedback()) {
8751 $this->results_presentation = $this->results_presentation ^ 8;
8752 }
8753 }
8754 }
8755
8762 public function setShowSolutionAnswersOnly($a_full = true)
8763 {
8764 if ($a_full) {
8765 $this->results_presentation = $this->results_presentation | 16;
8766 } else {
8767 if ($this->getShowSolutionAnswersOnly()) {
8768 $this->results_presentation = $this->results_presentation ^ 16;
8769 }
8770 }
8771 }
8772
8779 public function setShowSolutionSignature($a_signature = false)
8780 {
8781 if ($a_signature) {
8782 $this->results_presentation = $this->results_presentation | 32;
8783 } else {
8784 if ($this->getShowSolutionSignature()) {
8785 $this->results_presentation = $this->results_presentation ^ 32;
8786 }
8787 }
8788 }
8789
8796 public function setShowSolutionSuggested($a_solution = false)
8797 {
8798 if ($a_solution) {
8799 $this->results_presentation = $this->results_presentation | 64;
8800 } else {
8801 if ($this->getShowSolutionSuggested()) {
8802 $this->results_presentation = $this->results_presentation ^ 64;
8803 }
8804 }
8805 }
8806
8812 public function setShowSolutionListComparison($a_comparison = false)
8813 {
8814 if ($a_comparison) {
8815 $this->results_presentation = $this->results_presentation | 128;
8816 } else {
8817 if ($this->getShowSolutionListComparison()) {
8818 $this->results_presentation = $this->results_presentation ^ 128;
8819 }
8820 }
8821 }
8822
8826 public static function _getUserIdFromActiveId($active_id)
8827 {
8828 global $ilDB;
8829 $result = $ilDB->queryF(
8830 "SELECT user_fi FROM tst_active WHERE active_id = %s",
8831 array('integer'),
8832 array($active_id)
8833 );
8834 if ($result->numRows()) {
8835 $row = $ilDB->fetchAssoc($result);
8836 return $row["user_fi"];
8837 } else {
8838 return -1;
8839 }
8840 }
8841
8845 public function isLimitUsersEnabled()
8846 {
8848 }
8849
8854 {
8855 $this->limitUsersEnabled = $limitUsersEnabled;
8856 }
8857
8858 public function getAllowedUsers()
8859 {
8860 return ($this->allowedUsers) ? $this->allowedUsers : 0;
8861 }
8862
8863 public function setAllowedUsers($a_allowed_users)
8864 {
8865 $this->allowedUsers = $a_allowed_users;
8866 }
8867
8868 public function getAllowedUsersTimeGap()
8869 {
8870 return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
8871 }
8872
8873 public function setAllowedUsersTimeGap($a_allowed_users_time_gap)
8874 {
8875 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
8876 }
8877
8879 {
8880 global $ilDB;
8881
8882 $nr_of_users = $this->getAllowedUsers();
8883 $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
8884 if (($nr_of_users > 0) && ($time_gap > 0)) {
8885 $now = time();
8886 $time_border = $now - $time_gap;
8887 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
8888 $query = "
8889 SELECT DISTINCT tst_times.active_fi
8890 FROM tst_times
8891 INNER JOIN tst_active
8892 ON tst_times.active_fi = tst_active.active_id
8893 AND (
8894 tst_times.pass > tst_active.last_finished_pass OR tst_active.last_finished_pass IS NULL
8895 )
8896 WHERE tst_times.tstamp > %s
8897 AND tst_active.test_fi = %s
8898 ";
8899 $result = $ilDB->queryF($query, array('integer', 'integer'), array($time_border, $this->getTestId()));
8900 if ($result->numRows() >= $nr_of_users) {
8901 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
8903 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
8904 }
8905 return false;
8906 } else {
8907 return true;
8908 }
8909 }
8910 return true;
8911 }
8912
8913 public function _getLastAccess($active_id)
8914 {
8915 global $ilDB;
8916
8917 $result = $ilDB->queryF(
8918 "SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
8919 array('integer'),
8920 array($active_id)
8921 );
8922 if ($result->numRows()) {
8923 $row = $ilDB->fetchAssoc($result);
8924 return $row["finished"];
8925 }
8926 return "";
8927 }
8928
8929 public static function lookupLastTestPassAccess($activeId, $passIndex)
8930 {
8931 global $DIC; /* @var \ILIAS\DI\Container $DIC */
8932
8933 $query = "
8934 SELECT MAX(tst_times.tstamp) as last_pass_access
8935 FROM tst_times
8936 WHERE active_fi = %s
8937 AND pass = %s
8938 ";
8939
8940 $res = $DIC->database()->queryF(
8941 $query,
8942 array('integer', 'integer'),
8943 array($activeId, $passIndex)
8944 );
8945
8946 while ($row = $DIC->database()->fetchAssoc($res)) {
8947 return $row['last_pass_access'];
8948 }
8949
8950 return null;
8951 }
8952
8960 public function isHTML($a_text)
8961 {
8962 if (preg_match("/<[^>]*?>/", $a_text)) {
8963 return true;
8964 } else {
8965 return false;
8966 }
8967 }
8968
8976 public function QTIMaterialToString($a_material)
8977 {
8978 $result = "";
8979 for ($i = 0; $i < $a_material->getMaterialCount(); $i++) {
8980 $material = $a_material->getMaterial($i);
8981 if (strcmp($material["type"], "mattext") == 0) {
8982 $result .= $material["material"]->getContent();
8983 }
8984 if (strcmp($material["type"], "matimage") == 0) {
8985 $matimage = $material["material"];
8986 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
8987 // import an mediaobject which was inserted using tiny mce
8988 if (!is_array($_SESSION["import_mob_xhtml"])) {
8989 $_SESSION["import_mob_xhtml"] = array();
8990 }
8991 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
8992 }
8993 }
8994 }
8995 global $ilLog;
8996 $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
8997 return $result;
8998 }
8999
9008 public function addQTIMaterial(&$a_xml_writer, $a_material)
9009 {
9010 include_once "./Services/RTE/classes/class.ilRTE.php";
9011 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9012
9013 $a_xml_writer->xmlStartTag("material");
9014 $attrs = array(
9015 "texttype" => "text/plain"
9016 );
9017 if ($this->isHTML($a_material)) {
9018 $attrs["texttype"] = "text/xhtml";
9019 }
9020 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9021
9022 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9023 foreach ($mobs as $mob) {
9024 $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9025 if (strpos($a_material, "mm_$mob") !== false) {
9026 if (ilObjMediaObject::_exists($mob)) {
9027 $mob_obj = new ilObjMediaObject($mob);
9028 $imgattrs = array(
9029 "label" => $moblabel,
9030 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9031 );
9032 }
9033 $a_xml_writer->xmlElement("matimage", $imgattrs, null);
9034 }
9035 }
9036 $a_xml_writer->xmlEndTag("material");
9037 }
9038
9045 public function prepareTextareaOutput($txt_output, $prepare_for_latex_output = false, $omitNl2BrWhenTextArea = false)
9046 {
9047 include_once "./Services/Utilities/classes/class.ilUtil.php";
9048 return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output, $omitNl2BrWhenTextArea);
9049 }
9050
9057 public function saveCertificateVisibility($a_value)
9058 {
9059 global $ilDB;
9060
9061 $affectedRows = $ilDB->manipulateF(
9062 "UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9063 array('text', 'integer', 'integer'),
9064 array($a_value, time(), $this->getTestId())
9065 );
9066 }
9067
9075 {
9076 return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9077 }
9078
9085 public function setCertificateVisibility($a_value)
9086 {
9087 $this->certificate_visibility = $a_value;
9088 }
9089
9096 public function getAnonymity()
9097 {
9098 return ($this->anonymity) ? 1 : 0;
9099 }
9100
9107 public function setAnonymity($a_value = 0)
9108 {
9109 switch ($a_value) {
9110 case 1:
9111 $this->anonymity = 1;
9112 break;
9113 default:
9114 $this->anonymity = 0;
9115 break;
9116 }
9117 }
9118
9125 public function getShowCancel()
9126 {
9127 return ($this->show_cancel) ? 1 : 0;
9128 }
9129
9136 public function setShowCancel($a_value = 1)
9137 {
9138 switch ($a_value) {
9139 case 1:
9140 $this->show_cancel = 1;
9141 break;
9142 default:
9143 $this->show_cancel = 0;
9144 break;
9145 }
9146 }
9147
9154 public function getShowMarker()
9155 {
9156 return ($this->show_marker) ? 1 : 0;
9157 }
9158
9165 public function setShowMarker($a_value = 1)
9166 {
9167 switch ($a_value) {
9168 case 1:
9169 $this->show_marker = 1;
9170 break;
9171 default:
9172 $this->show_marker = 0;
9173 break;
9174 }
9175 }
9176
9183 public function getFixedParticipants()
9184 {
9185 return ($this->fixed_participants) ? 1 : 0;
9186 }
9187
9194 public function setFixedParticipants($a_value = 1)
9195 {
9196 switch ($a_value) {
9197 case 1:
9198 $this->fixed_participants = 1;
9199 break;
9200 default:
9201 $this->fixed_participants = 0;
9202 break;
9203 }
9204 }
9205
9213 public static function _lookupAnonymity($a_obj_id)
9214 {
9215 global $ilDB;
9216
9217 $result = $ilDB->queryF(
9218 "SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9219 array('integer'),
9220 array($a_obj_id)
9221 );
9222 while ($row = $ilDB->fetchAssoc($result)) {
9223 return $row['anonymity'];
9224 }
9225 return 0;
9226 }
9227
9234 public static function lookupQuestionSetTypeByActiveId($active_id)
9235 {
9236 global $ilDB;
9237
9238 $query = "
9239 SELECT tst_tests.question_set_type
9240 FROM tst_active
9241 INNER JOIN tst_tests
9242 ON tst_active.test_fi = tst_tests.test_id
9243 WHERE tst_active.active_id = %s
9244 ";
9245
9246 $res = $ilDB->queryF($query, array('integer'), array($active_id));
9247
9248 while ($row = $ilDB->fetchAssoc($res)) {
9249 return $row['question_set_type'];
9250 }
9251
9252 return null;
9253 }
9254
9263 public function _lookupRandomTestFromActiveId($active_id)
9264 {
9265 throw new Exception(__METHOD__ . ' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9266
9267 global $ilDB;
9268
9269 $result = $ilDB->queryF(
9270 "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",
9271 array('integer'),
9272 array($active_id)
9273 );
9274 while ($row = $ilDB->fetchAssoc($result)) {
9275 return $row['random_test'];
9276 }
9277 return 0;
9278 }
9279
9290 public function userLookupFullName($user_id, $overwrite_anonymity = false, $sorted_order = false, $suffix = "")
9291 {
9292 if ($this->getAnonymity() && !$overwrite_anonymity) {
9293 return $this->lng->txt("anonymous") . $suffix;
9294 } else {
9295 include_once './Services/User/classes/class.ilObjUser.php';
9296 $uname = ilObjUser::_lookupName($user_id);
9297 if (strlen($uname["firstname"] . $uname["lastname"]) == 0) {
9298 $uname["firstname"] = $this->lng->txt("deleted_user");
9299 }
9300 if ($sorted_order) {
9301 return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9302 } else {
9303 return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9304 }
9305 }
9306 }
9307
9315 public function getStartTestLabel($active_id)
9316 {
9317 if ($this->getNrOfTries() == 1) {
9318 return $this->lng->txt("tst_start_test");
9319 }
9320 $active_pass = self::_getPass($active_id);
9321 $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9322 if ($res == 0) {
9323 if ($active_pass == 0) {
9324 return $this->lng->txt("tst_start_test");
9325 } else {
9326 return $this->lng->txt("tst_start_new_test_pass");
9327 }
9328 } else {
9329 return $this->lng->txt("tst_resume_test");
9330 }
9331 }
9332
9338 public function getAvailableDefaults()
9339 {
9344 global $ilDB, $ilUser;
9345
9346 $result = $ilDB->queryF(
9347 "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9348 array('integer'),
9349 array($ilUser->getId())
9350 );
9351 $defaults = array();
9352 while ($row = $ilDB->fetchAssoc($result)) {
9353 $defaults[$row["test_defaults_id"]] = $row;
9354 }
9355 return $defaults;
9356 }
9357
9365 public function &getTestDefaults($test_defaults_id)
9366 {
9367 return self::_getTestDefaults($test_defaults_id);
9368 }
9369
9370 public static function _getTestDefaults($test_defaults_id)
9371 {
9372 global $ilDB;
9373
9374 $result = $ilDB->queryF(
9375 "SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9376 array('integer'),
9377 array($test_defaults_id)
9378 );
9379 if ($result->numRows() == 1) {
9380 $row = $ilDB->fetchAssoc($result);
9381 return $row;
9382 } else {
9383 return null;
9384 }
9385 }
9386
9393 public function deleteDefaults($test_default_id)
9394 {
9395 global $ilDB;
9396 $affectedRows = $ilDB->manipulateF(
9397 "DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9398 array('integer'),
9399 array($test_default_id)
9400 );
9401 }
9402
9409 public function addDefaults($a_name)
9410 {
9411 global $ilDB;
9412 global $ilUser;
9413 $testsettings = array(
9414 "TitleOutput" => $this->getTitleOutput(),
9415 "PassScoring" => $this->getPassScoring(),
9416 "IntroEnabled" => $this->isIntroductionEnabled(),
9417 "Introduction" => $this->getIntroduction(),
9418 "FinalStatement" => $this->getFinalStatement(),
9419 "ShowInfo" => $this->getShowInfo(),
9420 "ForceJS" => $this->getForceJS(),
9421 "CustomStyle" => $this->getCustomStyle(),
9422 "ShowFinalStatement" => $this->getShowFinalStatement(),
9423 "SequenceSettings" => $this->getSequenceSettings(),
9424 "ScoreReporting" => $this->getScoreReporting(),
9425 "ScoreCutting" => $this->getScoreCutting(),
9426 'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9427 'PrintBsWithRes' => (int) $this->isBestSolutionPrintedWithResult(),
9428 "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9429 "AnswerFeedback" => $this->getAnswerFeedback(),
9430 "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9431 "ResultsPresentation" => $this->getResultsPresentation(),
9432 "Anonymity" => $this->getAnonymity(),
9433 "ShowCancel" => $this->getShowCancel(),
9434 "ShowMarker" => $this->getShowMarker(),
9435 "ReportingDate" => $this->getReportingDate(),
9436 "NrOfTries" => $this->getNrOfTries(),
9437 "Shuffle" => $this->getShuffleQuestions(),
9438 "Kiosk" => $this->getKiosk(),
9439 "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9440 "ProcessingTime" => $this->getProcessingTime(),
9441 "EnableProcessingTime" => $this->getEnableProcessingTime(),
9442 "ResetProcessingTime" => $this->getResetProcessingTime(),
9443 "StartingTimeEnabled" => $this->isStartingTimeEnabled(),
9444 "StartingTime" => $this->getStartingTime(),
9445 "EndingTimeEnabled" => $this->isEndingTimeEnabled(),
9446 "EndingTime" => $this->getEndingTime(),
9447 "ECTSOutput" => $this->getECTSOutput(),
9448 "ECTSFX" => $this->getECTSFX(),
9449 "ECTSGrades" => $this->getECTSGrades(),
9450 "questionSetType" => $this->getQuestionSetType(),
9451 "CountSystem" => $this->getCountSystem(),
9452 "MCScoring" => $this->getMCScoring(),
9453 "mailnotification" => $this->getMailNotification(),
9454 "mailnottype" => $this->getMailNotificationType(),
9455 "exportsettings" => $this->getExportSettings(),
9456 "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9457 'obligations_enabled' => (int) $this->areObligationsEnabled(),
9458 'offer_question_hints' => (int) $this->isOfferingQuestionHintsEnabled(),
9459 'pass_deletion_allowed' => (int) $this->isPassDeletionAllowed(),
9460 'enable_examview' => $this->getEnableExamview(),
9461 'show_examview_html' => $this->getShowExamviewHtml(),
9462 'show_examview_pdf' => $this->getShowExamviewPdf(),
9463 'char_selector_availability' => $this->getCharSelectorAvailability(),
9464 'char_selector_definition' => $this->getCharSelectorDefinition(),
9465 'skill_service' => (int) $this->isSkillServiceEnabled(),
9466 'result_tax_filters' => (array) $this->getResultFilterTaxIds(),
9467 'show_grading_status' => (int) $this->isShowGradingStatusEnabled(),
9468 'show_grading_mark' => (int) $this->isShowGradingMarkEnabled(),
9469
9470 'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
9471 'force_inst_fb' => $this->isForceInstantFeedbackEnabled(),
9472 'redirection_mode' => $this->getRedirectionMode(),
9473 'redirection_url' => $this->getRedirectionUrl(),
9474 'sign_submission' => $this->getSignSubmission(),
9475 'autosave' => (int) $this->getAutosave(),
9476 'autosave_ival' => (int) $this->getAutosaveIval(),
9477 'examid_in_test_pass' => (int) $this->isShowExamIdInTestPassEnabled(),
9478 'examid_in_test_res' => (int) $this->isShowExamIdInTestResultsEnabled(),
9479
9480 'enable_archiving' => (int) $this->getEnableArchiving(),
9481 'password_enabled' => (int) $this->isPasswordEnabled(),
9482 'password' => (string) $this->getPassword(),
9483 'fixed_participants' => $this->getFixedParticipants(),
9484 'limit_users_enabled' => $this->isLimitUsersEnabled(),
9485 'allowedusers' => $this->getAllowedUsers(),
9486 'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9487 'pool_usage' => $this->getPoolUsage(),
9488 'activation_limited' => $this->isActivationLimited(),
9489 'activation_start_time' => $this->getActivationStartingTime(),
9490 'activation_end_time' => $this->getActivationEndingTime(),
9491 'activation_visibility' => $this->getActivationVisibility(),
9492 'highscore_enabled' => $this->getHighscoreEnabled(),
9493 'highscore_anon' => $this->getHighscoreAnon(),
9494 'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9495 'highscore_score' => $this->getHighscoreScore(),
9496 'highscore_percentage' => $this->getHighscorePercentage(),
9497 'highscore_hints' => $this->getHighscoreHints(),
9498 'highscore_wtime' => $this->getHighscoreWTime(),
9499 'highscore_own_table' => $this->getHighscoreOwnTable(),
9500 'highscore_top_table' => $this->getHighscoreTopTable(),
9501 'highscore_top_num' => $this->getHighscoreTopNum(),
9502 'use_previous_answers' => (string) $this->getUsePreviousAnswers(),
9503 'pass_waiting' => $this->getPassWaiting()
9504 );
9505
9506 $next_id = $ilDB->nextId('tst_test_defaults');
9507 $ilDB->insert(
9508 'tst_test_defaults',
9509 array(
9510 'test_defaults_id' => array('integer', $next_id),
9511 'name' => array('text', $a_name),
9512 'user_fi' => array('integer', $ilUser->getId()),
9513 'defaults' => array('clob', serialize($testsettings)),
9514 'marks' => array('clob', serialize($this->mark_schema)),
9515 'tstamp' => array('integer', time())
9516 )
9517 );
9518 }
9519
9527 public function applyDefaults($test_defaults)
9528 {
9529 $testsettings = unserialize($test_defaults["defaults"]);
9530 include_once "./Modules/Test/classes/class.assMarkSchema.php";
9531 $this->mark_schema = unserialize($test_defaults["marks"]);
9532
9533 $this->setTitleOutput($testsettings["TitleOutput"]);
9534 $this->setPassScoring($testsettings["PassScoring"]);
9535 $this->setIntroductionEnabled($testsettings["IntroEnabled"]);
9536 $this->setIntroduction($testsettings["Introduction"]);
9537 $this->setFinalStatement($testsettings["FinalStatement"]);
9538 $this->setShowInfo($testsettings["ShowInfo"]);
9539 $this->setForceJS($testsettings["ForceJS"]);
9540 $this->setCustomStyle($testsettings["CustomStyle"]);
9541 $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
9542 $this->setSequenceSettings($testsettings["SequenceSettings"]);
9543 $this->setScoreReporting($testsettings["ScoreReporting"]);
9544 $this->setScoreCutting($testsettings['ScoreCutting']);
9545 $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
9546 $this->setPrintBestSolutionWithResult((bool) $testsettings['PrintBsWithRes']);
9547 $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
9548 $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
9549 $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
9550 $this->setResultsPresentation($testsettings["ResultsPresentation"]);
9551 $this->setAnonymity($testsettings["Anonymity"]);
9552 $this->setShowCancel($testsettings["ShowCancel"]);
9553 $this->setShuffleQuestions($testsettings["Shuffle"]);
9554 $this->setShowMarker($testsettings["ShowMarker"]);
9555 $this->setReportingDate($testsettings["ReportingDate"]);
9556 $this->setNrOfTries($testsettings["NrOfTries"]);
9557 $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
9558 $this->setRedirectionMode($testsettings['redirection_mode']);
9559 $this->setRedirectionUrl($testsettings['redirection_url']);
9560 $this->setProcessingTime($testsettings["ProcessingTime"]);
9561 $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
9562 $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
9563 $this->setStartingTimeEnabled($testsettings["StartingTimeEnabled"]);
9564 $this->setStartingTime($testsettings["StartingTime"]);
9565 $this->setKiosk($testsettings["Kiosk"]);
9566 $this->setEndingTimeEnabled($testsettings["EndingTimeEnabled"]);
9567 $this->setEndingTime($testsettings["EndingTime"]);
9568 $this->setECTSOutput($testsettings["ECTSOutput"]);
9569 $this->setECTSFX($testsettings["ECTSFX"]);
9570 $this->setECTSGrades($testsettings["ECTSGrades"]);
9571 if (isset($testsettings["isRandomTest"])) {
9572 if ($testsettings["isRandomTest"]) {
9573 $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
9574 } else {
9575 $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
9576 }
9577 } elseif (isset($testsettings["questionSetType"])) {
9578 $this->setQuestionSetType($testsettings["questionSetType"]);
9579 }
9580 $this->setCountSystem($testsettings["CountSystem"]);
9581 $this->setMCScoring($testsettings["MCScoring"]);
9582 $this->setMailNotification($testsettings["mailnotification"]);
9583 $this->setMailNotificationType($testsettings["mailnottype"]);
9584 $this->setExportSettings($testsettings['exportsettings']);
9585 $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
9586 $this->setObligationsEnabled($testsettings["obligations_enabled"]);
9587 $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
9588 $this->setHighscoreEnabled($testsettings['highscore_enabled']);
9589 $this->setHighscoreAnon($testsettings['highscore_anon']);
9590 $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
9591 $this->setHighscoreScore($testsettings['highscore_score']);
9592 $this->setHighscorePercentage($testsettings['highscore_percentage']);
9593 $this->setHighscoreHints($testsettings['highscore_hints']);
9594 $this->setHighscoreWTime($testsettings['highscore_wtime']);
9595 $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
9596 $this->setHighscoreTopTable($testsettings['highscore_top_table']);
9597 $this->setHighscoreTopNum($testsettings['highscore_top_num']);
9598 $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
9599 if (isset($testsettings['examid_in_kiosk'])) {
9600 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
9601 } else {
9602 $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
9603 }
9604 if (isset($testsettings['show_exam_id'])) {
9605 $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
9606 } else {
9607 $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
9608 }
9609 $this->setEnableExamview($testsettings['enable_examview']);
9610 $this->setShowExamviewHtml($testsettings['show_examview_html']);
9611 $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
9612 $this->setEnableArchiving($testsettings['enable_archiving']);
9613 $this->setSignSubmission($testsettings['sign_submission']);
9614 $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
9615 $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
9616 $this->setSkillServiceEnabled((bool) $testsettings['skill_service']);
9617 $this->setResultFilterTaxIds((array) $testsettings['result_tax_filters']);
9618 $this->setShowGradingStatusEnabled((bool) $testsettings['show_grading_status']);
9619 $this->setShowGradingMarkEnabled((bool) $testsettings['show_grading_mark']);
9620
9621 $this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
9622 $this->setForceInstantFeedbackEnabled($testsettings['force_inst_fb']);
9623 $this->setRedirectionMode($testsettings['redirection_mode']);
9624 $this->setRedirectionUrl($testsettings['redirection_url']);
9625
9626 $this->setAutosave($testsettings['autosave']);
9627 $this->setAutosaveIval($testsettings['autosave_ival']);
9628 $this->setShowExamIdInTestResultsEnabled((int) $testsettings['examid_in_test_res']);
9629 $this->setPasswordEnabled($testsettings['password_enabled']);
9630 $this->setPassword($testsettings['password']);
9631 $this->setFixedParticipants($testsettings['fixed_participants']);
9632 $this->setLimitUsersEnabled($testsettings['limit_users_enabled']);
9633 $this->setAllowedUsers($testsettings['allowedusers']);
9634 $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
9635 $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
9636 $this->setPoolUsage($testsettings['pool_usage']);
9637 $this->setActivationLimited($testsettings['activation_limited']);
9638 $this->setActivationStartingTime($testsettings['activation_start_time']);
9639 $this->setActivationEndingTime($testsettings['activation_end_time']);
9640 $this->setActivationVisibility($testsettings['activation_visibility']);
9641 $this->setPassWaiting($testsettings['pass_waiting']);
9642
9643 $this->saveToDb();
9644
9645 return true;
9646 }
9647
9655 public function processPrintoutput2FO($print_output)
9656 {
9657 if (extension_loaded("tidy")) {
9658 $config = array(
9659 "indent" => false,
9660 "output-xml" => true,
9661 "numeric-entities" => true
9662 );
9663 $tidy = new tidy();
9664 $tidy->parseString($print_output, $config, 'utf8');
9665 $tidy->cleanRepair();
9666 $print_output = tidy_get_output($tidy);
9667 $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
9668 } else {
9669 $print_output = str_replace("&nbsp;", "&#160;", $print_output);
9670 $print_output = str_replace("&otimes;", "X", $print_output);
9671 }
9672 $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
9673
9674 // additional font support
9675 $xsl = str_replace(
9676 'font-family="Helvetica, unifont"',
9677 'font-family="' . $GLOBALS['ilSetting']->get('rpc_pdf_font', 'Helvetica, unifont') . '"',
9678 $xsl
9679 );
9680
9681 $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
9682 $xh = xslt_create();
9683 $params = array();
9684 $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
9685 xslt_error($xh);
9686 xslt_free($xh);
9687 return $output;
9688 }
9689
9696 public function deliverPDFfromHTML($content, $title = null)
9697 {
9698 $content = preg_replace("/href=\".*?\"/", "", $content);
9699 $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", true, true, "Modules/Test");
9700 $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
9701 $printbody->setVariable("ADM_CONTENT", $content);
9702 $printbody->setCurrentBlock("css_file");
9703 $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
9704 $printbody->parseCurrentBlock();
9705 $printbody->setCurrentBlock("css_file");
9706 $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
9707 $printbody->parseCurrentBlock();
9708 $printoutput = $printbody->get();
9709 $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
9710 $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
9711 if (extension_loaded("tidy")) {
9712 $config = array(
9713 "indent" => false,
9714 "output-xml" => true,
9715 "numeric-entities" => true
9716 );
9717 $tidy = new tidy();
9718 $tidy->parseString($html, $config, 'utf8');
9719 $tidy->cleanRepair();
9720 $html = tidy_get_output($tidy);
9721 $html = preg_replace("/^.*?(<html)/", "\\1", $html);
9722 } else {
9723 $html = str_replace("&nbsp;", "&#160;", $html);
9724 $html = str_replace("&otimes;", "X", $html);
9725 }
9726 $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
9728 }
9729
9736 public function deliverPDFfromFO($fo, $title = null)
9737 {
9738 global $ilLog;
9739
9740 include_once "./Services/Utilities/classes/class.ilUtil.php";
9741 $fo_file = ilUtil::ilTempnam() . ".fo";
9742 $fp = fopen($fo_file, "w");
9743 fwrite($fp, $fo);
9744 fclose($fp);
9745
9746 include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
9747 try {
9748 $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
9749 $filename = (strlen($title)) ? $title : $this->getTitle();
9750 ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
9751 return true;
9752 } catch (Exception $e) {
9753 $ilLog->write(__METHOD__ . ': ' . $e->getMessage());
9754 return false;
9755 }
9756 }
9757
9767 public static function getManualFeedback($active_id, $question_id, $pass)
9768 {
9769 global $ilDB;
9770 $feedback = "";
9771 $result = $ilDB->queryF(
9772 "SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
9773 array('integer', 'integer', 'integer'),
9774 array($active_id, $question_id, $pass)
9775 );
9776 if ($result->numRows()) {
9777 $row = $ilDB->fetchAssoc($result);
9778 include_once("./Services/RTE/classes/class.ilRTE.php");
9779 $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
9780 }
9781 return $feedback;
9782 }
9783
9794 public function saveManualFeedback($active_id, $question_id, $pass, $feedback)
9795 {
9796 global $ilDB;
9797
9798 $affectedRows = $ilDB->manipulateF(
9799 "DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
9800 array('integer', 'integer', 'integer'),
9801 array($active_id, $question_id, $pass)
9802 );
9803
9804 if (strlen($feedback)) {
9805 $next_id = $ilDB->nextId('tst_manual_fb');
9807 $result = $ilDB->insert(
9808 'tst_manual_fb',
9809 array(
9810 'manual_feedback_id' => array( 'integer', $next_id ),
9811 'active_fi' => array( 'integer', $active_id ),
9812 'question_fi' => array( 'integer', $question_id ),
9813 'pass' => array( 'integer', $pass),
9814 'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc($feedback, 0) ),
9815 'tstamp' => array( 'integer', time() ),
9816 )
9817 );
9818 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
9820 global $lng, $ilUser;
9821 include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
9822 $username = ilObjTestAccess::_getParticipantData($active_id);
9823 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
9824 $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
9825 }
9826 }
9827 return true;
9828 }
9829
9837 public function getJavaScriptOutput()
9838 {
9839 return true;
9840
9841 // global $ilUser;
9842// if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
9843// if ($this->getForceJS()) return TRUE;
9844// $assessmentSetting = new ilSetting("assessment");
9845// return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
9846 }
9847
9848 public function &createTestSequence($active_id, $pass, $shuffle)
9849 {
9850 include_once "./Modules/Test/classes/class.ilTestSequence.php";
9851 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
9852 }
9853
9859 public function setTestId($a_id)
9860 {
9861 $this->test_id = $a_id;
9862 }
9863
9872 public function getDetailedTestResults($participants)
9873 {
9874 $results = array();
9875 if (count($participants)) {
9876 foreach ($participants as $active_id => $user_rec) {
9877 $row = array();
9878 $reached_points = 0;
9879 $max_points = 0;
9880 foreach ($this->questions as $value) {
9881 $question =&ilObjTest::_instanciateQuestion($value);
9882 if (is_object($question)) {
9883 $max_points += $question->getMaximumPoints();
9884 $reached_points += $question->getReachedPoints($active_id);
9885 if ($max_points > 0) {
9886 $percentvalue = $reached_points / $max_points;
9887 if ($percentvalue < 0) {
9888 $percentvalue = 0.0;
9889 }
9890 } else {
9891 $percentvalue = 0;
9892 }
9893 if ($this->getAnonymity()) {
9894 $user_rec['firstname'] = "";
9895 $user_rec['lastname'] = $this->lng->txt("anonymous");
9896 }
9897 $row = array(
9898 "user_id"=>$user_rec['usr_id'],
9899 "matriculation" => $user_rec['matriculation'],
9900 "lastname" => $user_rec['lastname'],
9901 "firstname" => $user_rec['firstname'],
9902 "login"=>$user_rec['login'],
9903 "question_id" => $question->getId(),
9904 "question_title" => $question->getTitle(),
9905 "reached_points" => $reached_points,
9906 "max_points" => $max_points
9907 );
9908 $results[] = $row;
9909 }
9910 }
9911 }
9912 }
9913 return $results;
9914 }
9915
9919 public static function _lookupTestObjIdForQuestionId($a_q_id)
9920 {
9921 global $ilDB;
9922
9923 $result = $ilDB->queryF(
9924 "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",
9925 array('integer'),
9926 array($a_q_id)
9927 );
9928 $rec = $ilDB->fetchAssoc($result);
9929 return $rec["obj_id"];
9930 }
9931
9938 public function isPluginActive($a_pname)
9939 {
9940 global $ilPluginAdmin;
9941 if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname)) {
9942 return true;
9943 } else {
9944 return false;
9945 }
9946 }
9947
9948 public function getPassed($active_id)
9949 {
9950 global $ilDB;
9951
9952 $result = $ilDB->queryF(
9953 "SELECT passed FROM tst_result_cache WHERE active_fi = %s",
9954 array('integer'),
9955 array($active_id)
9956 );
9957 if ($result->numRows()) {
9958 $row = $ilDB->fetchAssoc($result);
9959 return $row['passed'];
9960 } else {
9961 $counted_pass = ilObjTest::_getResultPass($active_id);
9962 $result_array =&$this->getTestResult($active_id, $counted_pass);
9963 return $result_array["test"]["passed"];
9964 }
9965 }
9966
9972 public function canShowCertificate($testSession, $user_id, $active_id)
9973 {
9974 if ($this->canShowTestResults($testSession)) {
9975 include_once "./Services/Certificate/classes/class.ilCertificate.php";
9976 include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
9977 $cert = new ilCertificate(new ilTestCertificateAdapter($this));
9978 if ($cert->isComplete()) {
9979 $vis = $this->getCertificateVisibility();
9980 $showcert = false;
9981 switch ($vis) {
9982 case 0:
9983 $showcert = true;
9984 break;
9985 case 1:
9986 if ($this->getPassed($active_id)) {
9987 $showcert = true;
9988 }
9989 break;
9990 case 2:
9991 $showcert = false;
9992 break;
9993 }
9994 if ($showcert) {
9995 return true;
9996 } else {
9997 return false;
9998 }
9999 } else {
10000 return false;
10001 }
10002 } else {
10003 return false;
10004 }
10005 }
10006
10010 public function getParticipantsForTestAndQuestion($test_id, $question_id)
10011 {
10013 global $ilDB;
10014
10015 $query = "
10016 SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10017 FROM tst_test_result
10018 INNER JOIN tst_active ON tst_active.active_id = tst_test_result.active_fi AND tst_active.test_fi = %s
10019 INNER JOIN qpl_questions ON qpl_questions.question_id = tst_test_result.question_fi
10020 LEFT JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
10021 WHERE tst_test_result.question_fi = %s
10022 ORDER BY usr_data.lastname ASC, usr_data.firstname ASC
10023 ";
10024
10025 $result = $ilDB->queryF(
10026 $query,
10027 array('integer', 'integer'),
10028 array($test_id, $question_id)
10029 );
10030 $foundusers = array();
10032 while ($row = $ilDB->fetchAssoc($result)) {
10033 if (!array_key_exists($row["active_fi"], $foundusers)) {
10034 $foundusers[$row["active_fi"]] = array();
10035 }
10036 array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10037 }
10038 return $foundusers;
10039 }
10040
10047 {
10049 $foundParticipants =&$data->getParticipants();
10050 $results = array("overview" => array(), "questions" => array());
10051 if (count($foundParticipants)) {
10052 $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10053 $total_finished = $this->evalTotalFinished();
10054 $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10055 $average_time = $this->evalTotalStartedAverageTime();
10056 $diff_seconds = $average_time;
10057 $diff_hours = floor($diff_seconds/3600);
10058 $diff_seconds -= $diff_hours * 3600;
10059 $diff_minutes = floor($diff_seconds/60);
10060 $diff_seconds -= $diff_minutes * 60;
10061 $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10062 $total_passed = 0;
10063 $total_passed_reached = 0;
10064 $total_passed_max = 0;
10065 $total_passed_time = 0;
10066 foreach ($foundParticipants as $userdata) {
10067 if ($userdata->getPassed()) {
10068 $total_passed++;
10069 $total_passed_reached += $userdata->getReached();
10070 $total_passed_max += $userdata->getMaxpoints();
10071 $total_passed_time += $userdata->getTimeOfWork();
10072 }
10073 }
10074 $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10075 $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10076 $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10077 $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10078 $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);
10079 $average_time = $average_passed_time;
10080 $diff_seconds = $average_time;
10081 $diff_hours = floor($diff_seconds/3600);
10082 $diff_seconds -= $diff_hours * 3600;
10083 $diff_minutes = floor($diff_seconds/60);
10084 $diff_seconds -= $diff_minutes * 60;
10085 $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10086 }
10087
10088 foreach ($data->getQuestionTitles() as $question_id => $question_title) {
10089 $answered = 0;
10090 $reached = 0;
10091 $max = 0;
10092 foreach ($foundParticipants as $userdata) {
10093 for ($i = 0; $i <= $userdata->getLastPass(); $i++) {
10094 if (is_object($userdata->getPass($i))) {
10095 $question =&$userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10096 if (is_array($question)) {
10097 $answered++;
10098 $reached += $question["reached"];
10099 $max += $question["points"];
10100 }
10101 }
10102 }
10103 }
10104 $percent = $max ? $reached/$max * 100.0 : 0;
10105 $counter++;
10106 $results["questions"][$question_id] = array(
10107 $question_title,
10108 sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10109 sprintf("%.2f", $percent) . "%",
10110 $answered,
10111 sprintf("%.2f", $answered ? $reached / $answered : 0),
10112 sprintf("%.2f", $answered ? $max / $answered : 0),
10113 $percent / 100.0
10114 );
10115 }
10116 return $results;
10117 }
10118
10122 public function getXMLZip()
10123 {
10124 require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
10125 $expFactory = new ilTestExportFactory($this);
10126 $test_exp = $expFactory->getExporter('xml');
10127 return $test_exp->buildExportFile();
10128 }
10129
10133 public function getMailNotification()
10134 {
10136 }
10137
10143 public function setMailNotification($a_notification)
10144 {
10145 $this->mailnotification = $a_notification;
10146 }
10147
10148 public function sendSimpleNotification($active_id)
10149 {
10150 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10151
10152 $mail = new ilTestMailNotification();
10153 $owner_id = $this->getOwner();
10154 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10155 $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10156 }
10157
10164 {
10165 include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10166 include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10167 $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(''), 'outEvaluation', $this->getAnonymity());
10168 return $table_gui->getSelectedColumns();
10169 }
10170
10171 public function sendAdvancedNotification($active_id)
10172 {
10173 include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10174
10175 $mail = new ilTestMailNotification();
10176 $owner_id = $this->getOwner();
10177 $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10178
10179 require_once 'Modules/Test/classes/class.ilTestExportFactory.php';
10180 $expFactory = new ilTestExportFactory($this);
10181 $exportObj = $expFactory->getExporter('results');
10182 $file = $exportObj->exportToExcel($deliver = false, 'active_id', $active_id, $passedonly = false);
10183 include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10184 $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10185 $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10186 $file_names[] = "result_" . $active_id . ".xls";
10187
10188 $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10189
10190 if (count($file_names)) {
10191 $fd->unlinkFiles($file_names);
10192 unset($fd);
10193 @unlink($file);
10194 }
10195 }
10196
10197 public function createRandomSolutions($number)
10198 {
10199 global $ilDB;
10200
10201 // 1. get a user
10202 $query = "SELECT usr_id FROM usr_data";
10203 $result = $ilDB->query($query);
10204 while ($data = $ilDB->fetchAssoc($result)) {
10205 $activequery = sprintf(
10206 "SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10207 $ilDB->quote($this->getTestId()),
10208 $ilDB->quote($data['usr_id'])
10209 );
10210 $activeresult = $ilDB->query($activequery);
10211 if ($activeresult->numRows() == 0) {
10212 $user_id = $data['usr_id'];
10213 if ($user_id != 13) {
10214 include_once "./Modules/Test/classes/class.ilTestSession.php";
10216 $testSession->setRefId($this->getRefId());
10217 $testSession->setTestId($this->getTestId());
10218 $testSession->setUserId($user_id);
10219 $testSession->saveToDb();
10220 $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10221 $random = new \ilRandom();
10222 $nr_of_passes = $random->int(1, $passes);
10223 $active_id = $testSession->getActiveId();
10224 for ($pass = 0; $pass < $nr_of_passes; $pass++) {
10225 include_once "./Modules/Test/classes/class.ilTestSequence.php";
10226 $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10227 $testSequence->loadFromDb();
10228 $testSequence->loadQuestions();
10229 if (!$testSequence->hasSequence()) {
10230 $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10231 $testSequence->saveToDb();
10232 }
10233 for ($seq = 1; $seq <= count($this->questions); $seq++) {
10234 $question_id = $testSequence->getQuestionForSequence($seq);
10235 $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10236 $assSettings = new ilSetting('assessment');
10237 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
10238 $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
10239 $processLockerFactory->setQuestionId($objQuestion->getId());
10240 $processLockerFactory->setUserId($testSession->getUserId());
10241 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10242 $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
10243 $objQuestion->setProcessLocker($processLockerFactory->getLocker());
10244 $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10245 }
10246 $testSession->increasePass();
10247 $testSession->setLastSequence(0);
10248 $testSession->setLastFinishedPass($pass);
10249 $testSession->setSubmitted(1);
10250 $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10251 $testSession->saveToDb();
10252 }
10253 $number--;
10254 if ($number == 0) {
10255 return;
10256 }
10257 }
10258 }
10259 }
10260 }
10261
10262 public function getResultsForActiveId($active_id)
10263 {
10264 global $ilDB;
10265
10266 $query = "
10267 SELECT *
10268 FROM tst_result_cache
10269 WHERE active_fi = %s
10270 ";
10271
10272 $result = $ilDB->queryF(
10273 $query,
10274 array('integer'),
10275 array($active_id)
10276 );
10277
10278 if (!$result->numRows()) {
10279 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10280
10282
10283 $query = "
10284 SELECT *
10285 FROM tst_result_cache
10286 WHERE active_fi = %s
10287 ";
10288
10289 $result = $ilDB->queryF(
10290 $query,
10291 array('integer'),
10292 array($active_id)
10293 );
10294 }
10295
10296 $row = $ilDB->fetchAssoc($result);
10297
10298 return $row;
10299 }
10300
10301 public function getMailNotificationType()
10302 {
10303 if ($this->mailnottype == 1) {
10304 return $this->mailnottype;
10305 } else {
10306 return 0;
10307 }
10308 }
10309
10311 {
10312 if ($a_type == 1) {
10313 $this->mailnottype = 1;
10314 } else {
10315 $this->mailnottype = 0;
10316 }
10317 }
10318
10319 public function getExportSettings()
10320 {
10321 if ($this->exportsettings) {
10322 return $this->exportsettings;
10323 } else {
10324 return 0;
10325 }
10326 }
10327
10328 public function setExportSettings($a_settings)
10329 {
10330 if ($a_settings) {
10331 $this->exportsettings = $a_settings;
10332 } else {
10333 $this->exportsettings = 0;
10334 }
10335 }
10336
10338 {
10339 if (($this->exportsettings & 1) > 0) {
10340 return true;
10341 } else {
10342 return false;
10343 }
10344 }
10345
10346 public function setExportSettingsSingleChoiceShort($a_settings)
10347 {
10348 if ($a_settings) {
10349 $this->exportsettings = $this->exportsettings | 1;
10350 } else {
10352 $this->exportsettings = $this->exportsettings ^ 1;
10353 }
10354 }
10355 }
10356
10357 public function getEnabledViewMode()
10358 {
10359 return $this->enabled_view_mode;
10360 }
10361
10362 public function setEnabledViewMode($mode)
10363 {
10364 $this->enabled_view_mode = $mode;
10365 }
10366
10367 public function setTemplate($template_id)
10368 {
10369 $this->template_id = (int) $template_id;
10370 }
10371
10372 public function getTemplate()
10373 {
10374 return $this->template_id;
10375 }
10376
10377 public function moveQuestionAfterOLD($previous_question_id, $new_question_id)
10378 {
10379 $new_array = array();
10380 $position = 1;
10381
10382 $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10383 $types = array('integer');
10384 $values = array($this->getTestId());
10385
10386 $new_question_id += 1;
10387
10388 global $ilDB;
10389 $inserted = false;
10390 $res = $ilDB->queryF($query, $types, $values);
10391 while ($row = $ilDB->fetchAssoc($res)) {
10392 $qid = $row['question_fi'];
10393
10394 if ($qid == $new_question_id) {
10395 continue;
10396 } elseif ($qid == $previous_question_id) {
10397 $new_array[$position++] = $qid;
10398 $new_array[$position++] = $new_question_id;
10399 $inserted = true;
10400 } else {
10401 $new_array[$position++] = $qid;
10402 }
10403 }
10404
10405 $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10406 $update_types = array('integer', 'integer', 'integer');
10407
10408 foreach ($new_array as $position => $qid) {
10409 $ilDB->manipulateF(
10410 $update_query,
10411 $update_types,
10412 $vals = array(
10413 $position,
10414 $this->getTestId(),
10415 $qid
10416 )
10417 );
10418 }
10419 }
10420
10422 {
10423 if (is_array($options)) {
10424 $this->setGenericAnswerFeedback(in_array('instant_feedback_generic', $options) ? 1 : 0);
10425 $this->setSpecificAnswerFeedback(in_array('instant_feedback_specific', $options) ? 1 : 0);
10426 $this->setAnswerFeedbackPoints(in_array('instant_feedback_points', $options) ? 1 : 0);
10427 $this->setInstantFeedbackSolution(in_array('instant_feedback_solution', $options) ? 1 : 0);
10428 } else {
10429 $this->setGenericAnswerFeedback(0);
10430 $this->setSpecificAnswerFeedback(0);
10431 $this->setAnswerFeedbackPoints(0);
10433 }
10434 }
10435
10437 {
10438 $setter = array(
10439 'pass_details' => 'setShowPassDetails',
10440 'solution_details' => 'setShowSolutionDetails',
10441 'solution_printview' => 'setShowSolutionPrintview',
10442 'solution_feedback' => 'setShowSolutionFeedback',
10443 'solution_answers_only' => 'setShowSolutionAnswersOnly',
10444 'solution_signature' => 'setShowSolutionSignature',
10445 'solution_suggested' => 'setShowSolutionSuggested',
10446 );
10447 foreach ($setter as $key => $setter) {
10448 if (in_array($key, $options)) {
10449 $this->$setter(1);
10450 } else {
10451 $this->$setter(0);
10452 }
10453 }
10454 }
10455
10456 public function getPoolUsage()
10457 {
10458 return (boolean) $this->poolUsage;
10459 }
10460
10461 public function setPoolUsage($usage)
10462 {
10463 $this->poolUsage = (boolean) $usage;
10464 }
10465
10467 {
10468 $tree = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tree'] : $GLOBALS['tree'];
10469 $db = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilDB'] : $GLOBALS['ilDB'];
10470 $pluginAdmin = isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['ilPluginAdmin'] : $GLOBALS['ilPluginAdmin'];
10471
10472 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
10473 $qscFactory = new ilTestQuestionSetConfigFactory($tree, $db, $pluginAdmin, $this);
10474 $questionSetConfig = $qscFactory->getQuestionSetConfig();
10475
10476 /* @var ilTestFixedQuestionSetConfig $questionSetConfig */
10477 $questionSetConfig->reindexQuestionOrdering();
10478
10479 $this->loadQuestions();
10480 }
10481
10482 public function setQuestionOrderAndObligations($orders, $obligations)
10483 {
10484 global $ilDB;
10485
10486 asort($orders);
10487
10488 $i = 0;
10489
10490 foreach ($orders as $id => $position) {
10491 $i++;
10492
10493 $obligatory = (
10494 isset($obligations[$id]) && $obligations[$id] ? 1 : 0
10495 );
10496
10497 $query = "
10498 UPDATE tst_test_question
10499 SET sequence = %s,
10500 obligatory = %s
10501 WHERE question_fi = %s
10502 ";
10503
10504 $ilDB->manipulateF(
10505 $query,
10506 array('integer', 'integer', 'integer'),
10507 array($i, $obligatory, $id)
10508 );
10509 }
10510
10511 $this->loadQuestions();
10512 }
10513
10514 public function moveQuestionAfter($question_to_move, $question_before)
10515 {
10516 global $ilDB;
10517 //var_dump(func_get_args());
10518 if ($question_before) {
10519 $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
10520 $types = array('integer');
10521 $values = array($question_before);
10522 $rset = $ilDB->queryF($query, $types, $values);
10523 }
10524
10525 if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
10526 $row = array(
10527 'sequence' => 0,
10528 'test_fi' => $this->getTestId(),
10529 );
10530 }
10531
10532 $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
10533 $types = array('integer', 'integer');
10534 $values = array($row['sequence'], $row['test_fi']);
10535 $ilDB->manipulateF($update, $types, $values);
10536
10537 $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
10538 $types = array('integer', 'integer');
10539 $values = array($row['sequence'] + 1, $question_to_move);
10540 $ilDB->manipulateF($update, $types, $values);
10541
10543 }
10544
10546 {
10547 global $ilDB;
10548
10550
10551 $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
10552
10553 $query = "
10554 SELECT count(q1.question_id) cnt
10555
10556 FROM qpl_questions q1
10557
10558 INNER JOIN qpl_questions q2
10559 ON q2.question_id = q1.original_id
10560
10561 WHERE $IN_questions
10562 AND q1.obj_fi = q2.obj_fi
10563 ";
10564
10565 $rset = $ilDB->query($query);
10566
10567 $row = $ilDB->fetchAssoc($rset);
10568
10569 return $row['cnt'] > 0;
10570 }
10571
10578 public static function _lookupFinishedUserTests($a_user_id)
10579 {
10580 global $ilDB;
10581
10582 $result = $ilDB->queryF(
10583 "SELECT test_fi,MAX(pass) AS pass FROM tst_active" .
10584 " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)" .
10585 " WHERE user_fi=%s" .
10586 " GROUP BY test_fi",
10587 array('integer', 'integer'),
10588 array($a_user_id, 1)
10589 );
10590 $all = array();
10591 while ($row = $ilDB->fetchAssoc($result)) {
10592 $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
10593 $all[$obj_id] = (bool) $row["pass"];
10594 }
10595 return $all;
10596 }
10597 public function getQuestions()
10598 {
10599 return $this->questions;
10600 }
10601
10602 public function isOnline()
10603 {
10604 return $this->online;
10605 }
10606
10607 public function setOnline($a_online = true)
10608 {
10609 $this->online = (bool) $a_online;
10610 }
10611
10615 public function getOldOnlineStatus()
10616 {
10618 }
10619
10624 {
10625 $this->oldOnlineStatus = $oldOnlineStatus;
10626 }
10627
10628 public function setPrintBestSolutionWithResult($status)
10629 {
10630 $this->print_best_solution_with_result = (bool) $status;
10631 }
10632
10634 {
10636 }
10637
10644 {
10646 }
10647
10654 {
10655 $this->offeringQuestionHintsEnabled = (bool) $offeringQuestionHintsEnabled;
10656 }
10657
10658 public function setActivationVisibility($a_value)
10659 {
10660 $this->activation_visibility = (bool) $a_value;
10661 }
10662
10663 public function getActivationVisibility()
10664 {
10666 }
10667
10668 public function isActivationLimited()
10669 {
10670 return (bool) $this->activation_limited;
10671 }
10672
10673 public function setActivationLimited($a_value)
10674 {
10675 $this->activation_limited = (bool) $a_value;
10676 }
10677
10678 /* GET/SET for highscore feature */
10679
10685 public function setHighscoreEnabled($a_enabled)
10686 {
10687 $this->_highscore_enabled = (bool) $a_enabled;
10688 }
10689
10695 public function getHighscoreEnabled()
10696 {
10697 return (bool) $this->_highscore_enabled;
10698 }
10699
10707 public function setHighscoreAnon($a_anon)
10708 {
10709 $this->_highscore_anon = (bool) $a_anon;
10710 }
10711
10721 public function getHighscoreAnon()
10722 {
10723 return (bool) $this->_highscore_anon;
10724 }
10725
10734 public function isHighscoreAnon()
10735 {
10736 if ($this->getAnonymity() == 1) {
10737 return true;
10738 } else {
10739 return (bool) $this->getHighscoreAnon();
10740 }
10741 }
10742
10748 public function setHighscoreAchievedTS($a_achieved_ts)
10749 {
10750 $this->_highscore_achieved_ts = (bool) $a_achieved_ts;
10751 }
10752
10758 public function getHighscoreAchievedTS()
10759 {
10760 return (bool) $this->_highscore_achieved_ts;
10761 }
10762
10768 public function setHighscoreScore($a_score)
10769 {
10770 $this->_highscore_score = (bool) $a_score;
10771 }
10772
10778 public function getHighscoreScore()
10779 {
10780 return (bool) $this->_highscore_score;
10781 }
10782
10788 public function setHighscorePercentage($a_percentage)
10789 {
10790 $this->_highscore_percentage = (bool) $a_percentage;
10791 }
10792
10798 public function getHighscorePercentage()
10799 {
10800 return (bool) $this->_highscore_percentage;
10801 }
10802
10808 public function setHighscoreHints($a_hints)
10809 {
10810 $this->_highscore_hints = (bool) $a_hints;
10811 }
10812
10818 public function getHighscoreHints()
10819 {
10820 return (bool) $this->_highscore_hints;
10821 }
10822
10828 public function setHighscoreWTime($a_wtime)
10829 {
10830 $this->_highscore_wtime = (bool) $a_wtime;
10831 }
10832
10838 public function getHighscoreWTime()
10839 {
10840 return (bool) $this->_highscore_wtime;
10841 }
10842
10848 public function setHighscoreOwnTable($a_own_table)
10849 {
10850 $this->_highscore_own_table = (bool) $a_own_table;
10851 }
10852
10858 public function getHighscoreOwnTable()
10859 {
10860 return (bool) $this->_highscore_own_table;
10861 }
10862
10868 public function setHighscoreTopTable($a_top_table)
10869 {
10870 $this->_highscore_top_table = (bool) $a_top_table;
10871 }
10872
10878 public function getHighscoreTopTable()
10879 {
10880 return (bool) $this->_highscore_top_table;
10881 }
10882
10889 public function setHighscoreTopNum($a_top_num)
10890 {
10891 $this->_highscore_top_num = (int) $a_top_num;
10892 }
10893
10902 public function getHighscoreTopNum($a_retval = 10)
10903 {
10904 $retval = $a_retval;
10905 if ((int) $this->_highscore_top_num != 0) {
10906 $retval = $this->_highscore_top_num;
10907 }
10908
10909 return $retval;
10910 }
10911
10915 public function getHighscoreMode()
10916 {
10917 switch (true) {
10918 case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
10920 break;
10921
10922 case $this->getHighscoreTopTable():
10924 break;
10925
10926 case $this->getHighscoreOwnTable():
10927 default:
10929 break;
10930 }
10931 }
10932
10936 public function setHighscoreMode($mode)
10937 {
10938 switch ($mode) {
10940 $this->setHighscoreTopTable(1);
10941 $this->setHighscoreOwnTable(1);
10942 break;
10943
10945 $this->setHighscoreTopTable(1);
10946 $this->setHighscoreOwnTable(0);
10947 break;
10948
10950 default:
10951 $this->setHighscoreTopTable(0);
10952 $this->setHighscoreOwnTable(1);
10953 break;
10954 }
10955 }
10956 /* End GET/SET for highscore feature*/
10957
10958 public function setSpecificAnswerFeedback($specific_answer_feedback)
10959 {
10960 switch ($specific_answer_feedback) {
10961 case 1:
10962 $this->specific_answer_feedback = 1;
10963 break;
10964 default:
10965 $this->specific_answer_feedback = 0;
10966 break;
10967 }
10968 }
10969
10971 {
10972 switch ($this->specific_answer_feedback) {
10973 case 1:
10974 return 1;
10975 default:
10976 return 0;
10977 }
10978 }
10979
10986 {
10987 $this->obligationsEnabled = (bool) $obligationsEnabled;
10988 }
10989
10995 public function areObligationsEnabled()
10996 {
10997 return (bool) $this->obligationsEnabled;
10998 }
10999
11006 public static function isQuestionObligationPossible($questionId)
11007 {
11008 require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11009
11010 $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11011
11012 assQuestion::_includeClass($classConcreteQuestion, 0);
11013
11014 // static binder is not at work yet (in PHP < 5.3)
11015 //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11016 $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11017
11018 return $obligationPossible;
11019 }
11020
11027 public static function isQuestionObligatory($question_id)
11028 {
11029 global $ilDB;
11030
11031 $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11032
11033 if ($row = $ilDB->fetchAssoc($rset)) {
11034 return (bool) $row['obligatory'];
11035 }
11036
11037 return false;
11038 }
11039
11052 public static function allObligationsAnswered($test_id, $active_id, $pass)
11053 {
11054 global $ilDB;
11055
11056 $rset = $ilDB->queryF(
11057 'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11058 array('integer', 'integer'),
11059 array($active_id, $pass)
11060 );
11061
11062 if ($row = $ilDB->fetchAssoc($rset)) {
11063 return (bool) $row['obligations_answered'];
11064 }
11065
11067 }
11068
11077 public static function hasObligations($test_id)
11078 {
11079 global $ilDB;
11080
11081 $rset = $ilDB->queryF(
11082 'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11083 array('integer'),
11084 array($test_id)
11085 );
11086
11087 $row = $ilDB->fetchAssoc($rset);
11088
11089 return (bool) $row['cnt'] > 0;
11090 }
11091
11092 public function setAutosave($autosave)
11093 {
11094 $this->autosave = $autosave;
11095 }
11096
11097 public function getAutosave()
11098 {
11099 return $this->autosave;
11100 }
11101
11103 {
11104 $this->autosave_ival = $autosave_ival;
11105 }
11106
11107 public function getAutosaveIval()
11108 {
11109 return $this->autosave_ival;
11110 }
11111
11117 public function isPassDeletionAllowed()
11118 {
11120 }
11121
11128 {
11129 $this->passDeletionAllowed = (bool) $passDeletionAllowed;
11130 }
11131
11132 #region Examview / PDF Examview
11137 {
11138 $this->show_examview_html = $show_examview_html;
11139 }
11140
11144 public function getShowExamviewHtml()
11145 {
11147 }
11148
11153 {
11154 $this->show_examview_pdf = $show_examview_pdf;
11155 }
11156
11160 public function getShowExamviewPdf()
11161 {
11163 }
11164
11169 {
11170 $this->enable_examview = $enable_examview;
11171 }
11172
11176 public function getEnableExamview()
11177 {
11179 }
11180
11181 #endregion
11182
11184 {
11185 $this->activation_starting_time = $starting_time;
11186 }
11187
11189 {
11190 $this->activation_ending_time = $ending_time;
11191 }
11192
11194 {
11195 return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : null;
11196 }
11197
11198 public function getActivationEndingTime()
11199 {
11200 return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : null;
11201 }
11202
11204 {
11205 global $ilDB;
11206
11207 $times = array();
11208 $result = $ilDB->queryF("SELECT tst_times.active_fi, tst_times.started FROM tst_times, tst_active WHERE tst_times.active_fi = tst_active.active_id AND tst_active.test_fi = %s ORDER BY tst_times.tstamp DESC",
11209 array('integer'),
11210 array($this->getTestId())
11211 );
11212 while ($row = $ilDB->fetchAssoc($result)) {
11213 $times[$row['active_fi']] = $row['started'];
11214 }
11215 return $times;
11216 }
11217
11219 {
11220 global $ilDB;
11221
11222 $times = array();
11223 $result = $ilDB->queryF(
11224 "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",
11225 array('integer'),
11226 array($this->getTestId())
11227 );
11228 while ($row = $ilDB->fetchAssoc($result)) {
11229 $times[$row['active_fi']] = $row['additionaltime'];
11230 }
11231 return $times;
11232 }
11233
11234 public function getExtraTime($active_id)
11235 {
11236 global $ilDB;
11237
11238 $result = $ilDB->queryF(
11239 "SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11240 array('integer'),
11241 array($active_id)
11242 );
11243 if ($result->numRows() > 0) {
11244 $row = $ilDB->fetchAssoc($result);
11245 return $row['additionaltime'];
11246 }
11247 return 0;
11248 }
11249
11250 public function addExtraTime($active_id, $minutes)
11251 {
11252 global $ilDB;
11253
11254 $participants = array();
11255 if ($active_id == 0) {
11256 $result = $ilDB->queryF(
11257 "SELECT active_id FROM tst_active WHERE test_fi = %s",
11258 array('integer'),
11259 array($this->getTestId())
11260 );
11261 while ($row = $ilDB->fetchAssoc($result)) {
11262 array_push($participants, $row['active_id']);
11263 }
11264 } else {
11265 array_push($participants, $active_id);
11266 }
11267 foreach ($participants as $active_id) {
11268 $result = $ilDB->queryF(
11269 "SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11270 array('integer'),
11271 array($active_id)
11272 );
11273 if ($result->numRows() > 0) {
11274 $ilDB->manipulateF(
11275 "DELETE FROM tst_addtime WHERE active_fi = %s",
11276 array('integer'),
11277 array($active_id)
11278 );
11279 }
11280
11281 $ilDB->manipulateF(
11282 "UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11283 array('integer','integer','timestamp','integer'),
11284 array(0, 0, null, $active_id)
11285 );
11286
11287 $ilDB->manipulateF(
11288 "INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11289 array('integer','integer','integer'),
11290 array($active_id, $minutes, time())
11291 );
11292
11293 require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11295 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11296 }
11297 }
11298 }
11299
11306 {
11307 $this->enable_archiving = $enable_archiving;
11308 return $this;
11309 }
11310
11314 public function getEnableArchiving()
11315 {
11317 }
11318
11319 public function getMaxPassOfTest()
11320 {
11324 global $ilDB;
11325
11326 $query = '
11327 SELECT MAX(tst_pass_result.pass) + 1 max_res
11328 FROM tst_pass_result
11329 INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11330 WHERE test_fi = ' . $ilDB->quote($this->getTestId(), 'integer') . '
11331 ';
11332 $res = $ilDB->query($query);
11333 $data = $ilDB->fetchAssoc($res);
11334 return (int) $data['max_res'];
11335 }
11336
11342 public static function lookupExamId($active_id, $pass)
11343 {
11344 global $ilDB;
11345
11346 $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11347 $exam_id_result = $ilDB->queryF($exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ));
11348 if ($ilDB->numRows($exam_id_result) == 1) {
11349 $exam_id_row = $ilDB->fetchAssoc($exam_id_result);
11350
11351 if ($exam_id_row['exam_id'] != null) {
11352 return $exam_id_row['exam_id'];
11353 }
11354 }
11355
11356 return null;
11357 }
11358
11365 public static function buildExamId($active_id, $pass, $test_obj_id = null)
11366 {
11367 global $ilSetting;
11368
11369 $inst_id = $ilSetting->get('inst_id', null);
11370
11371 if ($test_obj_id === null) {
11372 $obj_id = self::_getObjectIDFromActiveID($active_id);
11373 } else {
11374 $obj_id = $test_obj_id;
11375 }
11376
11377 $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11378
11379 return $examId;
11380 }
11381
11383 {
11384 $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11385 }
11386
11388 {
11390 }
11391
11396 {
11397 $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11398 }
11399
11404 {
11406 }
11407
11412 {
11413 $this->sign_submission = $sign_submission;
11414 }
11415
11419 public function getSignSubmission()
11420 {
11422 }
11423
11427 public function setCharSelectorAvailability($availability)
11428 {
11429 $this->char_selector_availability = (int) $availability;
11430 }
11431
11436 {
11438 }
11439
11443 public function setCharSelectorDefinition($definition = '')
11444 {
11445 $this->char_selector_definition = $definition;
11446 }
11447
11452 {
11454 }
11455
11456
11463 {
11464 $this->questionSetType = $questionSetType;
11465 }
11466
11472 public function getQuestionSetType()
11473 {
11475 }
11476
11484 public static function lookupQuestionSetType($objId)
11485 {
11486 global $ilDB;
11487
11488 $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
11489
11490 $res = $ilDB->queryF($query, array('integer'), array($objId));
11491
11492 $questionSetType = null;
11493
11494 while ($row = $ilDB->fetchAssoc($res)) {
11495 $questionSetType = $row['question_set_type'];
11496 }
11497
11498 return $questionSetType;
11499 }
11500
11506 public function isFixedTest()
11507 {
11509 }
11510
11516 public function isRandomTest()
11517 {
11519 }
11520
11526 public function isDynamicTest()
11527 {
11529 }
11530
11538 public static function _lookupRandomTest($a_obj_id)
11539 {
11541 }
11542
11544 {
11545 switch ($questionSetType) {
11547 return $lng->txt('tst_question_set_type_fixed');
11548
11550 return $lng->txt('tst_question_set_type_random');
11551
11553 return $lng->txt('tst_question_set_type_dynamic');
11554 }
11555
11556 throw new ilTestException('invalid question set type value given: ' . $questionSetType);
11557 }
11558
11559 public function participantDataExist()
11560 {
11561 if ($this->participantDataExist === null) {
11562 $this->participantDataExist = (bool) $this->evalTotalPersons();
11563 }
11564
11566 }
11567
11569 {
11570 if ($this->getScoreReporting() == 4) {
11571 return false;
11572 }
11573
11574 if ($this->getScoreReporting() == 3 && $this->getReportingDate() > time()) {
11575 return false;
11576 }
11577
11578 return true;
11579 }
11580
11581 public function recalculateScores($preserve_manscoring = false)
11582 {
11583 require_once 'class.ilTestScoring.php';
11584 $scoring = new ilTestScoring($this);
11585 $scoring->setPreserveManualScores($preserve_manscoring);
11586 $scoring->recalculateSolutions();
11587 }
11588
11589 public static function getPoolQuestionChangeListeners(ilDBInterface $db, $poolObjId)
11590 {
11591 require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
11592
11593 $questionChangeListeners = array(
11595 );
11596
11597 return $questionChangeListeners;
11598 }
11599
11600 public static function getTestObjIdsWithActiveForUserId($userId)
11601 {
11602 global $ilDB;
11603
11604 $query = "
11605 SELECT obj_fi
11606 FROM tst_active
11607 INNER JOIN tst_tests
11608 ON test_id = test_fi
11609 WHERE user_fi = %s
11610 ";
11611
11612 $res = $ilDB->queryF($query, array('integer'), array($userId));
11613
11614 $objIds = array();
11615
11616 while ($row = $ilDB->fetchAssoc($res)) {
11617 $objIds[] = (int) $row['obj_fi'];
11618 }
11619
11620 return $objIds;
11621 }
11622
11624 {
11625 $this->skillServiceEnabled = $skillServiceEnabled;
11626 }
11627
11628 public function isSkillServiceEnabled()
11629 {
11631 }
11632
11634 {
11635 $this->resultFilterTaxIds = $resultFilterTaxIds;
11636 }
11637
11638 public function getResultFilterTaxIds()
11639 {
11641 }
11642
11644 {
11645 if (!$this->isSkillServiceEnabled()) {
11646 return false;
11647 }
11648
11649 if (!self::isSkillManagementGloballyActivated()) {
11650 return false;
11651 }
11652
11653 return true;
11654 }
11655
11657
11658 public static function isSkillManagementGloballyActivated()
11659 {
11660 if (self::$isSkillManagementGloballyActivated === null) {
11661 include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
11662 $skmgSet = new ilSkillManagementSettings();
11663
11664 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
11665 }
11666
11668 }
11669
11671 {
11672 $this->showGradingStatusEnabled = $showGradingStatusEnabled;
11673 }
11674
11676 {
11678 }
11679
11681 {
11682 $this->showGradingMarkEnabled = $showGradingMarkEnabled;
11683 }
11684
11685
11687 {
11689 }
11690
11692 {
11693 $this->instantFeedbackAnswerFixationEnabled = $instantFeedbackAnswerFixationEnabled;
11694 }
11695
11697 {
11699 }
11700
11705 {
11707 }
11708
11713 {
11714 $this->forceInstantFeedbackEnabled = $forceInstantFeedbackEnabled;
11715 }
11716
11717 public static function ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run = false)
11718 {
11719 global $ilDB, $lng, $ilPluginAdmin;
11720
11721 /* @var ilObjTest $testOBJ */
11722
11723 $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId, false);
11724
11725 $activeId = $testOBJ->getActiveIdOfUser($userId);
11726
11727 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
11728 $testSessionFactory = new ilTestSessionFactory($testOBJ);
11729
11730 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
11731 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
11732
11733 $testSession = $testSessionFactory->getSession($activeId);
11734 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
11735 $testSequence->loadFromDb();
11736
11737 // begin-patch lok changed smeyer
11738 if ($a_force_new_run) {
11739 if ($testSequence->hasSequence()) {
11740 $testSession->increasePass();
11741 }
11742 $testSession->setLastSequence(0);
11743 $testSession->saveToDb();
11744 }
11745 // end-patch lok
11746 }
11747
11748 public static function isParticipantsLastPassActive($testRefId, $userId)
11749 {
11750 global $ilDB, $lng, $ilPluginAdmin;
11751
11752 /* @var ilObjTest $testOBJ */
11753
11754 $testOBJ = ilObjectFactory::getInstanceByRefId($testRefId, false);
11755
11756
11757 $activeId = $testOBJ->getActiveIdOfUser($userId);
11758
11759 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
11760 $testSessionFactory = new ilTestSessionFactory($testOBJ);
11761 // Added temporarily bugfix smeyer
11762 $testSessionFactory->reset();
11763
11764 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
11765 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
11766
11767 $testSession = $testSessionFactory->getSession($activeId);
11768 $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $testSession->getPass());
11769 $testSequence->loadFromDb();
11770
11771 return $testSequence->hasSequence();
11772 }
11773
11777 public function isTestFinalBroken()
11778 {
11780 }
11781
11786 {
11787 $this->testFinalBroken = $testFinalBroken;
11788 }
11789
11790 public function adjustTestSequence()
11791 {
11795 global $ilDB;
11796
11797 $query = "
11798 SELECT COUNT(test_question_id) cnt
11799 FROM tst_test_question
11800 WHERE test_fi = %s
11801 ORDER BY sequence
11802 ";
11803
11804 $questRes = $ilDB->queryF($query, array('integer'), array($this->getTestId()));
11805
11806 $row = $ilDB->fetchAssoc($questRes);
11807 $questCount = $row['cnt'];
11808
11809 if ($this->getShuffleQuestions()) {
11810 $query = "
11811 SELECT tseq.*
11812 FROM tst_active tac
11813 INNER JOIN tst_sequence tseq
11814 ON tseq.active_fi = tac.active_id
11815 WHERE tac.test_fi = %s
11816 ";
11817
11818 $partRes = $ilDB->queryF(
11819 $query,
11820 array('integer'),
11821 array($this->getTestId())
11822 );
11823
11824 while ($row = $ilDB->fetchAssoc($partRes)) {
11825 $sequence = @unserialize($row['sequence']);
11826
11827 if (!$sequence) {
11828 $sequence = array();
11829 }
11830
11831 $sequence = array_filter($sequence, function ($value) use ($questCount) {
11832 return $value <= $questCount;
11833 });
11834
11835 $num_seq = count($sequence);
11836 if ($questCount > $num_seq) {
11837 $diff = $questCount - $num_seq;
11838 for ($i = 1; $i <= $diff; $i++) {
11839 $sequence[$num_seq + $i - 1] = $num_seq + $i;
11840 }
11841 }
11842
11843 $new_sequence = serialize($sequence);
11844
11845 $ilDB->update('tst_sequence', array(
11846 'sequence' => array('clob', $new_sequence)
11847 ), array(
11848 'active_fi' => array('integer', $row['active_fi']),
11849 'pass' => array('integer', $row['pass'])
11850 ));
11851 }
11852 } else {
11853 $new_sequence = serialize($questCount > 0 ? range(1, $questCount) : array());
11854
11855 $query = "
11856 SELECT tseq.*
11857 FROM tst_active tac
11858 INNER JOIN tst_sequence tseq
11859 ON tseq.active_fi = tac.active_id
11860 WHERE tac.test_fi = %s
11861 ";
11862
11863 $part_rest = $ilDB->queryF(
11864 $query,
11865 array('integer'),
11866 array($this->getTestId())
11867 );
11868
11869 while ($row = $ilDB->fetchAssoc($part_rest)) {
11870 $ilDB->update('tst_sequence', array(
11871 'sequence' => array('clob', $new_sequence)
11872 ), array(
11873 'active_fi' => array('integer', $row['active_fi']),
11874 'pass' => array('integer', $row['pass'])
11875 ));
11876 }
11877 }
11878 }
11879}
sprintf('%.4f', $callTime)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
$result
$total
Definition: Utf8Test.php:87
$test
Definition: Utf8Test.php:84
$files
Definition: add-vimline.php:18
if(!isset( $_REQUEST[ 'ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
Definition: as_login.php:20
$_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, $a_skip_day=false, $a_include_wd=false)
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 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 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 _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.
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.
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.
getAnsweredQuestionCount($active_id, $pass=null)
Retrieves the number of answered questions for a given user in a given test.
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.
canShowSolutionPrintview($user_id=null)
Calculates if a user may see the solution printview of his/her test results.
getEnableProcessingTime()
Returns the state of the processing time (enabled/disabled)
setShowKioskModeParticipant($a_participant=false)
Set to true, if the participant's name should be shown in kiosk mode.
getListOfQuestionsStart()
Returns if the list of questions should be presented as the first page of the test.
& getExistingQuestions($pass=null)
Get the id's of the questions which are already part of the test.
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
setAllowedUsers($a_allowed_users)
isNrOfTriesReached($tries)
returns if number of tries are reached
reindexFixedQuestionOrdering()
static getTestObjIdsWithActiveForUserId($userId)
setKioskMode($a_kiosk=false)
Sets the kiosk mode for the test.
setTemplate($template_id)
setShowExamviewPdf($show_examview_pdf)
setShowSolutionSignature($a_signature=false)
Set to TRUE, if the signature field should be shown in the solution.
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
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)
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)
isPreviousSolutionReuseEnabled($activeId)
getFixedParticipants()
Returns the fixed participants status.
isBestSolutionPrintedWithResult()
_lookupRandomTestFromActiveId($active_id)
Returns the random status of a test with a given object id.
setPassword($a_password=null)
Sets the password for test access.
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.
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.
setEndingTimeEnabled($ending_time_enabled)
loadQuestions($active_id="", $pass=null)
Load the test question id's from the database.
& getCompleteEvaluationData($withStatistics=true, $filterby="", $filtertext="")
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.
setRedirectionUrl($redirection_url=null)
hasQuestionsWithoutQuestionpool()
$print_best_solution_with_result
setCountSystem($a_count_system=COUNT_PARTIAL_SOLUTIONS)
Sets the count system for the calculation of points.
buildIso8601PeriodFromUnixtimeForExportCompatibility($unix_timestamp)
$instantFeedbackAnswerFixationEnabled
static _getUsePreviousAnswers($active_id, $user_active_user_setting=false)
Returns if the previous results should be hidden for a learner.
getImagePath()
Returns the image path for web accessable images of a test The image path is under the CLIENT_WEB_DIR...
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
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.
isExecutable($testSession, $user_id, $allowPassIncrease=false)
Checks if the test is executable by the given 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)
setListOfQuestions($a_value=true)
Sets if the the list of questions should be presented to the user or not.
& 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.
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='')
getKiosk()
Returns the kiosk mode.
getResultsForActiveId($active_id)
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)
$online
the object's online status
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.
randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id=0, $qpls="", $pass=null)
Returns a random selection of questions.
setIntroductionEnabled($introductionEnabled)
getProcessingTimeInSeconds($active_id="")
Returns the processing time for the test in seconds.
static lookupLastTestPassAccess($activeId, $passIndex)
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.
prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
setListOfQuestionsEnd($a_value=true)
Sets if the the list of questions as the end page of the test.
getTestParticipantsForManualScoring($filter=null)
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.
setActivationStartingTime($starting_time=null)
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.
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
setShowSolutionListComparison($a_comparison=false)
Set to TRUE, if the list of answers should be shown prior to finish the test.
getQuestionDataset($question_id)
Returns the dataset for a given question id.
& 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.
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.
setActivationEndingTime($ending_time=null)
& 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.
saveToDb($properties_only=false)
Saves a ilObjTest object to a database.
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.
& getWorkedQuestions($active_id, $pass=null)
Gets the id's of all questions a user already worked through.
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)
& processCSVRow($row, $quoteAll=false, $separator=";")
Processes an array as a CSV row and converts the array values to correct CSV values.
setMailNotificationType($a_type)
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)
& 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.
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.
deliverPDFfromHTML($content, $title=null)
Delivers a PDF file from XHTML.
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
setShowSolutionSuggested($a_solution=false)
Set to TRUE, if the suggested solution should be shown in the solution.
getEndingTime()
Returns the ending time of the test.
static _getAvailableTests($use_object_id=false)
Returns the available tests for the active user.
setShowKioskModeTitle($a_title=false)
Set to true, if the full test title should be shown in kiosk mode.
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.
setStartingTime($starting_time=null)
Sets the starting time in database timestamp format for the test.
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)
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.
& getAllQuestions($pass=null)
Returns all questions of a test in test order.
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.
setShowSolutionAnswersOnly($a_full=true)
Set to true, if the full solution (including the ILIAS content pages) should be shown in the solution...
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)
toXML()
Returns a QTI xml representation of the test.
& getRoleData($ids)
static lookupPassResultsUpdateTimestamp($active_id, $pass)
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.
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.
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.
setListOfQuestionsStart($a_value=true)
Sets if the the list of questions as the start page of the test.
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.
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}
setShowSolutionFeedback($a_feedback=true)
Sets if the the feedback should be presented to the user in the solution or not.
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.
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.
& 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.
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.
setListOfQuestionsDescription($a_value=true)
Sets the show_summary attribute to TRUE if the list of questions should be presented with the questio...
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
update()
update object data
canShowCertificate($testSession, $user_id, $active_id)
Checks whether the certificate button could be shown on the info page or not.
getTextAnswer($active_id, $question_id, $pass=null)
Returns the text answer of a given user for a given question.
userLookupFullName($user_id, $overwrite_anonymity=false, $sorted_order=false, $suffix="")
Returns the full name of a test user according to the anonymity status.
getNrOfResultsForPass($active_id, $pass)
Calculates the number of user results for a specific test pass.
createRandomSolutions($number)
getECTSFX()
{float|null}
setExportSettings($a_settings)
setEndingTime($ending_time=null)
Sets the ending time in database timestamp format for the test.
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.
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.
static ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run=false)
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.
setCustomStyle($a_customStyle=null)
Set the custom style.
const SCORE_REPORTING_DISABLED
setTmpCopyWizardCopyId($tmpCopyWizardCopyId)
getVisitTimeOfParticipant($active_id)
Returns the first and last visit of a participant.
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)
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
$key
Definition: croninfo.php:18
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
$userdata
Definition: demo.php:48
$i
Definition: disco.tpl.php:19
$html
Definition: example_001.php:87
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.
$time
Definition: cron.php:21
if($format !==null) $name
Definition: metadata.php:146
$index
Definition: metadata.php:60
$xml
Definition: metadata.php:240
$keys
update($pash, $contents, Config $config)
redirection script todo: (a better solution should control the processing via a xml file)
global $ilSetting
Definition: privfeed.php:17
$query
if(!file_exists("$old.txt")) if( $old===$new) if(file_exists("$new.txt")) $file
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
$datasets
Definition: showstats.php:61
global $ilDB
$results
Definition: svg-scanner.php:47
$mobs
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92
$params
Definition: disable.php:11
$rows
Definition: xhr_table.php:10