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