19 declare(strict_types=1);
157 public function __construct(
int $id = 0,
bool $a_call_by_reference =
true)
163 $this->
ctrl = $DIC[
'ilCtrl'];
165 $this->
settings = $DIC[
'ilSetting'];
166 $this->bench = $DIC[
'ilBench'];
167 $this->component_repository = $DIC[
'component.repository'];
168 $this->component_factory = $DIC[
'component.factory'];
169 $this->filesystem_web = $DIC->filesystem()->web();
170 $this->lo_metadata = $DIC->learningObjectMetadata();
173 $this->participant_access_filter = $local_dic[
'participant.access_filter.factory'];
174 $this->test_man_scoring_done_helper = $local_dic[
'scoring.manual.done_helper'];
175 $this->
logger = $local_dic[
'logging.logger'];
176 $this->log_viewer = $local_dic[
'logging.viewer'];
177 $this->global_settings_repo = $local_dic[
'settings.global.repository'];
178 $this->marks_repository = $local_dic[
'marks.repository'];
179 $this->questionrepository = $local_dic[
'question.general_properties.repository'];
180 $this->testrequest = $local_dic[
'request_data_collector'];
181 $this->participant_repository = $local_dic[
'participant.repository'];
182 $this->export_factory = $local_dic[
'exportimport.factory'];
186 $this->
lng->loadLanguageModule(
"assessment");
187 $this->score_settings = null;
194 $this->component_repository,
196 $this->questionrepository
202 return TestDIC::dic();
217 return $this->question_set_config_factory->getQuestionSetConfig();
240 $id = parent::create();
247 if (!parent::update()) {
259 $this->main_settings = null;
260 $this->score_settings = null;
261 $this->mark_schema = null;
265 public function delete():
bool 268 if (!parent::delete()) {
279 $qsaImportFails->deleteRegisteredImportFails();
281 $sltImportFails->deleteRegisteredImportFails();
283 if ($this->
logger->isLoggingEnabled()) {
284 $this->
logger->logTestAdministrationInteraction(
285 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
287 $this->
user->getId(),
290 AdditionalInformationGenerator::KEY_TEST_TITLE => $test_title =
$this->title 302 $participantData->load($this->
getTestId());
305 $this->db->manipulateF(
306 "DELETE FROM tst_mark WHERE test_fi = %s",
311 $this->db->manipulateF(
312 "DELETE FROM tst_tests WHERE test_id = %s",
318 $directory = $tst_data_dir .
"/tst_" . $this->
getId();
319 if (is_dir($directory)) {
327 foreach ($mobs as $mob) {
345 if (!is_writable($tst_data_dir)) {
346 $this->
ilias->raiseError(
"Test Data Directory (" . $tst_data_dir
347 .
") not writeable.", $this->
ilias->error_obj->MESSAGE);
351 $tst_dir = $tst_data_dir .
"/tst_" . $this->
getId();
353 if (!@is_dir($tst_dir)) {
354 $this->
ilias->raiseError(
"Creation of Test Directory failed.", $this->
ilias->error_obj->MESSAGE);
357 $export_dir = $tst_dir .
"/export";
359 if (!@is_dir($export_dir)) {
360 $this->
ilias->raiseError(
"Creation of Export Directory failed.", $this->
ilias->error_obj->MESSAGE);
370 public function getExportFiles(
string $dir =
''): array
373 if (!@is_dir($dir) || !is_writable($dir)) {
382 if ($file->isDir()) {
386 $files[] = $file->getBasename();
406 if (!is_writable($tst_data_dir)) {
408 .
") not writeable.",
$ilias->error_obj->FATAL);
412 $tst_dir = $tst_data_dir .
"/tst_import";
414 if (!@is_dir($tst_dir)) {
441 if ($this->
isComplete($test_question_set_config)) {
445 $this->db->manipulateF(
446 'UPDATE tst_tests SET complete = %s WHERE test_id = %s',
448 [$complete, $this->test_id]
453 public function saveToDb(
bool $properties_only =
false): void
455 if ($this->test_id === -1) {
457 $next_id = $this->db->nextId(
'tst_tests');
462 'test_id' => [
'integer', $next_id],
463 'obj_fi' => [
'integer', $this->
getId()],
464 'created' => [
'integer', time()],
465 'tstamp' => [
'integer', time()],
470 $this->test_id = $next_id;
476 $aresult = $this->db->queryF(
477 "SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = %s",
478 [
'integer',
'integer',
'integer'],
481 while ($row = $this->db->fetchAssoc($aresult)) {
482 $this->db->manipulateF(
483 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
484 [
'integer',
'timestamp',
'integer'],
485 [1, date(
'Y-m-d H:i:s'), $row[
"active_id"]]
490 $aresult = $this->db->queryF(
491 "SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = %s",
492 [
'integer',
'integer',
'integer'],
495 while ($row = $this->db->fetchAssoc($aresult)) {
496 $this->db->manipulateF(
497 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
498 [
'integer',
'timestamp',
'integer'],
499 [0, null, $row[
"active_id"]]
504 $aresult = $this->db->queryF(
505 "SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = %s",
506 [
'integer',
'integer'],
509 while ($row = $this->db->fetchAssoc($aresult)) {
510 $this->db->manipulateF(
511 "UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
512 [
'integer',
'timestamp',
'integer'],
513 [0, null, $row[
"active_id"]]
527 if ($properties_only) {
535 $this->marks_repository->storeMarkSchema($this->
getMarkSchema());
540 $this->db->manipulateF(
541 'DELETE FROM tst_test_question WHERE test_fi = %s',
545 foreach ($this->questions as $key => $value) {
546 $next_id = $this->db->nextId(
'tst_test_question');
547 $this->db->insert(
'tst_test_question', [
548 'test_question_id' => [
'integer', $next_id],
549 'test_fi' => [
'integer', $this->
getTestId()],
550 'question_fi' => [
'integer', $value],
551 'sequence' => [
'integer', $key],
552 'tstamp' => [
'integer', time()]
565 foreach ($question_ids as
$id) {
566 $question = assQuestion::instantiateQuestionGUI($id);
568 $title = $question->getObject()->getTitle();
570 while (in_array(
$title .
' (' . $i .
')', $question_titles)) {
574 $title .=
' (' . $i .
')';
576 $question_titles[] =
$title;
578 $new_id = $question->getObject()->duplicate(
false,
$title);
580 $clone = assQuestion::instantiateQuestionGUI($new_id);
581 $question = $clone->getObject();
582 $question->setObjId($this->
getId());
583 $clone->setObject($question);
584 $clone->getObject()->saveToDb();
598 $result = $this->db->queryF(
599 "SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
600 [
'integer',
'integer'],
603 return $result->numRows();
608 $result = $this->db->queryF(
609 "SELECT test_id FROM tst_tests WHERE obj_fi = %s",
613 if ($result->numRows() === 1) {
614 $data = $this->db->fetchObject($result);
620 if (isset($this->ref_id)) {
622 switch ($activation[
"timing_type"]) {
643 $this->questions = [];
645 if ($active_id === 0) {
648 if (is_null($pass)) {
649 $pass = self::_getPass($active_id);
651 $result = $this->db->queryF(
652 'SELECT tst_test_rnd_qst.* ' 653 .
'FROM tst_test_rnd_qst, qpl_questions ' 654 .
'WHERE tst_test_rnd_qst.active_fi = %s ' 655 .
'AND qpl_questions.question_id = tst_test_rnd_qst.question_fi ' 656 .
'AND tst_test_rnd_qst.pass = %s ' 657 .
'ORDER BY sequence',
658 [
'integer',
'integer'],
662 $result = $this->db->queryF(
663 'SELECT tst_test_question.* ' 664 .
'FROM tst_test_question, qpl_questions ' 665 .
'WHERE tst_test_question.test_fi = %s ' 666 .
'AND qpl_questions.question_id = tst_test_question.question_fi ' 667 .
'ORDER BY sequence',
673 if ($this->test_id !== -1) {
675 while (
$data = $this->db->fetchAssoc($result)) {
676 $this->questions[$index++] =
$data[
"question_fi"];
683 $page_id = $this->
getMainSettings()->getIntroductionSettings()->getIntroductionPageId();
684 if ($page_id !== null) {
688 return $this->
getMainSettings()->getIntroductionSettings()->getIntroductionText();
693 $page_id = $this->
getMainSettings()->getIntroductionSettings()->getIntroductionPageId();
694 if ($page_id === null) {
702 $page_id = $this->
getMainSettings()->getFinishingSettings()->getConcludingRemarksPageId();
703 if ($page_id !== null) {
706 return $this->
getMainSettings()->getFinishingSettings()->getConcludingRemarksText();
711 $page_id = $this->
getMainSettings()->getFinishingSettings()->getConcludingRemarksPageId();
712 if ($page_id === null) {
721 $page_object->setParentId($this->
getId());
722 $new_page_id = $page_object->createPageWithNextId();
723 (
new ilTestPage($source_page_id))->copy($new_page_id);
737 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getPostponedQuestionsMoveToEnd();
742 return $this->
getScoreSettings()->getResultSummarySettings()->getScoreReporting()->isReportingEnabled();
747 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getInstantFeedbackPointsEnabled();
752 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getInstantFeedbackGenericEnabled();
757 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getInstantFeedbackSolutionEnabled();
768 $ilDB = $DIC[
'ilDB'];
769 $result =
$ilDB->queryF(
770 "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",
774 if ($result->numRows()) {
775 $row =
$ilDB->fetchAssoc($result);
776 return $row[
"count_system"];
803 $ilDB = $DIC[
'ilDB'];
804 $result =
$ilDB->queryF(
805 "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",
809 if ($result->numRows()) {
810 $row =
$ilDB->fetchAssoc($result);
811 return (
int) $row[
"pass_scoring"];
822 $ilDB = $DIC[
'ilDB'];
823 $result =
$ilDB->queryF(
824 "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",
828 if ($result->numRows()) {
829 $row =
$ilDB->fetchAssoc($result);
830 return (
bool) $row[
"score_cutting"];
837 if ($this->mark_schema === null) {
838 $this->mark_schema = $this->marks_repository->getMarkSchemaFor($this->
getTestId());
846 $this->marks_repository->storeMarkSchema($mark_schema);
847 $this->mark_schema = null;
852 return $this->
getMainSettings()->getTestBehaviourSettings()->getNumberOfTries();
857 return $this->
getMainSettings()->getTestBehaviourSettings()->getBlockAfterPassedEnabled();
862 return $this->
getMainSettings()->getTestBehaviourSettings()->getKioskModeEnabled();
867 return $this->
getMainSettings()->getTestBehaviourSettings()->getShowTitleInKioskMode();
871 return $this->
getMainSettings()->getTestBehaviourSettings()->getShowParticipantNameInKioskMode();
876 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed();
881 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getQuestionTitleOutputMode();
886 $result = $this->db->queryF(
887 "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",
891 if ($result->numRows()) {
892 $row = $this->db->fetchAssoc($result);
893 $test_allows_reuse = $row[
"use_previous_answers"];
896 if ($test_allows_reuse ===
'1') {
897 $res = $this->
user->getPref(
"tst_use_previous_answers");
907 return $this->
getMainSettings()->getTestBehaviourSettings()->getProcessingTime();
912 $processing_time = $this->
getMainSettings()->getTestBehaviourSettings()->getProcessingTime();
913 if ($processing_time === null
914 || $processing_time ===
'' 915 || !preg_match(
'/(\d{2}):(\d{2}):(\d{2})/is', $processing_time, $matches)
930 $processing_time = $this->
getMainSettings()->getTestBehaviourSettings()->getProcessingTime() ??
'';
931 if (preg_match(
"/(\d{2}):(\d{2}):(\d{2})/", (
string) $processing_time, $matches)) {
933 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
941 return $this->
getMainSettings()->getTestBehaviourSettings()->getProcessingTimeEnabled();
946 return $this->
getMainSettings()->getTestBehaviourSettings()->getResetProcessingTime();
951 return $this->
getMainSettings()->getAccessSettings()->getStartTimeEnabled();
956 $start_time = $this->
getMainSettings()->getAccessSettings()->getStartTime();
957 return $start_time !== null ? $start_time->getTimestamp() : 0;
962 return $this->
getMainSettings()->getAccessSettings()->getEndTimeEnabled();
967 $end_time = $this->
getMainSettings()->getAccessSettings()->getEndTime();
968 return $end_time !== null ? $end_time->getTimestamp() : 0;
973 return $this->
getMainSettings()->getFinishingSettings()->getRedirectionMode();
978 return $this->
getMainSettings()->getFinishingSettings()->getRedirectionMode() === self::REDIRECT_KIOSK;
983 return $this->
getMainSettings()->getFinishingSettings()->getRedirectionMode() === self::REDIRECT_NONE;
988 return $this->
getMainSettings()->getFinishingSettings()->getRedirectionUrl() ??
'';
993 return $this->
getMainSettings()->getAccessSettings()->getPasswordEnabled();
1021 $participant_data->load($this->test_id);
1023 $question->removeAllExistingSolutions();
1030 $participant_data->getActiveIds(),
1037 $question->delete($question_id);
1046 if ($this->
logger->isLoggingEnabled()) {
1047 $this->
logger->logTestAdministrationInteraction(
1048 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
1050 $this->
user->getId(),
1051 TestAdministrationInteractionTypes::QUESTION_REMOVED_IN_CORRECTIONS,
1053 AdditionalInformationGenerator::KEY_QUESTION_TITLE => $question->getTitleForHTMLOutput(),
1054 AdditionalInformationGenerator::KEY_QUESTION_TEXT => $question->getQuestion(),
1055 AdditionalInformationGenerator::KEY_QUESTION_ID => $question->getId(),
1056 AdditionalInformationGenerator::KEY_QUESTION_TYPE => $question->getQuestionType()
1074 $this->questionrepository
1077 foreach ($active_ids as $active_id) {
1079 $passSelector->setActiveId($active_id);
1081 foreach ($passSelector->getExistingPasses() as $pass) {
1082 $test_sequence = $test_sequence_factory->getSequenceByActiveIdAndPass($active_id, $pass);
1085 $test_sequence->removeQuestion($question_id, $reindexed_sequence_position_map);
1096 foreach ($question_ids as $question_id) {
1106 $question = self::_instanciateQuestion($question_id);
1107 $question_title = $question->getTitleForHTMLOutput();
1108 $question->delete($question_id);
1109 if ($this->
logger->isLoggingEnabled()) {
1110 $this->
logger->logTestAdministrationInteraction(
1111 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
1113 $this->
user->getId(),
1114 TestAdministrationInteractionTypes::QUESTION_REMOVED,
1116 AdditionalInformationGenerator::KEY_QUESTION_TITLE => $question_title
1122 $this->
logger->error($e->getMessage());
1123 $this->
logger->error($e->getTraceAsString());
1140 $participantData->setUserIdsFilter($user_ids);
1141 $participantData->load($this->
getTestId());
1146 if ($this->
logger->isLoggingEnabled()) {
1147 $this->
logger->logTestAdministrationInteraction(
1148 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
1150 $this->
user->getId(),
1151 TestAdministrationInteractionTypes::PARTICIPANT_DATA_REMOVED,
1153 AdditionalInformationGenerator::KEY_USERS => $participantData->getUserIds()
1169 $this->participant_repository->removeExtraTimeByUserId($this->
getTestId(), $user_ids);
1172 if ($participant_data->
getUserIds() !== []) {
1175 if ($test_lp instanceof
ilTestLP) {
1176 $test_lp->setTestObject($this);
1177 $test_lp->resetLPDataForUserIds($participant_data->
getUserIds(),
false);
1180 $this->participant_repository->removeExtraTimeByUserId($this->
getTestId(), $participant_data->
getUserIds());
1190 $this->participant_repository->removeExtraTimeByUserId($this->
getTestId(), $user_ids);
1193 if ($this->
logger->isLoggingEnabled()) {
1194 $this->
logger->logTestAdministrationInteraction(
1195 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
1197 $this->
user->getId(),
1198 TestAdministrationInteractionTypes::PARTICIPANT_DATA_REMOVED,
1200 AdditionalInformationGenerator::KEY_USERS => $participant_data->
getUserIds(),
1211 $participantData->setUserIdsFilter($user_ids);
1212 $participantData->load($this->
getTestId());
1214 $in_user_ids = $this->db->in(
'usr_id', $participantData->getUserIds(),
false,
'integer');
1215 $this->db->manipulateF(
1216 "DELETE FROM usr_pref WHERE {$in_user_ids} AND keyword = %s",
1221 if ($participantData->getActiveIds() !== []) {
1228 $in_active_ids = $this->db->in(
'active_fi', $active_ids,
false,
'integer');
1230 $this->db->manipulate(
"DELETE FROM tst_solutions WHERE {$in_active_ids}");
1231 $this->db->manipulate(
"DELETE FROM tst_qst_solved WHERE {$in_active_ids}");
1232 $this->db->manipulate(
"DELETE FROM tst_test_result WHERE {$in_active_ids}");
1233 $this->db->manipulate(
"DELETE FROM tst_pass_result WHERE {$in_active_ids}");
1234 $this->db->manipulate(
"DELETE FROM tst_result_cache WHERE {$in_active_ids}");
1235 $this->db->manipulate(
"DELETE FROM tst_sequence WHERE {$in_active_ids}");
1236 $this->db->manipulate(
"DELETE FROM tst_times WHERE {$in_active_ids}");
1237 $this->db->manipulate(
1239 .
' WHERE ' . $this->db->in(
'active_id', $active_ids,
false,
'integer')
1243 $this->db->manipulate(
"DELETE FROM tst_test_rnd_qst WHERE {$in_active_ids}");
1246 foreach ($active_ids as $active_id) {
1261 $IN_activeIds = $this->db->in(
'active_id', $active_ids,
false,
'integer');
1262 $this->db->manipulate(
"DELETE FROM tst_active WHERE $IN_activeIds");
1275 $result = $this->db->queryF(
1276 "SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
1277 [
'integer',
'integer'],
1280 $data = $this->db->fetchObject($result);
1281 if (
$data->sequence > 1) {
1283 $result = $this->db->queryF(
1284 "SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
1285 [
'integer',
'integer'],
1288 $data_previous = $this->db->fetchObject($result);
1290 $this->db->manipulateF(
1291 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
1292 [
'integer',
'integer'],
1293 [
$data->sequence, $data_previous->test_question_id]
1296 $this->db->manipulateF(
1297 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
1298 [
'integer',
'integer'],
1299 [
$data->sequence - 1,
$data->test_question_id]
1314 $current_question_result = $this->db->queryF(
1315 "SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
1316 [
'integer',
'integer'],
1319 $current_question_data = $this->db->fetchObject($current_question_result);
1320 $next_question_result = $this->db->queryF(
1321 "SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
1322 [
'integer',
'integer'],
1323 [$this->
getTestId(), $current_question_data->sequence + 1]
1325 if ($this->db->numRows($next_question_result) === 1) {
1327 $next_question_data = $this->db->fetchObject($next_question_result);
1329 $this->db->manipulateF(
1330 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
1331 [
'integer',
'integer'],
1332 [$current_question_data->sequence, $next_question_data->test_question_id]
1335 $this->db->manipulateF(
1336 "UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
1337 [
'integer',
'integer'],
1338 [$current_question_data->sequence + 1, $current_question_data->test_question_id]
1353 $duplicate_id = $question->duplicate(
true,
'',
'', -1, $this->
getId());
1354 return $duplicate_id;
1360 $duplicate_id = $question_id;
1366 $result = $this->db->queryF(
1367 "SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
1373 if ($result->numRows() == 1) {
1374 $data = $this->db->fetchObject($result);
1375 $sequence =
$data->seq + 1;
1378 $next_id = $this->db->nextId(
'tst_test_question');
1379 $this->db->manipulateF(
1380 "INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
1381 [
'integer',
'integer',
'integer',
'integer',
'integer'],
1382 [$next_id, $this->
getTestId(), $duplicate_id, $sequence, time()]
1385 $this->db->manipulateF(
1386 "DELETE FROM tst_active WHERE test_fi = %s",
1391 $this->
saveCompleteStatus($this->question_set_config_factory->getQuestionSetConfig());
1393 if ($this->
logger->isLoggingEnabled()) {
1394 $this->
logger->logTestAdministrationInteraction(
1395 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
1397 $this->
user->getId(),
1398 TestAdministrationInteractionTypes::QUESTION_ADDED,
1400 AdditionalInformationGenerator::KEY_QUESTION_ID => $question_id
1402 ->toLog($this->
logger->getAdditionalInformationGenerator())
1407 return $duplicate_id;
1414 $result = $this->db->queryF(
1415 'SELECT qpl_questions.title FROM tst_test_question, qpl_questions ' 1416 .
'WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ' 1417 .
'ORDER BY tst_test_question.sequence',
1421 while ($row = $this->db->fetchAssoc($result)) {
1422 array_push($titles, $row[
'title']);
1439 $result = $this->db->queryF(
1440 'SELECT qpl_questions.title, qpl_questions.question_id ' 1441 .
'FROM tst_test_question, qpl_questions ' 1442 .
'WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ' 1443 .
'ORDER BY tst_test_question.sequence',
1447 while ($row = $this->db->fetchAssoc($result)) {
1448 $titles[$row[
'question_id']] = $row[
"title"];
1473 return $this->
lng->txt(
"ass_question") .
' ' . $nr;
1475 return $this->
lng->txt(
"ass_question");
1479 $txt = $this->
lng->txt(
"ass_question") .
' ' . $nr;
1481 $txt = $this->
lng->txt(
"ass_question");
1483 if ($points !=
'') {
1484 $lngv = $this->
lng->txt(
'points');
1486 $lngv = $this->
lng->txt(
'point');
1488 $txt .=
' - ' . $points .
' ' . $lngv;
1494 return $this->
lng->txt(
"ass_question");
1508 $result = $this->db->queryF(
1509 "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",
1513 $row = $this->db->fetchObject($result);
1525 $existing_questions = [];
1528 if (is_null($pass)) {
1531 $result = $this->db->queryF(
1532 "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",
1533 [
'integer',
'integer'],
1537 $result = $this->db->queryF(
1538 "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",
1543 while (
$data = $this->db->fetchObject($result)) {
1544 if (
$data->original_id === null) {
1548 array_push($existing_questions,
$data->original_id);
1550 return $existing_questions;
1562 if ($question_id < 1) {
1565 $result = $this->db->queryF(
1566 "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",
1570 if ($result->numRows() == 1) {
1571 $data = $this->db->fetchObject($result);
1572 return $data->type_tag;
1586 $next_id = $this->db->nextId(
'tst_times');
1587 $affectedRows = $this->db->manipulateF(
1588 "INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
1589 [
'integer',
'integer',
'timestamp',
'timestamp',
'integer',
'integer'],
1590 [$next_id, $active_id, date(
"Y-m-d H:i:s"), date(
"Y-m-d H:i:s"), $pass, time()]
1603 $affectedRows = $this->db->manipulateF(
1604 "UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
1605 [
'timestamp',
'integer',
'integer'],
1606 [date(
'Y-m-d H:i:s'), time(), $times_id]
1618 if (is_null($pass)) {
1619 $result = $this->db->queryF(
1620 "SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
1621 [
'integer',
'integer'],
1625 $result = $this->db->queryF(
1626 "SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
1627 [
'integer',
'integer'],
1632 while ($row = $this->db->fetchAssoc($result)) {
1633 array_push($result_array, $row[
"question_fi"]);
1635 return $result_array;
1649 return ((($currentpass > 0) && ($num == 0)) || $this->
isTestFinished($active_id)) ? true :
false;
1662 if ($active_id === null) {
1666 if (count($this->questions) === 0) {
1669 if (is_null($pass)) {
1670 $pass = self::_getPass($active_id);
1672 $result = $this->db->queryF(
1673 "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 " . $this->db->in(
'qpl_questions.question_id', $this->questions,
false,
'integer'),
1674 [
'integer',
'integer'],
1678 if (count($this->questions) === 0) {
1681 $result = $this->db->query(
"SELECT qpl_questions.* FROM qpl_questions, tst_test_question WHERE tst_test_question.question_fi = qpl_questions.question_id AND " . $this->db->in(
'qpl_questions.question_id', $this->questions,
false,
'integer'));
1684 while ($row = $this->db->fetchAssoc($result)) {
1685 $result_array[$row[
"question_id"]] = $row;
1687 return $result_array;
1705 if (is_array($tst_access_code) &&
1707 isset($tst_access_code[$this->
getTestId()]) &&
1708 $tst_access_code[$this->
getTestId()] !==
'') {
1709 $result = $this->db->queryF(
1710 'SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s',
1711 [
'integer',
'integer',
'text'],
1714 } elseif ((
string) $anonymous_id !==
'') {
1715 $result = $this->db->queryF(
1716 'SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s',
1717 [
'integer',
'integer',
'text'],
1718 [
$user_id, $this->test_id, $anonymous_id]
1724 $result = $this->db->queryF(
1725 'SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s',
1726 [
'integer',
'integer'],
1731 if ($result->numRows()) {
1732 $row = $this->db->fetchAssoc($result);
1733 return (
int) $row[
'active_id'];
1742 $ilDB = $DIC[
'ilDB'];
1743 $ilUser = $DIC[
'ilUser'];
1751 $result =
$ilDB->queryF(
1752 "SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
1753 [
'integer',
'integer'],
1756 if ($result->numRows()) {
1757 $row =
$ilDB->fetchAssoc($result);
1758 return $row[
"active_id"];
1772 $keys = array_keys($array);
1775 foreach ($keys as $key) {
1776 $result[$key] = $array[$key];
1790 bool $ordered_sequence =
false,
1791 bool $consider_hidden_questions =
true,
1792 bool $consider_optional_questions =
true 1796 if ($pass === null) {
1801 $test_sequence = $test_sequence_factory->getSequenceByActiveIdAndPass($active_id, $pass);
1803 $test_sequence->setConsiderHiddenQuestionsEnabled($consider_hidden_questions);
1804 $test_sequence->setConsiderOptionalQuestionsEnabled($consider_optional_questions);
1809 if ($ordered_sequence) {
1819 tst_test_result.question_fi, 1820 tst_test_result.points reached, 1821 tst_test_result.hint_count requested_hints, 1822 tst_test_result.hint_points hint_points, 1823 tst_test_result.answered answered, 1824 tst_manual_fb.finalized_evaluation finalized_evaluation 1826 FROM tst_test_result 1828 LEFT JOIN tst_solutions 1829 ON tst_solutions.active_fi = tst_test_result.active_fi 1830 AND tst_solutions.question_fi = tst_test_result.question_fi 1832 LEFT JOIN tst_manual_fb 1833 ON tst_test_result.active_fi = tst_manual_fb.active_fi 1834 AND tst_test_result.question_fi = tst_manual_fb.question_fi 1836 WHERE tst_test_result.active_fi = %s 1837 AND tst_test_result.pass = %s 1840 $solutionresult = $this->db->queryF(
1842 [
'integer',
'integer'],
1846 while ($row = $this->db->fetchAssoc($solutionresult)) {
1847 $arr_results[ $row[
'question_fi'] ] = $row;
1850 $num_worked_through = count($arr_results);
1852 $IN_question_ids = $this->db->in(
'qpl_questions.question_id', $sequence,
false,
'integer');
1855 SELECT qpl_questions.*, 1856 qpl_qst_type.type_tag, 1857 qpl_sol_sug.question_fi has_sug_sol 1862 LEFT JOIN qpl_sol_sug 1863 ON qpl_sol_sug.question_fi = qpl_questions.question_id 1865 WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi 1866 AND $IN_question_ids 1869 $result = $this->db->query($query);
1872 while ($row = $this->db->fetchAssoc($result)) {
1873 if (!isset($arr_results[ $row[
'question_id'] ])) {
1874 $percentvalue = 0.0;
1877 $row[
'points'] ? $arr_results[$row[
'question_id']][
'reached'] / $row[
'points'] : 0
1880 if ($percentvalue < 0) {
1881 $percentvalue = 0.0;
1887 "max" => round($row[
'points'], 2),
1888 "reached" => round($arr_results[$row[
'question_id']][
'reached'] ?? 0, 2),
1889 'requested_hints' => $arr_results[$row[
'question_id']][
'requested_hints'] ?? 0,
1890 'hint_points' => $arr_results[$row[
'question_id']][
'hint_points'] ?? 0,
1891 "percent" => sprintf(
"%2.2f ", ($percentvalue) * 100) .
"%",
1893 "type" => $row[
"type_tag"],
1894 "qid" => $row[
'question_id'],
1895 "original_id" => $row[
"original_id"],
1896 "workedthrough" => isset($arr_results[$row[
'question_id']]) ? 1 : 0,
1897 'answered' => $arr_results[$row[
'question_id']][
'answered'] ?? 0,
1898 'finalized_evaluation' => $arr_results[$row[
'question_id']][
'finalized_evaluation'] ?? 0,
1901 $unordered[ $row[
'question_id'] ] =
$data;
1905 $numQuestionsTotal = count($unordered);
1909 $pass_requested_hints = 0;
1910 $pass_hint_points = 0;
1914 foreach ($sequence as $qid) {
1917 $pass_max += round($unordered[$qid][
'max'], 2);
1918 $pass_reached += round($unordered[$qid][
'reached'], 2);
1919 $pass_requested_hints += $unordered[$qid][
'requested_hints'];
1920 $pass_hint_points += $unordered[$qid][
'hint_points'];
1921 $found[] = $unordered[$qid];
1927 if (
$results[
'reached_points'] < 0) {
1931 if ($pass_reached < 0) {
1936 $found[
'pass'][
'total_max_points'] = $pass_max;
1937 $found[
'pass'][
'total_reached_points'] = $pass_reached;
1938 $found[
'pass'][
'total_requested_hints'] = $pass_requested_hints;
1939 $found[
'pass'][
'total_hint_points'] = $pass_hint_points;
1940 $found[
'pass'][
'percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
1941 $found[
'pass'][
'num_workedthrough'] = $num_worked_through;
1942 $found[
'pass'][
'num_questions_total'] = $numQuestionsTotal;
1944 $found[
"test"][
"total_max_points"] =
$results[
'max_points'];
1945 $found[
"test"][
"total_reached_points"] =
$results[
'reached_points'];
1946 $found[
"test"][
"total_requested_hints"] =
$results[
'hint_count'];
1947 $found[
"test"][
"total_hint_points"] =
$results[
'hint_points'];
1948 $found[
"test"][
"result_pass"] =
$results[
'pass'];
1949 $found[
'test'][
'result_tstamp'] =
$results[
'tstamp'];
1951 if ((!$found[
'pass'][
'total_reached_points']) or (!$found[
'pass'][
'total_max_points'])) {
1954 $percentage = ($found[
'pass'][
'total_reached_points'] / $found[
'pass'][
'total_max_points']) * 100.0;
1956 if ($percentage < 0) {
1961 $found[
"test"][
"passed"] =
$results[
'passed'];
1974 $result = $this->db->queryF(
1975 'SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s',
1979 $row = $this->db->fetchAssoc($result);
1980 return $row[
'total'];
1991 $result = $this->db->queryF(
1992 "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",
1993 [
'integer',
'integer'],
1997 while ($row = $this->db->fetchAssoc($result)) {
1998 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"started"], $matches);
2007 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"finished"], $matches);
2016 $time += ($epoch_2 - $epoch_1);
2041 $result = $this->db->queryF(
2042 "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",
2048 while ($row = $this->db->fetchAssoc($result)) {
2049 if (!array_key_exists($row[
"active_fi"], $times)) {
2050 $times[$row[
"active_fi"]] = 0;
2052 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"started"], $matches);
2061 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"finished"], $matches);
2070 $times[$row[
"active_fi"]] += ($epoch_2 - $epoch_1);
2083 $result = $this->db->queryF(
2084 "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",
2085 [
'integer',
'integer'],
2089 while ($row = $this->db->fetchAssoc($result)) {
2090 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"started"], $matches);
2099 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"finished"], $matches);
2108 $time += ($epoch_2 - $epoch_1);
2115 $result = $this->db->queryF(
2116 "SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
2117 [
'integer',
'integer'],
2121 while ($row = $this->db->fetchAssoc($result)) {
2122 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"started"], $matches);
2131 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"finished"], $matches);
2140 $time += ($epoch_2 - $epoch_1);
2152 $result = $this->db->queryF(
2153 "SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
2160 while ($row = $this->db->fetchObject($result)) {
2161 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
2170 if (!$first_visit) {
2171 $first_visit = $epoch_1;
2173 if ($epoch_1 < $first_visit) {
2174 $first_visit = $epoch_1;
2176 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
2186 $last_visit = $epoch_2;
2188 if ($epoch_2 > $last_visit) {
2189 $last_visit = $epoch_2;
2191 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
2194 foreach ($times as $key => $value) {
2195 $max_time += $value;
2197 if ((!$test_result[
"test"][
"total_reached_points"]) or (!$test_result[
"test"][
"total_max_points"])) {
2200 $percentage = ($test_result[
"test"][
"total_reached_points"] / $test_result[
"test"][
"total_max_points"]) * 100.0;
2201 if ($percentage < 0) {
2205 $mark_obj = $this->
getMarkSchema()->getMatchingMark($percentage);
2206 $first_date = getdate($first_visit);
2207 $last_date = getdate($last_visit);
2208 $qworkedthrough = 0;
2209 foreach ($test_result as $key => $value) {
2210 if (preg_match(
"/\d+/", $key)) {
2211 $qworkedthrough += $value[
"workedthrough"];
2214 if (!$qworkedthrough) {
2217 $atimeofwork = $max_time / $qworkedthrough;
2223 if ($mark_obj !== null) {
2224 $result_mark = $mark_obj->getShortName();
2226 if ($mark_obj->getPassed()) {
2232 $percent_worked_through = 0;
2233 if (count($this->questions)) {
2234 $percent_worked_through = $qworkedthrough / count($this->questions);
2237 "qworkedthrough" => $qworkedthrough,
2238 "qmax" => count($this->questions),
2239 "pworkedthrough" => $percent_worked_through,
2240 "timeofwork" => $max_time,
2241 "atimeofwork" => $atimeofwork,
2242 "firstvisit" => $first_date,
2243 "lastvisit" => $last_date,
2244 "resultspoints" => $test_result[
"test"][
"total_reached_points"],
2245 "maxpoints" => $test_result[
"test"][
"total_max_points"],
2246 "resultsmarks" => $result_mark,
2247 "passed" => $passed,
2248 "distancemedian" =>
"0" 2250 foreach ($test_result as $key => $value) {
2251 if (preg_match(
"/\d+/", $key)) {
2252 $result_array[$key] = $value;
2255 return $result_array;
2267 $totalpoints_array = [];
2269 foreach ($all_users as $active_id => $user_name) {
2271 $reached = $test_result[
"test"][
"total_reached_points"];
2272 $total = $test_result[
"test"][
"total_max_points"];
2273 $percentage = $total != 0 ? $reached / $total : 0;
2274 $mark = $this->
getMarkSchema()->getMatchingMark($percentage * 100.0);
2276 if ($mark !== null && $mark->getPassed()) {
2277 array_push($totalpoints_array, $test_result[
"test"][
"total_reached_points"]);
2280 return $totalpoints_array;
2290 $result = $this->db->queryF(
2291 "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",
2295 $persons_array = [];
2296 while ($row = $this->db->fetchAssoc($result)) {
2297 $name = $this->
lng->txt(
"anonymous");
2298 $fullname = $this->
lng->txt(
"anonymous");
2301 if (strlen($row[
"firstname"] . $row[
"lastname"] . $row[
"title"]) == 0) {
2302 $name = $this->
lng->txt(
"deleted_user");
2303 $fullname = $this->
lng->txt(
"deleted_user");
2304 $login = $this->
lng->txt(
"unknown");
2306 $login = $row[
"login"];
2308 $name = $this->
lng->txt(
"anonymous");
2309 $fullname = $this->
lng->txt(
"anonymous");
2311 $name = trim($row[
"lastname"] .
", " . $row[
"firstname"] .
" " . $row[
"title"]);
2312 $fullname = trim($row[
"title"] .
" " . $row[
"firstname"] .
" " . $row[
"lastname"]);
2316 $persons_array[$row[
"active_id"]] = [
2318 "fullname" => $fullname,
2322 return $persons_array;
2327 $result = $this->db->queryF(
2328 "SELECT tst_active.user_fi, 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),
2332 $persons_array = [];
2333 while ($row = $this->db->fetchAssoc($result)) {
2339 $persons_array[$row[
"active_id"]] = $this->
lng->txt(
"anonymous");
2341 if (strlen($row[
"firstname"] . $row[
"lastname"] . $row[
"title"]) == 0) {
2342 $persons_array[$row[
"active_id"]] = $this->
lng->txt(
"deleted_user");
2345 $persons_array[$row[
"active_id"]] = $row[
"lastname"];
2347 $persons_array[$row[
"active_id"]] = trim($row[
"lastname"] .
", " . $row[
"firstname"] .
" " . $row[
"title"]);
2352 return $persons_array;
2357 $result = $this->db->queryF(
2358 'SELECT tst_active.user_fi, tst_active.active_id, usr_data.login, ' 2359 .
'usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active ' 2360 .
'LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id ' 2361 .
'WHERE tst_active.test_fi = %s ' 2362 .
'ORDER BY usr_data.lastname ' . strtoupper($name_sort_order),
2366 $persons_array = [];
2367 while ($row = $this->db->fetchAssoc($result)) {
2369 $persons_array[$row[
'active_id']] = [
'name' => $this->
lng->txt(
"anonymous")];
2371 if (strlen($row[
'firstname'] . $row[
'lastname'] . $row[
"title"]) == 0) {
2372 $persons_array[$row[
'active_id']] = [
'name' => $this->
lng->txt(
'deleted_user')];
2375 $persons_array[$row[
'active_id']] = [
'name' => $row[
'lastname']];
2377 $persons_array[$row[
'active_id']] = [
2378 'name' => trim($row[
'lastname'] .
', ' . $row[
'firstname']
2379 .
' ' . $row[
'title']),
2380 'login' => $row[
'login']
2386 return $persons_array;
2393 $result = $this->db->queryF(
2394 'SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, ' 2395 .
'tst_test_rnd_qst.pass, qpl_questions.points ' 2396 .
'FROM tst_test_rnd_qst, qpl_questions ' 2397 .
'WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id ' 2398 .
'AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence',
2403 $result = $this->db->queryF(
2404 'SELECT tst_test_question.sequence, tst_test_question.question_fi, ' 2405 .
'qpl_questions.points ' 2406 .
'FROM tst_test_question, tst_active, qpl_questions ' 2407 .
'WHERE tst_test_question.question_fi = qpl_questions.question_id ' 2408 .
'AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi',
2414 if ($result->numRows()) {
2415 while ($row = $this->db->fetchAssoc($result)) {
2416 array_push($qtest, $row);
2426 $result = $this->db->queryF(
2427 'SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, ' 2428 .
'qpl_questions.points ' 2429 .
'FROM tst_test_rnd_qst, qpl_questions ' 2430 .
'WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id ' 2431 .
'AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s ' 2432 .
'ORDER BY tst_test_rnd_qst.sequence',
2433 [
'integer',
'integer'],
2437 $result = $this->db->queryF(
2438 'SELECT tst_test_question.sequence, tst_test_question.question_fi, ' 2439 .
'qpl_questions.points ' 2440 .
'FROM tst_test_question, tst_active, qpl_questions ' 2441 .
'WHERE tst_test_question.question_fi = qpl_questions.question_id ' 2442 .
'AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi',
2448 if ($result->numRows()) {
2449 while ($row = $this->db->fetchAssoc($result)) {
2450 array_push($qpass, $row);
2471 return $list->getAccessFilteredList(
2472 $this->participant_access_filter->getAccessStatisticsUserFilter($this->getRefId())
2479 ->getEvaluationData();
2486 switch ($question_set_type) {
2488 $res = $this->db->queryF(
2490 SELECT tst_test_rnd_qst.pass, 2491 COUNT(tst_test_rnd_qst.question_fi) qcount, 2492 SUM(qpl_questions.points) qsum 2494 FROM tst_test_rnd_qst, 2497 WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id 2498 AND tst_test_rnd_qst.active_fi = %s 2501 GROUP BY tst_test_rnd_qst.active_fi, 2502 tst_test_rnd_qst.pass 2504 [
'integer',
'integer'],
2510 $res = $this->db->queryF(
2512 SELECT COUNT(tst_test_question.question_fi) qcount, 2513 SUM(qpl_questions.points) qsum 2515 FROM tst_test_question, 2519 WHERE tst_test_question.question_fi = qpl_questions.question_id 2520 AND tst_test_question.test_fi = tst_active.test_fi 2521 AND tst_active.active_id = %s 2523 GROUP BY tst_test_question.test_fi 2531 throw new ilTestException(
"not supported question set type: $question_set_type");
2534 $row = $this->db->fetchAssoc(
$res);
2536 if (is_array($row)) {
2537 return [
"count" => $row[
"qcount"],
"points" => $row[
"qsum"]];
2540 return [
"count" => 0,
"points" => 0];
2546 $data->setFilter($filterby, $filtertext);
2566 if ($user_id === null
2567 || $firstname . $lastname ===
'') {
2568 return $this->
lng->txt(
'deleted_user');
2572 return $this->
lng->txt(
'anonymous');
2579 return trim($lastname .
', ' . $firstname);
2584 $query =
"SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi";
2586 if ($active_ids_to_filter !== null && $active_ids_to_filter !== []) {
2587 $query .=
" AND " . $this->db->in(
'active_id', $active_ids_to_filter,
false,
'integer');
2590 $result = $this->db->queryF($query, [
'integer'], [$this->
getTestId()]);
2592 while ($row = $this->db->fetchObject($result)) {
2593 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
2602 preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
2611 if (isset($times[$row->active_fi])) {
2612 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
2614 $times[$row->active_fi] = ($epoch_2 - $epoch_1);
2619 foreach ($times as $value) {
2620 $max_time += $value;
2623 if ($counter === 0) {
2626 return (
int) round($max_time / $counter);
2636 bool $use_object_id =
false,
2637 ?
bool $equal_points =
false,
2638 bool $could_be_offline =
false,
2639 bool $show_path =
false,
2640 bool $with_questioncount =
false,
2641 string $permission =
'read' 2645 $equal_points ??
false,
2648 $with_questioncount,
2690 if ((!$question_type) and ($question_id > 0)) {
2694 if (!strlen($question_type)) {
2698 if ($question_id > 0) {
2699 $question_gui = assQuestion::instantiateQuestionGUI($question_id);
2701 $question_type_gui = $question_type .
'GUI';
2702 $question_gui =
new $question_type_gui();
2705 return $question_gui;
2716 if (strcmp((
string) $question_id,
"") !== 0) {
2727 public function moveQuestions(array $move_questions,
int $target_index,
int $insert_mode): void
2729 $this->questions = array_values($this->questions);
2730 $array_pos = array_search($target_index, $this->questions);
2731 if ($insert_mode == 0) {
2732 $part1 = array_slice($this->questions, 0, $array_pos);
2733 $part2 = array_slice($this->questions, $array_pos);
2734 } elseif ($insert_mode == 1) {
2735 $part1 = array_slice($this->questions, 0, $array_pos + 1);
2736 $part2 = array_slice($this->questions, $array_pos + 1);
2738 foreach ($move_questions as $question_id) {
2739 if (!(array_search($question_id, $part1) ===
false)) {
2740 unset($part1[array_search($question_id, $part1)]);
2742 if (!(array_search($question_id, $part2) ===
false)) {
2743 unset($part2[array_search($question_id, $part2)]);
2746 $part1 = array_values($part1);
2747 $part2 = array_values($part2);
2748 $new_array = array_values(array_merge($part1, $move_questions, $part2));
2749 $this->questions = [];
2751 foreach ($new_array as $question_id) {
2752 $this->questions[$counter] = $question_id;
2757 if ($this->
logger->isLoggingEnabled()) {
2758 $this->
logger->logTestAdministrationInteraction(
2759 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
2761 $this->
user->getId(),
2762 TestAdministrationInteractionTypes::QUESTION_MOVED,
2817 if (count($available_pools)) {
2818 $available =
" AND " . $this->db->in(
'qpl_questions.obj_fi', $available_pools,
false,
'integer');
2822 if ($completeonly) {
2823 $available .=
" AND qpl_questions.complete = " . $this->db->quote(
"1",
'text');
2827 if (is_array($arr_filter)) {
2828 if (array_key_exists(
'title', $arr_filter) && strlen($arr_filter[
'title'])) {
2829 $where .=
" AND " . $this->db->like(
'qpl_questions.title',
'text',
"%%" . $arr_filter[
'title'] .
"%%");
2831 if (array_key_exists(
'description', $arr_filter) && strlen($arr_filter[
'description'])) {
2832 $where .=
" AND " . $this->db->like(
'qpl_questions.description',
'text',
"%%" . $arr_filter[
'description'] .
"%%");
2834 if (array_key_exists(
'author', $arr_filter) && strlen($arr_filter[
'author'])) {
2835 $where .=
" AND " . $this->db->like(
'qpl_questions.author',
'text',
"%%" . $arr_filter[
'author'] .
"%%");
2837 if (array_key_exists(
'type', $arr_filter) && strlen($arr_filter[
'type'])) {
2838 $where .=
" AND qpl_qst_type.type_tag = " . $this->db->quote($arr_filter[
'type'],
'text');
2840 if (array_key_exists(
'qpl', $arr_filter) && strlen($arr_filter[
'qpl'])) {
2841 $where .=
" AND " . $this->db->like(
'object_data.title',
'text',
"%%" . $arr_filter[
'qpl'] .
"%%");
2846 $original_clause =
" qpl_questions.original_id IS NULL";
2847 if (count($original_ids)) {
2848 $original_clause =
" qpl_questions.original_id IS NULL AND " . $this->db->in(
'qpl_questions.question_id', $original_ids,
true,
'integer');
2851 $query_result = $this->db->query(
" 2852 SELECT qpl_questions.*, qpl_questions.tstamp, 2853 qpl_qst_type.type_tag, qpl_qst_type.plugin, qpl_qst_type.plugin_name, 2854 object_data.title parent_title 2855 FROM qpl_questions, qpl_qst_type, object_data 2856 WHERE $original_clause $available 2857 AND object_data.obj_id = qpl_questions.obj_fi 2858 AND qpl_questions.tstamp > 0 2859 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id 2864 if ($query_result->numRows()) {
2865 while ($row = $this->db->fetchAssoc($query_result)) {
2868 if (!$row[
'plugin']) {
2869 $row[
'ttype' ] = $this->
lng->txt($row[
"type_tag" ]);
2875 $plugin = $this->component_repository->getPluginByName($row[
'plugin_name']);
2880 $pl = $this->component_factory->getPlugin(
$plugin->getId());
2881 $row[
'ttype' ] = $pl->getQuestionTypeTranslation();
2895 if (($importdir =
ilSession::get(
'path_to_container_import_file')) === null) {
2913 $introduction_settings = $introduction_settings->withIntroductionEnabled(
false);
2914 foreach ($assessment->objectives as
$objectives) {
2915 foreach ($objectives->materials as $material) {
2917 $introduction_settings,
2929 $finishing_settings,
2945 foreach ($assessment->qtimetadata as
$metadata) {
2946 switch ($metadata[
"label"]) {
2947 case "solution_details":
2948 $result_details_settings = $result_details_settings->withShowPassDetails((
bool) $metadata[
"entry"]);
2950 case "show_solution_list_comparison":
2951 $result_details_settings = $result_details_settings->withShowSolutionListComparison((
bool) $metadata[
"entry"]);
2953 case "print_bs_with_res":
2954 $result_details_settings = $result_details_settings->withShowSolutionListComparison((
bool) $metadata[
"entry"]);
2960 $test_behaviour_settings = $test_behaviour_settings->withNumberOfTries((
int) $metadata[
"entry"]);
2962 case 'block_after_passed':
2963 $test_behaviour_settings = $test_behaviour_settings->withBlockAfterPassedEnabled((
bool) $metadata[
'entry']);
2965 case "pass_waiting":
2966 $test_behaviour_settings = $test_behaviour_settings->withPassWaiting($metadata[
"entry"]);
2969 $test_behaviour_settings = $test_behaviour_settings->withKioskMode((
int) $metadata[
"entry"]);
2971 case 'show_introduction':
2972 $introduction_settings = $introduction_settings->withIntroductionEnabled((
bool) $metadata[
'entry']);
2974 case "showfinalstatement":
2975 case 'show_concluding_remarks':
2976 $finishing_settings = $finishing_settings->withConcludingRemarksEnabled((
bool) $metadata[
"entry"]);
2978 case 'exam_conditions':
2979 $introduction_settings = $introduction_settings->withExamConditionsCheckboxEnabled($metadata[
'entry'] ===
'1');
2981 case "highscore_enabled":
2982 $gamification_settings = $gamification_settings->withHighscoreEnabled((
bool) $metadata[
"entry"]);
2984 case "highscore_anon":
2985 $gamification_settings = $gamification_settings->withHighscoreAnon((
bool) $metadata[
"entry"]);
2987 case "highscore_achieved_ts":
2988 $gamification_settings = $gamification_settings->withHighscoreAchievedTS((
bool) $metadata[
"entry"]);
2990 case "highscore_score":
2991 $gamification_settings = $gamification_settings->withHighscoreScore((
bool) $metadata[
"entry"]);
2993 case "highscore_percentage":
2994 $gamification_settings = $gamification_settings->withHighscorePercentage((
bool) $metadata[
"entry"]);
2996 case "highscore_hints":
2997 $gamification_settings = $gamification_settings->withHighscoreHints((
bool) $metadata[
"entry"]);
2999 case "highscore_wtime":
3000 $gamification_settings = $gamification_settings->withHighscoreWTime((
bool) $metadata[
"entry"]);
3002 case "highscore_own_table":
3003 $gamification_settings = $gamification_settings->withHighscoreOwnTable((
bool) $metadata[
"entry"]);
3005 case "highscore_top_table":
3006 $gamification_settings = $gamification_settings->withHighscoreTopTable((
bool) $metadata[
"entry"]);
3008 case "highscore_top_num":
3009 $gamification_settings = $gamification_settings->withHighscoreTopNum((
int) $metadata[
"entry"]);
3011 case "use_previous_answers":
3012 $participant_functionality_settings = $participant_functionality_settings->withUsePreviousAnswerAllowed((
bool) $metadata[
"entry"]);
3014 case 'question_list_enabled':
3015 $participant_functionality_settings = $participant_functionality_settings->withQuestionListEnabled((
bool) $metadata[
'entry']);
3017 case "title_output":
3018 $question_behaviour_settings = $question_behaviour_settings->withQuestionTitleOutputMode((
int) $metadata[
"entry"]);
3020 case "question_set_type":
3021 if ($metadata[
'entry'] === self::QUESTION_SET_TYPE_RANDOM) {
3022 $this->questions = [];
3024 $general_settings = $general_settings->withQuestionSetType($metadata[
"entry"]);
3027 $general_settings = $general_settings->withAnonymity((
bool) $metadata[
"entry"]);
3029 case "results_presentation":
3030 $result_details_settings = $result_details_settings->withResultsPresentation((
int) $metadata[
"entry"]);
3032 case "reset_processing_time":
3033 $test_behaviour_settings = $test_behaviour_settings->withResetProcessingTime($metadata[
"entry"] ===
'1');
3035 case "answer_feedback_points":
3036 $question_behaviour_settings = $question_behaviour_settings->withInstantFeedbackPointsEnabled((
bool) $metadata[
"entry"]);
3038 case "answer_feedback":
3039 $question_behaviour_settings = $question_behaviour_settings->withInstantFeedbackGenericEnabled((
bool) $metadata[
"entry"]);
3041 case 'instant_feedback_specific':
3042 $question_behaviour_settings = $question_behaviour_settings->withInstantFeedbackSpecificEnabled((
bool) $metadata[
'entry']);
3044 case "instant_verification":
3045 $question_behaviour_settings = $question_behaviour_settings->withInstantFeedbackSolutionEnabled((
bool) $metadata[
"entry"]);
3047 case "force_instant_feedback":
3048 $question_behaviour_settings = $question_behaviour_settings->withForceInstantFeedbackOnNextQuestion((
bool) $metadata[
"entry"]);
3050 case "follow_qst_answer_fixation":
3051 $question_behaviour_settings = $question_behaviour_settings->withLockAnswerOnNextQuestionEnabled((
bool) $metadata[
"entry"]);
3053 case "instant_feedback_answer_fixation":
3054 $question_behaviour_settings = $question_behaviour_settings->withLockAnswerOnInstantFeedbackEnabled((
bool) $metadata[
"entry"]);
3057 case "suspend_test_allowed":
3058 $participant_functionality_settings = $participant_functionality_settings->withSuspendTestAllowed((
bool) $metadata[
"entry"]);
3060 case "sequence_settings":
3061 $participant_functionality_settings = $participant_functionality_settings->withPostponedQuestionsMoveToEnd((
bool) $metadata[
"entry"]);
3064 $participant_functionality_settings = $participant_functionality_settings->withQuestionMarkingEnabled((
bool) $metadata[
"entry"]);
3066 case "fixed_participants":
3067 $access_settings = $access_settings->withFixedParticipants((
bool) $metadata[
"entry"]);
3069 case "score_reporting":
3070 if ($metadata[
'entry'] !== null) {
3071 $result_summary_settings = $result_summary_settings->withScoreReporting(
3072 ScoreReportingTypes::tryFrom((
int) $metadata[
'entry']) ?? ScoreReportingTypes::SCORE_REPORTING_DISABLED
3076 case "shuffle_questions":
3077 $question_behaviour_settings = $question_behaviour_settings->withShuffleQuestions((
bool) $metadata[
"entry"]);
3079 case "count_system":
3080 $scoring_settings = $scoring_settings->withCountSystem((
int) $metadata[
"entry"]);
3082 case "mailnotification":
3083 $finishing_settings = $finishing_settings->withMailNotificationContentType((
int) $metadata[
"entry"]);
3086 $finishing_settings = $finishing_settings->withAlwaysSendMailNotification((
bool) $metadata[
"entry"]);
3088 case "exportsettings":
3089 $result_details_settings = $result_details_settings->withExportSettings((
int) $metadata[
"entry"]);
3091 case "score_cutting":
3092 $scoring_settings = $scoring_settings->withScoreCutting((
int) $metadata[
"entry"]);
3095 $access_settings = $access_settings->withPasswordEnabled(
3096 $metadata[
"entry"] !== null && $metadata[
"entry"] !==
'' 3097 )->withPassword($metadata[
"entry"]);
3099 case 'ip_range_from':
3100 if ($metadata[
'entry'] !==
'') {
3101 $access_settings = $access_settings->withIpRangeFrom($metadata[
'entry']);
3105 if ($metadata[
'entry'] !==
'') {
3106 $access_settings = $access_settings->withIpRangeTo($metadata[
'entry']);
3109 case "pass_scoring":
3110 $scoring_settings = $scoring_settings->withPassScoring((
int) $metadata[
"entry"]);
3112 case 'pass_deletion_allowed':
3113 $result_summary_settings = $result_summary_settings->withPassDeletionAllowed((
bool) $metadata[
"entry"]);
3115 case "usr_pass_overview_mode":
3116 $participant_functionality_settings = $participant_functionality_settings->withUsrPassOverviewMode((
int) $metadata[
"entry"]);
3118 case "question_list":
3119 $participant_functionality_settings = $participant_functionality_settings->withQuestionListEnabled((
bool) $metadata[
"entry"]);
3122 case "reporting_date":
3124 if ($reporting_date !== null) {
3125 $result_summary_settings = $result_summary_settings->withReportingDate($reporting_date);
3128 case 'enable_processing_time':
3129 $test_behaviour_settings = $test_behaviour_settings->withProcessingTimeEnabled((
bool) $metadata[
'entry']);
3131 case "processing_time":
3132 $test_behaviour_settings = $test_behaviour_settings->withProcessingTime($metadata[
'entry']);
3134 case "starting_time":
3136 if ($starting_time !== null) {
3137 $access_settings = $access_settings->withStartTime($starting_time)
3138 ->withStartTimeEnabled(
true);
3143 if ($ending_time !== null) {
3144 $access_settings = $access_settings->withEndTime($ending_time)
3145 ->withStartTimeEnabled(
true);
3148 case "enable_examview":
3149 $finishing_settings = $finishing_settings->withShowAnswerOverview((
bool) $metadata[
"entry"]);
3151 case 'redirection_mode':
3152 $finishing_settings = $finishing_settings->withRedirectionMode((
int) $metadata[
'entry']);
3154 case 'redirection_url':
3155 $finishing_settings = $finishing_settings->withRedirectionUrl($metadata[
'entry']);
3157 case 'examid_in_test_pass':
3158 $test_behaviour_settings = $test_behaviour_settings->withExamIdInTestAttemptEnabled((
bool) $metadata[
'entry']);
3160 case 'examid_in_test_res':
3161 $result_details_settings = $result_details_settings->withShowExamIdInTestResults((
bool) $metadata[
"entry"]);
3163 case 'skill_service':
3164 $additional_settings = $additional_settings->withSkillsServiceEnabled((
bool) $metadata[
'entry']);
3166 case 'show_grading_status':
3167 $result_summary_settings = $result_summary_settings->withShowGradingStatusEnabled((
bool) $metadata[
"entry"]);
3169 case 'show_grading_mark':
3170 $result_summary_settings = $result_summary_settings->withShowGradingMarkEnabled((
bool) $metadata[
"entry"]);
3172 case 'activation_limited':
3175 case 'activation_start_time':
3178 case 'activation_end_time':
3181 case 'activation_visibility':
3185 $question_behaviour_settings = $question_behaviour_settings->withAutosaveEnabled((
bool) $metadata[
'entry']);
3187 case 'autosave_ival':
3188 $question_behaviour_settings = $question_behaviour_settings->withAutosaveInterval((
int) $metadata[
'entry']);
3190 case 'offer_question_hints':
3191 $question_behaviour_settings = $question_behaviour_settings->withQuestionHintsEnabled((
bool) $metadata[
'entry']);
3193 case 'show_summary':
3194 $participant_functionality_settings = $participant_functionality_settings->withQuestionListEnabled(($metadata[
'entry'] & 1) > 0)
3195 ->withUsrPassOverviewMode((
int) $metadata[
'entry']);
3198 case 'hide_info_tab':
3199 $additional_settings = $additional_settings->withHideInfoTab($metadata[
'entry'] ===
'1');
3201 if (preg_match(
"/mark_step_\d+/", $metadata[
"label"])) {
3202 $xmlmark = $metadata[
"entry"];
3203 preg_match(
"/<short>(.*?)<\/short>/", $xmlmark, $matches);
3204 $mark_short = $matches[1];
3205 preg_match(
"/<official>(.*?)<\/official>/", $xmlmark, $matches);
3206 $mark_official = $matches[1];
3207 preg_match(
"/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
3208 $mark_percentage = (float) $matches[1];
3209 preg_match(
"/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
3210 $mark_passed = (bool) $matches[1];
3211 $mark_steps[] =
new Mark($mark_short, $mark_official, $mark_percentage, $mark_passed);
3214 $this->mark_schema = $this->
getMarkSchema()->withMarkSteps($mark_steps);
3222 $main_settings = $main_settings
3224 ->withIntroductionSettings($introduction_settings)
3225 ->withAccessSettings($access_settings)
3226 ->withParticipantFunctionalitySettings($participant_functionality_settings)
3227 ->withTestBehaviourSettings($test_behaviour_settings)
3228 ->withQuestionBehaviourSettings($question_behaviour_settings)
3229 ->withFinishingSettings($finishing_settings)
3230 ->withAdditionalSettings($additional_settings);
3234 $score_settings = $score_settings
3236 ->withScoringSettings($scoring_settings)
3237 ->withResultDetailsSettings($result_details_settings)
3238 ->withResultSummarySettings($result_summary_settings);
3250 $text = $material[
'text'];
3251 $mobs = $material[
'mobs'];
3252 if (str_starts_with(
$text,
'<PageObject>')) {
3255 $mappings[
'components/ILIAS/MediaObjects'][
'mob'] ?? []
3259 $mappings[
'components/ILIAS/File'][
'file'] ?? []
3262 $page_object->setParentId($this->
getId());
3263 $page_object->setXMLContent(
$text);
3264 $new_page_id = $page_object->createPageWithNextId();
3284 $text = $material[
'text'];
3285 $mobs = $material[
'mobs'];
3286 if (str_starts_with(
$text,
'<PageObject>')) {
3289 $mappings[
'components/ILIAS/MediaObjects'][
'mob'] ?? []
3293 $mappings[
'components/ILIAS/File'][
'file'] ?? []
3296 $page_object->setParentId($this->
getId());
3297 $page_object->setXMLContent(
$text);
3298 $new_page_id = $page_object->createPageWithNextId();
3319 preg_match_all(
'/il_(\d+)_mob_(\d+)/', $text, $matches);
3320 foreach ($matches[0] as $index => $match) {
3321 if (empty($mappings[$matches[2][$index]])) {
3324 $text = str_replace($match,
"il__mob_{$mappings[$matches[2][$index]]}", $text);
3332 preg_match_all(
'/il_(\d+)_file_(\d+)/', $text, $matches);
3333 foreach ($matches[0] as $index => $match) {
3334 if (empty($mappings[$matches[2][$index]])) {
3337 $text = str_replace($match,
"il__file_{$mappings[$matches[2][$index]]}", $text);
3344 foreach ($mobs as $mob) {
3345 $importfile = $importdir . DIRECTORY_SEPARATOR . $mob[
'uri'];
3346 if (file_exists($importfile)) {
3351 'src="' . $mob[
'mob'] .
'"',
3352 'src="' .
'il_' .
IL_INST_ID .
'_mob_' . $media_object->getId() .
'"',
3372 $a_xml_writer->xmlHeader();
3373 $a_xml_writer->xmlSetDtdDef(
"<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
3374 $a_xml_writer->xmlStartTag(
"questestinterop");
3380 $a_xml_writer->xmlStartTag(
"assessment", $attrs);
3381 $a_xml_writer->xmlElement(
"qticomment", null, $this->
getDescription());
3384 $a_xml_writer->xmlElement(
3391 $a_xml_writer->xmlStartTag(
"qtimetadata");
3392 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3393 $a_xml_writer->xmlElement(
"fieldlabel", null,
"ILIAS_VERSION");
3394 $a_xml_writer->xmlElement(
"fieldentry", null,
ILIAS_VERSION);
3395 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3397 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3398 $a_xml_writer->xmlElement(
"fieldlabel", null,
"anonymity");
3399 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $main_settings->
getGeneralSettings()->getAnonymity()));
3400 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3402 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3403 $a_xml_writer->xmlElement(
"fieldlabel", null,
"question_set_type");
3404 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getGeneralSettings()->getQuestionSetType());
3405 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3407 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3408 $a_xml_writer->xmlElement(
"fieldlabel", null,
"sequence_settings");
3410 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3412 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3413 $a_xml_writer->xmlElement(
"fieldlabel", null,
"author");
3414 $a_xml_writer->xmlElement(
"fieldentry", null, $this->
getAuthor());
3415 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3417 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3418 $a_xml_writer->xmlElement(
"fieldlabel", null,
"reset_processing_time");
3419 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getTestBehaviourSettings()->getResetProcessingTime());
3420 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3422 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3423 $a_xml_writer->xmlElement(
"fieldlabel", null,
"count_system");
3424 $a_xml_writer->xmlElement(
"fieldentry", null, $this->
getCountSystem());
3425 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3427 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3428 $a_xml_writer->xmlElement(
"fieldlabel", null,
"score_cutting");
3429 $a_xml_writer->xmlElement(
"fieldentry", null, $this->
getScoreCutting());
3430 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3432 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3433 $a_xml_writer->xmlElement(
"fieldlabel", null,
"password");
3434 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getAccessSettings()->getPassword() ??
'');
3435 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3437 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3438 $a_xml_writer->xmlElement(
"fieldlabel", null,
"ip_range_from");
3439 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getAccessSettings()->getIpRangeFrom());
3440 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3442 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3443 $a_xml_writer->xmlElement(
"fieldlabel", null,
"ip_range_to");
3444 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getAccessSettings()->getIpRangeTo());
3445 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3447 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3448 $a_xml_writer->xmlElement(
"fieldlabel", null,
"pass_scoring");
3449 $a_xml_writer->xmlElement(
"fieldentry", null, $this->
getPassScoring());
3450 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3452 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3453 $a_xml_writer->xmlElement(
'fieldlabel', null,
'pass_deletion_allowed');
3455 $a_xml_writer->xmlEndTag(
'qtimetadatafield');
3457 if ($this->
getScoreSettings()->getResultSummarySettings()->getReportingDate() !== null) {
3458 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3459 $a_xml_writer->xmlElement(
"fieldlabel", null,
"reporting_date");
3460 $a_xml_writer->xmlElement(
3467 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3470 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3471 $a_xml_writer->xmlElement(
"fieldlabel", null,
"nr_of_tries");
3472 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $main_settings->
getTestBehaviourSettings()->getNumberOfTries()));
3473 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3475 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3476 $a_xml_writer->xmlElement(
'fieldlabel', null,
'block_after_passed');
3477 $a_xml_writer->xmlElement(
'fieldentry', null, (
int) $main_settings->
getTestBehaviourSettings()->getBlockAfterPassedEnabled());
3478 $a_xml_writer->xmlEndTag(
'qtimetadatafield');
3480 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3481 $a_xml_writer->xmlElement(
"fieldlabel", null,
"pass_waiting");
3483 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3485 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3486 $a_xml_writer->xmlElement(
"fieldlabel", null,
"kiosk");
3487 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $main_settings->
getTestBehaviourSettings()->getKioskMode()));
3488 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3490 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3491 $a_xml_writer->xmlElement(
"fieldlabel", null,
"redirection_mode");
3492 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getFinishingSettings()->getRedirectionMode());
3493 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3495 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3496 $a_xml_writer->xmlElement(
"fieldlabel", null,
"redirection_url");
3497 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getFinishingSettings()->getRedirectionUrl());
3498 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3500 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3501 $a_xml_writer->xmlElement(
"fieldlabel", null,
"use_previous_answers");
3503 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3505 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3506 $a_xml_writer->xmlElement(
'fieldlabel', null,
'question_list_enabled');
3508 $a_xml_writer->xmlEndTag(
'qtimetadatafield');
3510 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3511 $a_xml_writer->xmlElement(
"fieldlabel", null,
"title_output");
3512 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $main_settings->
getQuestionBehaviourSettings()->getQuestionTitleOutputMode()));
3513 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3515 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3516 $a_xml_writer->xmlElement(
"fieldlabel", null,
"results_presentation");
3517 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $this->
getScoreSettings()->getResultDetailsSettings()->getResultsPresentation()));
3518 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3520 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3521 $a_xml_writer->xmlElement(
"fieldlabel", null,
"examid_in_test_pass");
3522 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $main_settings->
getTestBehaviourSettings()->getExamIdInTestAttemptEnabled()));
3523 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3525 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3526 $a_xml_writer->xmlElement(
"fieldlabel", null,
"examid_in_test_res");
3527 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $this->
getScoreSettings()->getResultDetailsSettings()->getShowExamIdInTestResults()));
3528 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3530 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3531 $a_xml_writer->xmlElement(
"fieldlabel", null,
"usr_pass_overview_mode");
3533 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3535 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3536 $a_xml_writer->xmlElement(
"fieldlabel", null,
"score_reporting");
3537 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", $this->
getScoreSettings()->getResultSummarySettings()->getScoreReporting()->value));
3538 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3540 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3541 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_solution_list_comparison");
3542 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $this->score_settings->getResultDetailsSettings()->getShowSolutionListComparison());
3543 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3545 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3546 $a_xml_writer->xmlElement(
"fieldlabel", null,
"instant_verification");
3547 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getQuestionBehaviourSettings()->getInstantFeedbackSolutionEnabled()));
3548 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3550 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3551 $a_xml_writer->xmlElement(
"fieldlabel", null,
"answer_feedback");
3552 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getQuestionBehaviourSettings()->getInstantFeedbackGenericEnabled()));
3553 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3555 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3556 $a_xml_writer->xmlElement(
"fieldlabel", null,
"instant_feedback_specific");
3557 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getQuestionBehaviourSettings()->getInstantFeedbackSpecificEnabled()));
3558 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3560 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3561 $a_xml_writer->xmlElement(
"fieldlabel", null,
"answer_feedback_points");
3562 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getQuestionBehaviourSettings()->getInstantFeedbackPointsEnabled()));
3563 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3565 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3566 $a_xml_writer->xmlElement(
"fieldlabel", null,
"follow_qst_answer_fixation");
3567 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getQuestionBehaviourSettings()->getLockAnswerOnNextQuestionEnabled());
3568 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3570 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3571 $a_xml_writer->xmlElement(
"fieldlabel", null,
"instant_feedback_answer_fixation");
3572 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getQuestionBehaviourSettings()->getLockAnswerOnInstantFeedbackEnabled());
3573 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3575 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3576 $a_xml_writer->xmlElement(
"fieldlabel", null,
"force_instant_feedback");
3577 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getQuestionBehaviourSettings()->getForceInstantFeedbackOnNextQuestion());
3578 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3580 $highscore_metadata = [
3592 foreach ($highscore_metadata as $label =>
$data) {
3593 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3594 $a_xml_writer->xmlElement(
"fieldlabel", null, $label);
3595 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d",
$data[
'value']));
3596 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3599 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3600 $a_xml_writer->xmlElement(
"fieldlabel", null,
"suspend_test_allowed");
3602 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3604 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3605 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_marker");
3607 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3609 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3610 $a_xml_writer->xmlElement(
"fieldlabel", null,
"fixed_participants");
3611 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getAccessSettings()->getFixedParticipants()));
3612 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3614 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3615 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_introduction");
3616 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getIntroductionSettings()->getIntroductionEnabled()));
3617 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3619 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3620 $a_xml_writer->xmlElement(
"fieldlabel", null,
'exam_conditions');
3621 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getIntroductionSettings()->getExamConditionsCheckboxEnabled()));
3622 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3624 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3625 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_concluding_remarks");
3626 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getFinishingSettings()->getConcludingRemarksEnabled()));
3627 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3629 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3630 $a_xml_writer->xmlElement(
"fieldlabel", null,
"mailnotification");
3631 $a_xml_writer->xmlElement(
"fieldentry", null, $main_settings->
getFinishingSettings()->getMailNotificationContentType());
3632 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3634 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3635 $a_xml_writer->xmlElement(
"fieldlabel", null,
"mailnottype");
3636 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getFinishingSettings()->getAlwaysSendMailNotification());
3637 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3639 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3640 $a_xml_writer->xmlElement(
"fieldlabel", null,
"exportsettings");
3642 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3644 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3645 $a_xml_writer->xmlElement(
"fieldlabel", null,
"shuffle_questions");
3646 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
"%d", (
int) $main_settings->
getQuestionBehaviourSettings()->getShuffleQuestions()));
3647 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3649 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3650 $a_xml_writer->xmlElement(
"fieldlabel", null,
"processing_time");
3652 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3654 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3655 $a_xml_writer->xmlElement(
"fieldlabel", null,
"enable_examview");
3656 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getFinishingSettings()->getShowAnswerOverview());
3657 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3659 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3660 $a_xml_writer->xmlElement(
"fieldlabel", null,
"skill_service");
3661 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getAdditionalSettings()->getSkillsServiceEnabled());
3662 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3666 "solutionswitch" =>
"Yes" 3671 $a_xml_writer->xmlElement(
"assessmentcontrol", $attrs, null);
3673 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3674 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_grading_status");
3676 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3678 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3679 $a_xml_writer->xmlElement(
"fieldlabel", null,
"show_grading_mark");
3681 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3683 $a_xml_writer->xmlStartTag(
'qtimetadatafield');
3684 $a_xml_writer->xmlElement(
'fieldlabel', null,
'hide_info_tab');
3685 $a_xml_writer->xmlElement(
'fieldentry', null, (
int) $this->
getMainSettings()->getAdditionalSettings()->getHideInfoTab());
3686 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3689 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3690 $a_xml_writer->xmlElement(
"fieldlabel", null,
"starting_time");
3691 $a_xml_writer->xmlElement(
3698 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3702 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3703 $a_xml_writer->xmlElement(
"fieldlabel", null,
"ending_time");
3704 $a_xml_writer->xmlElement(
3711 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3714 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3715 $a_xml_writer->xmlElement(
"fieldlabel", null,
"activation_limited");
3717 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3719 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3720 $a_xml_writer->xmlElement(
"fieldlabel", null,
"activation_start_time");
3722 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3724 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3725 $a_xml_writer->xmlElement(
"fieldlabel", null,
"activation_end_time");
3727 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3729 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3730 $a_xml_writer->xmlElement(
"fieldlabel", null,
"activation_visibility");
3732 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3734 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3735 $a_xml_writer->xmlElement(
"fieldlabel", null,
"autosave");
3737 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3739 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3740 $a_xml_writer->xmlElement(
"fieldlabel", null,
"autosave_ival");
3742 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3744 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3745 $a_xml_writer->xmlElement(
"fieldlabel", null,
"offer_question_hints");
3747 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3749 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3750 $a_xml_writer->xmlElement(
"fieldlabel", null,
"instant_feedback_specific");
3751 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getQuestionBehaviourSettings()->getInstantFeedbackSpecificEnabled());
3752 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3754 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3755 $a_xml_writer->xmlElement(
"fieldlabel", null,
"instant_feedback_answer_fixation");
3756 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getQuestionBehaviourSettings()->getLockAnswerOnInstantFeedbackEnabled());
3757 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3759 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3760 $a_xml_writer->xmlElement(
"fieldlabel", null,
"enable_processing_time");
3761 $a_xml_writer->xmlElement(
"fieldentry", null, (
int) $main_settings->
getTestBehaviourSettings()->getProcessingTimeEnabled());
3762 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3764 foreach ($this->
getMarkSchema()->getMarkSteps() as $index => $mark) {
3765 $a_xml_writer->xmlStartTag(
"qtimetadatafield");
3766 $a_xml_writer->xmlElement(
"fieldlabel", null,
"mark_step_$index");
3767 $a_xml_writer->xmlElement(
"fieldentry", null, sprintf(
3768 "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
3769 $mark->getShortName(),
3770 $mark->getOfficialName(),
3771 $mark->getMinimumLevel(),
3774 $a_xml_writer->xmlEndTag(
"qtimetadatafield");
3776 $a_xml_writer->xmlEndTag(
"qtimetadata");
3779 $introduction = $page_id !== null
3780 ? (
new ilTestPage($page_id))->getXMLContent()
3783 $a_xml_writer->xmlStartTag(
"objectives");
3785 $a_xml_writer->xmlEndTag(
"objectives");
3789 "solutionswitch" =>
"Yes" 3794 $a_xml_writer->xmlElement(
"assessmentcontrol", $attrs, null);
3798 $concluding_remarks = $page_id !== null
3799 ? (
new ilTestPage($page_id))->getXMLContent()
3802 $a_xml_writer->xmlStartTag(
"presentation_material");
3803 $a_xml_writer->xmlStartTag(
"flow_mat");
3804 $this->
addQTIMaterial($a_xml_writer, $page_id, $concluding_remarks);
3805 $a_xml_writer->xmlEndTag(
"flow_mat");
3806 $a_xml_writer->xmlEndTag(
"presentation_material");
3812 $a_xml_writer->xmlElement(
"section", $attrs, null);
3813 $a_xml_writer->xmlEndTag(
"assessment");
3814 $a_xml_writer->xmlEndTag(
"questestinterop");
3816 $xml = $a_xml_writer->xmlDumpMem(
false);
3822 return $date_time->setTimezone(
new DateTimeZone(
'UTC'))->format(
'\PY\Yn\Mj\D\TG\Hi\Ms\S');
3827 if ($period === null) {
3830 if (preg_match(
"/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $period, $matches)) {
3833 "%02d-%02d-%02d %02d:%02d:%02d",
3853 public function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog): void
3855 $this->mob_ids = [];
3858 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Start Export Page Objects");
3859 $this->bench->start(
"ContentObjectExport",
"exportPageObjects");
3861 $this->bench->stop(
"ContentObjectExport",
"exportPageObjects");
3862 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Finished Export Page Objects");
3865 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Start Export Media Objects");
3866 $this->bench->start(
"ContentObjectExport",
"exportMediaObjects");
3868 $this->bench->stop(
"ContentObjectExport",
"exportMediaObjects");
3869 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Finished Export Media Objects");
3872 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Start Export File Items");
3873 $this->bench->start(
"ContentObjectExport",
"exportFileItems");
3875 $this->bench->stop(
"ContentObjectExport",
"exportFileItems");
3876 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Finished Export File Items");
3886 if ($a_tag ==
"Identifier" && $a_param ==
"Entry") {
3902 foreach ($this->questions as $question_id) {
3903 $this->bench->start(
"ContentObjectExport",
"exportPageObject");
3904 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Page Object " . $question_id);
3907 $a_xml_writer->xmlStartTag(
"PageObject", $attrs);
3911 $this->bench->start(
"ContentObjectExport",
"exportPageObject_XML");
3913 $page_object->buildDom();
3914 $page_object->insertInstIntoIDs((
string) $inst);
3915 $mob_ids = $page_object->collectMediaObjects(
false);
3917 $xml = $page_object->getXMLFromDom(
false,
false,
false,
"",
true);
3918 $xml = str_replace(
"&",
"&", $xml);
3919 $a_xml_writer->appendXML($xml);
3920 $page_object->freeDom();
3921 unset($page_object);
3923 $this->bench->stop(
"ContentObjectExport",
"exportPageObject_XML");
3926 $this->bench->start(
"ContentObjectExport",
"exportPageObject_CollectMedia");
3928 foreach ($mob_ids as $mob_id) {
3929 $this->mob_ids[$mob_id] = $mob_id;
3931 $this->bench->stop(
"ContentObjectExport",
"exportPageObject_CollectMedia");
3934 $this->bench->start(
"ContentObjectExport",
"exportPageObject_CollectFileItems");
3936 foreach ($file_ids as $file_id) {
3937 $this->file_ids[$file_id] = $file_id;
3939 $this->bench->stop(
"ContentObjectExport",
"exportPageObject_CollectFileItems");
3941 $a_xml_writer->xmlEndTag(
"PageObject");
3944 $this->bench->stop(
"ContentObjectExport",
"exportPageObject");
3953 foreach ($this->mob_ids as $mob_id) {
3954 $expLog->write(date(
"[y-m-d H:i:s] ") .
"Media Object " . $mob_id);
3956 $target_dir = $a_target_dir . DIRECTORY_SEPARATOR .
'objects' 3957 . DIRECTORY_SEPARATOR .
'il_' .
IL_INST_ID .
'_mob_' . $mob_id;
3960 $media_obj->exportXML($a_xml_writer, (
int) $a_inst);
3961 foreach ($media_obj->getMediaItems() as $item) {
3962 $stream = $item->getLocationStream();
3963 file_put_contents($target_dir . DIRECTORY_SEPARATOR . $item->getLocation(), $stream);
3977 foreach ($this->file_ids as $file_id) {
3978 $expLog->write(date(
"[y-m-d H:i:s] ") .
"File Item " . $file_id);
3979 $file_dir = $target_dir .
'/objects/il_' .
IL_INST_ID .
'_file_' . $file_id;
3981 $file_obj =
new ilObjFile((
int) $file_id,
false);
3982 $source_file = $file_obj->getFile($file_obj->getVersion());
3983 if (!is_file($source_file)) {
3984 $source_file = $file_obj->getFile();
3986 if (is_file($source_file)) {
3987 copy($source_file, $file_dir .
'/' . $file_obj->getFileName());
4006 $this->
saveCompleteStatus($this->question_set_config_factory->getQuestionSetConfig());
4019 $results_summary_settings = $this->
getScoreSettings()->getResultSummarySettings();
4021 || $results_summary_settings->getScoreReporting()->isReportingEnabled() ===
false) {
4025 if ($results_summary_settings->getScoreReporting() === ScoreReportingTypes::SCORE_REPORTING_DATE) {
4026 return $results_summary_settings->getReportingDate()
4044 $path_to_lifecycle = $this->lo_metadata->paths()->custom()->withNextStep(
'lifeCycle')->get();
4045 $path_to_authors = $this->lo_metadata->paths()->authors();
4047 $reader = $this->lo_metadata->read($this->
getId(), 0, $this->
getType(), $path_to_lifecycle);
4048 if (!is_null($reader->allData($path_to_lifecycle)->current())) {
4052 if ($author ===
'') {
4053 $author = $this->
user->getFullname();
4055 $this->lo_metadata->manipulate($this->
getId(), 0, $this->
getType())
4056 ->prepareCreateOrUpdate($path_to_authors, $author)
4077 $path_to_authors = $this->lo_metadata->paths()->authors();
4078 $author_data = $this->lo_metadata->read($this->
getId(), 0, $this->
getType(), $path_to_authors)
4079 ->allData($path_to_authors);
4081 return $this->lo_metadata->dataHelper()->makePresentableAsList(
', ', ...$author_data);
4095 $lo_metadata = $DIC->learningObjectMetadata();
4097 $path_to_authors = $lo_metadata->paths()->authors();
4098 $author_data = $lo_metadata->read($obj_id, 0,
"tst", $path_to_authors)
4099 ->allData($path_to_authors);
4101 return $lo_metadata->dataHelper()->makePresentableAsList(
',', ...$author_data);
4113 $ilUser = $DIC[
'ilUser'];
4116 $tests = array_slice(
4124 if (count($tests)) {
4127 if ($use_object_id) {
4129 $result_array[$obj_id] = $titles[
$ref_id];
4135 return $result_array;
4150 $new_obj = parent::cloneObject($target_id, $copy_id, $omit_tree);
4151 $new_obj->setTmpCopyWizardCopyId($copy_id);
4154 $new_obj->saveToDb();
4155 $new_obj->addToNewsOnOnline(
false, $new_obj->getObjectProperties()->getPropertyIsOnline()->getIsOnline());
4158 ->withIntroductionSettings(
4159 $this->
getMainSettings()->getIntroductionSettings()->withIntroductionPageId(
4161 )->withTestId($new_obj->getTestId())
4162 )->withFinishingSettings(
4163 $this->
getMainSettings()->getFinishingSettings()->withConcludingRemarksPageId(
4165 )->withTestId($new_obj->getTestId())
4171 $this->marks_repository->storeMarkSchema(
4184 $templateRepository,
4188 $cloneAction->cloneCertificate($this, $new_obj);
4190 $this->question_set_config_factory->getQuestionSetConfig()->cloneQuestionSetRelatedData($new_obj);
4191 $new_obj->saveQuestionsToDb();
4194 $skillLevelThresholdList->setTestId($this->
getTestId());
4195 $skillLevelThresholdList->loadFromDb();
4196 $skillLevelThresholdList->cloneListForTest($new_obj->getTestId());
4199 $obj_settings->cloneSettings($new_obj->getId());
4201 if ($new_obj->getTestLogger()->isLoggingEnabled()) {
4202 $new_obj->getTestLogger()->logTestAdministrationInteraction(
4203 $new_obj->getTestLogger()->getInteractionFactory()->buildTestAdministrationInteraction(
4204 $new_obj->getRefId(),
4205 $this->
user->getId(),
4206 TestAdministrationInteractionTypes::NEW_TEST_CREATED,
4225 $this->component_repository,
4227 $this->questionrepository
4230 $questionSetConfig->loadFromDb();
4232 if ($questionSetConfig->isQuestionAmountConfigurationModePerPool()) {
4239 $sourcePoolDefinitionList->loadDefinitions();
4241 if (is_int($sourcePoolDefinitionList->getQuestionAmount())) {
4242 $num = $sourcePoolDefinitionList->getQuestionAmount();
4244 } elseif (is_int($questionSetConfig->getQuestionAmountPerTest())) {
4245 $num = $questionSetConfig->getQuestionAmountPerTest();
4249 $num = count($this->questions);
4260 return count($this->questions);
4273 $ilDB = $DIC[
'ilDB'];
4275 $result =
$ilDB->queryF(
4276 "SELECT obj_fi FROM tst_tests WHERE test_id = %s",
4280 if ($result->numRows()) {
4281 $row =
$ilDB->fetchAssoc($result);
4282 $object_id = $row[
"obj_fi"];
4297 $ilDB = $DIC[
'ilDB'];
4299 $result =
$ilDB->queryF(
4300 "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",
4304 if ($result->numRows()) {
4305 $row =
$ilDB->fetchAssoc($result);
4306 $object_id = $row[
"obj_fi"];
4321 $ilDB = $DIC[
'ilDB'];
4323 $result =
$ilDB->queryF(
4324 "SELECT test_id FROM tst_tests WHERE obj_fi = %s",
4328 if ($result->numRows()) {
4329 $row =
$ilDB->fetchAssoc($result);
4330 $test_id = $row[
"test_id"];
4345 if (($active_id) && ($question_id)) {
4346 if ($pass === null) {
4349 if ($pass === null) {
4352 $query = $this->db->queryF(
4353 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
4354 [
'integer',
'integer',
'integer'],
4355 [$active_id, $question_id, $pass]
4357 $result = $this->db->fetchAll($query);
4358 if (count($result) == 1) {
4359 return $result[0][
"value1"];
4376 $result = $this->db->queryF(
4377 "SELECT question_text FROM qpl_questions WHERE question_id = %s",
4381 if ($result->numRows() == 1) {
4382 $row = $this->db->fetchAssoc($result);
4383 $res = $row[
"question_text"];
4394 return $participant_list;
4409 $result = $this->db->queryF(
4410 "SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, " .
4411 "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 " .
4412 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
4413 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
4415 [
'text',
'text',
'text',
'integer',
'integer'],
4419 $result = $this->db->queryF(
4420 "SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, " .
4421 "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 " .
4422 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
4423 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
4425 [
'text',
'text',
'text',
'integer'],
4426 [
'', $this->
lng->txt(
'anonymous'),
'', $this->
getTestId()]
4431 $result = $this->db->queryF(
4432 "SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, " .
4433 "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 " .
4434 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
4435 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
4437 [
'integer',
'integer'],
4441 $result = $this->db->queryF(
4442 "SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, " .
4443 "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 " .
4444 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
4445 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
4453 while ($row = $this->db->fetchAssoc($result)) {
4454 $result_array[$row[
'usr_id']] = $row;
4456 return $result_array;
4463 SELECT tst_active.active_id, 4465 tst_active.user_fi usr_id, 4469 tst_active.submitted test_finished, 4470 usr_data.matriculation, 4472 tst_active.lastindex, 4473 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes 4476 ON tst_active.user_fi = usr_data.usr_id 4477 WHERE tst_active.test_fi = %s 4478 ORDER BY usr_data.lastname 4480 $result = $this->db->queryF(
4482 [
'text',
'text',
'text',
'integer'],
4483 [
'', $this->
lng->txt(
"anonymous"),
"", $this->
getTestId()]
4487 SELECT tst_active.active_id, 4489 tst_active.user_fi usr_id, 4493 tst_active.submitted test_finished, 4494 usr_data.matriculation, 4496 tst_active.lastindex, 4497 COALESCE(tst_active.last_finished_pass, -1) <> tst_active.last_started_pass unfinished_passes 4500 ON tst_active.user_fi = usr_data.usr_id 4501 WHERE tst_active.test_fi = %s 4502 ORDER BY usr_data.lastname 4504 $result = $this->db->queryF(
4511 while ($row = $this->db->fetchAssoc($result)) {
4512 $data[$row[
'active_id']] = $row;
4514 foreach (
$data as $index => $participant) {
4515 if (strlen(trim($participant[
"firstname"] . $participant[
"lastname"])) == 0) {
4516 $data[$index][
"lastname"] = $this->
lng->txt(
"deleted_user");
4528 $filtered_participants = [];
4530 if ($participant[
'tries'] > 0) {
4533 if ($this->test_man_scoring_done_helper->isDone((
int) $active_id)) {
4534 $filtered_participants[$active_id] = $participant;
4538 if (!$this->test_man_scoring_done_helper->isDone((
int) $active_id)) {
4539 $filtered_participants[$active_id] = $participant;
4543 $filtered_participants[$active_id] = $participant;
4547 return $filtered_participants;
4558 if (!is_array($ids) || count($ids) == 0) {
4563 $result = $this->db->queryF(
4564 "SELECT usr_id, %s login, %s lastname, %s firstname, client_ip clientip FROM usr_data WHERE " . $this->db->in(
'usr_id', $ids,
false,
'integer') .
" ORDER BY login",
4565 [
'text',
'text',
'text'],
4566 [
"", $this->
lng->txt(
"anonymous"),
""]
4569 $result = $this->db->query(
"SELECT usr_id, login, lastname, firstname, client_ip clientip FROM usr_data WHERE " . $this->db->in(
'usr_id', $ids,
false,
'integer') .
" ORDER BY login");
4573 while ($row = $this->db->fetchAssoc($result)) {
4574 $result_array[$row[
"usr_id"]] = $row;
4576 return $result_array;
4581 if (!is_array($ids) || count($ids) == 0) {
4594 if (!is_array($ids) || count($ids) == 0) {
4598 foreach ($ids as $obj_id) {
4612 $this->db->manipulateF(
4613 "DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
4614 [
'integer',
'integer'],
4617 $this->db->manipulateF(
4618 "INSERT INTO tst_invited_user (test_fi, user_fi, ip_range_from, ip_range_to, tstamp) VALUES (%s, %s, %s, %s, %s)",
4619 [
'integer',
'integer',
'text',
'text',
'integer'],
4620 [$this->
getTestId(),
$user_id, (strlen($client_ip)) ? $client_ip : null, (strlen($client_ip)) ? $client_ip : null,time()]
4632 $ilDB = $DIC[
'ilDB'];
4633 if (is_numeric($question_fi)) {
4634 $result =
$ilDB->queryF(
4635 "SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
4636 [
'integer',
'integer'],
4637 [$active_id, $question_fi]
4640 $result =
$ilDB->queryF(
4641 "SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
4647 while ($row =
$ilDB->fetchAssoc($result)) {
4648 $result_array[$row[
"question_fi"]] = $row;
4650 return $result_array;
4660 $this->db->manipulateF(
4661 "DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
4662 [
'integer',
'integer'],
4663 [$active_id, $question_id]
4665 $this->db->manipulateF(
4666 "INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
4667 [
'integer',
'integer',
'integer'],
4668 [$value, $question_id, $active_id]
4677 $result = $this->db->queryF(
4678 "SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
4679 [
'integer',
'integer'],
4682 return $result->numRows() == 1;
4694 $result = $this->db->queryF(
4695 "SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
4696 [
'integer',
'integer',
'integer'],
4699 return $result->numRows() == 1;
4733 "user_id" => $this->
lng->txt(
"user_id"),
4734 "matriculation" => $this->
lng->txt(
"matriculation"),
4735 "lastname" => $this->
lng->txt(
"lastname"),
4736 "firstname" => $this->
lng->txt(
"firstname"),
4737 "login" => $this->
lng->txt(
"login"),
4738 "reached_points" => $this->
lng->txt(
"tst_reached_points"),
4739 "max_points" => $this->
lng->txt(
"tst_maximum_points"),
4740 "percent_value" => $this->
lng->txt(
"tst_percent_solved"),
4741 "mark" => $this->
lng->txt(
"tst_mark"),
4742 "passed" => $this->
lng->txt(
"tst_mark_passed"),
4745 if (count($participants)) {
4746 foreach ($participants as $active_id => $user_rec) {
4749 $reached_points = 0;
4753 if (!is_int($pass)) {
4756 foreach ($this->questions as $value) {
4758 if (is_object($question)) {
4759 $max_points += $question->getMaximumPoints();
4760 $reached_points += $question->getReachedPoints($active_id, $pass);
4763 if ($max_points > 0) {
4764 $percentvalue = $reached_points / $max_points;
4765 if ($percentvalue < 0) {
4766 $percentvalue = 0.0;
4771 $mark_obj = $this->
getMarkSchema()->getMatchingMark($percentvalue * 100);
4773 if ($mark_obj !== null) {
4774 $mark = $mark_obj->getOfficialName();
4777 $user_rec[
'firstname'] =
"";
4778 $user_rec[
'lastname'] = $this->
lng->txt(
"anonymous");
4781 "user_id" => $user_rec[
'usr_id'],
4782 "matriculation" => $user_rec[
'matriculation'],
4783 "lastname" => $user_rec[
'lastname'],
4784 "firstname" => $user_rec[
'firstname'],
4785 "login" => $user_rec[
'login'],
4786 "reached_points" => $reached_points,
4787 "max_points" => $max_points,
4788 "percent_value" => $percentvalue,
4790 "passed" => $user_rec[
'passed'] ?
'1' :
'0',
4808 $ilDB = $DIC[
'ilDB'];
4809 $result =
$ilDB->queryF(
4810 "SELECT tries FROM tst_active WHERE active_id = %s",
4814 if ($result->numRows()) {
4815 $row =
$ilDB->fetchAssoc($result);
4816 return $row[
"tries"];
4834 $ilDB = $DIC[
'ilDB'];
4835 $result =
$ilDB->queryF(
4836 "SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
4841 if ($result->numRows()) {
4842 $row =
$ilDB->fetchAssoc($result);
4843 return $row[
"maxpass"];
4857 $ilDB = $DIC[
'ilDB'];
4859 $result =
$ilDB->queryF(
4860 "SELECT * FROM tst_pass_result WHERE active_fi = %s",
4865 if (!$result->numRows()) {
4871 while ($row =
$ilDB->fetchAssoc($result)) {
4872 if ($row[
"maxpoints"] > 0.0) {
4873 $factor = (float) ($row[
"points"] / $row[
"maxpoints"]);
4877 if ($factor === 0.0 && $bestfactor === 0.0
4878 || $factor > $bestfactor) {
4880 $bestfactor = $factor;
4884 if (is_array($bestrow)) {
4885 return $bestrow[
"pass"];
4901 $counted_pass = null;
4907 return $counted_pass;
4925 foreach ($this->questions as $value) {
4926 if ($this->questionrepository->lookupResultRecordExist($active_id, $value, $pass)) {
4927 $workedthrough += 1;
4930 return $workedthrough;
4942 $ilDB = $DIC[
'ilDB'];
4944 if (is_null($pass)) {
4949 SELECT tst_pass_result.tstamp pass_res_tstamp, 4950 tst_test_result.tstamp quest_res_tstamp 4952 FROM tst_pass_result 4954 LEFT JOIN tst_test_result 4955 ON tst_test_result.active_fi = tst_pass_result.active_fi 4956 AND tst_test_result.pass = tst_pass_result.pass 4958 WHERE tst_pass_result.active_fi = %s 4959 AND tst_pass_result.pass = %s 4961 ORDER BY tst_test_result.tstamp DESC 4964 $result =
$ilDB->queryF(
4966 [
'integer',
'integer'],
4970 while ($row =
$ilDB->fetchAssoc($result)) {
4971 if ($row[
'quest_res_tstamp']) {
4972 return $row[
'quest_res_tstamp'];
4975 return $row[
'pass_res_tstamp'];
4992 "executable" =>
true,
4993 "errormessage" =>
"" 4997 $result[
"executable"] =
false;
4998 $result[
"errormessage"] = $this->
lng->txt(
'autosave_failed') .
': ' . $this->
lng->txt(
'offline');
5003 $result[
"executable"] =
false;
5008 $result[
"executable"] =
false;
5019 $result[
"executable"] =
false;
5020 $result[
"errormessage"] = $this->
lng->txt(
"detail_max_processing_time_reached");
5025 $testPassesSelector->setActiveId($active_id);
5026 $testPassesSelector->setLastFinishedPass($test_session->getLastFinishedPass());
5029 $closedPasses = $testPassesSelector->getClosedPasses();
5032 $result[
"executable"] =
false;
5033 $result[
"errormessage"] = $this->
lng->txt(
"maximum_nr_of_tries_reached");
5039 $result[
'executable'] =
false;
5040 $result[
'errormessage'] = $this->
lng->txt(
"tst_addit_passes_blocked_after_passed_msg");
5046 $next_pass_allowed_timestamp = 0;
5047 if (!$this->
isNextPassAllowed($testPassesSelector, $next_pass_allowed_timestamp)) {
5050 $result[
'executable'] =
false;
5051 $result[
'errormessage'] = sprintf($this->
lng->txt(
'wait_for_next_pass_hint_msg'), $date);
5059 $waiting_between_passes = $this->
getMainSettings()->getTestBehaviourSettings()->getPassWaiting();
5063 $this->
getMainSettings()->getTestBehaviourSettings()->getPassWaitingEnabled()
5064 && ($waiting_between_passes !==
'')
5066 && ($last_finished_pass_timestamp !== null)
5068 $time_values = explode(
':', $waiting_between_passes);
5069 $next_pass_allowed_timestamp = strtotime(
'+ ' . $time_values[0] .
' Days + ' . $time_values[1] .
' Hours' . $time_values[2] .
' Minutes', $last_finished_pass_timestamp);
5070 return (time() > $next_pass_allowed_timestamp);
5080 $pass_selector->setActiveId($test_session->
getActiveId());
5083 return $pass_selector->hasReportablePasses();
5090 $pass_selector->setActiveId($test_session->
getActiveId());
5093 return $pass_selector->hasExistingPasses();
5105 if ($active_id < 1) {
5108 if ($pass === null) {
5111 $result = $this->db->queryF(
5112 "SELECT tst_times.started FROM tst_times WHERE tst_times.active_fi = %s AND tst_times.pass = %s ORDER BY tst_times.started",
5113 [
'integer',
'integer'],
5116 if ($result->numRows()) {
5117 $row = $this->db->fetchAssoc($result);
5118 if (preg_match(
"/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row[
"started"], $matches)) {
5149 if ($now > ($starting_time + $processing_time)) {
5158 $tags_trafo = $this->
refinery->string()->stripTags();
5162 questtypes.type_tag, 5164 origquest.obj_fi orig_obj_fi 5166 FROM qpl_questions questions 5168 INNER JOIN qpl_qst_type questtypes 5169 ON questtypes.question_type_id = questions.question_type_fi 5171 INNER JOIN tst_test_question tstquest 5172 ON tstquest.question_fi = questions.question_id 5174 LEFT JOIN qpl_questions origquest 5175 ON origquest.question_id = questions.original_id 5177 WHERE tstquest.test_fi = %s 5179 ORDER BY tstquest.sequence 5182 $query_result = $this->db->queryF(
5190 while ($row = $this->db->fetchAssoc($query_result)) {
5191 $row[
'title'] = $tags_trafo->transform($row[
'title']);
5192 $row[
'description'] = $tags_trafo->transform($row[
'description'] !==
'' && $row[
'description'] !== null ? $row[
'description'] :
' ');
5193 $row[
'author'] = $tags_trafo->transform($row[
'author']);
5195 $questions[] = $row;
5204 if ($questionData[
'question_id'] != $question_id) {
5216 $row = $this->db->fetchAssoc($this->db->queryF(
5217 "SELECT COUNT(question_id) cnt FROM qpl_questions WHERE question_id = %s AND obj_fi = %s",
5218 [
'integer',
'integer'],
5219 [$question_id, $this->getId()]
5222 return (
bool) $row[
'cnt'];
5230 $points += $question_data[
'points'];
5243 questtypes.type_tag, 5244 origquest.obj_fi orig_obj_fi 5246 FROM qpl_questions questions 5248 INNER JOIN qpl_qst_type questtypes 5249 ON questtypes.question_type_id = questions.question_type_fi 5251 INNER JOIN tst_rnd_cpy tstquest 5252 ON tstquest.qst_fi = questions.question_id 5254 LEFT JOIN qpl_questions origquest 5255 ON origquest.question_id = questions.original_id 5257 WHERE tstquest.tst_fi = %s 5260 $query_result = $this->db->queryF(
5266 return $this->db->fetchAll($query_result);
5271 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getShuffleQuestions();
5287 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getUsrPassOverviewMode();
5292 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getQuestionListEnabled();
5297 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getUsrPassOverviewEnabled();
5302 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getShownQuestionListAtBeginning();
5307 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getShownQuestionListAtEnd();
5312 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getShowDescriptionInQuestionList();
5320 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowPassDetails();
5328 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionPrintview();
5343 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionFeedback();
5351 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionAnswersOnly();
5359 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionSignature();
5367 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionSuggested();
5376 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionListComparison();
5381 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowSolutionListOwnAnswers();
5390 $ilDB = $DIC[
'ilDB'];
5391 $result =
$ilDB->queryF(
5392 "SELECT user_fi FROM tst_active WHERE active_id = %s",
5396 if ($result->numRows()) {
5397 $row =
$ilDB->fetchAssoc($result);
5398 return $row[
"user_fi"];
5406 $result = $this->db->queryF(
5407 "SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
5411 if ($result->numRows()) {
5412 $row = $this->db->fetchAssoc($result);
5413 return $row[
"finished"];
5418 public static function lookupLastTestPassAccess(
int $active_id,
int $pass_index): ?
int 5422 $ilDB = $DIC[
'ilDB'];
5425 SELECT MAX(tst_times.tstamp) as last_pass_access 5427 WHERE active_fi = %s 5433 [
'integer',
'integer'],
5434 [$active_id, $pass_index]
5437 while ($row =
$ilDB->fetchAssoc(
$res)) {
5438 return $row[
'last_pass_access'];
5453 if (preg_match(
"/<[^>]*?>/", $a_text)) {
5470 for ($i = 0; $i < $a_material->getMaterialCount(); $i++) {
5471 $material = $a_material->getMaterial($i);
5472 if ($material[
'type'] ===
'mattext') {
5473 $result .= $material[
'material']->getContent();
5475 if ($material[
'type'] ===
'matimage') {
5476 $matimage = $material[
'material'];
5477 if (preg_match(
'/(il_([0-9]+)_mob_([0-9]+))/', $matimage->getLabel(), $matches)) {
5479 'mob' => $matimage->getLabel(),
5480 'uri' => $matimage->getUri()
5486 $decoded_result = base64_decode($result);
5487 if (str_starts_with($decoded_result,
'<PageObject>')) {
5488 $result = $decoded_result;
5502 'texttype' =>
'text/plain' 5506 if ($page_id !== null) {
5507 $attrs[
'texttype'] =
'text/xml';
5510 $page_object->buildDom();
5511 $page_object->insertInstIntoIDs((
string)
IL_INST_ID);
5512 $material = base64_encode($page_object->getXMLFromDom());
5514 foreach ($file_ids as $file_id) {
5515 $this->file_ids[] = (
int) $file_id;
5517 $mob_string =
'il_' . IL_INST_ID .
'_mob_';
5518 } elseif ($this->
isHTML($material)) {
5519 $attrs[
'texttype'] =
'text/xhtml';
5521 $mob_string =
'mm_';
5524 $xml_writer->
xmlElement(
'mattext', $attrs, $material);
5525 foreach ($mobs as $mob) {
5526 $mob_id_string = (string) $mob;
5527 $moblabel =
'il_' .
IL_INST_ID .
'_mob_' . $mob_id_string;
5528 if (strpos($material, $mob_string . $mob_id_string) !==
false) {
5532 'label' => $moblabel,
5533 'uri' =>
'objects/' .
'il_' .
IL_INST_ID .
'_mob_' . $mob_id_string .
'/' . $mob_obj->getTitle()
5536 $xml_writer->
xmlElement(
'matimage', $imgattrs, null);
5550 if ($txt_output == null) {
5555 $prepare_for_latex_output,
5556 $omitNl2BrWhenTextArea
5562 return $this->
getMainSettings()->getGeneralSettings()->getAnonymity();
5569 $ilDB = $DIC[
'ilDB'];
5571 $result =
$ilDB->queryF(
5572 "SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
5576 while ($row =
$ilDB->fetchAssoc($result)) {
5577 return (
int) $row[
'anonymity'];
5584 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getSuspendTestAllowed();
5589 return $this->
getMainSettings()->getParticipantFunctionalitySettings()->getQuestionMarkingEnabled();
5594 return $this->
getMainSettings()->getAccessSettings()->getFixedParticipants();
5600 SELECT tst_tests.question_set_type 5602 INNER JOIN tst_tests 5603 ON tst_active.test_fi = tst_tests.test_id 5604 WHERE tst_active.active_id = %s 5607 $res = $this->db->queryF($query, [
'integer'], [$active_id]);
5609 while ($row = $this->db->fetchAssoc(
$res)) {
5610 return $row[
'question_set_type'];
5629 return $this->
lng->txt(
"anonymous") . $suffix;
5632 if (strlen($uname[
"firstname"] . $uname[
"lastname"]) == 0) {
5633 $uname[
"firstname"] = $this->
lng->txt(
"deleted_user");
5635 if ($sorted_order) {
5636 return trim($uname[
"lastname"] .
", " . $uname[
"firstname"]) . $suffix;
5638 return trim($uname[
"firstname"] .
" " . $uname[
"lastname"]) . $suffix;
5650 $result = $this->db->queryF(
5651 "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
5653 [$this->
user->getId()]
5656 while ($row = $this->db->fetchAssoc($result)) {
5657 $defaults[$row[
"test_defaults_id"]] = $row;
5664 $result = $this->db->queryF(
5665 "SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
5669 if ($result->numRows() == 1) {
5670 $row = $this->db->fetchAssoc($result);
5679 $this->db->manipulateF(
5680 "DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
5748 'mailnotification' => $main_settings->
getFinishingSettings()->getMailNotificationContentType(),
5782 fn(
Mark $v): array => [
5791 $next_id = $this->db->nextId(
'tst_test_defaults');
5793 'tst_test_defaults',
5795 'test_defaults_id' => [
'integer', $next_id],
5796 'name' => [
'text', $a_name],
5797 'user_fi' => [
'integer', $this->
user->getId()],
5798 'defaults' => [
'clob', serialize($testsettings)],
5799 'marks' => [
'clob', json_encode($marks)],
5800 'tstamp' => [
'integer', time()]
5807 $testsettings = unserialize($test_defaults[
'defaults'], [
'allowed_classes' => [DateTimeImmutable::class]]);
5808 $activation_starting_time = is_numeric($testsettings[
'activation_starting_time'] ??
false)
5809 ? (
int) $testsettings[
'activation_starting_time']
5811 $activation_ending_time = is_numeric($testsettings[
'activation_ending_time'] ??
false)
5812 ? (
int) $testsettings[
'activation_ending_time']
5814 $unserialized_marks = json_decode($test_defaults[
'marks'],
true);
5817 if (is_array($unserialized_marks)
5818 && is_array($unserialized_marks[0])) {
5823 $v[
'official_name'],
5824 $v[
'minimum_level'],
5831 $info =
'old_mark_default_not_applied';
5836 (
bool) ($testsettings[
'is_activation_limited'] ??
false),
5837 $activation_starting_time,
5838 $activation_ending_time,
5839 (
bool) ($testsettings[
'activation_visibility'] ??
false),
5853 $main_settings = $main_settings
5856 ->withQuestionSetType(
5857 $testsettings[
'questionSetType'] ?? $general_settings->getQuestionSetType()
5859 (
bool) ($testsettings[
'Anonymity'] ?? $general_settings->getAnonymity())
5861 )->withIntroductionSettings(
5862 $introduction_settings
5863 ->withIntroductionEnabled(
5864 (
bool) $testsettings[
'IntroEnabled'] ?? $introduction_settings->getIntroductionEnabled()
5865 )->withExamConditionsCheckboxEnabled(
5866 (
bool) ($testsettings[
'ExamConditionsCheckboxEnabled'] ?? $introduction_settings->getExamConditionsCheckboxEnabled())
5868 )->withAccessSettings(
5870 ->withStartTimeEnabled(
5871 (
bool) ($testsettings[
'StartingTimeEnabled'] ?? $access_settings->getStartTimeEnabled())
5874 $testsettings[
'StartingTime'] ?? $access_settings->getStartTime()
5876 )->withEndTimeEnabled(
5877 (
bool) $testsettings[
'EndingTimeEnabled'] ?? $access_settings->getEndTimeEnabled()
5880 $testsettings[
'EndingTime'] ?? $access_settings->getEndTime()
5882 )->withPasswordEnabled(
5883 (
bool) ($testsettings[
'password_enabled'] ?? $access_settings->getPasswordEnabled())
5885 $testsettings[
'password'] ?? $access_settings->getPassword()
5886 )->withFixedParticipants(
5887 (
bool) ($testsettings[
'fixed_participants'] ?? $access_settings->getFixedParticipants())
5889 )->withTestBehaviourSettings(
5890 $test_behavior_settings
5891 ->withNumberOfTries(
5892 (
int) ($testsettings[
'NrOfTries'] ?? $test_behavior_settings->getNumberOfTries())
5893 )->withBlockAfterPassedEnabled(
5894 (
bool) ($testsettings[
'BlockAfterPassed'] ?? $test_behavior_settings->getBlockAfterPassedEnabled())
5896 $testsettings[
'pass_waiting'] ?? $test_behavior_settings->getPassWaiting()
5898 $testsettings[
'Kiosk'] ?? $test_behavior_settings->getKioskMode()
5899 )->withProcessingTimeEnabled(
5900 (
bool) ($testsettings[
'EnableProcessingTime'] ?? $test_behavior_settings->getProcessingTimeEnabled())
5901 )->withProcessingTime(
5902 $testsettings[
'ProcessingTime'] ?? $test_behavior_settings->getProcessingTime()
5903 )->withResetProcessingTime(
5904 (
bool) ($testsettings[
'ResetProcessingTime'] ?? $test_behavior_settings->getResetProcessingTime())
5905 )->withExamIdInTestAttemptEnabled(
5906 (
bool) ($testsettings[
'examid_in_test_pass'] ?? $test_behavior_settings->getExamIdInTestAttemptEnabled())
5908 )->withQuestionBehaviourSettings(
5909 $question_behavior_settings
5910 ->withQuestionTitleOutputMode(
5911 $testsettings[
'TitleOutput'] ?? $question_behavior_settings->getQuestionTitleOutputMode()
5912 )->withAutosaveEnabled(
5913 (
bool) ($testsettings[
'autosave'] ?? $question_behavior_settings->getAutosaveEnabled())
5914 )->withAutosaveInterval(
5915 $testsettings[
'autosave_ival'] ?? $question_behavior_settings->getAutosaveInterval()
5916 )->withShuffleQuestions(
5917 (
bool) ($testsettings[
'Shuffle'] ?? $question_behavior_settings->getShuffleQuestions())
5918 )->withQuestionHintsEnabled(
5919 (
bool) ($testsettings[
'offer_question_hints'] ?? $question_behavior_settings->getQuestionHintsEnabled())
5920 )->withInstantFeedbackPointsEnabled(
5921 (
bool) ($testsettings[
'AnswerFeedbackPoints'] ?? $question_behavior_settings->getInstantFeedbackPointsEnabled())
5922 )->withInstantFeedbackGenericEnabled(
5923 (
bool) ($testsettings[
'AnswerFeedback'] ?? $question_behavior_settings->getInstantFeedbackGenericEnabled())
5924 )->withInstantFeedbackSpecificEnabled(
5925 (
bool) ($testsettings[
'SpecificAnswerFeedback'] ?? $question_behavior_settings->getInstantFeedbackSpecificEnabled())
5926 )->withInstantFeedbackSolutionEnabled(
5927 (
bool) ($testsettings[
'InstantFeedbackSolution'] ?? $question_behavior_settings->getInstantFeedbackSolutionEnabled())
5928 )->withForceInstantFeedbackOnNextQuestion(
5929 (
bool) ($testsettings[
'force_inst_fb'] ?? $question_behavior_settings->getForceInstantFeedbackOnNextQuestion())
5930 )->withLockAnswerOnInstantFeedbackEnabled(
5931 (
bool) ($testsettings[
'inst_fb_answer_fixation'] ?? $question_behavior_settings->getLockAnswerOnInstantFeedbackEnabled())
5932 )->withLockAnswerOnNextQuestionEnabled(
5933 (
bool) ($testsettings[
'follow_qst_answer_fixation'] ?? $question_behavior_settings->getLockAnswerOnNextQuestionEnabled())
5935 )->withParticipantFunctionalitySettings(
5936 $participant_functionality_settings
5937 ->withUsePreviousAnswerAllowed(
5938 (
bool) ($testsettings[
'use_previous_answers'] ?? $participant_functionality_settings->getUsePreviousAnswerAllowed())
5939 )->withSuspendTestAllowed(
5940 (
bool) ($testsettings[
'ShowCancel'] ?? $participant_functionality_settings->getSuspendTestAllowed())
5941 )->withPostponedQuestionsMoveToEnd(
5942 (
bool) ($testsettings[
'SequenceSettings'] ?? $participant_functionality_settings->getPostponedQuestionsMoveToEnd())
5943 )->withUsrPassOverviewMode(
5944 (
int) ($testsettings[
'ListOfQuestionsSettings'] ?? $participant_functionality_settings->getUsrPassOverviewMode())
5945 )->withQuestionMarkingEnabled(
5946 (
bool) ($testsettings[
'ShowMarker'] ?? $participant_functionality_settings->getQuestionMarkingEnabled())
5948 )->withFinishingSettings(
5950 ->withShowAnswerOverview(
5951 (
bool) ($testsettings[
'enable_examview'] ?? $finishing_settings->getShowAnswerOverview())
5952 )->withConcludingRemarksEnabled(
5953 (
bool) ($testsettings[
'ShowFinalStatement'] ?? $finishing_settings->getConcludingRemarksEnabled())
5954 )->withRedirectionMode(
5955 (
int) ($testsettings[
'redirection_mode'] ?? $finishing_settings->getRedirectionMode())
5956 )->withRedirectionUrl(
5957 $testsettings[
'redirection_url'] ?? $finishing_settings->getRedirectionUrl()
5958 )->withMailNotificationContentType(
5959 (
int) ($testsettings[
'mailnotification'] ?? $finishing_settings->getMailNotificationContentType())
5960 )->withAlwaysSendMailNotification(
5961 (
bool) ($testsettings[
'mailnottype'] ?? $finishing_settings->getAlwaysSendMailNotification())
5963 )->withAdditionalSettings(
5964 $additional_settings
5965 ->withSkillsServiceEnabled(
5966 (
bool) ($testsettings[
'skill_service'] ?? $additional_settings->getSkillsServiceEnabled())
5968 (
bool) ($testsettings[
'HideInfoTab'] ?? $additional_settings->getHideInfoTab())
5974 $score_reporting = ScoreReportingTypes::SCORE_REPORTING_DISABLED;
5975 if ($testsettings[
'ScoreReporting'] !== null) {
5976 $score_reporting = ScoreReportingTypes::tryFrom($testsettings[
'ScoreReporting'])
5977 ?? ScoreReportingTypes::SCORE_REPORTING_DISABLED;
5980 $reporting_date = $testsettings[
'ReportingDate'];
5981 if (is_string($reporting_date)) {
5992 $score_settings = $score_settings
5996 $testsettings[
'PassScoring'] ?? $scoring_settings->getPassScoring()
5997 )->withScoreCutting(
5998 $testsettings[
'ScoreCutting'] ?? $scoring_settings->getScoreCutting()
6000 $testsettings[
'CountSystem'] ?? $scoring_settings->getCountSystem()
6002 )->withResultSummarySettings(
6003 $result_summary_settings
6004 ->withPassDeletionAllowed(
6005 (
bool) ($testsettings[
'pass_deletion_allowed'] ?? $result_summary_settings->getPassDeletionAllowed())
6006 )->withShowGradingStatusEnabled(
6007 (
bool) ($testsettings[
'show_grading_status'] ?? $result_summary_settings->getShowGradingStatusEnabled())
6008 )->withShowGradingMarkEnabled(
6009 (
bool) ($testsettings[
'show_grading_mark'] ?? $result_summary_settings->getShowGradingMarkEnabled())
6010 )->withScoreReporting(
6012 )->withReportingDate(
6015 )->withResultDetailsSettings(
6016 $result_details_settings
6017 ->withResultsPresentation(
6018 (
int) ($testsettings[
'ResultsPresentation'] ?? $result_details_settings->getResultsPresentation())
6019 )->withShowSolutionListComparison(
6020 (
bool) ($testsettings[
'show_solution_list_comparison'] ?? $result_details_settings->getShowSolutionListComparison())
6021 )->withShowExamIdInTestResults(
6022 (
bool) ($testsettings[
'examid_in_test_res'] ?? $result_details_settings->getShowExamIdInTestResults())
6024 )->withGamificationSettings(
6025 $gamification_settings
6026 ->withHighscoreEnabled(
6027 (
bool) ($testsettings[
'highscore_enabled'] ?? $gamification_settings->getHighscoreEnabled())
6028 )->withHighscoreAnon(
6029 (
bool) ($testsettings[
'highscore_anon'] ?? $gamification_settings->getHighscoreAnon())
6030 )->withHighscoreAchievedTS(
6031 $testsettings[
'highscore_achieved_ts'] ?? $gamification_settings->getHighscoreAchievedTS()
6032 )->withHighscoreScore(
6033 (
bool) ($testsettings[
'highscore_score'] ?? $gamification_settings->getHighscoreScore())
6034 )->withHighscorePercentage(
6035 $testsettings[
'highscore_percentage'] ?? $gamification_settings->getHighscorePercentage()
6036 )->withHighscoreHints(
6037 (
bool) ($testsettings[
'highscore_hints'] ?? $gamification_settings->getHighscoreHints())
6038 )->withHighscoreWTime(
6039 (
bool) ($testsettings[
'highscore_wtime'] ?? $gamification_settings->getHighscoreWTime())
6040 )->withHighscoreOwnTable(
6041 (
bool) ($testsettings[
'highscore_own_table'] ?? $gamification_settings->getHighscoreOwnTable())
6042 )->withHighscoreTopTable(
6043 (
bool) ($testsettings[
'highscore_top_table'] ?? $gamification_settings->getHighscoreTopTable())
6044 )->withHighscoreTopNum(
6045 $testsettings[
'highscore_top_num'] ?? $gamification_settings->getHighscoreTopNum()
6062 return DateTimeImmutable::createFromFormat(
'U', (
string) $date_time);
6074 if (extension_loaded(
"tidy")) {
6077 "output-xml" =>
true,
6078 "numeric-entities" => true
6081 $tidy->parseString($print_output, $config,
'utf8');
6082 $tidy->cleanRepair();
6083 $print_output = tidy_get_output($tidy);
6084 $print_output = preg_replace(
"/^.*?(<html)/",
"\\1", $print_output);
6086 $print_output = str_replace(
" ",
" ", $print_output);
6087 $print_output = str_replace(
"⊗",
"X", $print_output);
6089 $xsl = file_get_contents(
"./components/ILIAS/Test/xml/question2fo.xsl");
6094 'font-family="Helvetica, unifont"',
6095 'font-family="' . $this->
settings->get(
'rpc_pdf_font',
'Helvetica, unifont') .
'"',
6099 $args = [
'/_xml' => $print_output,
'/_xsl' => $xsl ];
6100 $xh = xslt_create();
6102 $output = xslt_process($xh,
"arg:/_xml",
"arg:/_xsl", null, $args,
$params);
6116 $content = preg_replace(
"/href=\".*?\"/",
"", $content);
6117 $printbody =
new ilTemplate(
"tpl.il_as_tst_print_body.html",
true,
true,
"components/ILIAS/Test");
6119 $printbody->setVariable(
"ADM_CONTENT", $content);
6120 $printbody->setCurrentBlock(
"css_file");
6122 $printbody->parseCurrentBlock();
6123 $printoutput = $printbody->get();
6124 $html = str_replace(
"href=\"./",
"href=\"" . ILIAS_HTTP_PATH .
"/", $printoutput);
6125 $html = preg_replace(
"/<div id=\"dontprint\">.*?<\\/div>/ims",
"", $html);
6126 if (extension_loaded(
"tidy")) {
6129 "output-xml" =>
true,
6130 "numeric-entities" => true
6133 $tidy->parseString($html, $config,
'utf8');
6134 $tidy->cleanRepair();
6135 $html = tidy_get_output($tidy);
6136 $html = preg_replace(
"/^.*?(<html)/",
"\\1", $html);
6138 $html = str_replace(
" ",
" ", $html);
6139 $html = str_replace(
"⊗",
"X", $html);
6141 $html = preg_replace(
"/src=\".\\//ims",
"src=\"" . ILIAS_HTTP_PATH .
"/", $html);
6153 $fp = fopen($fo_file,
"w");
6162 $pdf_base64->scalar,
6168 $this->
logger->info(__METHOD__ .
': ' . $e->getMessage());
6184 if ($pass === null) {
6188 $row = self::getSingleManualFeedback((
int) $active_id, (
int) $question_id, (
int) $pass);
6191 $feedback = $row[
'feedback'] ??
'';
6200 $ilDB = $DIC[
'ilDB'];
6202 $result =
$ilDB->queryF(
6203 "SELECT * FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
6204 [
'integer',
'integer',
'integer'],
6205 [$active_id, $question_id, $pass]
6208 if (
$ilDB->numRows($result) === 1) {
6209 $row =
$ilDB->fetchAssoc($result);
6211 } elseif (
$ilDB->numRows($result) > 1) {
6212 $DIC->logger()->root()->warning(
6213 "WARNING: Multiple feedback entries on tst_manual_fb for " .
6214 "active_fi = $active_id , question_fi = $question_id and pass = $pass" 6231 $ilDB = $DIC[
'ilDB'];
6234 $result =
$ilDB->queryF(
6235 "SELECT * FROM tst_manual_fb WHERE question_fi = %s",
6240 while ($row =
$ilDB->fetchAssoc($result)) {
6241 $active = $row[
'active_fi'];
6242 $pass = $row[
'pass'];
6243 $question = $row[
'question_fi'];
6247 $feedback[$active][$pass][$question] = $row;
6258 bool $finalized =
false 6260 $feedback_old = self::getSingleManualFeedback($active_id, $question_id, $pass);
6261 $this->db->manipulateF(
6262 'DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s',
6263 [
'integer',
'integer',
'integer'],
6264 [$active_id, $question_id, $pass]
6267 $this->
insertManualFeedback($active_id, $question_id, $pass, $feedback, $finalized, $feedback_old);
6279 $next_id = $this->db->nextId(
'tst_manual_fb');
6281 $finalized_time = time();
6284 'manual_feedback_id' => [
'integer', $next_id],
6285 'active_fi' => [
'integer', $active_id],
6286 'question_fi' => [
'integer', $question_id],
6287 'pass' => [
'integer', $pass],
6289 'tstamp' => [
'integer', time()]
6292 if ($feedback_old !== [] && (
int) $feedback_old[
'finalized_evaluation'] === 1) {
6293 $user = $feedback_old[
'finalized_by_usr_id'];
6294 $finalized_time = $feedback_old[
'finalized_tstamp'];
6297 if ($finalized ===
false) {
6298 $update_default[
'finalized_evaluation'] = [
'integer', 0];
6299 $update_default[
'finalized_by_usr_id'] = [
'integer', 0];
6300 $update_default[
'finalized_tstamp'] = [
'integer', 0];
6301 } elseif ($finalized ===
true) {
6302 $update_default[
'finalized_evaluation'] = [
'integer', 1];
6303 $update_default[
'finalized_by_usr_id'] = [
'integer',
$user];
6304 $update_default[
'finalized_tstamp'] = [
'integer', $finalized_time];
6307 $this->db->insert(
'tst_manual_fb', $update_default);
6309 if ($this->
logger->isLoggingEnabled()) {
6310 $this->
logger->logScoringInteraction(
6311 $this->
logger->getInteractionFactory()->buildScoringInteraction(
6314 $this->
user->getId(),
6315 self::_getUserIdFromActiveId($active_id),
6316 TestScoringInteractionTypes::QUESTION_GRADED,
6318 AdditionalInformationGenerator::KEY_EVAL_FINALIZED => $this->
logger 6319 ->getAdditionalInformationGenerator()->getTrueFalseTagForBool($finalized),
6351 $this->test_id = $a_id;
6364 if (count($participants)) {
6365 foreach ($participants as $active_id => $user_rec) {
6367 $reached_points = 0;
6370 foreach ($this->questions as $value) {
6372 if (is_object($question)) {
6373 $max_points += $question->getMaximumPoints();
6374 $reached_points += $question->getReachedPoints($active_id, $pass);
6375 if ($max_points > 0) {
6376 $percentvalue = $reached_points / $max_points;
6377 if ($percentvalue < 0) {
6378 $percentvalue = 0.0;
6384 $user_rec[
'firstname'] =
"";
6385 $user_rec[
'lastname'] = $this->
lng->txt(
"anonymous");
6388 "user_id" => $user_rec[
'usr_id'],
6389 "matriculation" => $user_rec[
'matriculation'],
6390 "lastname" => $user_rec[
'lastname'],
6391 "firstname" => $user_rec[
'firstname'],
6392 "login" => $user_rec[
'login'],
6393 "question_id" => $question->getId(),
6394 "question_title" => $question->getTitle(),
6395 "reached_points" => $reached_points,
6396 "max_points" => $max_points,
6397 "passed" => $user_rec[
'passed'] ?
'1' :
'0',
6412 $ilDB = $DIC[
'ilDB'];
6414 $result =
$ilDB->queryF(
6415 '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',
6419 $rec =
$ilDB->fetchAssoc($result);
6420 return $rec[
'obj_id'] ?? null;
6431 if (!$this->component_repository->getComponentByTypeAndName(
6434 )->getPluginSlotById(
'qst')->hasPluginName($a_pname)) {
6438 return $this->component_repository
6439 ->getComponentByTypeAndName(
6443 ->getPluginSlotById(
6453 $result = $this->db->queryF(
6454 "SELECT passed FROM tst_result_cache WHERE active_fi = %s",
6458 if ($result->numRows()) {
6459 $row = $this->db->fetchAssoc($result);
6460 return $row[
'passed'];
6463 $result_array = &$this->
getTestResult($active_id, $counted_pass);
6464 return $result_array[
"test"][
"passed"];
6474 SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass 6475 FROM tst_test_result 6476 INNER JOIN tst_active ON tst_active.active_id = tst_test_result.active_fi AND tst_active.test_fi = %s 6477 INNER JOIN qpl_questions ON qpl_questions.question_id = tst_test_result.question_fi 6478 LEFT JOIN usr_data ON usr_data.usr_id = tst_active.user_fi 6479 WHERE tst_test_result.question_fi = %s 6480 ORDER BY usr_data.lastname ASC, usr_data.firstname ASC 6483 $result = $this->db->queryF(
6485 [
'integer',
'integer'],
6486 [$test_id, $question_id]
6490 while ($row = $this->db->fetchAssoc($result)) {
6495 if (!array_key_exists($row[
"active_fi"], $foundusers)) {
6496 $foundusers[$row[
"active_fi"]] = [];
6498 array_push($foundusers[$row[
"active_fi"]], [
"pass" => $row[
"pass"],
"qid" => $row[
"question_fi"]]);
6506 $found_participants =
$data->getParticipants();
6507 $results = [
'overview' => [],
'questions' => []];
6508 if ($found_participants !== []) {
6509 $results[
'overview'][
'tst_stat_result_mark_median'] =
$data->getStatistics()->getEvaluationDataOfMedianUser()?->getMark()?->getShortName() ??
'';
6510 $results[
'overview'][
'tst_stat_result_rank_median'] =
$data->getStatistics()->rankMedian();
6511 $results[
'overview'][
'tst_stat_result_total_participants'] =
$data->getStatistics()->count();
6512 $results[
'overview'][
'tst_stat_result_median'] =
$data->getStatistics()->median();
6513 $results[
'overview'][
'tst_eval_total_persons'] = count($found_participants);
6514 $total_finished =
$data->getTotalFinishedParticipants();
6515 $results[
'overview'][
'tst_eval_total_finished'] = $total_finished;
6516 $results[
'overview'][
'tst_eval_total_finished_average_time'] =
6521 $total_passed_reached = 0;
6522 $total_passed_max = 0;
6523 $total_passed_time = 0;
6524 foreach ($found_participants as $userdata) {
6525 if ($userdata->getMark()?->getPassed()) {
6527 $total_passed_reached += $userdata->getReached();
6528 $total_passed_max += $userdata->getMaxpoints();
6529 $total_passed_time += $userdata->getTimeOnTask();
6532 $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
6533 $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
6534 $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
6535 $results[
'overview'][
'tst_eval_total_passed'] = $total_passed;
6536 $results[
'overview'][
'tst_eval_total_passed_average_points'] = sprintf(
'%2.2f', $average_passed_reached)
6537 .
' ' . strtolower(
'of') .
' ' . sprintf(
'%2.2f', $average_passed_max);
6538 $results[
'overview'][
'tst_eval_total_passed_average_time'] =
6542 foreach (
$data->getQuestionTitles() as $question_id => $question_title) {
6546 foreach ($found_participants as $userdata) {
6547 for ($i = 0; $i <= $userdata->getLastPass(); $i++) {
6548 if (is_object($userdata->getPass($i))) {
6549 $question = $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
6550 if (is_array($question)) {
6552 $reached += $question[
'reached'];
6553 $max += $question[
'points'];
6558 $percent = $max ? $reached / $max * 100.0 : 0;
6559 $results[
'questions'][$question_id] = [
6561 sprintf(
'%.2f', $answered ? $reached / $answered : 0) .
' ' . strtolower($this->
lng->txt(
'of')) .
' ' . sprintf(
'%.2f', $answered ? $max / $answered : 0),
6562 sprintf(
'%.2f', $percent) .
'%',
6564 sprintf(
'%.2f', $answered ? $reached / $answered : 0),
6565 sprintf(
'%.2f', $answered ? $max / $answered : 0),
6574 $diff_hours = floor($seconds / 3600);
6575 $seconds -= $diff_hours * 3600;
6576 $diff_minutes = floor($seconds / 60);
6577 $seconds -= $diff_minutes * 60;
6578 return sprintf(
'%02d:%02d:%02d', $diff_hours, $diff_minutes, $seconds);
6586 return $this->export_factory->getExporter($this,
'xml')
6592 return $this->
getMainSettings()->getFinishingSettings()->getMailNotificationContentType();
6600 $mail->sendSimpleNotification($owner_id, $this->
getTitle(), $usr_data);
6609 $path = $this->export_factory->getExporter(
6611 ExportImportTypes::SCORED_ATTEMPT
6612 )->withFilterByActiveId($active_id)
6615 $delivered_file_name =
'result_' . $active_id .
'.xlsx';
6617 $fd->copyAttachmentFile(
$path, $delivered_file_name);
6618 $file_names[] = $delivered_file_name;
6620 $mail->sendAdvancedNotification($owner_id, $this->
getTitle(), $usr_data, $file_names);
6622 if (count($file_names)) {
6623 $fd->unlinkFiles($file_names);
6633 FROM tst_result_cache 6634 WHERE active_fi = %s 6637 $result = $this->db->queryF(
6643 if (!$result->numRows()) {
6648 FROM tst_result_cache 6649 WHERE active_fi = %s 6652 $result = $this->db->queryF(
6659 $row = $this->db->fetchAssoc($result);
6666 return $this->
getMainSettings()->getFinishingSettings()->getAlwaysSendMailNotification();
6671 return $this->
getScoreSettings()->getResultDetailsSettings()->getExportSettings();
6686 $question_set_config = $this->question_set_config_factory->getQuestionSetConfig();
6687 $reindexed_sequence_position_map = $question_set_config->reindexQuestionOrdering();
6691 return $reindexed_sequence_position_map;
6700 foreach (array_keys($order) as
$id) {
6704 UPDATE tst_test_question 6706 WHERE question_fi = %s 6709 $this->db->manipulateF(
6711 [
'integer',
'integer'],
6716 if ($this->
logger->isLoggingEnabled()) {
6717 $this->
logger->logTestAdministrationInteraction(
6718 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
6720 $this->
user->getId(),
6721 TestAdministrationInteractionTypes::QUESTION_MOVED,
6723 AdditionalInformationGenerator::KEY_QUESTION_ORDER => $order
6736 $IN_questions = $this->db->in(
'q1.question_id', array_keys($questions),
false,
'integer');
6739 SELECT count(q1.question_id) cnt 6741 FROM qpl_questions q1 6743 INNER JOIN qpl_questions q2 6744 ON q2.question_id = q1.original_id 6747 AND q1.obj_fi = q2.obj_fi 6749 $rset = $this->db->query($query);
6750 $row = $this->db->fetchAssoc($rset);
6752 return $row[
'cnt'] > 0;
6764 $ilDB = $DIC[
'ilDB'];
6766 $result =
$ilDB->queryF(
6767 "SELECT test_fi,MAX(pass) AS pass FROM tst_active" .
6768 " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)" .
6769 " WHERE user_fi=%s" .
6770 " GROUP BY test_fi",
6771 [
'integer',
'integer'],
6775 while ($row =
$ilDB->fetchAssoc($result)) {
6776 $obj_id = self::_getObjectIDFromTestID($row[
"test_fi"]);
6777 $all[$obj_id] = (bool) $row[
"pass"];
6794 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getQuestionHintsEnabled();
6799 $this->activation_visibility = (bool) $a_value;
6814 $this->activation_limited = (bool) $a_value;
6818 ?
bool $is_activation_limited =
false,
6819 ?
int $activation_starting_time = null,
6820 ?
int $activation_ending_time = null,
6821 bool $activation_visibility =
false,
6823 if (!$this->ref_id) {
6828 $is_activation_limited ??=
false;
6830 if (!$is_activation_limited) {
6834 $item->setTimingStart($activation_starting_time);
6835 $item->setTimingEnd($activation_ending_time);
6836 $item->toggleVisible($activation_visibility);
6839 $item->update($this->ref_id);
6849 $page_id = $this->
getMainSettings()->getIntroductionSettings()->getIntroductionPageId();
6850 if ($page_id !== null) {
6855 $page_object->setParentId($this->
getId());
6856 $new_page_id = $page_object->createPageWithNextId();
6858 ->withIntroductionPageId($new_page_id);
6862 return $new_page_id;
6867 $page_id = $this->
getMainSettings()->getFinishingSettings()->getConcludingRemarksPageId();
6868 if ($page_id !== null) {
6873 $page_object->setParentId($this->
getId());
6874 $new_page_id = $page_object->createPageWithNextId();
6876 ->withConcludingRemarksPageId($new_page_id);
6880 return $new_page_id;
6885 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreEnabled();
6899 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreAnon();
6920 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreAchievedTS();
6928 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreScore();
6936 return $this->
getScoreSettings()->getGamificationSettings()->getHighscorePercentage();
6944 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreHints();
6952 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreWTime();
6960 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreOwnTable();
6968 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreTopTable();
6977 return $this->
getScoreSettings()->getGamificationSettings()->getHighscoreTopNum();
6982 return $this->
getScoreSettings()->getGamificationSettings()->getHighScoreMode();
6987 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getInstantFeedbackSpecificEnabled();
6992 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getAutosaveEnabled();
6997 return $this->
getScoreSettings()->getResultSummarySettings()->getPassDeletionAllowed();
7002 return $this->
getMainSettings()->getFinishingSettings()->getShowAnswerOverview();
7007 $this->activation_starting_time = $starting_time;
7012 $this->activation_ending_time = $ending_time;
7034 $result = $this->db->queryF(
7035 "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",
7039 while ($row = $this->db->fetchAssoc($result)) {
7040 $times[$row[
'active_fi']] = $row[
'started'];
7048 $result = $this->db->queryF(
7049 "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",
7053 while ($row = $this->db->fetchAssoc($result)) {
7054 $times[$row[
'active_fi']] = $row[
'additionaltime'];
7061 if ($active_id === 0) {
7064 return $this->participant_repository
7065 ->getParticipantByActiveId($this->
getTestId(), $active_id)
7066 ?->getExtraTime() ?? 0;
7072 SELECT MAX(tst_pass_result.pass) + 1 max_res 7073 FROM tst_pass_result 7074 INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi 7075 WHERE test_fi = ' . $this->db->quote($this->
getTestId(),
'integer') .
' 7077 $res = $this->db->query($query);
7079 return (
int)
$data[
'max_res'];
7085 $ilDB = $DIC[
'ilDB'];
7087 $exam_id_query =
'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
7088 $exam_id_result =
$ilDB->queryF($exam_id_query, [
'integer',
'integer' ], [ $active_id, $pass ]);
7089 if (
$ilDB->numRows($exam_id_result) == 1) {
7090 $exam_id_row =
$ilDB->fetchAssoc($exam_id_result);
7092 if ($exam_id_row[
'exam_id'] != null) {
7093 return $exam_id_row[
'exam_id'];
7100 public static function buildExamId($active_id, $pass, $test_obj_id = null): string
7107 if ($test_obj_id === null) {
7108 $obj_id = self::_getObjectIDFromActiveID($active_id);
7110 $obj_id = $test_obj_id;
7113 $examId =
'I' . $inst_id .
'_T' . $obj_id .
'_A' . $active_id .
'_P' . $pass;
7120 return $this->
getMainSettings()->getTestBehaviourSettings()->getExamIdInTestAttemptEnabled();
7125 return $this->
getScoreSettings()->getResultDetailsSettings()->getShowExamIdInTestResults();
7133 ->withQuestionSetType($question_set_type)
7139 return $this->
getMainSettings()->getGeneralSettings()->getQuestionSetType();
7164 switch ($questionSetType) {
7166 return $lng->
txt(
'tst_question_set_type_fixed');
7169 return $lng->
txt(
'tst_question_set_type_random');
7172 throw new ilTestException(
'invalid question set type value given: ' . $questionSetType);
7187 $scoring->setPreserveManualScores($preserve_manscoring);
7188 $scoring->recalculateSolutions();
7194 $ilDB = $DIC[
'ilDB'];
7199 INNER JOIN tst_tests 7200 ON test_id = test_fi 7204 $res =
$ilDB->queryF($query, [
'integer'], [$userId]);
7208 while ($row =
$ilDB->fetchAssoc(
$res)) {
7209 $objIds[] = (
int) $row[
'obj_fi'];
7217 return $this->
getMainSettings()->getAdditionalSettings()->getSkillsServiceEnabled();
7233 if (!$this->
getMainSettings()->getAdditionalSettings()->getSkillsServiceEnabled()) {
7237 if (!self::isSkillManagementGloballyActivated()) {
7248 if (self::$isSkillManagementGloballyActivated === null) {
7251 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
7254 return self::$isSkillManagementGloballyActivated;
7259 return $this->
getScoreSettings()->getResultSummarySettings()->getShowGradingStatusEnabled();
7264 return $this->
getScoreSettings()->getResultSummarySettings()->getShowGradingMarkEnabled();
7269 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getLockAnswerOnNextQuestionEnabled();
7274 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getLockAnswerOnInstantFeedbackEnabled();
7279 return $this->
getMainSettings()->getQuestionBehaviourSettings()->getForceInstantFeedbackOnNextQuestion();
7286 $ilDB = $DIC[
'ilDB'];
7287 $ilUser = $DIC[
'ilUser'];
7291 $active_id = $test_obj->getActiveIdOfUser($user_id);
7296 $test_session_factory->reset();
7298 $test_sequence_factory =
new ilTestSequenceFactory($test_obj,
$ilDB, TestDIC::dic()[
'question.general_properties.repository']);
7300 $test_session = $test_session_factory->getSession($active_id);
7301 $test_sequence = $test_sequence_factory->getSequenceByActiveIdAndPass($active_id, $test_session->getPass());
7310 SELECT COUNT(test_question_id) cnt 7311 FROM tst_test_question 7316 $questRes = $this->db->queryF($query, [
'integer'], [$this->
getTestId()]);
7318 $row = $this->db->fetchAssoc($questRes);
7319 $questCount = $row[
'cnt'];
7325 INNER JOIN tst_sequence tseq 7326 ON tseq.active_fi = tac.active_id 7327 WHERE tac.test_fi = %s 7330 $partRes = $this->db->queryF(
7336 while ($row = $this->db->fetchAssoc($partRes)) {
7337 $sequence = @unserialize($row[
'sequence']);
7343 $sequence = array_filter($sequence,
function ($value) use ($questCount) {
7344 return $value <= $questCount;
7347 $num_seq = count($sequence);
7348 if ($questCount > $num_seq) {
7349 $diff = $questCount - $num_seq;
7350 for ($i = 1; $i <= $diff; $i++) {
7351 $sequence[$num_seq + $i - 1] = $num_seq + $i;
7355 $new_sequence = serialize($sequence);
7357 $this->db->update(
'tst_sequence', [
7358 'sequence' => [
'clob', $new_sequence]
7360 'active_fi' => [
'integer', $row[
'active_fi']],
7361 'pass' => [
'integer', $row[
'pass']]
7365 $new_sequence = serialize($questCount > 0 ? range(1, $questCount) : []);
7370 INNER JOIN tst_sequence tseq 7371 ON tseq.active_fi = tac.active_id 7372 WHERE tac.test_fi = %s 7375 $part_rest = $this->db->queryF(
7381 while ($row = $this->db->fetchAssoc($part_rest)) {
7382 $this->db->update(
'tst_sequence', [
7383 'sequence' => [
'clob', $new_sequence]
7385 'active_fi' => [
'integer', $row[
'active_fi']],
7386 'pass' => [
'integer', $row[
'pass']]
7407 return $this->global_settings_repo->getGlobalSettings();
7412 if (!$this->main_settings) {
7421 if (!$this->main_settings_repo) {
7429 if (!$this->score_settings) {
7438 if (!$this->score_settings_repo) {
7448 if ($pass !== null) {
7450 SELECT tst_pass_result.*, 7451 tst_active.last_finished_pass 7452 FROM tst_pass_result 7453 INNER JOIN tst_active 7454 on tst_pass_result.active_fi = tst_active.active_id 7455 WHERE active_fi = %s 7459 $result = $this->db->queryF(
7461 [
'integer',
'integer'],
7465 $test_pass_result_row = $this->db->fetchAssoc($result);
7467 if (!is_array($test_pass_result_row)) {
7468 $test_pass_result_row = [];
7470 $max = (float) ($test_pass_result_row[
'maxpoints'] ?? 0);
7471 $reached = (float) ($test_pass_result_row[
'points'] ?? 0);
7472 $percentage = ($max <= 0.0 || $reached <= 0.0) ? 0 : ($reached / $max) * 100.0;
7474 $mark = $this->
getMarkSchema()->getMatchingMark($percentage);
7475 $is_passed = $test_pass_result_row[
'last_finished_pass'] !== null
7476 && $pass <= $test_pass_result_row[
'last_finished_pass']
7477 && $mark->getPassed();
7479 $hint_count = $test_pass_result_row[
'hint_count'] ?? 0;
7480 $hint_points = $test_pass_result_row[
'hint_points'] ?? 0.0;
7482 $user_test_result_update_callback =
function () use ($active_id, $pass, $max, $reached, $is_passed, $hint_count, $hint_points, $mark) {
7483 $passed_once_before = 0;
7484 $query =
'SELECT passed_once FROM tst_result_cache WHERE active_fi = %s';
7485 $res = $this->db->queryF($query, [
'integer'], [$active_id]);
7486 while ($passed_once_result_row = $this->db->fetchAssoc(
$res)) {
7487 $passed_once_before = (
int) $passed_once_result_row[
'passed_once'];
7490 $passed_once = (
int) ($is_passed || $passed_once_before);
7492 $this->db->manipulateF(
7493 'DELETE FROM tst_result_cache WHERE active_fi = %s',
7498 if ($reached < 0.0) {
7502 $mark_short_name = $mark->getShortName();
7503 if ($mark_short_name ===
'') {
7504 $mark_short_name =
' ';
7507 $mark_official_name = $mark->getOfficialName();
7508 if ($mark_official_name ===
'') {
7509 $mark_official_name =
' ';
7515 'active_fi' => [
'integer', $active_id],
7516 'pass' => [
'integer', $pass ?? 0],
7517 'max_points' => [
'float', $max],
7518 'reached_points' => [
'float', $reached],
7519 'mark_short' => [
'text', $mark_short_name],
7520 'mark_official' => [
'text', $mark_official_name],
7521 'passed_once' => [
'integer', $passed_once],
7522 'passed' => [
'integer', (
int) $is_passed],
7523 'failed' => [
'integer', (
int) !$is_passed],
7524 'tstamp' => [
'integer', time()],
7525 'hint_count' => [
'integer', $hint_count],
7526 'hint_points' => [
'float', $hint_points]
7531 if (is_object($process_locker)) {
7532 $process_locker->executeUserTestResultUpdateLockOperation($user_test_result_update_callback);
7534 $user_test_result_update_callback();
7543 int $test_obj_id = null
7548 $result = $this->db->queryF(
7550 SELECT SUM(r.points) reachedpoints, 7551 SUM(r.hint_count) hint_count, 7552 SUM(r.hint_points) hint_points, 7553 COUNT(DISTINCT(r.question_fi)) answeredquestions, 7554 pr.finalized_by finalized_by 7555 FROM tst_test_result r 7556 INNER JOIN tst_pass_result pr 7557 ON r.active_fi = pr.active_fi AND r.pass = pr.pass 7558 WHERE r.active_fi = %s 7561 [
'integer',
'integer'],
7565 if ($result->numRows() > 0) {
7566 $row = $this->db->fetchAssoc($result);
7568 if ($row[
'reachedpoints'] === null
7569 || $row[
'reachedpoints'] < 0.0) {
7570 $row[
'reachedpoints'] = 0.0;
7572 if ($row[
'hint_count'] === null) {
7573 $row[
'hint_count'] = 0;
7575 if ($row[
'hint_points'] === null) {
7576 $row[
'hint_points'] = 0.0;
7581 $update_pass_result_callback =
function () use (
$data, $active_id, $pass, $row, $time, $exam_identifier) {
7585 'active_fi' => [
'integer', $active_id],
7586 'pass' => [
'integer', $pass]
7589 'points' => [
'float', $row[
'reachedpoints']],
7590 'maxpoints' => [
'float',
$data[
'points']],
7591 'questioncount' => [
'integer',
$data[
'count']],
7592 'answeredquestions' => [
'integer', $row[
'answeredquestions']],
7593 'workingtime' => [
'integer', $time],
7594 'tstamp' => [
'integer', time()],
7595 'hint_count' => [
'integer', $row[
'hint_count']],
7596 'hint_points' => [
'float', $row[
'hint_points']],
7597 'exam_id' => [
'text', $exam_identifier],
7598 'finalized_by' => [
'text', $row[
'finalized_by']]
7604 $process_locker->executeUserPassResultUpdateLockOperation($update_pass_result_callback);
7606 $update_pass_result_callback();
7613 'active_fi' => $active_id,
7615 'points' => $row[
'reachedpoints'],
7616 'maxpoints' =>
$data[
'points'],
7617 'questioncount' =>
$data[
'count'],
7618 'answeredquestions' => $row[
'answeredquestions'],
7619 'workingtime' => $time,
7621 'hint_count' => $row[
'hint_count'],
7622 'hint_points' => $row[
'hint_points'],
7623 'exam_id' => $exam_identifier
7628 bool $old_online_status,
7629 bool $new_online_status
7631 if (!$old_online_status && $new_online_status) {
7633 $newsItem->setContext($this->
getId(),
'tst');
7635 $newsItem->setTitle(
'new_test_online');
7636 $newsItem->setContentIsLangVar(
true);
7637 $newsItem->setContent(
'');
7638 $newsItem->setUserId($this->
user->getId());
7640 $newsItem->create();
7644 if ($old_online_status && !$new_online_status) {
7650 if (!$new_online_status && $newsId > 0) {
7652 $newsItem->setTitle(
'new_test_online');
7653 $newsItem->setContentIsLangVar(
true);
7654 $newsItem->setContent(
'');
7655 $newsItem->update();
7666 $query =
'SELECT question_set_type FROM tst_tests WHERE obj_fi = %s';
7668 $res = $DIC[
'ilDB']->queryF($query, [
'integer'], [$obj_id]);
7670 $question_set_type = null;
7672 while ($row = $DIC[
'ilDB']->fetchAssoc(
$res)) {
7673 $question_set_type = $row[
'question_set_type'];
7676 return $question_set_type === self::QUESTION_SET_TYPE_RANDOM;
7681 return $this->participant_repository->getFirstAndLastVisitForActiveId($active_id);
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
isShowGradingMarkEnabled()
static isParticipantsLastPassActive(int $test_ref_id, int $user_id)
replaceFilesInPageImports(string $text, array $mappings)
addConcludingRemarksToSettingsFromImport(SettingsFinishing $settings, array $material, string $importdir, array $mappings)
withGamificationSettings(SettingsGamification $settings)
setQuestionSetType(string $question_set_type)
& getWorkedQuestions($active_id, $pass=null)
Gets the id's of all questions a user already worked through.
isNextPassAllowed(ilTestPassesSelector $testPassesSelector, int &$next_pass_allowed_timestamp)
getListOfQuestionsDescription()
raiseError(string $a_msg, int $a_err_obj)
wrapper for downward compability
static get(string $a_var)
buildStatisticsAccessFilteredParticipantList()
getTimeExtensionsOfParticipants()
isHTML($a_text)
Checks if a given string contains HTML or not.
static getStyleSheetLocation(string $mode="output", string $a_css_name="")
get full style sheet file name (path inclusive) of current user
static completeMissingPluginName(array $question_type_data)
isBlockPassesAfterPassedEnabled()
isTestFinished($active_id)
returns if the active for user_id has been submitted
MainSettingsRepository $main_settings_repo
getExtraTime(int $active_id)
Readable part of repository interface to ilComponentDataDB.
getActivationVisibility()
getHighscoreOwnTable()
Gets if the own rankings table should be shown.
int $activation_starting_time
getHighscoreTopNum(int $a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ilObjUser $user=null,)
exportFileItems($target_dir, &$expLog)
export files of file itmes
TestAdministrationInteractionTypes
static _getObjectIDFromTestID($test_id)
Returns the ILIAS test object id for a given test id.
A class defining mark schemas for assessment test objects.
deliverPDFfromFO($fo, $title=null)
Delivers a PDF file from a XSL-FO string.
isComplete(ilTestQuestionSetConfig $test_question_set_config)
storePropertyIsOnline(ilObjectPropertyIsOnline $property_is_online)
ilComponentRepository $component_repository
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
exportXMLPageObjects(&$a_xml_writer, $inst, &$expLog)
export page objects to xml (see ilias_co.dtd)
getUnfilteredEvaluationData()
isShowExamIdInTestPassEnabled()
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
static deleteNewsOfContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Delete all news of a context.
applyDefaults(array $test_defaults)
getTestBehaviourSettings()
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getEnableProcessingTime()
const QUESTION_SET_TYPE_RANDOM
static _getSuggestedSolutionOutput(int $question_id)
getListOfQuestionsStart()
MarksRepository $marks_repository
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
A class defining marks for assessment test objects.
getCompleteWorkingTimeOfParticipant($active_id)
Returns the complete working time in seconds for a test participant.
This class handles all operations on files (attachments) in directory ilias_data/mail.
setActivationStartingTime(?int $starting_time=null)
qtiMaterialToArray($a_material)
Reads an QTI material tag and creates a text string.
TestManScoringDoneHelper $test_man_scoring_done_helper
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
getShowSolutionListOwnAnswers()
getPresentationMaterial()
getShowSolutionFeedback()
Returns if the feedback should be presented to the solution or not.
removeTestResults(ilTestParticipantData $participant_data)
static lookupPassResultsUpdateTimestamp($active_id, $pass)
& getExistingQuestions($pass=null)
Get the id's of the questions which are already part of the test.
bool $print_best_solution_with_result
isExecutable($test_session, $user_id, $allow_pass_increase=false)
Checks if the test is executable by the given user.
loadQuestions(int $active_id=0, ?int $pass=null)
Load the test question id's from the database.
getShowKioskModeParticipant()
static $isSkillManagementGloballyActivated
buildDateTimeImmutableFromPeriod(?string $period)
getQuestionSetTypeTranslation(ilLanguage $lng, $questionSetType)
saveCompleteStatus(ilTestQuestionSetConfig $test_question_set_config)
getHighscoreAchievedTS()
Returns if date and time of the scores achievement should be displayed.
getTestId()
Gets the database id of the additional test data.
moveQuestions(array $move_questions, int $target_index, int $insert_mode)
static factory(string $a_package, int $a_timeout=0)
Creates an ilRpcClient instance to our ilServer.
Class ilTestMailNotification.
trait TestQuestionsImportTrait
getListOfQuestionsSettings()
Returns the settings for the list of questions options in the test properties This could contain one ...
createQuestionGUI($question_type, $question_id=-1)
Creates a question GUI instance of a given question type.
TestLogViewer $log_viewer
getMailNotificationType()
getJavaScriptOutput()
Returns if Javascript should be chosen for drag & drop actions for the active user.
const TIMINGS_DEACTIVATED
getShowSolutionAnswersOnly()
Returns if the full solution (including ILIAS content) should be presented to the solution or not...
static _lookupName(int $a_user_id)
lookup user name
& createTestSequence($active_id, $pass, $shuffle)
getQuestionTitle($title, $nr=null, $points=null)
Returns the title of a test question and checks if the title output is allowed.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$test_sequence
contains the test sequence data
getXMLZip()
Get zipped xml file for test.
inviteUser($user_id, $client_ip="")
Invites a user to a test.
getAvailableQuestionpools(bool $use_object_id=false, ?bool $equal_points=false, bool $could_be_offline=false, bool $show_path=false, bool $with_questioncount=false, string $permission='read')
Returns the available question pools for the active user.
evalTotalPersonsArray(string $name_sort_order='asc')
TestScoringInteractionTypes
& getInvitedUsers(int $user_id=0, $order="login, lastname, firstname")
Returns a list of all invited users in a test.
ParticipantRepository $participant_repository
toXML()
Returns a QTI xml representation of the test.
getAlwaysSendMailNotification()
GlobalSettingsRepository $global_settings_repo
setTemplate(int $template_id)
setActivationLimited($a_value)
static isManScoringDone(int $active_id)
setActivationEndingTime(?int $ending_time=null)
setTestId($a_id)
Sets the test ID.
getUsrPassOverviewEnabled()
static _lookupRandomTest(int $obj_id)
isShowExamIdInTestResultsEnabled()
getProcessingTimeInSeconds(int $active_id=0)
static deliverData(string $a_data, string $a_filename, string $mime="application/octet-stream")
getCompleteWorkingTime($user_id)
Returns the complete working time in seconds a user worked on the test.
getQuestionsOfPass(int $active_id, int $pass)
getImagePathWeb()
Returns the web image path for web accessable images of a test The image path is under the web access...
startingTimeReached()
Returns true if the starting time of a test is reached A starting time is not available for self asse...
questionMoveDown($question_id)
Moves a question down in order.
getHighscoreWTime()
Gets if the column with the workingtime should be shown.
getResultDetailsSettings()
hasAnyTestResult(ilTestSession $test_session)
getActiveIdOfUser($user_id="", $anonymous_id="")
Gets the active id of a given user.
static _getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
$participantDataExist
holds the fact wether participant data exists or not DO NOT USE TIS PROPERTY DRIRECTLY ALWAYS USE ilO...
getActiveParticipantList()
static _isPassed($user_id, $a_obj_id)
Returns TRUE if the user with the user id $user_id passed the test with the object id $a_obj_id...
buildName(?int $user_id, ?string $firstname, ?string $lastname)
Builds a user name for the output depending on test type and existence of the user.
static _getBestPass($active_id)
Retrieves the best pass of a given user for a given test.
evalTotalStartedAverageTime(?array $active_ids_to_filter=null)
saveToDb(bool $properties_only=false)
static _lookupTestObjIdForQuestionId(int $q_id)
Get test Object ID for question ID.
withGeneralSettings(SettingsGeneral $settings)
static _lookupAnonymity($a_obj_id)
getTestResult(int $active_id, ?int $pass=null, bool $ordered_sequence=false, bool $consider_hidden_questions=true, bool $consider_optional_questions=true)
Calculates the results of a test for a given user and returns an array with all test results...
sort()
description: > Example for rendering a Sort Glyph.
getPotentialRandomTestQuestions()
getShowSolutionListComparison()
setQuestionSetSolved($value, $question_id, $user_id)
sets question solved state to value for given user_id
Base Exception for all Exceptions relating to Modules/Test.
getHighscoreTopTable()
Gets, if the top-rankings table should be shown.
lookupQuestionSetTypeByActiveId(int $active_id)
updateTestPassResults(int $active_id, int $pass, ilAssQuestionProcessLocker $process_locker=null, int $test_obj_id=null)
getQuestionsOfTest(int $active_id)
startWorkingTime($active_id, $pass)
Write the initial entry for the tests working time to the database.
static removeTrailingPathSeparators(string $path)
removeAllQuestionResults($question_id)
$evaluation_data
Contains the evaluation data settings the tutor defines for the user.
static _lookupObjId(int $ref_id)
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
setQuestionOrder(array $order)
& _getCompleteWorkingTimeOfParticipants($test_id)
Returns the complete working time in seconds for all test participants.
isRandomTest()
Returns the fact wether this test is a random questions test or not.
static getASCIIFilename(string $a_filename)
getHighscorePercentage()
Gets if the percentage column should be shown.
xmlEndTag(string $tag)
Writes an endtag.
isFixedTest()
Returns the fact wether this test is a fixed question set test or not.
static _getUserIdFromActiveId(int $active_id)
updateWorkingTime($times_id)
Update the working time of a test when a question is answered.
getFixedQuestionSetTotalPoints()
secondsToHoursMinutesSecondsString(int $seconds)
getHtmlQuestionContentPurifier()
ExportImportFactory $export_factory
ilTestParticipantList $access_filtered_participant_list
getSpecificAnswerFeedback()
getImportMapping()
get array of (two) new created questions for import id
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...
addDefaults($a_name)
Adds the defaults of this test to the test defaults.
cloneObject(int $target_id, int $copy_id=0, bool $omit_tree=false)
Clone object.
removeTestResultsByUserIds(array $user_ids)
static collectFileItems(ilPageObject $a_page, DOMDocument $a_domdoc)
Get all file items that are used within the page.
static instantiateQuestion(int $question_id)
$metadata
A reference to an IMS compatible matadata set.
checkQuestionParent(int $question_id)
Interface for html sanitizing functionality.
evalStatistical($active_id)
Returns the statistical evaluation of the test for a specified user.
removeQuestionWithResults(int $question_id, TestScoring $scoring)
static getSingleManualFeedback(int $active_id, int $question_id, int $pass)
getGamificationSettings()
getHighscoreHints()
Gets, if the column with the number of requested hints should be shown.
getTotalPointsPassedArray()
Returns an array with the total points of all users who passed the test This array could be used for ...
cloneMetaData(ilObject $target_obj)
Copy meta data.
getAccessFilteredParticipantList()
getVisitingTimeOfParticipant(int $active_id)
getQuestiontext($question_id)
Returns the question text for a given question.
replaceMobsInPageImports(string $text, array $mappings)
static _lookupTitle(int $obj_id)
getAllQuestions($pass=null)
Returns all questions of a test in test order.
getHighscoreAnon()
Gets if the highscores should be anonymized per setting.
sendAdvancedNotification(int $active_id)
getTestParticipantsForManualScoring($filter=null)
fromXML(ilQTIAssessment $assessment, array $mappings)
Receives parameters from a QTI parser and creates a valid ILIAS test object.
storeMarkSchema(MarkSchema $mark_schema)
static _prepareCloneSelection(array $ref_ids, string $new_type, bool $show_path=true)
Prepare copy wizard object selection.
setActivationVisibility($a_value)
hasQuestionsWithoutQuestionpool()
evalTotalPersons()
Returns the number of persons who started the test.
retrieveMobsFromLegacyImports(string $text, array $mobs, string $importdir)
getStartingTimeOfUser($active_id, $pass=null)
Returns the unix timestamp of the time a user started a test.
sendSimpleNotification($active_id)
getShowSolutionPrintview()
Returns if the solution printview should be presented to the user or not.
updateTestResultCache(int $active_id, ilAssQuestionProcessLocker $process_locker=null)
hasNrOfTriesRestriction()
returns if the numbers of tries have to be checked
getAuthor()
Gets the authors name of the ilObjTest object.
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
getTestDefaults($test_defaults_id)
getShowPassDetails()
Returns if the pass details should be shown when a test is not finished.
ilTestPageGUI: ilPageEditorGUI, ilEditClipboardGUI, ilMDEditorGUI ilTestPageGUI: ilPublicUserProfile...
removeQuestion(int $question_id)
isTestFinishedToViewResults($active_id, $currentpass)
Returns true if an active user completed a test pass and did not start a new pass.
getUserData($ids)
Returns a data of all users specified by id list.
questionMoveUp($question_id)
Moves a question up in order.
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
MainSettings $main_settings
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static _getSolutionMaxPass(int $question_id, int $active_id)
Returns the maximum pass a users question solution.
getShowSolutionSuggested()
isSkillServiceToBeConsidered()
Returns whether this test must consider skills, usually by providing appropriate extensions in the us...
static _getCountSystem($active_id)
static _getSolvedQuestions($active_id, $question_fi=null)
get solved questions
getResultsForActiveId(int $active_id)
static createDirectory(string $a_dir, int $a_mod=0755)
create directory
ilTestEditPageGUI: ilPageEditorGUI, ilEditClipboardGUI, ilMDEditorGUI ilTestEditPageGUI: ilPublicUse...
isOfferingQuestionHintsEnabled()
static _refreshStatus(int $a_obj_id, ?array $a_users=null)
Filesystem $filesystem_web
exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
export media objects to xml (see ilias_co.dtd)
Class ilObjForumAdministration.
getAnsweredQuestionCount($active_id, $pass=null)
Retrieves the number of answered questions for a given user in a given test.
getAvailableDefaults()
Returns the available test defaults for the active user.
withIntroductionPageId(?int $introduction_page_id)
convertTimeToDateTimeImmutableIfNecessary(DateTimeImmutable|int|null $date_time)
static getInstanceByType(string $type)
static isSkillManagementGloballyActivated()
getAnswerFeedbackPoints()
canShowTestResults(ilTestSession $test_session)
createExportDirectory()
creates data directory for export files (data_dir/tst_data/tst_<id>/export, depending on data directo...
getAggregatedResultsData()
static _lookupAuthor($obj_id)
Gets the authors name of the ilObjTest object.
static _getObjectsByOperations( $a_obj_type, string $a_operation, int $a_usr_id=0, int $limit=0)
Get all objects of a specific type and check access This function is not recursive, instead it parses the serialized rbac_pa entries.
removeTestActives(array $active_ids)
copyQuestions(array $question_ids)
getStartingTimeOfParticipants()
Note, this function should only be used if absolutely necessary, since it perform joins on tables tha...
RequestDataCollector $testrequest
static getDataDir()
get data directory (outside webspace)
getLastFinishedPassTimestamp()
getResultSummarySettings()
getShowSolutionSignature()
Returns if the signature field should be shown in the test results.
static _lookupFinishedUserTests($a_user_id)
Gather all finished tests for user.
pcArrayShuffle($array)
Shuffles the values of a given array.
ilTestQuestionSetConfigFactory $question_set_config_factory
getMainSettingsRepository()
getCompleteEvaluationData($filterby='', $filtertext='')
static _lookupDescription(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getTestIDFromObjectID($object_id)
Returns the ILIAS test id for a given object id.
getInstantFeedbackSolution()
getAllTestResults($participants)
returns all test results for all participants
removeQuestionsWithResults(array $question_ids)
isHighscoreAnon()
Gets if the highscores should be displayed anonymized.
isInstantFeedbackAnswerFixationEnabled()
prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
storeActivationSettings(?bool $is_activation_limited=false, ?int $activation_starting_time=null, ?int $activation_ending_time=null, bool $activation_visibility=false,)
static _createImportDirectory()
creates data directory for import files (data_dir/tst_data/tst_<id>/import, depending on data directo...
buildImportDirectoryFromImportFile(string $file_to_import)
getProcessingTimeForXML()
updatePassAndTestResults(array $active_ids)
duplicateQuestionForTest($question_id)
Takes a question and creates a copy of the question for use in the test.
addIntroductionToSettingsFromImport(SettingsIntroduction $settings, array $material, string $importdir, array $mappings)
evalTotalParticipantsArray(string $name_sort_order='asc')
isScoreReportingEnabled()
getAvailableQuestions($arr_filter, $completeonly=0)
Calculates the available questions for a test.
isForceInstantFeedbackEnabled()
getQuestionDataset($question_id)
Returns the dataset for a given question id.
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
withConcludingRemarksPageId(?int $concluding_remarks_page_id)
ilObjectProperties $object_properties
removeQuestions(array $question_ids)
getParticipantFunctionalitySettings()
removeTestResultsByActiveIds(array $active_ids)
A news item can be created by different sources.
getGenericAnswerFeedback()
static _getScoreCutting(int $active_id)
Determines if the score of a question should be cut at 0 points or the score of the whole test...
removeQuestionFromSequences(int $question_id, array $active_ids, ilTestReindexedSequencePositionMap $reindexed_sequence_position_map)
addToNewsOnOnline(bool $old_online_status, bool $new_online_status)
static getItem(int $ref_id)
buildIso8601PeriodForExportCompatibility(DateTimeImmutable $date_time)
isQuestionSetConfigured()
getActivationStartingTime()
int $activation_ending_time
getTextAnswer($active_id, $question_id, $pass=null)
Returns the text answer of a given user for a given question.
getScoreCutting()
Determines if the score of a question should be cut at 0 points or the score of the whole test...
getTitleFilenameCompliant()
returns the object title prepared to be used as a filename
bool $activation_visibility
getParticipantsForTestAndQuestion($test_id, $question_id)
Creates an associated array with all active id's for a given test and original question id...
setTmpCopyWizardCopyId(int $tmpCopyWizardCopyId)
static _getAvailableTests($use_object_id=false)
Returns the available tests for the active user.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
__construct(Container $dic, ilPlugin $plugin)
static getFirstNewsIdForContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Get first new id of news set related to a certain context.
getQuestionCountAndPointsForPassOfParticipant(int $active_id, int $pass)
exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
export pages of test to xml (see ilias_co.dtd)
recalculateScores($preserve_manscoring=false)
clonePage(int $source_page_id)
getMailNotificationContentType()
ScoreSettings $score_settings
ScoreSettingsRepository $score_settings_repo
deleteDefaults($test_default_id)
endingTimeReached()
Returns true if the ending time of a test is reached An ending time is not available for self assessm...
getGeneralQuestionPropertiesRepository()
getActivationEndingTime()
getCompleteManualFeedback(int $question_id)
Retrieves the manual feedback for a question in a test.
getParticipants()
Returns all persons who started the test.
const QUESTION_SET_TYPE_FIXED
getConcludingRemarksPageId()
isActiveTestSubmitted($user_id=null)
returns if the active for user_id has been submitted
modifyExportIdentifier($a_tag, $a_param, $a_value)
Returns the installation id for a given identifier.
getQuestionTitlesAndIndexes()
Returns the titles of the test questions in question sequence.
getIntroductionSettings()
getQuestionType($question_id)
Returns the question type of a question with a given id.
static buildExamId($active_id, $pass, $test_obj_id=null)
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
GeneralQuestionPropertiesRepository $questionrepository
isTestQuestion(int $question_id)
static _getPassScoring(int $active_id)
Gets the pass scoring type.
& getCompleteWorkingTimeOfParticipants()
Returns the complete working time in seconds for all test participants.
getNrOfResultsForPass($active_id, $pass)
Calculates the number of user results for a specific test pass.
getQuestionBehaviourSettings()
ilComponentFactory $component_factory
addQTIMaterial(ilXmlWriter &$xml_writer, ?int $page_id, string $material='')
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
isShowGradingStatusEnabled()
canShowSolutionPrintview($user_id=null)
getQuestionCountWithoutReloading()
getHighscoreScore()
Gets if the score column should be shown.
static getTestObjIdsWithActiveForUserId($userId)
isPluginActive($a_pname)
Checks wheather or not a question plugin with a given name is active.
isFollowupQuestionAnswerFixationEnabled()
saveManualFeedback(int $active_id, int $question_id, int $pass, ?string $feedback, bool $finalized=false)
saveAuthorToMetadata($author="")
Saves an authors name into the lifecycle metadata if no lifecycle metadata exists This will only be c...
static getManualFeedback(int $active_id, int $question_id, ?int $pass)
Retrieves the feedback comment for a question in a test if it is finalized.
getScoreSettingsRepository()
static insertInstIntoID(string $a_value)
inserts installation id into ILIAS id
getWorkingTimeOfParticipantForPass(int $active_id, int $pass)
deliverPDFfromHTML($content, $title=null)
Delivers a PDF file from XHTML.
getDetailedTestResults($participants)
returns all test results for all participants
static getInstance(int $obj_id)
static clear(string $a_var)
isNrOfTriesReached($tries)
returns if number of tries are reached
Class ilObjectActivation.
_getLastAccess(int $active_id)
setAccessFilteredParticipantList(ilTestParticipantList $access_filtered_participant_list)
static deleteRequestsByActiveIds($activeIds)
Deletes all hint requests relating to a testactive included in given active ids.
insertManualFeedback(int $active_id, int $question_id, int $pass, ?string $feedback, bool $finalized, array $feedback_old)
insertQuestion(int $question_id, bool $link_only=false)
reindexFixedQuestionOrdering()
static _getAvailableQuestionpools(bool $use_object_id=false, bool $equal_points=false, bool $could_be_offline=false, bool $showPath=false, bool $with_questioncount=false, string $permission='read', int $usr_id=0)
Returns the available question pools for the active user.
ilTestParticipantAccessFilterFactory $participant_access_filter
withScoringSettings(SettingsScoring $settings)
userLookupFullName($user_id, $overwrite_anonymity=false, $sorted_order=false, $suffix="")
Returns the full name of a test user according to the anonymity status.
static _getActiveIdOfUser($user_id="", $test_id="")
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
isMaxProcessingTimeReached(int $starting_time, int $active_id)
Returns whether the maximum processing time for a test is reached or not.
isPreviousSolutionReuseEnabled($active_id)
getUserIdByActiveId($activeId)
getImagePath()
Returns the image path for web accessable images of a test The image path is under the CLIENT_WEB_DIR...
static lookupExamId($active_id, $pass)
removeTestResultsFromSoapLpAdministration(array $user_ids)
getPassScoring()
Gets the pass scoring type.