ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f87
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 
569  protected $testFinalBroken;
570 
571  #endregion
572 
581  public function __construct($a_id = 0,$a_call_by_reference = true)
582  {
583  global $ilUser, $lng;
584  $this->type = "tst";
585 
586  $lng->loadLanguageModule("assessment");
587  // Defaults:
588  include_once "./Modules/Test/classes/class.assMarkSchema.php";
589  $this->mark_schema = new ASS_MarkSchema();
590  $this->mark_schema->createSimpleSchema(
591  $lng->txt("failed_short"),
592  $lng->txt("failed_official"),
593  0,
594  0,
595  $lng->txt("passed_short"),
596  $lng->txt("passed_official"),
597  50,
598  1
599  );
600 
601  $this->test_id = -1;
602  $this->author = $ilUser->fullname;
603  $this->introductionEnabled = false;
604  $this->introduction = "";
605  $this->questions = array();
606  $this->sequence_settings = TEST_FIXED_SEQUENCE;
607  $this->score_reporting = REPORT_AFTER_TEST;
608  $this->instant_verification = 0;
609  $this->answer_feedback_points = 0;
610  $this->reporting_date = "";
611  $this->nr_of_tries = 0;
612  $this->_kiosk = 0;
613  $this->use_previous_answers = 1;
614  $this->title_output = 0;
615  $this->starting_time = "";
616  $this->ending_time = "";
617  $this->processing_time = "";
618  $this->enable_processing_time = "0";
619  $this->reset_processing_time = 0;
620  $this->ects_output = FALSE;
621  $this->ects_fx = NULL;
622  $this->shuffle_questions = FALSE;
623  $this->mailnottype = 0;
624  $this->exportsettings = 0;
625  $this->show_summary = 8;
626  $this->count_system = COUNT_PARTIAL_SOLUTIONS;
627  $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
628  $this->score_cutting = SCORE_CUT_QUESTION;
629  $this->pass_scoring = SCORE_LAST_PASS;
630  $this->answer_feedback = 0;
631  $this->password = "";
632  $this->certificate_visibility = 0;
633  $this->allowedUsers = "";
634  $this->_showfinalstatement = FALSE;
635  $this->_finalstatement = "";
636  $this->_showinfo = TRUE;
637  $this->_forcejs = TRUE;
638  $this->_customStyle = "";
639  $this->allowedUsersTimeGap = "";
640  $this->anonymity = 0;
641  $this->show_cancel = 0;
642  $this->show_marker = 0;
643  $this->fixed_participants = 0;
644  $this->setShowPassDetails(TRUE);
645  $this->setShowSolutionDetails(TRUE);
646  $this->setShowSolutionAnswersOnly(FALSE);
647  $this->setShowSolutionSignature(FALSE);
648  $this->testSession = FALSE;
649  $this->testSequence = FALSE;
650  $this->mailnotification = 0;
651  $this->poolUsage = 1;
652 
653  $this->ects_grades = array(
654  'A' => 90,
655  'B' => 65,
656  'C' => 35,
657  'D' => 10,
658  'E' => 0
659  );
660 
661  $this->autosave = FALSE;
662  $this->autosave_ival = 30000;
663 
664  $this->enable_examview = false;
665  $this->show_examview_html = false;
666  $this->show_examview_pdf = false;
667  $this->enable_archiving = false;
668 
669  $this->express_mode = false;
670  $this->template_id = '';
671  $this->redirection_mode = 0;
672  $this->redirection_url = NULL;
673  $this->show_exam_id_in_test_pass_enabled = false;
674  $this->show_exam_id_in_test_results_enabled = false;
675  $this->sign_submission = false;
676  $this->char_selector_availability = 0;
677  $this->char_selector_definition = null;
678 
679  $this->showGradingStatusEnabled = true;
680  $this->showGradingMarkEnabled = true;
681 
682  $this->instantFeedbackAnswerFixationEnabled = false;
683 
684  $this->testFinalBroken = false;
685 
686  $this->ilObject($a_id, $a_call_by_reference);
687  }
688 
692  function create($a_upload = false)
693  {
694  parent::create();
695 
696  // meta data will be created by
697  // import parser
698  if (!$a_upload)
699  {
700  $this->createMetaData();
701  }
702  }
703 
710  function update()
711  {
712  if (!parent::update())
713  {
714  return false;
715  }
716 
717  // put here object specific stuff
718 
719  return true;
720  }
721 
727  function read($a_force_db = false)
728  {
729  parent::read($a_force_db);
730  $this->loadFromDb();
731  }
732 
733 
740  function delete()
741  {
742  // always call parent delete function first!!
743  if (!parent::delete())
744  {
745  return false;
746  }
747 
748  // delet meta data
749  $this->deleteMetaData();
750 
751  //put here your module specific stuff
752  $this->deleteTest();
753 
754  return true;
755  }
756 
762  function deleteTest()
763  {
764  global $tree, $ilDB, $ilPluginAdmin;
765 
766  // first of all remove all test editings, because the delete statements used for this
767  // contain a subquery for active ids, that are deleted in the next steps
768  $this->removeAllTestEditings();
769 
770  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
771  array('integer'),
772  array($this->getTestId())
773  );
774  $active_array = array();
775  while ($row = $ilDB->fetchAssoc($result))
776  {
777  array_push($active_array, $row["active_id"]);
778  }
779 
780  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
781  array('integer'),
782  array($this->getTestId())
783  );
784 
785  if (count($active_array))
786  {
787  foreach ($active_array as $active_id)
788  {
789  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_times WHERE active_fi = %s",
790  array('integer'),
791  array($active_id)
792  );
793 
794  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
795  array('integer'),
796  array($active_id)
797  );
798  }
799  }
800 
801  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_mark WHERE test_fi = %s",
802  array('integer'),
803  array($this->getTestId())
804  );
805 
806  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_tests WHERE test_id = %s",
807  array('integer'),
808  array($this->getTestId())
809  );
810 
811  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
812  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
813  $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
814 
815  // delete export files
816  include_once "./Services/Utilities/classes/class.ilUtil.php";
817  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
818  $directory = $tst_data_dir."/tst_".$this->getId();
819  if (is_dir($directory))
820  {
821  include_once "./Services/Utilities/classes/class.ilUtil.php";
822  ilUtil::delDir($directory);
823  }
824  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
825  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
826  // remaining usages are not in text anymore -> delete them
827  // and media objects (note: delete method of ilObjMediaObject
828  // checks whether object is used in another context; if yes,
829  // the object is not deleted!)
830  foreach($mobs as $mob)
831  {
832  ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
833  if (ilObjMediaObject::_exists($mob))
834  {
835  $mob_obj =& new ilObjMediaObject($mob);
836  $mob_obj->delete();
837  }
838  }
839  }
840 
841 
855  function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
856  {
857  global $tree;
858 
859  switch ($a_event)
860  {
861  case "link":
862 
863  //var_dump("<pre>",$a_params,"</pre>");
864  //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
865  //exit;
866  break;
867 
868  case "cut":
869 
870  //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
871  //exit;
872  break;
873 
874  case "copy":
875 
876  //var_dump("<pre>",$a_params,"</pre>");
877  //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
878  //exit;
879  break;
880 
881  case "paste":
882 
883  //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
884  //exit;
885  break;
886 
887  case "new":
888 
889  //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
890  //exit;
891  break;
892  }
893 
894  // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
895  if ($a_node_id==$_GET["ref_id"])
896  {
897  $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
898  $parent_type = $parent_obj->getType();
899  if ($parent_type == $this->getType())
900  {
901  $a_node_id = (int) $tree->getParentId($a_node_id);
902  }
903  }
904 
905  parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
906  }
907 
914  {
915  include_once "./Services/Utilities/classes/class.ilUtil.php";
916  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
917  ilUtil::makeDir($tst_data_dir);
918  if (!is_writable($tst_data_dir))
919  {
920  $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
921  .") not writeable.",$this->ilias->error_obj->MESSAGE);
922  }
923 
924  // create learning module directory (data_dir/lm_data/lm_<id>)
925  $tst_dir = $tst_data_dir."/tst_".$this->getId();
926  ilUtil::makeDir($tst_dir);
927  if (!@is_dir($tst_dir))
928  {
929  $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
930  }
931  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
932  $export_dir = $tst_dir."/export";
933  ilUtil::makeDir($export_dir);
934  if (!@is_dir($export_dir))
935  {
936  $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
937  }
938  }
939 
946  {
947  include_once "./Services/Utilities/classes/class.ilUtil.php";
948  $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
949  return $export_dir;
950  }
951 
958  function getExportFiles($dir)
959  {
960  // quit if import dir not available
961  if(!@is_dir($dir) || !is_writeable($dir))
962  {
963  return array();
964  }
965 
966  $files = array();
967  foreach(new DirectoryIterator($dir) as $file)
968  {
972  if($file->isDir())
973  {
974  continue;
975  }
976 
977  $files[] = $file->getBasename();
978  }
979 
980  sort($files);
981 
982  return $files;
983  }
984 
988  function _setImportDirectory($a_import_dir = null)
989  {
990  if (strlen($a_import_dir))
991  {
992  $_SESSION["tst_import_dir"] = $a_import_dir;
993  }
994  else
995  {
996  unset($_SESSION["tst_import_dir"]);
997  }
998  }
999 
1007  {
1008  if (strlen($_SESSION["tst_import_dir"]))
1009  {
1010  return $_SESSION["tst_import_dir"];
1011  }
1012  return null;
1013  }
1014 
1016  {
1018  }
1019 
1026  {
1027  global $ilias;
1028  include_once "./Services/Utilities/classes/class.ilUtil.php";
1029  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
1030  ilUtil::makeDir($tst_data_dir);
1031 
1032  if (!is_writable($tst_data_dir))
1033  {
1034  $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
1035  .") not writeable.",$this->ilias->error_obj->FATAL);
1036  }
1037 
1038  // create test directory (data_dir/tst_data/tst_import)
1039  $tst_dir = $tst_data_dir."/tst_import";
1040  ilUtil::makeDir($tst_dir);
1041  if (!@is_dir($tst_dir))
1042  {
1043  $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
1044  }
1045  return $tst_dir;
1046  }
1047 
1055  {
1056  global $ilDB;
1057 
1058  $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",
1059  array('integer'),
1060  array($this->getTestId())
1061  );
1062  $hasSC = false;
1063  while ($row = $ilDB->fetchAssoc($result))
1064  {
1065  if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1066  {
1067  $hasSC = true;
1068  }
1069  }
1070  return $hasSC;
1071  }
1072 
1080  {
1081  global $ilDB;
1082 
1083  $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",
1084  array('integer'),
1085  array($this->getTestId())
1086  );
1087  if ($result->numRows() == 1)
1088  {
1089  $row = $ilDB->fetchAssoc($result);
1090  if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1091  {
1092  return TRUE;
1093  }
1094  else
1095  {
1096  return false;
1097  }
1098  }
1099  return FALSE;
1100  }
1101 
1109  {
1110  global $ilDB;
1111 
1112  if (!$this->hasSingleChoiceQuestions()) return false;
1113 
1114  $result = $ilDB->queryF("
1115  SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1116  FROM qpl_questions,
1117  qpl_qst_sc,
1118  tst_test_result,
1119  qpl_qst_type,
1120  tst_active
1121  WHERE tst_test_result.question_fi = qpl_questions.question_id
1122  AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1123  AND tst_test_result.active_fi = tst_active.active_id
1124  AND qpl_questions.question_id = qpl_qst_sc.question_fi
1125  AND tst_active.test_fi = %s
1126  AND qpl_qst_type.type_tag = %s
1127  ",
1128  array('integer', 'text'),
1129  array($this->getTestId(), 'assSingleChoice')
1130  );
1131  if ($result->numRows() == 1)
1132  {
1133  $row = $ilDB->fetchAssoc($result);
1134  return ($row['foundshuffles'] == 0);
1135  }
1136  return FALSE;
1137  }
1138 
1145  final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1146  {
1147  if( !count($this->mark_schema->mark_steps) )
1148  {
1149  return false;
1150  }
1151 
1152  if( !$testQuestionSetConfig->isQuestionSetConfigured() )
1153  {
1154  return false;
1155  }
1156 
1157  return true;
1158  }
1159 
1166  function _isComplete($obj_id)
1167  {
1168  global $tree, $ilDB, $ilPluginAdmin;
1169 
1170  $test = new ilObjTest($obj_id, false);
1171  $test->loadFromDb();
1172 
1173  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1174  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1175 
1176  return $test->isComplete( $testQuestionSetConfigFactory->getQuestionSetConfig() );
1177  }
1178 
1182  public function saveECTSStatus()
1183  {
1187  global $ilDB;
1188 
1189  if($this->getTestId() > 0)
1190  {
1191  $this->setECTSFX(preg_replace('/,/', '.', $this->getECTSFX()));
1192  if(!preg_match('/\d+/', $this->getECTSFX()))
1193  {
1194  $this->setECTSFX(NULL);
1195  }
1196 
1197  $grades = $this->getECTSGrades();
1198  $ilDB->manipulateF(
1199  "UPDATE tst_tests
1200  SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s
1201  WHERE test_id = %s",
1202  array('text', 'float', 'float', 'float', 'float', 'float', 'float', 'integer'),
1203  array(
1204  (int)$this->getECTSOutput(),
1205  $grades['A'], $grades['B'], $grades['C'], $grades['D'], $grades['E'],
1206  $this->getECTSFX(),
1207  $this->getTestId()
1208  )
1209  );
1210  }
1211  }
1212 
1217  public function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1218  {
1219  global $ilDB;
1220 
1221  $complete = 0;
1222  if($this->isComplete($testQuestionSetConfig))
1223  {
1224  $complete = 1;
1225  }
1226  if($this->getTestId() > 0)
1227  {
1228  $ilDB->manipulateF(
1229  "UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1230  array('text', 'integer'),
1231  array($complete, $this->test_id)
1232  );
1233  }
1234  }
1235 
1241  function getAllRTEContent()
1242  {
1243  $result = array();
1244  array_push($result, $this->getIntroduction());
1245  array_push($result, $this->getFinalStatement());
1246  return $result;
1247  }
1248 
1255  {
1256  include_once("./Services/RTE/classes/class.ilRTE.php");
1257  $completecontent = "";
1258  foreach ($this->getAllRTEContent() as $content)
1259  {
1260  $completecontent .= $content;
1261  }
1262  ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
1263  $this->getId());
1264  }
1265 
1271  public function saveToDb($properties_only = FALSE)
1272  {
1273  global $tree, $ilDB, $ilPluginAdmin;
1274 
1275  // moved online_status to ilObjectActivation (see below)
1276 
1277  // cleanup RTE images
1278  $this->cleanupMediaobjectUsage();
1279 
1280  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1281  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1282  $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1283 
1284  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1285  if ($this->test_id == -1)
1286  {
1287  // Create new dataset
1288  $next_id = $ilDB->nextId('tst_tests');
1289 
1290  $ilDB->insert('tst_tests', array(
1291  'test_id' => array('integer', $next_id),
1292  'obj_fi' => array('integer', $this->getId()),
1293  'author' => array('text', $this->getAuthor()),
1294  'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1295  'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1296  'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1297  'showinfo' => array('integer', $this->getShowInfo()),
1298  'forcejs' => array('integer', $this->getForceJS()),
1299  'customstyle' => array('text', $this->getCustomStyle()),
1300  'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1301  'sequence_settings' => array('integer', $this->getSequenceSettings()),
1302  'score_reporting' => array('integer', $this->getScoreReporting()),
1303  'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1304  'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1305  'answer_feedback' => array('text', $this->getAnswerFeedback()),
1306  'anonymity' => array('text', $this->getAnonymity()),
1307  'show_cancel' => array('text', $this->getShowCancel()),
1308  'show_marker' => array('integer', $this->getShowMarker()),
1309  'fixed_participants' => array('text', $this->getFixedParticipants()),
1310  'nr_of_tries' => array('integer', $this->getNrOfTries()),
1311  'kiosk' => array('integer', $this->getKiosk()),
1312  'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1313  'title_output' => array('text', $this->getTitleOutput()),
1314  'processing_time' => array('text', $this->getProcessingTime()),
1315  'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1316  'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1317  'reporting_date' => array('text', $this->getReportingDate()),
1318  'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1319  'starting_time' => array('text', $this->getStartingTime()),
1320  'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1321  'ending_time' => array('text', $this->getEndingTime()),
1322  'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1323  'ects_output' => array('text', $this->getECTSOutput()),
1324  'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1325  'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1326  'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1327  'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1328  'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1329  'ects_fx' => array('float', $this->getECTSFX()),
1330  'count_system' => array('text', $this->getCountSystem()),
1331  'mc_scoring' => array('text', $this->getMCScoring()),
1332  'score_cutting' => array('text', $this->getScoreCutting()),
1333  'pass_scoring' => array('text', $this->getPassScoring()),
1334  'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1335  'results_presentation' => array('integer', $this->getResultsPresentation()),
1336  'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1337  'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1338  'password' => array('text', $this->getPassword()),
1339  'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1340  'allowedusers' => array('integer', $this->getAllowedUsers()),
1341  'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1342  'mailnottype' => array('integer', $this->getMailNotificationType()),
1343  'exportsettings' => array('integer', $this->getExportSettings()),
1344  'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1345  'mailnotification' => array('integer', $this->getMailNotification()),
1346  'created' => array('integer', time()),
1347  'tstamp' => array('integer', time()),
1348  'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1349  'template_id' => array('integer', $this->getTemplate()),
1350  'pool_usage' => array('integer', $this->getPoolUsage()),
1351  'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1352  'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1353  'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1354  'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1355  'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1356  'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1357  'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1358  'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1359  'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1360  'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1361  'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1362  'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1363  'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1364  'online_status' => array('integer', (int)$this->isOnline()),
1365  'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1366  'autosave' => array('integer', (int)$this->getAutosave()),
1367  'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1368  'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1369  'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1370  'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1371  'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1372  'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1373  'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1374  'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1375  'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1376  'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1377  'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1378  'question_set_type' => array('text', $this->getQuestionSetType()),
1379  'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1380  'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1381  'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1382  'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1383  'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1384  'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1385  'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
1386  'broken' => array('integer', (int)$this->isTestFinalBroken())
1387  ));
1388 
1389  $this->test_id = $next_id;
1390 
1392  {
1393  $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1394  }
1395  }
1396  else
1397  {
1398  // Modify existing dataset
1399  $oldrow = array();
1401  {
1402  $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1403  array('integer'),
1404  array($this->test_id)
1405  );
1406  if ($result->numRows() == 1)
1407  {
1408  $oldrow = $ilDB->fetchAssoc($result);
1409  }
1410  }
1411 
1412  $ilDB->update('tst_tests',
1413  array(
1414  'author' => array('text', $this->getAuthor()),
1415  'intro_enabled' => array('integer', (int)$this->isIntroductionEnabled()),
1416  'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1417  'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1418  'showinfo' => array('integer', $this->getShowInfo()),
1419  'forcejs' => array('integer', $this->getForceJS()),
1420  'customstyle' => array('text', $this->getCustomStyle()),
1421  'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1422  'sequence_settings' => array('integer', $this->getSequenceSettings()),
1423  'score_reporting' => array('integer', $this->getScoreReporting()),
1424  'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1425  'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1426  'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1427  'anonymity' => array('text', $this->getAnonymity()),
1428  'show_cancel' => array('text', $this->getShowCancel()),
1429  'show_marker' => array('integer', $this->getShowMarker()),
1430  'fixed_participants' => array('text', $this->getFixedParticipants()),
1431  'nr_of_tries' => array('integer', $this->getNrOfTries()),
1432  'kiosk' => array('integer', $this->getKiosk()),
1433  'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1434  'title_output' => array('text', $this->getTitleOutput()),
1435  'processing_time' => array('text', $this->getProcessingTime()),
1436  'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1437  'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1438  'reporting_date' => array('text', $this->getReportingDate()),
1439  'starting_time_enabled' => array('integer', $this->isStartingTimeEnabled()),
1440  'starting_time' => array('text', $this->getStartingTime()),
1441  'ending_time_enabled' => array('integer', $this->isEndingTimeEnabled()),
1442  'ending_time' => array('text', $this->getEndingTime()),
1443  'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1444  'ects_output' => array('text', $this->getECTSOutput()),
1445  'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1446  'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1447  'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1448  'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1449  'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1450  'ects_fx' => array('float', $this->getECTSFX()),
1451  'count_system' => array('text', $this->getCountSystem()),
1452  'mc_scoring' => array('text', $this->getMCScoring()),
1453  'score_cutting' => array('text', $this->getScoreCutting()),
1454  'pass_scoring' => array('text', $this->getPassScoring()),
1455  'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1456  'results_presentation' => array('integer', $this->getResultsPresentation()),
1457  'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1458  'password_enabled' => array('integer', (int)$this->isPasswordEnabled()),
1459  'password' => array('text', $this->getPassword()),
1460  'limit_users_enabled' => array('integer', (int)$this->isLimitUsersEnabled()),
1461  'allowedusers' => array('integer', $this->getAllowedUsers()),
1462  'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1463  'mailnottype' => array('integer', $this->getMailNotificationType()),
1464  'exportsettings' => array('integer', $this->getExportSettings()),
1465  'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1466  'mailnotification' => array('integer', $this->getMailNotification()),
1467  'tstamp' => array('integer', time()),
1468  'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1469  'template_id' => array('integer', $this->getTemplate()),
1470  'pool_usage' => array('integer', $this->getPoolUsage()),
1471  'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1472  'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1473  'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1474  'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1475  'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1476  'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1477  'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1478  'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1479  'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1480  'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1481  'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1482  'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1483  'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1484  'online_status' => array('integer', (int)$this->isOnline()),
1485  'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1486  'autosave' => array('integer', (int)$this->getAutosave()),
1487  'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1488  'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1489  'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1490  'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1491  'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1492  'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1493  'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1494  'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1495  'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1496  'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1497  'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1498  'question_set_type' => array('text', $this->getQuestionSetType()),
1499  'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1500  'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1501  'skill_service' => array('integer', (int)$this->isSkillServiceEnabled()),
1502  'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
1503  'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
1504  'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
1505  'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
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->setTestFinalBroken((bool)$data->broken);
2001  $this->loadQuestions();
2002  }
2003 
2004  // moved activation to ilObjectActivation
2005  if($this->ref_id)
2006  {
2007  include_once "./Services/Object/classes/class.ilObjectActivation.php";
2008  $activation = ilObjectActivation::getItem($this->ref_id);
2009  switch($activation["timing_type"])
2010  {
2012  $this->setActivationLimited(true);
2013  $this->setActivationStartingTime($activation["timing_start"]);
2014  $this->setActivationEndingTime($activation["timing_end"]);
2015  $this->setActivationVisibility($activation["visible"]);
2016  break;
2017 
2018  default:
2019  $this->setActivationLimited(false);
2020  break;
2021  }
2022  }
2023  }
2024 
2031 function loadQuestions($active_id = "", $pass = NULL)
2032 {
2033  global $ilUser;
2034  global $ilDB;
2035 
2036  $this->questions = array();
2037  if (strcmp($active_id, "") == 0)
2038  {
2039  $active_id = $this->getActiveIdOfUser($ilUser->getId());
2040  }
2041  if ($this->isRandomTest())
2042  {
2043  if (is_null($pass))
2044  {
2045  $pass = $this->_getPass($active_id);
2046  }
2047  $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",
2048  array('integer', 'integer'),
2049  array($active_id, $pass)
2050  );
2051  // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
2052  // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
2053  // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
2054  // no questions are present for a newer pass.
2055  if ($result->numRows() == 0)
2056  {
2057  $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",
2058  array('integer'),
2059  array($active_id)
2060  );
2061  }
2062  }
2063  else
2064  {
2065  $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",
2066  array('integer'),
2067  array($this->test_id)
2068  );
2069  }
2070  $index = 1;
2071  while ($data = $ilDB->fetchAssoc($result))
2072  {
2073  $this->questions[$index++] = $data["question_fi"];
2074  }
2075 }
2076 
2080  public function isIntroductionEnabled()
2081  {
2083  }
2084 
2089  {
2090  $this->introductionEnabled = $introductionEnabled;
2091  }
2092 
2099  public function getIntroduction()
2100  {
2101  return (strlen($this->introduction)) ? $this->introduction : NULL;
2102  }
2103 
2111  public function setIntroduction($introduction = "")
2112  {
2113  $this->introduction = $introduction;
2114  }
2115 
2116 
2124  public function setFinalStatement($a_statement = "")
2125  {
2126  $this->_finalstatement = $a_statement;
2127  }
2128 
2136  public function setShowInfo($a_info = 1)
2137  {
2138  $this->_showinfo = ($a_info) ? 1 : 0;
2139  }
2140 
2148  public function setForceJS($a_js = 1)
2149  {
2150  $this->_forcejs = ($a_js) ? 1 : 0;
2151  }
2152 
2160  public function setCustomStyle($a_customStyle = NULL)
2161  {
2162  $this->_customStyle = $a_customStyle;
2163  }
2164 
2172  public function getCustomStyle()
2173  {
2174  return (strlen($this->_customStyle)) ? $this->_customStyle : NULL;
2175  }
2176 
2184  public function getCustomStyles()
2185  {
2186  $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2187  $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2188  $customstyles = array();
2189  if (is_dir($css_path))
2190  {
2191  $results = array();
2192  include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2194  if (is_array($results["file"]))
2195  {
2196  foreach ($results["file"] as $filename)
2197  {
2198  if (strpos($filename, ".css"))
2199  {
2200  array_push($customstyles, $filename);
2201  }
2202  }
2203  }
2204  }
2205  return $customstyles;
2206  }
2207 
2215  public function getTestStyleLocation($mode = "output")
2216  {
2217  if (strlen($this->getCustomStyle()))
2218  {
2219  $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2220  $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2221  if (file_exists($custom))
2222  {
2223  $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2224  $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2225  return $custom;
2226  }
2227  else
2228  {
2229  return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2230  }
2231  }
2232  else
2233  {
2234  return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2235  }
2236  }
2237 
2245  public function setShowFinalStatement($show = 0)
2246  {
2247  $this->_showfinalstatement = ($show) ? 1 : 0;
2248  }
2249 
2256  public function getFinalStatement()
2257  {
2258  return (strlen($this->_finalstatement)) ? $this->_finalstatement : NULL;
2259  }
2260 
2268  public function getShowInfo()
2269  {
2270  return ($this->_showinfo) ? 1 : 0;
2271  }
2272 
2280  public function getForceJS()
2281  {
2282  return ($this->_forcejs) ? 1 : 0;
2283  }
2284 
2292  public function getShowFinalStatement()
2293  {
2294  return ($this->_showfinalstatement) ? 1 : 0;
2295  }
2296 
2304  function getTestId()
2305  {
2306  return $this->test_id;
2307  }
2308 
2312  public function getECTSOutput()
2313  {
2314  return ($this->ects_output) ? 1 : 0;
2315  }
2316 
2320  public function setECTSOutput($a_ects_output)
2321  {
2322  $this->ects_output = $a_ects_output ? 1 : 0;
2323  }
2324 
2328  public function getECTSFX()
2329  {
2330  return (strlen($this->ects_fx)) ? $this->ects_fx : NULL;
2331  }
2332 
2336  public function setECTSFX($a_ects_fx)
2337  {
2338  $this->ects_fx = $a_ects_fx;
2339  }
2340 
2344  public function getECTSGrades()
2345  {
2346  return $this->ects_grades;
2347  }
2348 
2352  public function setECTSGrades(array $a_ects_grades)
2353  {
2354  $this->ects_grades = $a_ects_grades;
2355  }
2356 
2362  public function getSequenceSettings()
2363  {
2364  return ($this->sequence_settings) ? $this->sequence_settings : 0;
2365  }
2366 
2372  public function setSequenceSettings($sequence_settings = 0)
2373  {
2374  $this->sequence_settings = $sequence_settings;
2375  }
2376 
2380  public function isPostponingEnabled()
2381  {
2382  return (bool)$this->getSequenceSettings();
2383  }
2384 
2388  public function setPostponingEnabled($postponingEnabled)
2389  {
2390  $this->setSequenceSettings((int)$postponingEnabled);
2391  }
2392 
2400  function setScoreReporting($score_reporting = 0)
2401  {
2402  $this->score_reporting = $score_reporting;
2403  }
2404 
2412  function setInstantFeedbackSolution($instant_feedback = 0)
2413  {
2414  switch ($instant_feedback)
2415  {
2416  case 1:
2417  $this->instant_verification = 1;
2418  break;
2419  default:
2420  $this->instant_verification = 0;
2421  break;
2422  }
2423  }
2424 
2432 function setAnswerFeedback($answer_feedback = 0)
2433 {
2434  switch ($answer_feedback)
2435  {
2436  case 1:
2437  $this->answer_feedback = 1;
2438  break;
2439  default:
2440  $this->answer_feedback = 0;
2441  break;
2442  }
2443 }
2444 
2451 function setGenericAnswerFeedback($generic_answer_feedback = 0)
2452 {
2453  switch ($generic_answer_feedback)
2454  {
2455  case 1:
2456  $this->answer_feedback = 1;
2457  break;
2458  default:
2459  $this->answer_feedback = 0;
2460  break;
2461  }
2462 }
2463 
2471  function setAnswerFeedbackPoints($answer_feedback_points = 0)
2472  {
2473  switch ($answer_feedback_points)
2474  {
2475  case 1:
2476  $this->answer_feedback_points = 1;
2477  break;
2478  default:
2479  $this->answer_feedback_points = 0;
2480  break;
2481  }
2482  }
2483 
2488  public function setReportingDate($reporting_date)
2489  {
2490  if(!$reporting_date)
2491  {
2492  $this->reporting_date = '';
2493  $this->setECTSOutput(false);
2494  }
2495  else
2496  {
2497  $this->reporting_date = $reporting_date;
2498  }
2499  }
2500 
2505 
2514  {
2515  return ($this->score_reporting) ? $this->score_reporting : 0;
2516  }
2517 
2518  public function isScoreReportingEnabled()
2519  {
2520  return $this->getScoreReporting() > 0 && $this->getScoreReporting() < 4;
2521  }
2522 
2531  {
2532  return ($this->instant_verification) ? $this->instant_verification : 0;
2533  }
2534 
2543  public function getAnswerFeedback()
2544  {
2545  return ($this->answer_feedback) ? $this->answer_feedback : 0;
2546  }
2547 
2556  public function getGenericAnswerFeedback()
2557  {
2558  return ($this->answer_feedback) ? $this->answer_feedback : 0;
2559  }
2560 
2569 {
2570  return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2571 }
2572 
2580  function getCountSystem()
2581  {
2582  return ($this->count_system) ? $this->count_system : 0;
2583  }
2584 
2592  function _getCountSystem($active_id)
2593  {
2594  global $ilDB;
2595  $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",
2596  array('integer'),
2597  array($active_id)
2598  );
2599  if ($result->numRows())
2600  {
2601  $row = $ilDB->fetchAssoc($result);
2602  return $row["count_system"];
2603  }
2604  return FALSE;
2605  }
2606 
2614  function getMCScoring()
2615  {
2616  return ($this->mc_scoring) ? $this->mc_scoring : 0;
2617  }
2618 
2626  function getScoreCutting()
2627  {
2628  return ($this->score_cutting) ? $this->score_cutting : 0;
2629  }
2630 
2638  function getPassScoring()
2639  {
2640  return ($this->pass_scoring) ? $this->pass_scoring : 0;
2641  }
2642 
2650  function _getPassScoring($active_id)
2651  {
2652  global $ilDB;
2653  $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",
2654  array('integer'),
2655  array($active_id)
2656  );
2657  if ($result->numRows())
2658  {
2659  $row = $ilDB->fetchAssoc($result);
2660  return $row["pass_scoring"];
2661  }
2662  return 0;
2663  }
2664 
2672  function _getMCScoring($active_id)
2673  {
2674  global $ilDB;
2675  $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",
2676  array('integer'),
2677  array($active_id)
2678  );
2679  if ($result->numRows())
2680  {
2681  $row = $ilDB->fetchAssoc($result);
2682  return $row["mc_scoring"];
2683  }
2684  return FALSE;
2685  }
2686 
2694  function _getScoreCutting($active_id)
2695  {
2696  global $ilDB;
2697  $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",
2698  array('integer'),
2699  array($active_id)
2700  );
2701  if ($result->numRows())
2702  {
2703  $row = $ilDB->fetchAssoc($result);
2704  return $row["score_cutting"];
2705  }
2706  return FALSE;
2707  }
2708 
2716  function getReportingDate()
2717  {
2718  return (strlen($this->reporting_date)) ? $this->reporting_date : NULL;
2719  }
2720 
2728  function getNrOfTries()
2729  {
2730  return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2731  }
2732 
2740  function getKiosk()
2741  {
2742  return ($this->_kiosk) ? $this->_kiosk : 0;
2743  }
2744 
2745 
2753  function setKiosk($kiosk = 0)
2754  {
2755  $this->_kiosk = $kiosk;
2756  }
2757 
2765  function getKioskMode()
2766  {
2767  if (($this->_kiosk & 1) > 0)
2768  {
2769  return TRUE;
2770  }
2771  else
2772  {
2773  return FALSE;
2774  }
2775  }
2776 
2784  public function setKioskMode($a_kiosk = FALSE)
2785  {
2786  if ($a_kiosk)
2787  {
2788  $this->_kiosk = $this->_kiosk | 1;
2789  }
2790  else
2791  {
2792  if ($this->getKioskMode())
2793  {
2794  $this->_kiosk = $this->_kiosk ^ 1;
2795  }
2796  }
2797  }
2798 
2806  public function getShowKioskModeTitle()
2807  {
2808  if (($this->_kiosk & 2) > 0)
2809  {
2810  return TRUE;
2811  }
2812  else
2813  {
2814  return FALSE;
2815  }
2816  }
2817 
2824  public function setShowKioskModeTitle($a_title = FALSE)
2825  {
2826  if ($a_title)
2827  {
2828  $this->_kiosk = $this->_kiosk | 2;
2829  }
2830  else
2831  {
2832  if ($this->getShowKioskModeTitle())
2833  {
2834  $this->_kiosk = $this->_kiosk ^ 2;
2835  }
2836  }
2837  }
2838 
2847  {
2848  if (($this->_kiosk & 4) > 0)
2849  {
2850  return TRUE;
2851  }
2852  else
2853  {
2854  return FALSE;
2855  }
2856  }
2857 
2864  public function setShowKioskModeParticipant($a_participant = FALSE)
2865  {
2866  if ($a_participant)
2867  {
2868  $this->_kiosk = $this->_kiosk | 4;
2869  }
2870  else
2871  {
2872  if ($this->getShowKioskModeParticipant())
2873  {
2874  $this->_kiosk = $this->_kiosk ^ 4;
2875  }
2876  }
2877  }
2878 
2887  {
2888  return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2889  }
2890 
2898  function getTitleOutput()
2899  {
2900  return ($this->title_output) ? $this->title_output : 0;
2901  }
2902 
2911  function _getTitleOutput($active_id)
2912  {
2913  global $ilDB;
2914 
2915  $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",
2916  array('integer'),
2917  array($active_id)
2918  );
2919  if ($result->numRows())
2920  {
2921  $row = $ilDB->fetchAssoc($result);
2922  return $row["title_output"];
2923  }
2924  return 0;
2925  }
2926 
2936  function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2937  {
2938  global $ilDB;
2939  global $ilUser;
2940 
2941  $use_previous_answers = 1;
2942 
2943  $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",
2944  array("integer"),
2945  array($active_id)
2946  );
2947  if ($result->numRows())
2948  {
2949  $row = $ilDB->fetchAssoc($result);
2950  $use_previous_answers = $row["use_previous_answers"];
2951  }
2952 
2953  if ($use_previous_answers == 1)
2954  {
2955  if ($user_active_user_setting)
2956  {
2957  $res = $ilUser->getPref("tst_use_previous_answers");
2958  if ($res !== FALSE)
2959  {
2960  $use_previous_answers = $res;
2961  }
2962  }
2963  }
2964  return $use_previous_answers;
2965  }
2966 
2975  {
2976  return (strlen($this->processing_time)) ? $this->processing_time : NULL;
2977  }
2978 
2985  public function getProcessingTimeAsArray()
2986  {
2987  if (strlen($this->processing_time))
2988  {
2989  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
2990  {
2991  if ((int)$matches[1]+(int)$matches[2]+(int)$matches[3] == 0)
2992  {
2993  return $this->getEstimatedWorkingTime();
2994  }
2995  else
2996  {
2997  return array(
2998  'hh' => $matches[1],
2999  'mm' => $matches[2],
3000  'ss' => $matches[3],
3001  );
3002  }
3003  }
3004  }
3005  return $this->getEstimatedWorkingTime();
3006  }
3007 
3008  public function getProcessingTimeAsMinutes()
3009  {
3010  if (strlen($this->processing_time))
3011  {
3012  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
3013  {
3014  return ($matches[1] * 60) + $matches[2];
3015  }
3016  }
3017 
3018  return self::DEFAULT_PROCESSING_TIME_MINUTES;
3019  }
3020 
3028  function getProcessingTimeInSeconds($active_id = "")
3029  {
3030  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
3031  {
3032  $extratime = $this->getExtraTime($active_id) * 60;
3033  return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
3034  }
3035  else
3036  {
3037  return 0;
3038  }
3039  }
3040 
3049  {
3050  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
3051  {
3052  $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
3053  $now = time();
3054  return $ending - $now;
3055  }
3056  else
3057  {
3058  return 0;
3059  }
3060  }
3061 
3070  {
3071  return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
3072  }
3073 
3082  {
3083  return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
3084  }
3085 
3089  public function isStartingTimeEnabled()
3090  {
3092  }
3093 
3098  {
3099  $this->starting_time_enabled = $starting_time_enabled;
3100  }
3101 
3109  public function getStartingTime()
3110  {
3111  return (strlen($this->starting_time)) ? $this->starting_time : NULL;
3112  }
3113 
3121  public function setStartingTime($starting_time = NULL)
3122  {
3123  $this->starting_time = $starting_time;
3124  }
3125 
3129  public function isEndingTimeEnabled()
3130  {
3132  }
3133 
3138  {
3139  $this->ending_time_enabled = $ending_time_enabled;
3140  }
3141 
3149  public function getEndingTime()
3150  {
3151  return (strlen($this->ending_time)) ? $this->ending_time : NULL;
3152  }
3153 
3161  public function setEndingTime($ending_time = NULL)
3162  {
3163  $this->ending_time = $ending_time;
3164  }
3165 
3173  function setNrOfTries($nr_of_tries = 0)
3174  {
3175  $this->nr_of_tries = $nr_of_tries;
3176  }
3177 
3185  function setUsePreviousAnswers($use_previous_answers = 1)
3186  {
3187  if ($use_previous_answers)
3188  {
3189  $this->use_previous_answers = 1;
3190  }
3191  else
3192  {
3193  $this->use_previous_answers = 0;
3194  }
3195  }
3196 
3198  {
3199  $this->redirection_mode = $redirection_mode;
3200  }
3202  {
3203  return $this->redirection_mode;
3204  }
3206  {
3207  $this->redirection_url = $redirection_url;
3208  }
3210  {
3211  return $this->redirection_url;
3212  }
3213 
3221  function setTitleOutput($title_output = 0)
3222  {
3223  switch ($title_output)
3224  {
3225  case 1:
3226  $this->title_output = 1;
3227  break;
3228  case 2:
3229  $this->title_output = 2;
3230  break;
3231  default:
3232  $this->title_output = 0;
3233  break;
3234  }
3235  }
3236 
3244  function setProcessingTime($processing_time = "00:00:00")
3245  {
3246  $this->processing_time = $processing_time;
3247  }
3248 
3249  public function setProcessingTimeByMinutes($minutes)
3250  {
3251  $this->processing_time = sprintf("%02d:%02d:00", floor($minutes/60), $minutes%60);
3252  }
3253 
3261  function setEnableProcessingTime($enable = 0)
3262  {
3263  if ($enable) {
3264  $this->enable_processing_time = "1";
3265  } else {
3266  $this->enable_processing_time = "0";
3267  }
3268  }
3269 
3277  function setResetProcessingTime($reset = 0)
3278  {
3279  if ($reset)
3280  {
3281  $this->reset_processing_time = 1;
3282  }
3283  else
3284  {
3285  $this->reset_processing_time = 0;
3286  }
3287  }
3288 
3296  function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3297  {
3298  $this->count_system = $a_count_system;
3299  }
3300 
3304  public function isPasswordEnabled()
3305  {
3306  return $this->passwordEnabled;
3307  }
3308 
3313  {
3314  $this->passwordEnabled = $passwordEnabled;
3315  }
3316 
3324  public function getPassword()
3325  {
3326  return (strlen($this->password)) ? $this->password : NULL;
3327  }
3328 
3336  public function setPassword($a_password = NULL)
3337  {
3338  $this->password = $a_password;
3339  }
3340 
3348  function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3349  {
3350  $this->score_cutting = $a_score_cutting;
3351  }
3352 
3361  {
3362  $this->mc_scoring = $a_mc_scoring;
3363  }
3364 
3372  function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3373  {
3374  switch ($a_pass_scoring)
3375  {
3376  case SCORE_BEST_PASS:
3377  $this->pass_scoring = SCORE_BEST_PASS;
3378  break;
3379  default:
3380  $this->pass_scoring = SCORE_LAST_PASS;
3381  break;
3382  }
3383  }
3384 
3392  function removeQuestion($question_id)
3393  {
3394  $question =& ilObjTest::_instanciateQuestion($question_id);
3395  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3397  {
3398  $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3399  }
3400  $question->delete($question_id);
3401  $this->removeAllTestEditings($question_id);
3402  $this->loadQuestions();
3403  $this->saveQuestionsToDb();
3404  }
3405 
3413  public function removeAllTestEditings($question_id = "")
3414  {
3415  global $ilDB;
3416 
3417  // remove the question from tst_solutions
3418  if ($question_id)
3419  {
3420  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_solutions.question_fi = %s",
3421  array('integer','integer'),
3422  array($this->getTestId(), $question_id)
3423  );
3424  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_qst_solved.question_fi = %s",
3425  array('integer','integer'),
3426  array($this->getTestId(), $question_id)
3427  );
3428  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s) AND tst_test_result.question_fi = %s",
3429  array('integer','integer'),
3430  array($this->getTestId(), $question_id)
3431  );
3432  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3433  array('integer'),
3434  array($this->getTestId())
3435  );
3436 
3437  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3439  }
3440  else
3441  {
3442  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3443  array('integer'),
3444  array($this->getTestId())
3445  );
3446  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE tst_qst_solved.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3447  array('integer'),
3448  array($this->getTestId())
3449  );
3450  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE tst_test_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3451  array('integer'),
3452  array($this->getTestId())
3453  );
3454  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE tst_pass_result.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3455  array('integer'),
3456  array($this->getTestId())
3457  );
3458 
3459  $query = "SELECT active_id FROM tst_active WHERE test_fi = %s";
3460  $res = $ilDB->queryF($query, array('integer'), array($this->getTestId()));
3461  $activeIds = array();
3462  while( $row = $ilDB->fetchAssoc($res) )
3463  {
3464  $activeIds[] = $row['active_id'];
3465  }
3466 
3467  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3469 
3470  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3472  {
3473  $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
3474  }
3475  }
3476 
3477  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE tst_sequence.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3478  array('integer'),
3479  array($this->getTestId())
3480  );
3481 
3482  if ($this->isRandomTest())
3483  {
3484  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE tst_test_rnd_qst.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3485  array('integer'),
3486  array($this->getTestId())
3487  );
3488  }
3489 
3490  // remove test_active entries, because test has changed
3491  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3492  array('integer'),
3493  array($this->getTestId())
3494  );
3495 
3496  // remove saved user passwords
3497  $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE keyword = %s",
3498  array('text'),
3499  array("tst_password_".$this->getTestId())
3500  );
3501 
3502  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3503  // remove file uploads
3504  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId()))
3505  {
3506  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId());
3507  }
3508  }
3509 
3510  public function removeTestResults(ilTestParticipantData $participantData)
3511  {
3512  if( count($participantData->getAnonymousActiveIds()) )
3513  {
3514  $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3515  }
3516 
3517  if( count($participantData->getUserIds()) )
3518  {
3519  /* @var ilTestLP $testLP */
3520  require_once 'Services/Object/classes/class.ilObjectLP.php';
3521  $testLP = ilObjectLP::getInstance($this->getId());
3522  $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3523  }
3524 
3525  if( count($participantData->getActiveIds()) )
3526  {
3527  $this->removeTestActives($participantData->getActiveIds());
3528  }
3529  }
3530 
3531  public function removeTestResultsByUserIds($userIds)
3532  {
3533  global $ilDB, $lng;
3534 
3535  require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3536  $participantData = new ilTestParticipantData($ilDB, $lng);
3537  $participantData->setUserIds($userIds);
3538  $participantData->load($this->getTestId());
3539 
3540  $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3541  $ilDB->manipulateF("DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3542  array('text'), array("tst_password_".$this->getTestId())
3543  );
3544 
3545  if( count($participantData->getActiveIds()) )
3546  {
3547  $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3548  }
3549  }
3550 
3551  public function removeTestResultsByActiveIds($activeIds)
3552  {
3553  global $ilDB;
3554 
3555  $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3556 
3557  $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3558  $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3559  $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3560  $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3561  $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3562  $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3563 
3564  if( $this->isRandomTest() )
3565  {
3566  $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3567  }
3568  elseif( $this->isDynamicTest() )
3569  {
3570  $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3571  $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3572  $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3573  $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3574  }
3575 
3576  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3577 
3578  foreach ($activeIds as $active_id)
3579  {
3580  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3581  // remove file uploads
3582  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3583  {
3584  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3585  }
3586 
3588  {
3589  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3590  }
3591  }
3592 
3593  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3595  }
3596 
3597  public function removeTestActives($activeIds)
3598  {
3599  global $ilDB;
3600 
3601  $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3602  $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3603  }
3604 
3605  function removeTestResultsForUser($user_id)
3606  {
3607  global $ilDB;
3608 
3609  $active_id = $this->getActiveIdOfUser($user_id);
3610 
3611  // remove the question from tst_solutions
3612  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s",
3613  array('integer'),
3614  array($active_id)
3615  );
3616  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s",
3617  array('integer'),
3618  array($active_id)
3619  );
3620  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE active_fi = %s",
3621  array('integer'),
3622  array($active_id)
3623  );
3624  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE active_fi = %s",
3625  array('integer'),
3626  array($active_id)
3627  );
3628 
3629  if ($this->isRandomTest())
3630  {
3631  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE active_fi = %s",
3632  array('integer'),
3633  array($active_id)
3634  );
3635  }
3636 
3637  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3639  {
3640  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3641  }
3642 
3643  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
3644  array('integer'),
3645  array($active_id)
3646  );
3647 
3648  // remove test_active entry
3649  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE active_id = %s",
3650  array('integer'),
3651  array($active_id)
3652  );
3653 
3654  // remove saved user password
3655  if ($user_id > 0)
3656  {
3657  $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s",
3658  array('integer', 'text'),
3659  array($user_id, "tst_password_".$this->getTestId())
3660  );
3661  }
3662 
3663  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3664  // remove file uploads
3665  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3666  {
3667  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3668  }
3669 
3670  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3672  }
3673 
3681  function questionMoveUp($question_id)
3682  {
3683  global $ilDB;
3684 
3685  // Move a question up in sequence
3686  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3687  array('integer', 'integer'),
3688  array($this->getTestId(), $question_id)
3689  );
3690  $data = $ilDB->fetchObject($result);
3691  if ($data->sequence > 1)
3692  {
3693  // OK, it's not the top question, so move it up
3694  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3695  array('integer','integer'),
3696  array($this->getTestId(), $data->sequence - 1)
3697  );
3698  $data_previous = $ilDB->fetchObject($result);
3699  // change previous dataset
3700  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3701  array('integer','integer'),
3702  array($data->sequence, $data_previous->test_question_id)
3703  );
3704  // move actual dataset up
3705  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3706  array('integer','integer'),
3707  array($data->sequence - 1, $data->test_question_id)
3708  );
3709  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3711  {
3712  $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3713  }
3714  }
3715  $this->loadQuestions();
3716  }
3717 
3725  function questionMoveDown($question_id)
3726  {
3727  global $ilDB;
3728 
3729  // Move a question down in sequence
3730  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3731  array('integer','integer'),
3732  array($this->getTestId(), $question_id)
3733  );
3734  $data = $ilDB->fetchObject($result);
3735  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3736  array('integer','integer'),
3737  array($this->getTestId(), $data->sequence + 1)
3738  );
3739  if ($result->numRows() == 1)
3740  {
3741  // OK, it's not the last question, so move it down
3742  $data_next = $ilDB->fetchObject($result);
3743  // change next dataset
3744  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3745  array('integer','integer'),
3746  array($data->sequence, $data_next->test_question_id)
3747  );
3748  // move actual dataset down
3749  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3750  array('integer','integer'),
3751  array($data->sequence + 1, $data->test_question_id)
3752  );
3753  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3755  {
3756  $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3757  }
3758  }
3759  $this->loadQuestions();
3760  }
3761 
3769  function duplicateQuestionForTest($question_id)
3770  {
3771  global $ilUser;
3772  $question =& ilObjTest::_instanciateQuestion($question_id);
3773  $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3774 
3775  return $duplicate_id;
3776  }
3777 
3786  public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3787  {
3788  global $ilDB;
3789 #var_dump($question_id);
3790  if ($linkOnly)
3791  {
3792  $duplicate_id = $question_id;
3793  }
3794  else
3795  {
3796  $duplicate_id = $this->duplicateQuestionForTest($question_id);
3797  }
3798 
3799  // get maximum sequence index in test
3800  $result = $ilDB->queryF("SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3801  array('integer'),
3802  array($this->getTestId())
3803  );
3804  $sequence = 1;
3805 
3806  if ($result->numRows() == 1)
3807  {
3808  $data = $ilDB->fetchObject($result);
3809  $sequence = $data->seq + 1;
3810  }
3811 
3812  $next_id = $ilDB->nextId('tst_test_question');
3813  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3814  array('integer', 'integer','integer','integer','integer'),
3815  array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3816  );
3817  if ($affectedRows == 1)
3818  {
3819  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3821  {
3822  $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3823  }
3824  }
3825  // remove test_active entries, because test has changed
3826  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3827  array('integer'),
3828  array($this->getTestId())
3829  );
3830  $this->loadQuestions();
3831  $this->saveCompleteStatus($testQuestionSetConfig);
3832  return $duplicate_id;
3833  }
3834 
3842  function &getQuestionTitles()
3843  {
3844  $titles = array();
3845  if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3846  {
3847  global $ilDB;
3848  $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",
3849  array('integer'),
3850  array($this->getTestId())
3851  );
3852  while ($row = $ilDB->fetchAssoc($result))
3853  {
3854  array_push($titles, $row["title"]);
3855  }
3856  }
3857  return $titles;
3858  }
3859 
3868  {
3869  $titles = array();
3870  if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3871  {
3872  global $ilDB;
3873  $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",
3874  array('integer'),
3875  array($this->getTestId())
3876  );
3877  while ($row = $ilDB->fetchAssoc($result))
3878  {
3879  $titles[$row['question_id']] = $row["title"];
3880  }
3881  }
3882  return $titles;
3883  }
3884 
3894  {
3895  if ($this->getTitleOutput() == 2)
3896  {
3897  return $this->lng->txt("ass_question");
3898  }
3899  else
3900  {
3901  return $title;
3902  }
3903  }
3904 
3913  function getQuestionDataset($question_id)
3914  {
3915  global $ilDB;
3916 
3917  $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",
3918  array('integer'),
3919  array($question_id)
3920  );
3921  $row = $ilDB->fetchObject($result);
3922  return $row;
3923  }
3924 
3931  function &getExistingQuestions($pass = NULL)
3932  {
3933  global $ilUser;
3934  global $ilDB;
3935 
3936  $existing_questions = array();
3937  $active_id = $this->getActiveIdOfUser($ilUser->getId());
3938  if ($this->isRandomTest())
3939  {
3940  if (is_null($pass)) $pass = 0;
3941  $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",
3942  array('integer','integer'),
3943  array($active_id, $pass)
3944  );
3945  }
3946  else
3947  {
3948  $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",
3949  array('integer'),
3950  array($this->getTestId())
3951  );
3952  }
3953  while ($data = $ilDB->fetchObject($result))
3954  {
3955  if( $data->original_id === null )
3956  {
3957  continue;
3958  }
3959 
3960  array_push($existing_questions, $data->original_id);
3961  }
3962  return $existing_questions;
3963  }
3964 
3972  function getQuestionType($question_id)
3973  {
3974  global $ilDB;
3975 
3976  if ($question_id < 1) return -1;
3977  $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",
3978  array('integer'),
3979  array($question_id)
3980  );
3981  if ($result->numRows() == 1)
3982  {
3983  $data = $ilDB->fetchObject($result);
3984  return $data->type_tag;
3985  }
3986  else
3987  {
3988  return "";
3989  }
3990  }
3991 
3998  function startWorkingTime($active_id, $pass)
3999  {
4000  global $ilDB;
4001 
4002  $next_id = $ilDB->nextId('tst_times');
4003  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
4004  array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
4005  array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
4006  );
4007  return $next_id;
4008  }
4009 
4016  function updateWorkingTime($times_id)
4017  {
4018  global $ilDB;
4019 
4020  $affectedRows = $ilDB->manipulateF("UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
4021  array('timestamp', 'integer', 'integer'),
4022  array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
4023  );
4024  }
4025 
4032  function &getWorkedQuestions($active_id, $pass = NULL)
4033  {
4034  global $ilUser;
4035  global $ilDB;
4036 
4037  if (is_null($pass))
4038  {
4039  $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
4040  array('integer','integer'),
4041  array($active_id, 0)
4042  );
4043  }
4044  else
4045  {
4046  $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
4047  array('integer','integer'),
4048  array($active_id, $pass)
4049  );
4050  }
4051  $result_array = array();
4052  while ($row = $ilDB->fetchAssoc($result))
4053  {
4054  array_push($result_array, $row["question_fi"]);
4055  }
4056  return $result_array;
4057  }
4058 
4067  function isTestFinishedToViewResults($active_id, $currentpass)
4068  {
4069  $num = $this->getPassFinishDate($active_id, $currentpass);
4070  return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
4071  }
4072 
4079  function &getAllQuestions($pass = NULL)
4080  {
4081  global $ilUser;
4082  global $ilDB;
4083 
4084  $result_array = array();
4085  if ($this->isRandomTest())
4086  {
4087  $active_id = $this->getActiveIdOfUser($ilUser->getId());
4088  $this->loadQuestions($active_id, $pass);
4089  if (count($this->questions) == 0) return $result_array;
4090  if (is_null($pass))
4091  {
4092  $pass = $this->_getPass($active_id);
4093  }
4094  $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'),
4095  array('integer','integer'),
4096  array($active_id, $pass)
4097  );
4098  }
4099  else
4100  {
4101  if (count($this->questions) == 0) return $result_array;
4102  $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'));
4103  }
4104  while ($row = $ilDB->fetchAssoc($result))
4105  {
4106  $result_array[$row["question_id"]] = $row;
4107  }
4108  return $result_array;
4109  }
4110 
4119  function getActiveIdOfUser($user_id = "", $anonymous_id = "")
4120  {
4121  global $ilDB;
4122  global $ilUser;
4123 
4124  if (!$user_id) $user_id = $ilUser->getId();
4125  if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
4126  {
4127  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4128  array('integer','integer','text'),
4129  array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
4130  );
4131  }
4132  else if (strlen($anonymous_id))
4133  {
4134  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
4135  array('integer','integer','text'),
4136  array($user_id, $this->test_id, $anonymous_id)
4137  );
4138  }
4139  else
4140  {
4141  if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
4142  {
4143  return NULL;
4144  }
4145  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4146  array('integer','integer'),
4147  array($user_id, $this->test_id)
4148  );
4149  }
4150  if ($result->numRows())
4151  {
4152  $row = $ilDB->fetchAssoc($result);
4153  return $row["active_id"];
4154  }
4155  else
4156  {
4157  return 0;
4158  }
4159  }
4160 
4169  function _getActiveIdOfUser($user_id = "", $test_id = "")
4170  {
4171  global $ilDB;
4172  global $ilUser;
4173 
4174  if (!$user_id) {
4175  $user_id = $ilUser->id;
4176  }
4177  if (!$test_id)
4178  {
4179  return "";
4180  }
4181  $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4182  array('integer', 'integer'),
4183  array($user_id, $test_id)
4184  );
4185  if ($result->numRows())
4186  {
4187  $row = $ilDB->fetchAssoc($result);
4188  return $row["active_id"];
4189  }
4190  else
4191  {
4192  return "";
4193  }
4194  }
4195 
4202  function pcArrayShuffle($array)
4203  {
4204  $keys = array_keys($array);
4205  shuffle($keys);
4206  $result = array();
4207  foreach ($keys as $key)
4208  {
4209  $result[$key] = $array[$key];
4210  }
4211  return $result;
4212  }
4213 
4221  function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE)
4222  {
4223  global $tree, $ilDB, $lng, $ilPluginAdmin;
4224 
4225  $results = $this->getResultsForActiveId($active_id);
4226 
4227  if( is_null($pass) )
4228  {
4229  $pass = $results['pass'];
4230  }
4231 
4232  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
4233  $testSessionFactory = new ilTestSessionFactory($this);
4234  $testSession = $testSessionFactory->getSession($active_id);
4235 
4236  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4237  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
4238  $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $pass);
4239 
4240  if( $this->isDynamicTest() )
4241  {
4242  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4243  $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
4244  $dynamicQuestionSetConfig->loadFromDb();
4245 
4246  $testSequence->loadFromDb($dynamicQuestionSetConfig);
4247  $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4248 
4249  $sequence = $testSequence->getUserSequenceQuestions();
4250  }
4251  else
4252  {
4253  $testSequence->loadFromDb();
4254  $testSequence->loadQuestions();
4255 
4256  if( $ordered_sequence )
4257  {
4258  $sequence = $testSequence->getOrderedSequenceQuestions();
4259  }
4260  else
4261  {
4262  $sequence = $testSequence->getUserSequenceQuestions();
4263  }
4264  }
4265 
4266  $arrResults = array();
4267 
4268  $query = "
4269  SELECT tst_test_result.question_fi,
4270  tst_test_result.points reached,
4271  tst_test_result.hint_count requested_hints,
4272  tst_test_result.hint_points hint_points,
4273  tst_test_result.answered answered
4274 
4275  FROM tst_test_result
4276 
4277  LEFT JOIN tst_solutions
4278  ON tst_solutions.active_fi = tst_test_result.active_fi
4279  AND tst_solutions.question_fi = tst_test_result.question_fi
4280 
4281  WHERE tst_test_result.active_fi = %s
4282  AND tst_test_result.pass = %s
4283  ";
4284 
4285  $solutionresult = $ilDB->queryF(
4286  $query, array('integer', 'integer'), array($active_id, $pass)
4287  );
4288 
4289  while( $row = $ilDB->fetchAssoc($solutionresult) )
4290  {
4291  $arrResults[ $row['question_fi'] ] = $row;
4292  }
4293 
4294  $numWorkedThrough = count($arrResults);
4295 
4296  require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4297 
4298  $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4299 
4300  $query = "
4301  SELECT qpl_questions.*,
4302  qpl_qst_type.type_tag,
4303  qpl_sol_sug.question_fi has_sug_sol
4304 
4305  FROM qpl_qst_type,
4306  qpl_questions
4307 
4308  LEFT JOIN qpl_sol_sug
4309  ON qpl_sol_sug.question_fi = qpl_questions.question_id
4310 
4311  WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4312  AND $IN_question_ids
4313  ";
4314 
4315  $result = $ilDB->query($query);
4316 
4317  $unordered = array();
4318 
4319  $key = 1;
4320 
4321  $obligationsAnswered = true;
4322 
4323  while( $row = $ilDB->fetchAssoc($result) )
4324  {
4325  $percentvalue = (
4326  $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4327  );
4328 
4329  if( $percentvalue < 0 ) $percentvalue = 0.0;
4330 
4331  $data = array(
4332  "nr" => "$key",
4333  "title" => ilUtil::prepareFormOutput($row['title']),
4334  "max" => round($row['points'], 2),
4335  "reached" => round($arrResults[$row['question_id']]['reached'],2),
4336  'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4337  'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4338  "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4339  "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4340  "type" => $row["type_tag"],
4341  "qid" => $row['question_id'],
4342  "original_id" => $row["original_id"],
4343  "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4344  'answered' => $arrResults[$row['question_id']]['answered']
4345  );
4346 
4347  if( !$arrResults[ $row['question_id'] ]['answered'] )
4348  {
4349  $obligationsAnswered = false;
4350  }
4351 
4352  $unordered[ $row['question_id'] ] = $data;
4353 
4354  $key++;
4355  }
4356 
4357  $pass_max = 0;
4358  $pass_reached = 0;
4359  $pass_requested_hints = 0;
4360  $pass_hint_points = 0;
4361  $key = 1;
4362 
4363  $found = array();
4364 
4365  foreach( $sequence as $qid )
4366  {
4367  // building pass point sums based on prepared data
4368  // for question that exists in users qst sequence
4369  $pass_max += round($unordered[$qid]['max'], 2);
4370  $pass_reached += round($unordered[$qid]['reached'], 2);
4371  $pass_requested_hints += $unordered[$qid]['requested_hints'];
4372  $pass_hint_points += $unordered[$qid]['hint_points'];
4373 
4374  // pickup prepared data for question
4375  // that exists in users qst sequence
4376  $unordered[$qid]['nr'] = $key;
4377  array_push($found, $unordered[$qid]);
4378 
4379  // increment key counter
4380  $key++;
4381  }
4382 
4383  $unordered = null;
4384 
4385  if( $this->getScoreCutting() == 1 )
4386  {
4387  if( $results['reached_points'] < 0 )
4388  {
4389  $results['reached_points'] = 0;
4390  }
4391 
4392  if( $pass_reached < 0 ) $pass_reached = 0;
4393  }
4394 
4395  $found['pass']['total_max_points'] = $pass_max;
4396  $found['pass']['total_reached_points'] = $pass_reached;
4397  $found['pass']['total_requested_hints'] = $pass_requested_hints;
4398  $found['pass']['total_hint_points'] = $pass_hint_points;
4399  $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4400  $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4401  $found['pass']['num_workedthrough'] = $numWorkedThrough;
4402 
4403  $found["test"]["total_max_points"] = $results['max_points'];
4404  $found["test"]["total_reached_points"] = $results['reached_points'];
4405  $found["test"]["total_requested_hints"] = $results['hint_count'];
4406  $found["test"]["total_hint_points"] = $results['hint_points'];
4407  $found["test"]["result_pass"] = $results['pass'];
4408  $found['test']['obligations_answered'] = $results['obligations_answered'];
4409 
4410  if( (!$total_reached_points) or (!$total_max_points) )
4411  {
4412  $percentage = 0.0;
4413  }
4414  else
4415  {
4416  $percentage = ($total_reached_points / $total_max_points) * 100.0;
4417 
4418  if( $percentage < 0 ) $percentage = 0.0;
4419  }
4420 
4421  $found["test"]["passed"] = $results['passed'];
4422 
4423  return $found;
4424  }
4425 
4432  function evalTotalPersons()
4433  {
4434  global $ilDB;
4435 
4436  $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4437  array('integer'),
4438  array($this->getTestId())
4439  );
4440  $row = $ilDB->fetchAssoc($result);
4441  return $row["total"];
4442  }
4443 
4450  function getCompleteWorkingTime($user_id)
4451  {
4452  global $ilDB;
4453 
4454  $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",
4455  array('integer','integer'),
4456  array($this->getTestId(), $user_id)
4457  );
4458  $time = 0;
4459  while ($row = $ilDB->fetchAssoc($result))
4460  {
4461  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4462  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4463  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4464  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4465  $time += ($epoch_2 - $epoch_1);
4466  }
4467  return $time;
4468  }
4469 
4477  {
4478  return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4479  }
4480 
4489  {
4490  global $ilDB;
4491 
4492  $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",
4493  array('integer'),
4494  array($test_id)
4495  );
4496  $time = 0;
4497  $times = array();
4498  while ($row = $ilDB->fetchAssoc($result))
4499  {
4500  if (!array_key_exists($row["active_fi"], $times))
4501  {
4502  $times[$row["active_fi"]] = 0;
4503  }
4504  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4505  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4506  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4507  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4508  $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4509  }
4510  return $times;
4511  }
4512 
4520  {
4521  global $ilDB;
4522 
4523  $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",
4524  array('integer','integer'),
4525  array($this->getTestId(), $active_id)
4526  );
4527  $time = 0;
4528  while ($row = $ilDB->fetchAssoc($result))
4529  {
4530  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4531  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4532  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4533  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4534  $time += ($epoch_2 - $epoch_1);
4535  }
4536  return $time;
4537  }
4538 
4546  {
4547  global $ilDB;
4548 
4549  $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4550  array('integer','integer'),
4551  array($active_id, $pass)
4552  );
4553  $time = 0;
4554  while ($row = $ilDB->fetchAssoc($result))
4555  {
4556  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4557  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4558  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4559  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4560  $time += ($epoch_2 - $epoch_1);
4561  }
4562  return $time;
4563  }
4564 
4572  function getVisitTimeOfParticipant($active_id)
4573  {
4574  return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4575  }
4576 
4585  function _getVisitTimeOfParticipant($test_id, $active_id)
4586  {
4587  global $ilDB;
4588 
4589  $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",
4590  array('integer','integer'),
4591  array($test_id, $active_id)
4592  );
4593  $firstvisit = 0;
4594  $lastvisit = 0;
4595  while ($row = $ilDB->fetchAssoc($result))
4596  {
4597  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4598  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4599  if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
4600  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4601  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4602  if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
4603  }
4604  return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4605  }
4606 
4613  function &evalStatistical($active_id)
4614  {
4615  global $ilDB;
4616 // global $ilBench;
4617  $pass = ilObjTest::_getResultPass($active_id);
4618  $test_result =& $this->getTestResult($active_id, $pass);
4619  $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",
4620  array('integer'),
4621  array($active_id)
4622  );
4623  $times = array();
4624  $first_visit = 0;
4625  $last_visit = 0;
4626  while ($row = $ilDB->fetchObject($result))
4627  {
4628  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4629  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4630  if (!$first_visit) {
4631  $first_visit = $epoch_1;
4632  }
4633  if ($epoch_1 < $first_visit) {
4634  $first_visit = $epoch_1;
4635  }
4636  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4637  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4638  if (!$last_visit) {
4639  $last_visit = $epoch_2;
4640  }
4641  if ($epoch_2 > $last_visit) {
4642  $last_visit = $epoch_2;
4643  }
4644  $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4645  }
4646  $max_time = 0;
4647  foreach ($times as $key => $value) {
4648  $max_time += $value;
4649  }
4650  if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
4651  {
4652  $percentage = 0.0;
4653  }
4654  else
4655  {
4656  $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4657  if ($percentage < 0) $percentage = 0.0;
4658  }
4659  $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4660  $first_date = getdate($first_visit);
4661  $last_date = getdate($last_visit);
4662  $qworkedthrough = 0;
4663  foreach ($test_result as $key => $value)
4664  {
4665  if (preg_match("/\d+/", $key))
4666  {
4667  $qworkedthrough += $value["workedthrough"];
4668  }
4669  }
4670  if (!$qworkedthrough)
4671  {
4672  $atimeofwork = 0;
4673  }
4674  else
4675  {
4676  $atimeofwork = $max_time / $qworkedthrough;
4677  }
4678 
4679  $obligationsAnswered = $test_result["test"]["obligations_answered"];
4680 
4681  $result_mark = "";
4682  $passed = "";
4683 
4684  if ($mark_obj)
4685  {
4686  $result_mark = $mark_obj->getShortName();
4687 
4688  if( $mark_obj->getPassed() && $obligationsAnswered )
4689  {
4690  $passed = 1;
4691  }
4692  else
4693  {
4694  $passed = 0;
4695  }
4696  }
4697  $percent_worked_through = 0;
4698  if (count($this->questions))
4699  {
4700  $percent_worked_through = $qworkedthrough / count($this->questions);
4701  }
4702  $result_array = array(
4703  "qworkedthrough" => $qworkedthrough,
4704  "qmax" => count($this->questions),
4705  "pworkedthrough" => $percent_worked_through,
4706  "timeofwork" => $max_time,
4707  "atimeofwork" => $atimeofwork,
4708  "firstvisit" => $first_date,
4709  "lastvisit" => $last_date,
4710  "resultspoints" => $test_result["test"]["total_reached_points"],
4711  "maxpoints" => $test_result["test"]["total_max_points"],
4712  "resultsmarks" => $result_mark,
4713  "passed" => $passed,
4714  "distancemedian" => "0"
4715  );
4716  foreach ($test_result as $key => $value)
4717  {
4718  if (preg_match("/\d+/", $key))
4719  {
4720  $result_array[$key] = $value;
4721  }
4722  }
4723  return $result_array;
4724  }
4725 
4734  {
4735  $totalpoints_array = array();
4736  $all_users =& $this->evalTotalParticipantsArray();
4737  foreach ($all_users as $active_id => $user_name)
4738  {
4739  $test_result =& $this->getTestResult($active_id);
4740  $reached = $test_result["test"]["total_reached_points"];
4741  $total = $test_result["test"]["total_max_points"];
4742  $percentage = $total != 0 ? $reached/$total : 0;
4743  $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4744 
4745  $obligationsAnswered = $test_result["test"]["obligations_answered"];
4746 
4747  if ($mark)
4748  {
4749  if( $mark->getPassed() && $obligationsAnswered )
4750  {
4751  array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4752  }
4753  }
4754  }
4755  return $totalpoints_array;
4756  }
4757 
4763  public function &getParticipants()
4764  {
4765  global $ilDB;
4766  $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",
4767  array('integer'),
4768  array($this->getTestId())
4769  );
4770  $persons_array = array();
4771  while ($row = $ilDB->fetchAssoc($result))
4772  {
4773  $name = $this->lng->txt("anonymous");
4774  $fullname = $this->lng->txt("anonymous");
4775  $login = "";
4776  if (!$this->getAnonymity())
4777  {
4778  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4779  {
4780  $name = $this->lng->txt("deleted_user");
4781  $fullname = $this->lng->txt("deleted_user");
4782  $login = $this->lng->txt("unknown");
4783  }
4784  else
4785  {
4786  $login = $row["login"];
4787  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4788  {
4789  $name = $this->lng->txt("anonymous");
4790  $fullname = $this->lng->txt("anonymous");
4791  }
4792  else
4793  {
4794  $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4795  $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4796  }
4797  }
4798  }
4799  $persons_array[$row["active_id"]] = array(
4800  "name" => $name,
4801  "fullname" => $fullname,
4802  "login" => $login
4803  );
4804  }
4805  return $persons_array;
4806  }
4807 
4814  function &evalTotalPersonsArray($name_sort_order = "asc")
4815  {
4816  global $ilDB;
4817  $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),
4818  array('integer'),
4819  array($this->getTestId())
4820  );
4821  $persons_array = array();
4822  while ($row = $ilDB->fetchAssoc($result))
4823  {
4824  if ($this->getAnonymity())
4825  {
4826  $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
4827  }
4828  else
4829  {
4830  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4831  {
4832  $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4833  }
4834  else
4835  {
4836  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4837  {
4838  $persons_array[$row["active_id"]] = $row["lastname"];
4839  }
4840  else
4841  {
4842  $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4843  }
4844  }
4845  }
4846  }
4847  return $persons_array;
4848  }
4849 
4856  function &evalTotalParticipantsArray($name_sort_order = "asc")
4857  {
4858  global $ilDB;
4859  $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),
4860  array('integer'),
4861  array($this->getTestId())
4862  );
4863  $persons_array = array();
4864  while ($row = $ilDB->fetchAssoc($result))
4865  {
4866  if ($this->getAnonymity())
4867  {
4868  $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
4869  }
4870  else
4871  {
4872  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4873  {
4874  $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4875  }
4876  else
4877  {
4878  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4879  {
4880  $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4881  }
4882  else
4883  {
4884  $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4885  }
4886  }
4887  }
4888  }
4889  return $persons_array;
4890  }
4891 
4899  {
4900  global $ilDB;
4901 
4902  $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4903  array('integer', 'integer'),
4904  array($this->getTestId(), 1)
4905  );
4906  $row = $ilDB->fetchAssoc($result);
4907  return $row["total"];
4908  }
4909 
4916  function &getQuestionsOfTest($active_id)
4917  {
4918  global $ilDB;
4919  if ($this->isRandomTest())
4920  {
4921  $ilDB->setLimit($this->getQuestionCount(), 0);
4922  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4923  "tst_test_rnd_qst.pass, qpl_questions.points " .
4924  "FROM tst_test_rnd_qst, qpl_questions " .
4925  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4926  "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4927  array('integer'),
4928  array($active_id)
4929  );
4930  }
4931  else
4932  {
4933  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4934  "qpl_questions.points " .
4935  "FROM tst_test_question, tst_active, qpl_questions " .
4936  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4937  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4938  array('integer'),
4939  array($active_id)
4940  );
4941  }
4942  $qtest = array();
4943  if ($result->numRows())
4944  {
4945  while ($row = $ilDB->fetchAssoc($result))
4946  {
4947  array_push($qtest, $row);
4948  }
4949  }
4950  return $qtest;
4951  }
4952 
4959  function &getQuestionsOfPass($active_id, $pass)
4960  {
4961  global $ilDB;
4962  if ($this->isRandomTest())
4963  {
4964  $ilDB->setLimit($this->getQuestionCount(), 0);
4965  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4966  "qpl_questions.points " .
4967  "FROM tst_test_rnd_qst, qpl_questions " .
4968  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4969  "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4970  "ORDER BY tst_test_rnd_qst.sequence",
4971  array('integer', 'integer'),
4972  array($active_id, $pass)
4973  );
4974  }
4975  else
4976  {
4977  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4978  "qpl_questions.points " .
4979  "FROM tst_test_question, tst_active, qpl_questions " .
4980  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4981  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4982  array('integer'),
4983  array($active_id)
4984  );
4985  }
4986  $qpass = array();
4987  if ($result->numRows())
4988  {
4989  while ($row = $ilDB->fetchAssoc($result))
4990  {
4991  array_push($qpass, $row);
4992  }
4993  }
4994  return $qpass;
4995  }
4996 
4997  function getUnfilteredEvaluationData()
4998  {
5000  global $DIC;
5001 
5002  $ilDB = $DIC->database();
5003 
5004  include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5005  include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5006  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5007 
5008  $data = new ilTestEvaluationData($this);
5009 
5010  $query = "
5011  SELECT tst_test_result.*,
5012  qpl_questions.original_id,
5013  qpl_questions.title questiontitle,
5014  qpl_questions.points maxpoints
5015 
5016  FROM tst_test_result, qpl_questions, tst_active
5017 
5018  WHERE tst_active.active_id = tst_test_result.active_fi
5019  AND qpl_questions.question_id = tst_test_result.question_fi
5020  AND tst_active.test_fi = %s
5021 
5022  ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
5023  ";
5024 
5025  $result = $ilDB->queryF(
5026  $query, array('integer'), array($this->getTestId())
5027  );
5028 
5029  $pass = NULL;
5030  $checked = array();
5031  $datasets = 0;
5032  $questionData = [];
5033 
5034  while( $row = $ilDB->fetchAssoc($result) )
5035  {
5036  $participantObject = $data->getParticipant($row["active_fi"]);
5037 
5038  if( !($participantObject instanceof ilTestEvaluationUserData) )
5039  {
5040  continue;
5041  }
5042 
5043  $passObject = $participantObject->getPass($row["pass"]);
5044 
5045  if( !($passObject instanceof ilTestEvaluationPassData) )
5046  {
5047  continue;
5048  }
5049 
5050  $passObject->addAnsweredQuestion(
5051  $row["question_fi"], $row["maxpoints"], $row["points"], $row['answered'], null, $row['manual']
5052  );
5053  }
5054 
5055  foreach( array_keys($data->getParticipants()) as $active_id )
5056  {
5057  if( $this->isRandomTest() )
5058  {
5059  for( $testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++ )
5060  {
5061  $ilDB->setLimit($this->getQuestionCount(), 0);
5062  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id, " .
5063  "tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title " .
5064  "FROM tst_test_rnd_qst, qpl_questions " .
5065  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
5066  "AND tst_test_rnd_qst.pass = %s " .
5067  "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
5068  array('integer','integer'),
5069  array($testpass, $active_id)
5070  );
5071  if ($result->numRows())
5072  {
5073  while ($row = $ilDB->fetchAssoc($result))
5074  {
5075  $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
5076  $data->getParticipant($active_id)->addQuestion($row["original_id"], $row["question_fi"], $row["points"], $row["sequence"], $tpass);
5077  $data->addQuestionTitle($row["question_fi"], $row["title"]);
5078  }
5079  }
5080  }
5081  }
5082  else if($this->isDynamicTest())
5083  {
5084  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
5085  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
5086  require_once 'Modules/Test/classes/class.ilTestDynamicQuestionSetFilterSelection.php';
5087 
5088  $lastPass = $data->getParticipant($active_id)->getLastPass();
5089  for($testpass = 0; $testpass <= $lastPass; $testpass++)
5090  {
5091  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
5092  $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig(
5093  $DIC->repositoryTree(), $DIC->database(), $DIC['ilPluginAdmin'], $this
5094  );
5095  $dynamicQuestionSetConfig->loadFromDb();
5096 
5097  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
5098  $testSequenceFactory = new ilTestSequenceFactory($DIC->database(), $DIC->language(), $DIC['ilPluginAdmin'], $this);
5099  $testSequence = $testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $testpass);
5100 
5101  $testSequence->loadFromDb($dynamicQuestionSetConfig);
5102  $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
5103 
5104  $sequence = (array)$testSequence->getUserSequenceQuestions();
5105 
5106  $questionsIdsToRequest = array_diff(array_values($sequence), array_values($questionData));
5107  if(count($questionsIdsToRequest) > 0)
5108  {
5109  $questionIdsCondition = ' ' . $DIC->database()->in('question_id', array_values($questionsIdsToRequest), false, 'integer') . ' ';
5110 
5111  $res = $DIC->database()->queryF("
5112  SELECT *
5113  FROM qpl_questions
5114  WHERE {$questionIdsCondition}",
5115  array('integer'),
5116  array($active_id)
5117  );
5118  while($row = $DIC->database()->fetchAssoc($res))
5119  {
5120  $questionData[$row['question_id']] = $row;
5121  $data->addQuestionTitle($row['question_id'], $row['title']);
5122  }
5123  }
5124 
5125  foreach($sequence as $questionId)
5126  {
5127  if(!isset($questionData[$questionId]))
5128  {
5129  continue;
5130  }
5131 
5132  $row = $questionData[$questionId];
5133 
5134  $data->getParticipant(
5135  $active_id)->addQuestion($row['original_id'], $row['question_id'], $row['points'],
5136  NULL, $testpass
5137  );
5138  }
5139  }
5140  }
5141  else
5142  {
5143  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
5144  "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
5145  "FROM tst_test_question, tst_active, qpl_questions " .
5146  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
5147  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
5148  array('integer'),
5149  array($active_id)
5150  );
5151  if ($result->numRows())
5152  {
5153  $questionsbysequence = array();
5154 
5155  while ($row = $ilDB->fetchAssoc($result))
5156  {
5157  $questionsbysequence[$row["sequence"]] = $row;
5158  }
5159 
5160  $seqresult = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s",
5161  array('integer'),
5162  array($active_id)
5163  );
5164 
5165  while ($seqrow = $ilDB->fetchAssoc($seqresult))
5166  {
5167  $questionsequence = unserialize($seqrow["sequence"]);
5168  foreach ($questionsequence as $sidx => $seq)
5169  {
5170  $data->getParticipant($active_id)->addQuestion($questionsbysequence[$seq]["original_id"], $questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
5171  $data->addQuestionTitle($questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["title"]);
5172  }
5173  }
5174  }
5175  }
5176  }
5177 
5178  if($this->getECTSOutput())
5179  {
5180  $passed_array =& $this->getTotalPointsPassedArray();
5181  }
5182 
5183  foreach( array_keys($data->getParticipants()) as $active_id )
5184  {
5185  $tstUserData = $data->getParticipant($active_id);
5186 
5187  $percentage = $tstUserData->getReachedPointsInPercent();
5188 
5189  $obligationsAnswered = $tstUserData->areObligationsAnswered();
5190 
5191  $mark = $this->mark_schema->getMatchingMark($percentage);
5192 
5193  if (is_object($mark))
5194  {
5195  $tstUserData->setMark($mark->getShortName());
5196  $tstUserData->setMarkOfficial($mark->getOfficialName());
5197 
5198  $tstUserData->setPassed(
5199  $mark->getPassed() && $tstUserData->areObligationsAnswered()
5200  );
5201  }
5202 
5203  if($this->getECTSOutput())
5204  {
5205  $ects_mark = $this->getECTSGrade(
5206  $passed_array, $tstUserData->getReached(), $tstUserData->getMaxPoints()
5207  );
5208 
5209  $tstUserData->setECTSMark($ects_mark);
5210  }
5211 
5212  $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
5213 
5214  $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
5215  $tstUserData->setLastVisit($visitingTime["lastvisit"]);
5216  }
5217 
5218  return $data;
5219  }
5220 
5222  {
5223  global $ilDB;
5224 
5226 
5227  switch( $questionSetType )
5228  {
5230 
5231  $res = $ilDB->queryF("
5232  SELECT COUNT(qpl_questions.question_id) qcount,
5233  SUM(qpl_questions.points) qsum
5234  FROM tst_active
5235  INNER JOIN tst_tests
5236  ON tst_tests.test_id = tst_active.test_fi
5237  INNER JOIN tst_dyn_quest_set_cfg
5238  ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
5239  INNER JOIN qpl_questions
5240  ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
5241  AND qpl_questions.original_id IS NULL
5242  AND qpl_questions.complete = %s
5243  WHERE tst_active.active_id = %s
5244  ",
5245  array('integer', 'integer'),
5246  array(1, $active_id)
5247  );
5248 
5249  break;
5250 
5252 
5253  $res = $ilDB->queryF("
5254  SELECT tst_test_rnd_qst.pass,
5255  COUNT(tst_test_rnd_qst.question_fi) qcount,
5256  SUM(qpl_questions.points) qsum
5257 
5258  FROM tst_test_rnd_qst,
5259  qpl_questions
5260 
5261  WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
5262  AND tst_test_rnd_qst.active_fi = %s
5263  AND pass = %s
5264 
5265  GROUP BY tst_test_rnd_qst.active_fi,
5266  tst_test_rnd_qst.pass
5267  ",
5268  array('integer', 'integer'),
5269  array($active_id, $pass)
5270  );
5271 
5272  break;
5273 
5275 
5276  $res = $ilDB->queryF("
5277  SELECT COUNT(tst_test_question.question_fi) qcount,
5278  SUM(qpl_questions.points) qsum
5279 
5280  FROM tst_test_question,
5281  qpl_questions,
5282  tst_active
5283 
5284  WHERE tst_test_question.question_fi = qpl_questions.question_id
5285  AND tst_test_question.test_fi = tst_active.test_fi
5286  AND tst_active.active_id = %s
5287 
5288  GROUP BY tst_test_question.test_fi
5289  ",
5290  array('integer'),
5291  array($active_id)
5292  );
5293 
5294  break;
5295 
5296  default:
5297 
5298  throw new ilTestException("not supported question set type: $questionSetType");
5299  }
5300 
5301  $row = $ilDB->fetchAssoc($res);
5302 
5303  if( is_array($row) )
5304  {
5305  return array("count" => $row["qcount"], "points" => $row["qsum"]);
5306  }
5307 
5308  return array("count" => 0, "points" => 0);
5309  }
5310 
5311  function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
5312  {
5313  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5314  include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5315  include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5316  $data = $this->getUnfilteredEvaluationData();
5317  if ($withStatistics)
5318  {
5319  $data->calculateStatistics();
5320  }
5321  $data->setFilter($filterby, $filtertext);
5322  return $data;
5323  }
5324 
5332  {
5333  return $this->_evalResultsOverview($this->getTestId());
5334  }
5335 
5342  function &_evalResultsOverview($test_id)
5343  {
5344  global $ilDB;
5345 
5346  $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5347  "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5348  "qpl_questions.points maxpoints " .
5349  "FROM tst_test_result, qpl_questions, tst_active " .
5350  "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5351  "WHERE tst_active.active_id = tst_test_result.active_fi " .
5352  "AND qpl_questions.question_id = tst_test_result.question_fi " .
5353  "AND tst_active.test_fi = %s " .
5354  "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5355  array('integer'),
5356  array($test_id)
5357  );
5358  $overview = array();
5359  while ($row = $ilDB->fetchAssoc($result))
5360  {
5361  if (!array_key_exists($row["active_fi"], $overview))
5362  {
5363  $overview[$row["active_fi"]] = array();
5364  $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5365  $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5366  $overview[$row["active_fi"]]["title"] = $row["title"];
5367  $overview[$row["active_fi"]]["login"] = $row["login"];
5368  $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5369  $overview[$row["active_fi"]]["started"] = $row["started"];
5370  $overview[$row["active_fi"]]["finished"] = $row["finished"];
5371  }
5372  if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5373  {
5374  $overview[$row["active_fi"]][$row["pass"]] = array();
5375  $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5376  $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5377  }
5378  array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5379  $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5380  }
5381  return $overview;
5382  }
5383 
5391  function &evalResultsOverviewOfParticipant($active_id)
5392  {
5393  global $ilDB;
5394 
5395  $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5396  "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5397  "qpl_questions.points maxpoints " .
5398  "FROM tst_test_result, qpl_questions, tst_active " .
5399  "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5400  "WHERE tst_active.active_id = tst_test_result.active_fi " .
5401  "AND qpl_questions.question_id = tst_test_result.question_fi " .
5402  "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5403  "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5404  array('integer', 'integer'),
5405  array($this->getTestId(), $active_id)
5406  );
5407  $overview = array();
5408  while ($row = $ilDB->fetchAssoc($result))
5409  {
5410  if (!array_key_exists($row["active_fi"], $overview))
5411  {
5412  $overview[$row["active_fi"]] = array();
5413  $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5414  $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5415  $overview[$row["active_fi"]]["title"] = $row["title"];
5416  $overview[$row["active_fi"]]["login"] = $row["login"];
5417  $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5418  $overview[$row["active_fi"]]["started"] = $row["started"];
5419  $overview[$row["active_fi"]]["finished"] = $row["finished"];
5420  }
5421  if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5422  {
5423  $overview[$row["active_fi"]][$row["pass"]] = array();
5424  $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5425  $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5426  }
5427  array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5428  $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5429  }
5430  return $overview;
5431  }
5432 
5444  function buildName($user_id, $firstname, $lastname, $title)
5445  {
5446  $name = "";
5447  if (strlen($firstname.$lastname.$title) == 0)
5448  {
5449  $name = $this->lng->txt("deleted_user");
5450  }
5451  else
5452  {
5453  if ($user_id == ANONYMOUS_USER_ID)
5454  {
5455  $name = $lastname;
5456  }
5457  else
5458  {
5459  $name = trim($lastname . ", " . $firstname . " " . $title);
5460  }
5461  if ($this->getAnonymity())
5462  {
5463  $name = $this->lng->txt("anonymous");
5464  }
5465  }
5466  return $name;
5467  }
5468 
5481  function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5482  {
5483  global $lng;
5484  $name = "";
5485  if (strlen($firstname.$lastname.$title) == 0)
5486  {
5487  $name = $lng->txt("deleted_user");
5488  }
5489  else
5490  {
5491  if ($user_id == ANONYMOUS_USER_ID)
5492  {
5493  $name = $lastname;
5494  }
5495  else
5496  {
5497  $name = trim($lastname . ", " . $firstname . " " . $title);
5498  }
5499  if ($is_anonymous)
5500  {
5501  $name = $lng->txt("anonymous");
5502  }
5503  }
5504  return $name;
5505  }
5506 
5514  {
5515  global $ilDB;
5516 
5517  $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",
5518  array('integer'),
5519  array($this->getTestId())
5520  );
5521  $times = array();
5522  while ($row = $ilDB->fetchObject($result))
5523  {
5524  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5525  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5526  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5527  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5528  $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5529  }
5530  $max_time = 0;
5531  $counter = 0;
5532  foreach ($times as $key => $value)
5533  {
5534  $max_time += $value;
5535  $counter++;
5536  }
5537  if ($counter)
5538  {
5539  $average_time = round($max_time / $counter);
5540  }
5541  else
5542  {
5543  $average_time = 0;
5544  }
5545  return $average_time;
5546  }
5547 
5554  function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
5555  {
5556  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5557  return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5558  }
5559 
5567  {
5568  $time_in_seconds = 0;
5569  foreach ($this->questions as $question_id)
5570  {
5571  $question =& ilObjTest::_instanciateQuestion($question_id);
5572  $est_time = $question->getEstimatedWorkingTime();
5573  $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5574  }
5575  $hours = (int)($time_in_seconds / 3600) ;
5576  $time_in_seconds = $time_in_seconds - ($hours * 3600);
5577  $minutes = (int)($time_in_seconds / 60);
5578  $time_in_seconds = $time_in_seconds - ($minutes * 60);
5579  $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5580  return $result;
5581  }
5582 
5589  function getImagePath()
5590  {
5591  return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5592  }
5593 
5600  function getImagePathWeb()
5601  {
5602  include_once "./Services/Utilities/classes/class.ilUtil.php";
5603  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5605  }
5606 
5615  function &createQuestionGUI($question_type, $question_id = -1)
5616  {
5617  if ((!$question_type) and ($question_id > 0))
5618  {
5619  $question_type = $this->getQuestionType($question_id);
5620  }
5621 
5622  if (!strlen($question_type)) return null;
5623 
5624  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5625  assQuestion::_includeClass($question_type, 1);
5626 
5627  $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5628  $question = new $question_type_gui();
5629 
5630  $question->object->setObligationsToBeConsidered( $this->areObligationsEnabled() );
5631 
5632  if ($question_id > 0)
5633  {
5634  $question->object->loadFromDb($question_id);
5635 
5636  global $ilCtrl, $ilDB, $ilUser, $lng;
5637 
5638  $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5639  $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5640 
5641  $assSettings = new ilSetting('assessment');
5642  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5643  $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5644  $processLockerFactory->setQuestionId($question->object->getId());
5645  $processLockerFactory->setUserId($ilUser->getId());
5646  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5647  $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5648  $question->object->setProcessLocker($processLockerFactory->getLocker());
5649  }
5650 
5651  return $question;
5652  }
5653 
5663  function &_instanciateQuestion($question_id)
5664  {
5665  if (strcmp($question_id, "") != 0)
5666  {
5667  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5668  return assQuestion::_instanciateQuestion($question_id);
5669  }
5670  }
5671 
5680  function moveQuestions($move_questions, $target_index, $insert_mode)
5681  {
5682  $this->questions = array_values($this->questions);
5683  $array_pos = array_search($target_index, $this->questions);
5684  if ($insert_mode == 0)
5685  {
5686  $part1 = array_slice($this->questions, 0, $array_pos);
5687  $part2 = array_slice($this->questions, $array_pos);
5688  }
5689  else if ($insert_mode == 1)
5690  {
5691  $part1 = array_slice($this->questions, 0, $array_pos + 1);
5692  $part2 = array_slice($this->questions, $array_pos + 1);
5693  }
5694  foreach ($move_questions as $question_id)
5695  {
5696  if (!(array_search($question_id, $part1) === FALSE))
5697  {
5698  unset($part1[array_search($question_id, $part1)]);
5699  }
5700  if (!(array_search($question_id, $part2) === FALSE))
5701  {
5702  unset($part2[array_search($question_id, $part2)]);
5703  }
5704  }
5705  $part1 = array_values($part1);
5706  $part2 = array_values($part2);
5707  $new_array = array_values(array_merge($part1, $move_questions, $part2));
5708  $this->questions = array();
5709  $counter = 1;
5710  foreach ($new_array as $question_id)
5711  {
5712  $this->questions[$counter] = $question_id;
5713  $counter++;
5714  }
5715  $this->saveQuestionsToDb();
5716  }
5717 
5718 
5727  {
5728  if( $this->isStartingTimeEnabled() && $this->getStartingTime() )
5729  {
5730  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
5731  {
5732  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5733  $now = mktime();
5734  if ($now < $epoch_time)
5735  {
5736  // starting time not reached
5737  return false;
5738  }
5739  }
5740  }
5741  return true;
5742  }
5743 
5752  {
5753  if( $this->isEndingTimeEnabled() && $this->getEndingTime() )
5754  {
5755  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
5756  {
5757  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5758  $now = mktime();
5759  if ($now > $epoch_time)
5760  {
5761  // ending time reached
5762  return true;
5763  }
5764  }
5765  }
5766  return false;
5767  }
5768 
5774  function getAvailableQuestions($arrFilter, $completeonly = 0)
5775  {
5776  global $ilUser;
5777  global $ilDB;
5778 
5779  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5780  $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
5781  $available = "";
5782  if (count($available_pools))
5783  {
5784  $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5785  }
5786  else
5787  {
5788  return array();
5789  }
5790  if ($completeonly)
5791  {
5792  $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5793  }
5794 
5795  $where = "";
5796  if (is_array($arrFilter))
5797  {
5798  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
5799  {
5800  $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5801  }
5802  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
5803  {
5804  $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5805  }
5806  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
5807  {
5808  $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5809  }
5810  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
5811  {
5812  $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5813  }
5814  if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl']))
5815  {
5816  $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5817  }
5818  }
5819 
5820  $original_ids =& $this->getExistingQuestions();
5821  $original_clause = " qpl_questions.original_id IS NULL";
5822  if (count($original_ids))
5823  {
5824  $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5825  }
5826 
5827  $query_result = $ilDB->query(
5828  "SELECT qpl_questions.*, qpl_questions.tstamp, qpl_qst_type.type_tag, qpl_qst_type.plugin, object_data.title qpl " .
5829  "FROM qpl_questions, qpl_qst_type, object_data WHERE $original_clause $available AND " .
5830  "object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.tstamp > 0 AND " .
5831  "qpl_questions.question_type_fi = qpl_qst_type.question_type_id$where");
5832  $rows = array();
5833  $types = $this->getQuestionTypeTranslations();
5834  if ($query_result->numRows())
5835  {
5836  while ($row = $ilDB->fetchAssoc($query_result))
5837  {
5838  $row['ttype'] = $types[$row['type_tag']];
5839  if ($row["plugin"])
5840  {
5841  if ($this->isPluginActive($row["type_tag"]))
5842  {
5843  array_push($rows, $row);
5844  }
5845  }
5846  else
5847  {
5848  array_push($rows, $row);
5849  }
5850  }
5851  }
5852  return $rows;
5853  }
5854 
5855  public function &getQuestionTypeTranslations()
5856  {
5857  global $ilDB;
5858  global $lng;
5859  global $ilLog;
5860  global $ilPluginAdmin;
5861 
5862  $lng->loadLanguageModule("assessment");
5863  $result = $ilDB->query("SELECT * FROM qpl_qst_type");
5864  $types = array();
5865  while ($row = $ilDB->fetchAssoc($result))
5866  {
5867  if ($row["plugin"] == 0)
5868  {
5869  $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
5870  }
5871  else
5872  {
5873  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
5874  foreach ($pl_names as $pl_name)
5875  {
5876  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
5877  if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0)
5878  {
5879  $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
5880  }
5881  }
5882  }
5883  }
5884  ksort($types);
5885  return $types;
5886  }
5887 
5892  public function fromXML(ilQTIAssessment $assessment)
5893  {
5894  unset($_SESSION["import_mob_xhtml"]);
5895 
5896  $this->setDescription($assessment->getComment());
5897  $this->setTitle($assessment->getTitle());
5898 
5899  $this->setIntroductionEnabled(false);
5900  foreach ($assessment->objectives as $objectives)
5901  {
5902  foreach ($objectives->materials as $material)
5903  {
5904  $intro = $this->QTIMaterialToString($material);
5905  $this->setIntroduction($intro);
5906  $this->setIntroductionEnabled(strlen($intro) > 0);
5907  }
5908  }
5909 
5910  if(
5911  $assessment->getPresentationMaterial() &&
5912  $assessment->getPresentationMaterial()->getFlowMat(0) &&
5913  $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5914  )
5915  {
5916  $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5917  }
5918 
5919  foreach ($assessment->assessmentcontrol as $assessmentcontrol)
5920  {
5921  switch ($assessmentcontrol->getSolutionswitch())
5922  {
5923  case "Yes":
5924  $this->setInstantFeedbackSolution(1);
5925  break;
5926  default:
5927  $this->setInstantFeedbackSolution(0);
5928  break;
5929  }
5930  }
5931 
5932  $this->setStartingTimeEnabled(false);
5933  $this->setEndingTimeEnabled(false);
5934  $this->setPasswordEnabled(false);
5935  $this->setLimitUsersEnabled(false);
5936 
5937  foreach ($assessment->qtimetadata as $metadata)
5938  {
5939  switch ($metadata["label"])
5940  {
5941  case "test_type":
5942  // for old tests with a test type
5943  $type = $metadata["entry"];
5944  switch ($type)
5945  {
5946  case 1:
5947  // assessment
5948  $this->setAnonymity(1);
5949  break;
5950  case 2:
5951  // self assessment
5952  break;
5953  case 4:
5954  // online exam
5955  $this->setFixedParticipants(1);
5956  $this->setListOfQuestionsSettings(7);
5957  $this->setShowSolutionPrintview(1);
5958  break;
5959  case 5:
5960  // varying random test
5961  break;
5962  }
5963  break;
5964  case "sequence_settings":
5965  $this->setSequenceSettings($metadata["entry"]);
5966  break;
5967  case "solution_details":
5968  $this->setShowSolutionDetails((int)$metadata["entry"]);
5969  break;
5970  case "print_bs_with_res":
5971  $this->setPrintBestSolutionWithResult((int)$metadata["entry"]);
5972  break;
5973  case "author":
5974  $this->setAuthor($metadata["entry"]);
5975  break;
5976  case "nr_of_tries":
5977  $this->setNrOfTries($metadata["entry"]);
5978  break;
5979  case "kiosk":
5980  $this->setKiosk($metadata["entry"]);
5981  break;
5982  case "showfinalstatement":
5983  $this->setShowFinalStatement($metadata["entry"]);
5984  break;
5985  case "showinfo":
5986  $this->setShowInfo($metadata["entry"]);
5987  break;
5988  case "forcejs":
5989  $this->setForceJS($metadata["entry"]);
5990  break;
5991  case "customstyle":
5992  $this->setCustomStyle($metadata["entry"]);
5993  break;
5994 
5995  case "highscore_enabled":
5996  $this->setHighscoreEnabled($metadata["entry"]);
5997  break;
5998 
5999  case "highscore_anon":
6000  $this->setHighscoreAnon($metadata["entry"]);
6001  break;
6002 
6003  case "highscore_achieved_ts":
6004  $this->setHighscoreAchievedTS($metadata["entry"]);
6005  break;
6006 
6007  case "highscore_score":
6008  $this->setHighscoreScore($metadata["entry"]);
6009  break;
6010 
6011  case "highscore_percentage":
6012  $this->setHighscorePercentage($metadata["entry"]);
6013  break;
6014 
6015  case "highscore_hints":
6016  $this->setHighscoreHints($metadata["entry"]);
6017  break;
6018 
6019  case "highscore_wtime":
6020  $this->setHighscoreWTime($metadata["entry"]);
6021  break;
6022 
6023  case "highscore_own_table":
6024  $this->setHighscoreOwnTable($metadata["entry"]);
6025  break;
6026 
6027  case "highscore_top_table":
6028  $this->setHighscoreTopTable($metadata["entry"]);
6029  break;
6030 
6031  case "highscore_top_num":
6032  $this->setHighscoreTopNum($metadata["entry"]);
6033  break;
6034 
6035  case "hide_previous_results":
6036  if ($metadata["entry"] == 0)
6037  {
6038  $this->setUsePreviousAnswers(1);
6039  }
6040  else
6041  {
6042  $this->setUsePreviousAnswers(0);
6043  }
6044  break;
6045  case "use_previous_answers":
6046  $this->setUsePreviousAnswers($metadata["entry"]);
6047  break;
6048  case "answer_feedback":
6049  $this->setAnswerFeedback($metadata["entry"]);
6050  break;
6051  case "hide_title_points":
6052  $this->setTitleOutput($metadata["entry"]);
6053  break;
6054  case "title_output":
6055  $this->setTitleOutput($metadata["entry"]);
6056  break;
6057  case "question_set_type":
6058  $this->setQuestionSetType($metadata["entry"]);
6059  break;
6060  case "random_test":
6061  if( $metadata["entry"] )
6062  {
6063  $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
6064  }
6065  else
6066  {
6067  $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
6068  }
6069  break;
6070  case "results_presentation":
6071  $this->setResultsPresentation($metadata["entry"]);
6072  break;
6073  case "reset_processing_time":
6074  $this->setResetProcessingTime($metadata["entry"]);
6075  break;
6076  case "instant_verification":
6077  $this->setInstantFeedbackSolution($metadata["entry"]);
6078  break;
6079  case "answer_feedback_points":
6080  $this->setAnswerFeedbackPoints($metadata["entry"]);
6081  break;
6082  case "anonymity":
6083  $this->setAnonymity($metadata["entry"]);
6084  break;
6085  case "show_cancel":
6086  $this->setShowCancel($metadata["entry"]);
6087  break;
6088  case "show_marker":
6089  $this->setShowMarker($metadata["entry"]);
6090  break;
6091  case "fixed_participants":
6092  $this->setFixedParticipants($metadata["entry"]);
6093  break;
6094  case "score_reporting":
6095  $this->setScoreReporting($metadata["entry"]);
6096  break;
6097  case "shuffle_questions":
6098  $this->setShuffleQuestions($metadata["entry"]);
6099  break;
6100  case "count_system":
6101  $this->setCountSystem($metadata["entry"]);
6102  break;
6103  case "mc_scoring":
6104  $this->setMCScoring($metadata["entry"]);
6105  break;
6106  case "mailnotification":
6107  $this->setMailNotification($metadata["entry"]);
6108  break;
6109  case "mailnottype":
6110  $this->setMailNotificationType($metadata["entry"]);
6111  break;
6112  case "exportsettings":
6113  $this->setExportSettings($metadata['entry']);
6114  break;
6115  case "score_cutting":
6116  $this->setScoreCutting($metadata["entry"]);
6117  break;
6118  case "password":
6119  $this->setPassword($metadata["entry"]);
6120  $this->setPasswordEnabled(strlen($metadata["entry"]) > 0);
6121  break;
6122  case "allowedUsers":
6123  $this->setAllowedUsers($metadata["entry"]);
6124  $this->setLimitUsersEnabled((int)$metadata["entry"] > 0);
6125  break;
6126  case "allowedUsersTimeGap":
6127  $this->setAllowedUsersTimeGap($metadata["entry"]);
6128  break;
6129  case "pass_scoring":
6130  $this->setPassScoring($metadata["entry"]);
6131  break;
6132  case "show_summary":
6133  $this->setListOfQuestionsSettings($metadata["entry"]);
6134  break;
6135  case "reporting_date":
6136  $iso8601period = $metadata["entry"];
6137  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6138  {
6139  $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6140  }
6141  break;
6142  case 'enable_processing_time':
6143  $this->setEnableProcessingTime($metadata['entry']);
6144  break;
6145  case "processing_time":
6146  $this->setProcessingTime($metadata['entry']);
6147  break;
6148  case "starting_time":
6149  $iso8601period = $metadata["entry"];
6150  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6151  {
6152  $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6153  $this->setStartingTimeEnabled(true);
6154  }
6155  break;
6156  case "ending_time":
6157  $iso8601period = $metadata["entry"];
6158  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
6159  {
6160  $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
6161  $this->setEndingTimeEnabled(true);
6162  }
6163  break;
6164  case "enable_examview":
6165  $this->setEnableExamview($metadata["entry"]);
6166  break;
6167  case 'show_examview_html':
6168  $this->setShowExamviewHtml($metadata['entry']);
6169  break;
6170  case 'show_examview_pdf':
6171  $this->setShowExamviewPdf($metadata['entry']);
6172  break;
6173  case 'redirection_mode':
6174  $this->setRedirectionMode($metadata['entry']);
6175  break;
6176  case 'redirection_url':
6177  $this->setRedirectionUrl($metadata['entry']);
6178  break;
6179  case 'examid_in_kiosk':
6180  case 'examid_in_test_pass':
6181  $this->setShowExamIdInTestPassEnabled($metadata['entry']);
6182  break;
6183  case 'show_exam_id':
6184  case 'examid_in_test_res':
6185  $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
6186  break;
6187  case 'enable_archiving':
6188  $this->setEnableArchiving($metadata['entry']);
6189  break;
6190  case 'sign_submission':
6191  $this->setSignSubmission($metadata['entry']);
6192  break;
6193  case 'char_selector_availability':
6194  $this->setCharSelectorAvailability($metadata['entry']);
6195  break;
6196  case 'char_selector_definition':
6197  $this->setCharSelectorDefinition($metadata['entry']);
6198  break;
6199  case 'skill_service':
6200  $this->setSkillServiceEnabled((bool)$metadata['entry']);
6201  break;
6202  case 'result_tax_filters':
6203  $this->setResultFilterTaxIds(strlen($metadata['entry']) ? unserialize($metadata['entry']) : array());
6204  break;
6205  case 'show_grading_status':
6206  $this->setShowGradingStatusEnabled((bool)$metadata['entry']);
6207  break;
6208  case 'show_grading_mark':
6209  $this->setShowGradingMarkEnabled((bool)$metadata['entry']);
6210  break;
6211  case 'activation_limited':
6212  $this->setActivationLimited($metadata['entry']);
6213  break;
6214  case 'activation_start_time':
6215  $this->setActivationStartingTime($metadata['entry']);
6216  break;
6217  case 'activation_end_time':
6218  $this->setActivationEndingTime($metadata['entry']);
6219  break;
6220  case 'activation_visibility':
6221  $this->setActivationVisibility($metadata['entry']);
6222  break;
6223  case 'autosave':
6224  $this->setAutosave($metadata['entry']);
6225  break;
6226  case 'autosave_ival':
6227  $this->setAutosaveIval($metadata['entry']);
6228  break;
6229  case 'offer_question_hints':
6230  $this->setOfferingQuestionHintsEnabled($metadata['entry']);
6231  break;
6232  case 'instant_feedback_specific':
6233  $this->setSpecificAnswerFeedback($metadata['entry']);
6234  break;
6235  case 'instant_feedback_answer_fixation':
6236  $this->setInstantFeedbackAnswerFixationEnabled($metadata['entry']);
6237  break;
6238  case 'obligations_enabled':
6239  $this->setObligationsEnabled($metadata['entry']);
6240  break;
6241  }
6242  if (preg_match("/mark_step_\d+/", $metadata["label"]))
6243  {
6244  $xmlmark = $metadata["entry"];
6245  preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
6246  $mark_short = $matches[1];
6247  preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
6248  $mark_official = $matches[1];
6249  preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
6250  $mark_percentage = $matches[1];
6251  preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
6252  $mark_passed = $matches[1];
6253  $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
6254  }
6255  }
6256  // handle the import of media objects in XHTML code
6257  if (is_array($_SESSION["import_mob_xhtml"]))
6258  {
6259  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6260  include_once "./Services/RTE/classes/class.ilRTE.php";
6261  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
6262  foreach ($_SESSION["import_mob_xhtml"] as $mob)
6263  {
6264  $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
6265  if (file_exists($importfile))
6266  {
6267  $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
6268  ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
6269  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
6270  $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
6271  }
6272  else
6273  {
6274  global $ilLog;
6275  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
6276  }
6277  }
6278  $this->saveToDb();
6279  }
6280  }
6281 
6287  public function toXML()
6288  {
6289  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
6290  $a_xml_writer = new ilXmlWriter;
6291  // set xml header
6292  $a_xml_writer->xmlHeader();
6293  $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
6294  $a_xml_writer->xmlStartTag("questestinterop");
6295 
6296  $attrs = array(
6297  "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
6298  "title" => $this->getTitle()
6299  );
6300  $a_xml_writer->xmlStartTag("assessment", $attrs);
6301  // add qti comment
6302  $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
6303 
6304  // add qti duration
6305  if ($this->enable_processing_time)
6306  {
6307  preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
6308  $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
6309  }
6310 
6311  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
6312  $a_xml_writer->xmlStartTag("qtimetadata");
6313  $a_xml_writer->xmlStartTag("qtimetadatafield");
6314  $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
6315  $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
6316  $a_xml_writer->xmlEndTag("qtimetadatafield");
6317 
6318  // anonymity
6319  $a_xml_writer->xmlStartTag("qtimetadatafield");
6320  $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
6321  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
6322  $a_xml_writer->xmlEndTag("qtimetadatafield");
6323 
6324  // question set type (fixed, random, dynamic, ...)
6325  $a_xml_writer->xmlStartTag("qtimetadatafield");
6326  $a_xml_writer->xmlElement("fieldlabel", NULL, "question_set_type");
6327  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getQuestionSetType());
6328  $a_xml_writer->xmlEndTag("qtimetadatafield");
6329 
6330  // sequence settings
6331  $a_xml_writer->xmlStartTag("qtimetadatafield");
6332  $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
6333  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
6334  $a_xml_writer->xmlEndTag("qtimetadatafield");
6335 
6336  // author
6337  $a_xml_writer->xmlStartTag("qtimetadatafield");
6338  $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
6339  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
6340  $a_xml_writer->xmlEndTag("qtimetadatafield");
6341 
6342  // reset processing time
6343  $a_xml_writer->xmlStartTag("qtimetadatafield");
6344  $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
6345  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
6346  $a_xml_writer->xmlEndTag("qtimetadatafield");
6347 
6348  // count system
6349  $a_xml_writer->xmlStartTag("qtimetadatafield");
6350  $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
6351  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
6352  $a_xml_writer->xmlEndTag("qtimetadatafield");
6353 
6354  // multiple choice scoring
6355  $a_xml_writer->xmlStartTag("qtimetadatafield");
6356  $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
6357  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
6358  $a_xml_writer->xmlEndTag("qtimetadatafield");
6359 
6360  // multiple choice scoring
6361  $a_xml_writer->xmlStartTag("qtimetadatafield");
6362  $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
6363  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
6364  $a_xml_writer->xmlEndTag("qtimetadatafield");
6365 
6366  // multiple choice scoring
6367  $a_xml_writer->xmlStartTag("qtimetadatafield");
6368  $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
6369  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
6370  $a_xml_writer->xmlEndTag("qtimetadatafield");
6371 
6372  // allowed users
6373  $a_xml_writer->xmlStartTag("qtimetadatafield");
6374  $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
6375  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
6376  $a_xml_writer->xmlEndTag("qtimetadatafield");
6377 
6378  // allowed users time gap
6379  $a_xml_writer->xmlStartTag("qtimetadatafield");
6380  $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
6381  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
6382  $a_xml_writer->xmlEndTag("qtimetadatafield");
6383 
6384  // pass scoring
6385  $a_xml_writer->xmlStartTag("qtimetadatafield");
6386  $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
6387  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
6388  $a_xml_writer->xmlEndTag("qtimetadatafield");
6389 
6390  // score reporting date
6391  if ($this->getReportingDate())
6392  {
6393  $a_xml_writer->xmlStartTag("qtimetadatafield");
6394  $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
6395  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6396  $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]));
6397  $a_xml_writer->xmlEndTag("qtimetadatafield");
6398  }
6399  // number of tries
6400  $a_xml_writer->xmlStartTag("qtimetadatafield");
6401  $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
6402  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
6403  $a_xml_writer->xmlEndTag("qtimetadatafield");
6404 
6405  // kiosk
6406  $a_xml_writer->xmlStartTag("qtimetadatafield");
6407  $a_xml_writer->xmlElement("fieldlabel", NULL, "kiosk");
6408  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getKiosk()));
6409  $a_xml_writer->xmlEndTag("qtimetadatafield");
6410 
6411 
6412  //redirection_mode
6413  $a_xml_writer->xmlStartTag('qtimetadatafield');
6414  $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_mode");
6415  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionMode());
6416  $a_xml_writer->xmlEndTag("qtimetadatafield");
6417 
6418  //redirection_url
6419  $a_xml_writer->xmlStartTag('qtimetadatafield');
6420  $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_url");
6421  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionUrl());
6422  $a_xml_writer->xmlEndTag("qtimetadatafield");
6423 
6424  // use previous answers
6425  $a_xml_writer->xmlStartTag("qtimetadatafield");
6426  $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
6427  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
6428  $a_xml_writer->xmlEndTag("qtimetadatafield");
6429 
6430  // hide title points
6431  $a_xml_writer->xmlStartTag("qtimetadatafield");
6432  $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
6433  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
6434  $a_xml_writer->xmlEndTag("qtimetadatafield");
6435 
6436  // results presentation
6437  $a_xml_writer->xmlStartTag("qtimetadatafield");
6438  $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
6439  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
6440  $a_xml_writer->xmlEndTag("qtimetadatafield");
6441 
6442  // examid in test pass
6443  $a_xml_writer->xmlStartTag("qtimetadatafield");
6444  $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_pass");
6445  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6446  $a_xml_writer->xmlEndTag("qtimetadatafield");
6447 
6448  // examid in kiosk
6449  $a_xml_writer->xmlStartTag("qtimetadatafield");
6450  $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_res");
6451  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6452  $a_xml_writer->xmlEndTag("qtimetadatafield");
6453 
6454  // solution details
6455  $a_xml_writer->xmlStartTag("qtimetadatafield");
6456  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
6457  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
6458  $a_xml_writer->xmlEndTag("qtimetadatafield");
6459 
6460  // solution details
6461  $a_xml_writer->xmlStartTag("qtimetadatafield");
6462  $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
6463  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
6464  $a_xml_writer->xmlEndTag("qtimetadatafield");
6465 
6466  $a_xml_writer->xmlStartTag("qtimetadatafield");
6467  $a_xml_writer->xmlElement("fieldlabel", NULL, "solution_details");
6468  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails());
6469  $a_xml_writer->xmlEndTag("qtimetadatafield");
6470  $a_xml_writer->xmlStartTag("qtimetadatafield");
6471  $a_xml_writer->xmlElement("fieldlabel", NULL, "print_bs_with_res");
6472  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowSolutionDetails() ? (int)$this->isBestSolutionPrintedWithResult() : 0);
6473  $a_xml_writer->xmlEndTag("qtimetadatafield");
6474 
6475  // solution details
6476  $a_xml_writer->xmlStartTag("qtimetadatafield");
6477  $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
6478  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
6479  $a_xml_writer->xmlEndTag("qtimetadatafield");
6480 
6481  // answer specific feedback
6482  $a_xml_writer->xmlStartTag("qtimetadatafield");
6483  $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
6484  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
6485  $a_xml_writer->xmlEndTag("qtimetadatafield");
6486 
6487  // answer specific feedback of reached points
6488  $a_xml_writer->xmlStartTag("qtimetadatafield");
6489  $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
6490  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
6491  $a_xml_writer->xmlEndTag("qtimetadatafield");
6492 
6493  // highscore
6494  $highscore_metadata = array(
6495  'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6496  'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6497  'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6498  'highscore_score' => array('value' => $this->getHighscoreScore()),
6499  'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6500  'highscore_hints' => array('value' => $this->getHighscoreHints()),
6501  'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6502  'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6503  'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6504  'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6505  );
6506  foreach($highscore_metadata as $label => $data)
6507  {
6508  $a_xml_writer->xmlStartTag("qtimetadatafield");
6509  $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
6510  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $data['value']));
6511  $a_xml_writer->xmlEndTag("qtimetadatafield");
6512  }
6513 
6514  // show cancel
6515  $a_xml_writer->xmlStartTag("qtimetadatafield");
6516  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
6517  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
6518  $a_xml_writer->xmlEndTag("qtimetadatafield");
6519 
6520  // show marker
6521  $a_xml_writer->xmlStartTag("qtimetadatafield");
6522  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
6523  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
6524  $a_xml_writer->xmlEndTag("qtimetadatafield");
6525 
6526  // fixed participants
6527  $a_xml_writer->xmlStartTag("qtimetadatafield");
6528  $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
6529  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
6530  $a_xml_writer->xmlEndTag("qtimetadatafield");
6531 
6532  // show final statement
6533  $a_xml_writer->xmlStartTag("qtimetadatafield");
6534  $a_xml_writer->xmlElement("fieldlabel", NULL, "showfinalstatement");
6535  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6536  $a_xml_writer->xmlEndTag("qtimetadatafield");
6537 
6538  // show introduction only
6539  $a_xml_writer->xmlStartTag("qtimetadatafield");
6540  $a_xml_writer->xmlElement("fieldlabel", NULL, "showinfo");
6541  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6542  $a_xml_writer->xmlEndTag("qtimetadatafield");
6543 
6544  // mail notification
6545  $a_xml_writer->xmlStartTag("qtimetadatafield");
6546  $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnotification");
6547  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotification());
6548  $a_xml_writer->xmlEndTag("qtimetadatafield");
6549 
6550  // mail notification type
6551  $a_xml_writer->xmlStartTag("qtimetadatafield");
6552  $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnottype");
6553  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotificationType());
6554  $a_xml_writer->xmlEndTag("qtimetadatafield");
6555 
6556  // export settings
6557  $a_xml_writer->xmlStartTag("qtimetadatafield");
6558  $a_xml_writer->xmlElement("fieldlabel", NULL, "exportsettings");
6559  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getExportSettings());
6560  $a_xml_writer->xmlEndTag("qtimetadatafield");
6561 
6562  // force JavaScript
6563  $a_xml_writer->xmlStartTag("qtimetadatafield");
6564  $a_xml_writer->xmlElement("fieldlabel", NULL, "forcejs");
6565  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6566  $a_xml_writer->xmlEndTag("qtimetadatafield");
6567 
6568  // custom style
6569  $a_xml_writer->xmlStartTag("qtimetadatafield");
6570  $a_xml_writer->xmlElement("fieldlabel", NULL, "customstyle");
6571  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCustomStyle());
6572  $a_xml_writer->xmlEndTag("qtimetadatafield");
6573 
6574  // shuffle questions
6575  $a_xml_writer->xmlStartTag("qtimetadatafield");
6576  $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
6577  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
6578  $a_xml_writer->xmlEndTag("qtimetadatafield");
6579 
6580  // processing time
6581  $a_xml_writer->xmlStartTag("qtimetadatafield");
6582  $a_xml_writer->xmlElement("fieldlabel", NULL, "processing_time");
6583  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getProcessingTime());
6584  $a_xml_writer->xmlEndTag("qtimetadatafield");
6585 
6586  // enable_examview
6587  $a_xml_writer->xmlStartTag("qtimetadatafield");
6588  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_examview");
6589  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableExamview());
6590  $a_xml_writer->xmlEndTag("qtimetadatafield");
6591 
6592  // show_examview_html
6593  $a_xml_writer->xmlStartTag("qtimetadatafield");
6594  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_html");
6595  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewHtml());
6596  $a_xml_writer->xmlEndTag("qtimetadatafield");
6597 
6598  // show_examview_pdf
6599  $a_xml_writer->xmlStartTag("qtimetadatafield");
6600  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_pdf");
6601  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewPdf());
6602  $a_xml_writer->xmlEndTag("qtimetadatafield");
6603 
6604  // enable_archiving
6605  $a_xml_writer->xmlStartTag("qtimetadatafield");
6606  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_archiving");
6607  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableArchiving());
6608  $a_xml_writer->xmlEndTag("qtimetadatafield");
6609 
6610  // sign_submission
6611  $a_xml_writer->xmlStartTag("qtimetadatafield");
6612  $a_xml_writer->xmlElement("fieldlabel", NULL, "sign_submission");
6613  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSignSubmission());
6614  $a_xml_writer->xmlEndTag("qtimetadatafield");
6615 
6616  // char_selector_availability
6617  $a_xml_writer->xmlStartTag("qtimetadatafield");
6618  $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_availability");
6619  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getCharSelectorAvailability()));
6620  $a_xml_writer->xmlEndTag("qtimetadatafield");
6621 
6622  // char_selector_definition
6623  $a_xml_writer->xmlStartTag("qtimetadatafield");
6624  $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_definition");
6625  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCharSelectorDefinition());
6626  $a_xml_writer->xmlEndTag("qtimetadatafield");
6627 
6628  // skill_service
6629  $a_xml_writer->xmlStartTag("qtimetadatafield");
6630  $a_xml_writer->xmlElement("fieldlabel", NULL, "skill_service");
6631  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isSkillServiceEnabled());
6632  $a_xml_writer->xmlEndTag("qtimetadatafield");
6633 
6634  // result_tax_filters
6635  $a_xml_writer->xmlStartTag("qtimetadatafield");
6636  $a_xml_writer->xmlElement("fieldlabel", NULL, "result_tax_filters");
6637  $a_xml_writer->xmlElement("fieldentry", NULL, serialize((array)$this->getResultFilterTaxIds()));
6638  $a_xml_writer->xmlEndTag("qtimetadatafield");
6639 
6640  // show_grading_status
6641  $a_xml_writer->xmlStartTag("qtimetadatafield");
6642  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_status");
6643  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingStatusEnabled());
6644  $a_xml_writer->xmlEndTag("qtimetadatafield");
6645 
6646  // show_grading_mark
6647  $a_xml_writer->xmlStartTag("qtimetadatafield");
6648  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_grading_mark");
6649  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isShowGradingMarkEnabled());
6650  $a_xml_writer->xmlEndTag("qtimetadatafield");
6651 
6652 
6653  // starting time
6654  if ($this->getStartingTime())
6655  {
6656  $a_xml_writer->xmlStartTag("qtimetadatafield");
6657  $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
6658  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
6659  $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]));
6660  $a_xml_writer->xmlEndTag("qtimetadatafield");
6661  }
6662  // ending time
6663  if ($this->getEndingTime())
6664  {
6665  $a_xml_writer->xmlStartTag("qtimetadatafield");
6666  $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
6667  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
6668  $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]));
6669  $a_xml_writer->xmlEndTag("qtimetadatafield");
6670  }
6671 
6672 
6673  //activation_limited
6674  $a_xml_writer->xmlStartTag("qtimetadatafield");
6675  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_limited");
6676  $a_xml_writer->xmlElement("fieldentry", NULL,(int)$this->isActivationLimited());
6677  $a_xml_writer->xmlEndTag("qtimetadatafield");
6678 
6679  //activation_start_time
6680  $a_xml_writer->xmlStartTag("qtimetadatafield");
6681  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_start_time");
6682  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationStartingTime());
6683  $a_xml_writer->xmlEndTag("qtimetadatafield");
6684 
6685  //activation_end_time
6686  $a_xml_writer->xmlStartTag("qtimetadatafield");
6687  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_end_time");
6688  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationEndingTime());
6689  $a_xml_writer->xmlEndTag("qtimetadatafield");
6690 
6691  //activation_visibility
6692  $a_xml_writer->xmlStartTag("qtimetadatafield");
6693  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_visibility");
6694  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationVisibility());
6695  $a_xml_writer->xmlEndTag("qtimetadatafield");
6696 
6697  // autosave
6698  $a_xml_writer->xmlStartTag("qtimetadatafield");
6699  $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave");
6700  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosave());
6701  $a_xml_writer->xmlEndTag("qtimetadatafield");
6702 
6703  // autosave_ival
6704  $a_xml_writer->xmlStartTag("qtimetadatafield");
6705  $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave_ival");
6706  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosaveIval());
6707  $a_xml_writer->xmlEndTag("qtimetadatafield");
6708 
6709  //offer_question_hints
6710  $a_xml_writer->xmlStartTag("qtimetadatafield");
6711  $a_xml_writer->xmlElement("fieldlabel", NULL, "offer_question_hints");
6712  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isOfferingQuestionHintsEnabled());
6713  $a_xml_writer->xmlEndTag("qtimetadatafield");
6714 
6715  //instant_feedback_specific
6716  $a_xml_writer->xmlStartTag("qtimetadatafield");
6717  $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_specific");
6718  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSpecificAnswerFeedback());
6719  $a_xml_writer->xmlEndTag("qtimetadatafield");
6720 
6721  //instant_feedback_answer_fixation
6722  $a_xml_writer->xmlStartTag("qtimetadatafield");
6723  $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
6724  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isInstantFeedbackAnswerFixationEnabled());
6725  $a_xml_writer->xmlEndTag("qtimetadatafield");
6726 
6727  //obligations_enabled
6728  $a_xml_writer->xmlStartTag("qtimetadatafield");
6729  $a_xml_writer->xmlElement("fieldlabel", NULL, "obligations_enabled");
6730  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->areObligationsEnabled());
6731  $a_xml_writer->xmlEndTag("qtimetadatafield");
6732 
6733  //enable_processing_time
6734  $a_xml_writer->xmlStartTag("qtimetadatafield");
6735  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_processing_time");
6736  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableProcessingTime());
6737  $a_xml_writer->xmlEndTag("qtimetadatafield");
6738 
6739  foreach ($this->mark_schema->mark_steps as $index => $mark)
6740  {
6741  // mark steps
6742  $a_xml_writer->xmlStartTag("qtimetadatafield");
6743  $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
6744  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf(
6745  "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6746  $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()
6747  ));
6748  $a_xml_writer->xmlEndTag("qtimetadatafield");
6749  }
6750  $a_xml_writer->xmlEndTag("qtimetadata");
6751 
6752  // add qti objectives
6753  $a_xml_writer->xmlStartTag("objectives");
6754  $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6755  $a_xml_writer->xmlEndTag("objectives");
6756 
6757  // add qti assessmentcontrol
6758  if ($this->getInstantFeedbackSolution() == 1)
6759  {
6760  $attrs = array(
6761  "solutionswitch" => "Yes"
6762  );
6763  }
6764  else
6765  {
6766  $attrs = NULL;
6767  }
6768  $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
6769 
6770  if (strlen($this->getFinalStatement()))
6771  {
6772  // add qti presentation_material
6773  $a_xml_writer->xmlStartTag("presentation_material");
6774  $a_xml_writer->xmlStartTag("flow_mat");
6775  $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6776  $a_xml_writer->xmlEndTag("flow_mat");
6777  $a_xml_writer->xmlEndTag("presentation_material");
6778  }
6779 
6780  $attrs = array(
6781  "ident" => "1"
6782  );
6783  $a_xml_writer->xmlElement("section", $attrs, NULL);
6784  $a_xml_writer->xmlEndTag("assessment");
6785  $a_xml_writer->xmlEndTag("questestinterop");
6786 
6787  $xml = $a_xml_writer->xmlDumpMem(FALSE);
6788 
6789  foreach ($this->questions as $question_id)
6790  {
6791  $question =& ilObjTest::_instanciateQuestion($question_id);
6792  $qti_question = $question->toXML(false);
6793  $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
6794  $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
6795  if (strpos($xml, "</section>") !== false)
6796  {
6797  $xml = str_replace("</section>", "$qti_question</section>", $xml);
6798  }
6799  else
6800  {
6801  $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
6802  }
6803  }
6804  return $xml;
6805  }
6806 
6813  function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6814  {
6815  global $ilBench;
6816 
6817  $this->mob_ids = array();
6818  $this->file_ids = array();
6819 
6820  $attrs = array();
6821  $attrs["Type"] = "Test";
6822  $a_xml_writer->xmlStartTag("ContentObject", $attrs);
6823 
6824  // MetaData
6825  $this->exportXMLMetaData($a_xml_writer);
6826 
6827  // PageObjects
6828  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
6829  $ilBench->start("ContentObjectExport", "exportPageObjects");
6830  $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6831  $ilBench->stop("ContentObjectExport", "exportPageObjects");
6832  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
6833 
6834  // MediaObjects
6835  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
6836  $ilBench->start("ContentObjectExport", "exportMediaObjects");
6837  $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6838  $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6839  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
6840 
6841  // FileItems
6842  $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
6843  $ilBench->start("ContentObjectExport", "exportFileItems");
6844  $this->exportFileItems($a_target_dir, $expLog);
6845  $ilBench->stop("ContentObjectExport", "exportFileItems");
6846  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
6847 
6848  $a_xml_writer->xmlEndTag("ContentObject");
6849  }
6850 
6857  function exportXMLMetaData(&$a_xml_writer)
6858  {
6859  include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6860  $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6861  $md2xml->setExportMode(true);
6862  $md2xml->startExport();
6863  $a_xml_writer->appendXML($md2xml->getXML());
6864  }
6865 
6871  function modifyExportIdentifier($a_tag, $a_param, $a_value)
6872  {
6873  if ($a_tag == "Identifier" && $a_param == "Entry")
6874  {
6875  include_once "./Services/Utilities/classes/class.ilUtil.php";
6876  $a_value = ilUtil::insertInstIntoID($a_value);
6877  }
6878 
6879  return $a_value;
6880  }
6881 
6882 
6889  function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6890  {
6891  global $ilBench;
6892 
6893  include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6894 
6895  foreach ($this->questions as $question_id)
6896  {
6897  $ilBench->start("ContentObjectExport", "exportPageObject");
6898  $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
6899 
6900  $attrs = array();
6901  $a_xml_writer->xmlStartTag("PageObject", $attrs);
6902 
6903 
6904  // export xml to writer object
6905  $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6906  include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6907  $page_object = new ilAssQuestionPage($question_id);
6908  $page_object->buildDom();
6909  $page_object->insertInstIntoIDs($a_inst);
6910  $mob_ids = $page_object->collectMediaObjects(false);
6911  require_once 'Services/COPage/classes/class.ilPCFileList.php';
6912  $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6913  $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6914  $xml = str_replace("&","&amp;", $xml);
6915  $a_xml_writer->appendXML($xml);
6916  $page_object->freeDom();
6917  unset ($page_object);
6918 
6919  $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6920 
6921  // collect media objects
6922  $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6923  //$mob_ids = $page_obj->getMediaObjectIDs();
6924  foreach($mob_ids as $mob_id)
6925  {
6926  $this->mob_ids[$mob_id] = $mob_id;
6927  }
6928  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6929 
6930  // collect all file items
6931  $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6932  //$file_ids = $page_obj->getFileItemIds();
6933  foreach($file_ids as $file_id)
6934  {
6935  $this->file_ids[$file_id] = $file_id;
6936  }
6937  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6938 
6939  $a_xml_writer->xmlEndTag("PageObject");
6940  //unset($page_obj);
6941 
6942  $ilBench->stop("ContentObjectExport", "exportPageObject");
6943 
6944 
6945  }
6946  }
6947 
6954  function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6955  {
6956  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6957 
6958  foreach ($this->mob_ids as $mob_id)
6959  {
6960  $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
6961  if (ilObjMediaObject::_exists($mob_id))
6962  {
6963  $media_obj = new ilObjMediaObject($mob_id);
6964  $media_obj->exportXML($a_xml_writer, $a_inst);
6965  $media_obj->exportFiles($a_target_dir);
6966  unset($media_obj);
6967  }
6968  }
6969  }
6970 
6975  function exportFileItems($a_target_dir, &$expLog)
6976  {
6977  include_once "./Modules/File/classes/class.ilObjFile.php";
6978 
6979  foreach ($this->file_ids as $file_id)
6980  {
6981  $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
6982  $file_obj = new ilObjFile($file_id, false);
6983  $file_obj->export($a_target_dir);
6984  unset($file_obj);
6985  }
6986  }
6987 
6992  function getImportMapping()
6993  {
6994  if (!is_array($this->import_mapping))
6995  {
6996  return array();
6997  }
6998  else
6999  {
7000  return $this->import_mapping;
7001  }
7002  }
7003 
7007  public function canEditEctsGrades()
7008  {
7009  return $this->getReportingDate();
7010  }
7011 
7015  public function getECTSGrade($passed_array, $reached_points, $max_points)
7016  {
7017  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);
7018  }
7019 
7023  public static function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
7024  {
7025  include_once "./Modules/Test/classes/class.ilStatistics.php";
7026  // calculate the median
7027  $passed_statistics = new ilStatistics();
7028  $passed_statistics->setData($points_passed);
7029  $ects_percentiles = array
7030  (
7031  "A" => $passed_statistics->quantile($a),
7032  "B" => $passed_statistics->quantile($b),
7033  "C" => $passed_statistics->quantile($c),
7034  "D" => $passed_statistics->quantile($d),
7035  "E" => $passed_statistics->quantile($e)
7036  );
7037  if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
7038  {
7039  return "A";
7040  }
7041  else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
7042  {
7043  return "B";
7044  }
7045  else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
7046  {
7047  return "C";
7048  }
7049  else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
7050  {
7051  return "D";
7052  }
7053  else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
7054  {
7055  return "E";
7056  }
7057  else if (strcmp($fx, "") != 0)
7058  {
7059  if ($max_points > 0)
7060  {
7061  $percentage = ($reached_points / $max_points) * 100.0;
7062  if ($percentage < 0) $percentage = 0.0;
7063  }
7064  else
7065  {
7066  $percentage = 0.0;
7067  }
7068  if ($percentage >= $fx)
7069  {
7070  return "FX";
7071  }
7072  else
7073  {
7074  return "F";
7075  }
7076  }
7077  else
7078  {
7079  return "F";
7080  }
7081  }
7082 
7086  public function checkMarks()
7087  {
7088  return $this->mark_schema->checkMarks();
7089  }
7090 
7094  public function getMarkSchema()
7095  {
7096  return $this->mark_schema;
7097  }
7098 
7102  public function getMarkSchemaForeignId()
7103  {
7104  return $this->getTestId();
7105  }
7106 
7109  public function onMarkSchemaSaved()
7110  {
7116  global $ilDB, $ilPluginAdmin, $tree;
7117 
7118  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7119  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7120  $this->saveCompleteStatus($testQuestionSetConfigFactory->getQuestionSetConfig());
7121 
7122  if( $this->participantDataExist() )
7123  {
7124  $this->recalculateScores(true);
7125  }
7126  }
7127 
7131  public function canEditMarks()
7132  {
7133  $total = $this->evalTotalPersons();
7134  if($total > 0)
7135  {
7136  if($this->getReportingDate())
7137  {
7138  if(preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
7139  {
7140  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
7141  $now = mktime();
7142  if($now < $epoch_time)
7143  {
7144  return true;
7145  }
7146  }
7147  }
7148  return false;
7149  }
7150  else
7151  {
7152  return true;
7153  }
7154  }
7155 
7163  function setAuthor($author = "")
7164  {
7165  $this->author = $author;
7166  }
7167 
7177  function saveAuthorToMetadata($a_author = "")
7178  {
7179  $md =& new ilMD($this->getId(), 0, $this->getType());
7180  $md_life =& $md->getLifecycle();
7181  if (!$md_life)
7182  {
7183  if (strlen($a_author) == 0)
7184  {
7185  global $ilUser;
7186  $a_author = $ilUser->getFullname();
7187  }
7188 
7189  $md_life =& $md->addLifecycle();
7190  $md_life->save();
7191  $con =& $md_life->addContribute();
7192  $con->setRole("Author");
7193  $con->save();
7194  $ent =& $con->addEntity();
7195  $ent->setEntity($a_author);
7196  $ent->save();
7197  }
7198  }
7199 
7205  function createMetaData()
7206  {
7207  parent::createMetaData();
7208  $this->saveAuthorToMetadata();
7209  }
7210 
7218  function getAuthor()
7219  {
7220  $author = array();
7221  include_once "./Services/MetaData/classes/class.ilMD.php";
7222  $md =& new ilMD($this->getId(), 0, $this->getType());
7223  $md_life =& $md->getLifecycle();
7224  if ($md_life)
7225  {
7226  $ids =& $md_life->getContributeIds();
7227  foreach ($ids as $id)
7228  {
7229  $md_cont =& $md_life->getContribute($id);
7230  if (strcmp($md_cont->getRole(), "Author") == 0)
7231  {
7232  $entids =& $md_cont->getEntityIds();
7233  foreach ($entids as $entid)
7234  {
7235  $md_ent =& $md_cont->getEntity($entid);
7236  array_push($author, $md_ent->getEntity());
7237  }
7238  }
7239  }
7240  }
7241  return join($author, ",");
7242  }
7243 
7251  function _lookupAuthor($obj_id)
7252  {
7253  $author = array();
7254  include_once "./Services/MetaData/classes/class.ilMD.php";
7255  $md =& new ilMD($obj_id, 0, "tst");
7256  $md_life =& $md->getLifecycle();
7257  if ($md_life)
7258  {
7259  $ids =& $md_life->getContributeIds();
7260  foreach ($ids as $id)
7261  {
7262  $md_cont =& $md_life->getContribute($id);
7263  if (strcmp($md_cont->getRole(), "Author") == 0)
7264  {
7265  $entids =& $md_cont->getEntityIds();
7266  foreach ($entids as $entid)
7267  {
7268  $md_ent =& $md_cont->getEntity($entid);
7269  array_push($author, $md_ent->getEntity());
7270  }
7271  }
7272  }
7273  }
7274  return join($author, ",");
7275  }
7276 
7283  function &_getAvailableTests($use_object_id = FALSE)
7284  {
7285  global $ilUser;
7286  global $ilDB;
7287 
7288  $result_array = array();
7289  $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
7290  if (count($tests))
7291  {
7292  $titles = ilObject::_prepareCloneSelection($tests, "tst");
7293  foreach ($tests as $ref_id)
7294  {
7295  if ($use_object_id)
7296  {
7297  $obj_id = ilObject::_lookupObjId($ref_id);
7298  $result_array[$obj_id] = $titles[$ref_id];
7299  }
7300  else
7301  {
7302  $result_array[$ref_id] = $titles[$ref_id];
7303  }
7304  }
7305  }
7306  return $result_array;
7307  }
7308 
7317  public function cloneObject($a_target_id,$a_copy_id = 0)
7318  {
7319  global $ilLog, $tree, $ilDB, $ilPluginAdmin;
7320 
7321  $this->loadFromDb();
7322 
7323  // Copy settings
7325  $newObj = parent::cloneObject($a_target_id,$a_copy_id);
7326  $this->cloneMetaData($newObj);
7327 
7328  //copy online status if object is not the root copy object
7329  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
7330 
7331  if(!$cp_options->isRootNode($this->getRefId()))
7332  {
7333  $newObj->setOnline($this->isOnline());
7334  }
7335 
7336  $newObj->setAnonymity($this->getAnonymity());
7337  $newObj->setAnswerFeedback($this->getAnswerFeedback());
7338  $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
7339  $newObj->setAuthor($this->getAuthor());
7340  $newObj->setLimitUsersEnabled($this->isLimitUsersEnabled());
7341  $newObj->setAllowedUsers($this->getAllowedUsers());
7342  $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
7343  $newObj->setCountSystem($this->getCountSystem());
7344  $newObj->setECTSFX($this->getECTSFX());
7345  $newObj->setECTSGrades($this->getECTSGrades());
7346  $newObj->setECTSOutput($this->getECTSOutput());
7347  $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
7348  $newObj->setEndingTimeEnabled($this->isEndingTimeEnabled());
7349  $newObj->setEndingTime($this->getEndingTime());
7350  $newObj->setFixedParticipants($this->getFixedParticipants());
7351  $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
7352  $newObj->setIntroductionEnabled($this->isIntroductionEnabled());
7353  $newObj->setIntroduction($this->getIntroduction());
7354  $newObj->setFinalStatement($this->getFinalStatement());
7355  $newObj->setShowInfo($this->getShowInfo());
7356  $newObj->setForceJS($this->getForceJS());
7357  $newObj->setCustomStyle($this->getCustomStyle());
7358  $newObj->setKiosk($this->getKiosk());
7359  $newObj->setShowFinalStatement($this->getShowFinalStatement());
7360  $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
7361  $newObj->setMCScoring($this->getMCScoring());
7362  $newObj->setMailNotification($this->getMailNotification());
7363  $newObj->setMailNotificationType($this->getMailNotificationType());
7364  $newObj->setNrOfTries($this->getNrOfTries());
7365  $newObj->setPassScoring($this->getPassScoring());
7366  $newObj->setPasswordEnabled($this->isPasswordEnabled());
7367  $newObj->setPassword($this->getPassword());
7368  $newObj->setProcessingTime($this->getProcessingTime());
7369  $newObj->setQuestionSetType($this->getQuestionSetType());
7370  $newObj->setReportingDate($this->getReportingDate());
7371  $newObj->setResetProcessingTime($this->getResetProcessingTime());
7372  $newObj->setResultsPresentation($this->getResultsPresentation());
7373  $newObj->setScoreCutting($this->getScoreCutting());
7374  $newObj->setScoreReporting($this->getScoreReporting());
7375  $newObj->setSequenceSettings($this->getSequenceSettings());
7376  $newObj->setShowCancel($this->getShowCancel());
7377  $newObj->setShowMarker($this->getShowMarker());
7378  $newObj->setShuffleQuestions($this->getShuffleQuestions());
7379  $newObj->setStartingTimeEnabled($this->isStartingTimeEnabled());
7380  $newObj->setStartingTime($this->getStartingTime());
7381  $newObj->setTitleOutput($this->getTitleOutput());
7382  $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
7383  $newObj->setRedirectionMode($this->getRedirectionMode());
7384  $newObj->setRedirectionUrl($this->getRedirectionUrl());
7385  $newObj->setCertificateVisibility($this->getCertificateVisibility());
7386  $newObj->mark_schema = clone $this->mark_schema;
7387  $newObj->setEnabledViewMode($this->getEnabledViewMode());
7388  $newObj->setTemplate($this->getTemplate());
7389  $newObj->setPoolUsage($this->getPoolUsage());
7390  $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
7391  $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
7392  $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
7393  $newObj->setEnableExamView($this->getEnableExamview());
7394  $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7395  $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7396  $newObj->setEnableArchiving($this->getEnableArchiving());
7397  $newObj->setSignSubmission($this->getSignSubmission());
7398  $newObj->setCharSelectorAvailability((int)$this->getCharSelectorAvailability());
7399  $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7400  $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
7401  $newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
7402  $newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
7403  $newObj->saveToDb();
7404 
7405  // clone certificate
7406  include_once "./Services/Certificate/classes/class.ilCertificate.php";
7407  include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7408  $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7409  $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7410  $cert->cloneCertificate($newcert);
7411 
7412  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7413  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7414  $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7415 
7416  $newObj->saveToDb();
7417  $newObj->updateMetaData();// #14467
7418 
7419  include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
7420  $obj_settings = new ilLPObjSettings($this->getId());
7421  $obj_settings->cloneSettings($newObj->getId());
7422 
7423  return $newObj;
7424  }
7425 
7432  function getQuestionCount()
7433  {
7434  $num = 0;
7435 
7436  if( $this->isRandomTest() )
7437  {
7438  global $tree, $ilDB, $ilPluginAdmin;
7439 
7440  $questionSetConfig = new ilTestRandomQuestionSetConfig(
7441  $tree, $ilDB, $ilPluginAdmin, $this
7442  );
7443 
7444  $questionSetConfig->loadFromDb();
7445 
7446  if( $questionSetConfig->isQuestionAmountConfigurationModePerPool() )
7447  {
7448  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7449  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7450  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7451 
7452  $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList(
7453  $ilDB, $this, new ilTestRandomQuestionSetSourcePoolDefinitionFactory($ilDB, $this)
7454  );
7455 
7456  $sourcePoolDefinitionList->loadDefinitions();
7457 
7458  $num = $sourcePoolDefinitionList->getQuestionAmount();
7459  }
7460  else
7461  {
7462  $num = $questionSetConfig->getQuestionAmountPerTest();
7463  }
7464  }
7465  else
7466  {
7467  $num = count($this->questions);
7468  }
7469 
7470  return $num;
7471  }
7472 
7480  function logAction($logtext = "", $question_id = "")
7481  {
7482  global $ilUser;
7483 
7484  $original_id = "";
7485  if (strcmp($question_id, "") != 0)
7486  {
7487  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7488  $original_id = assQuestion::_getOriginalId($question_id);
7489  }
7490  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7491  ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
7492  }
7493 
7501  function _getObjectIDFromTestID($test_id)
7502  {
7503  global $ilDB;
7504  $object_id = FALSE;
7505  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7506  array('integer'),
7507  array($test_id)
7508  );
7509  if ($result->numRows())
7510  {
7511  $row = $ilDB->fetchAssoc($result);
7512  $object_id = $row["obj_fi"];
7513  }
7514  return $object_id;
7515  }
7516 
7524  function _getObjectIDFromActiveID($active_id)
7525  {
7526  global $ilDB;
7527  $object_id = FALSE;
7528  $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",
7529  array('integer'),
7530  array($active_id)
7531  );
7532  if ($result->numRows())
7533  {
7534  $row = $ilDB->fetchAssoc($result);
7535  $object_id = $row["obj_fi"];
7536  }
7537  return $object_id;
7538  }
7539 
7547  function _getTestIDFromObjectID($object_id)
7548  {
7549  global $ilDB;
7550  $test_id = FALSE;
7551  $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7552  array('integer'),
7553  array($object_id)
7554  );
7555  if ($result->numRows())
7556  {
7557  $row = $ilDB->fetchAssoc($result);
7558  $test_id = $row["test_id"];
7559  }
7560  return $test_id;
7561  }
7562 
7571  function getTextAnswer($active_id, $question_id, $pass = NULL)
7572  {
7573  global $ilDB;
7574 
7575  $res = "";
7576  if (($active_id) && ($question_id))
7577  {
7578  if (is_null($pass))
7579  {
7580  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7581  $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7582  }
7583  $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7584  array('integer', 'integer', 'integer'),
7585  array($active_id, $question_id, $pass)
7586  );
7587  if ($result->numRows() == 1)
7588  {
7589  $row = $ilDB->fetchAssoc($result);
7590  $res = $row["value1"];
7591  }
7592  }
7593  return $res;
7594  }
7595 
7603  function getQuestiontext($question_id)
7604  {
7605  global $ilDB;
7606 
7607  $res = "";
7608  if ($question_id)
7609  {
7610  $result = $ilDB->queryF("SELECT question_text FROM qpl_questions WHERE question_id = %s",
7611  array('integer'),
7612  array($question_id)
7613  );
7614  if ($result->numRows() == 1)
7615  {
7616  $row = $ilDB->fetchAssoc($result);
7617  $res = $row["question_text"];
7618  }
7619  }
7620  return $res;
7621  }
7622 
7629  function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7630  {
7631  global $ilDB;
7632 
7633  $result_array = array();
7634 
7635  if ($this->getAnonymity())
7636  {
7637  if (is_numeric($user_id))
7638  {
7639  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7640  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7641  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7642  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7643  "ORDER BY $order",
7644  array('text', 'text', 'text', 'integer', 'integer'),
7645  array("", $this->lng->txt("anonymous"), "", $this->getTestId(), $user_id)
7646  );
7647  }
7648  else
7649  {
7650  $result = $ilDB->queryF("SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7651  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7652  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7653  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7654  "ORDER BY $order",
7655  array('text', 'text', 'text', 'integer'),
7656  array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7657  );
7658  }
7659  }
7660  else
7661  {
7662  if (is_numeric($user_id))
7663  {
7664  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7665  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7666  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7667  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7668  "ORDER BY $order",
7669  array('integer', 'integer'),
7670  array($this->getTestId(), $user_id)
7671  );
7672  }
7673  else
7674  {
7675  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7676  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7677  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7678  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7679  "ORDER BY $order",
7680  array('integer'),
7681  array($this->getTestId())
7682  );
7683  }
7684  }
7685  $result_array = array();
7686  while ($row = $ilDB->fetchAssoc($result))
7687  {
7688  $result_array[$row['usr_id']]= $row;
7689  }
7690  return $result_array;
7691  }
7692 
7700  {
7701  global $ilDB;
7702 
7703  if ($this->getAnonymity())
7704  {
7705  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi usr_id, %s login, %s lastname, %s firstname, tst_active.submitted test_finished, usr_data.matriculation, usr_data.active ".
7706  "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),
7707  array('text', 'text', 'text', 'integer'),
7708  array("", $this->lng->txt("anonymous"), "", $this->getTestId())
7709  );
7710  }
7711  else
7712  {
7713  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi usr_id, usr_data.login, usr_data.lastname, usr_data.firstname, tst_active.submitted test_finished, usr_data.matriculation, usr_data.active ".
7714  "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),
7715  array('integer'),
7716  array($this->getTestId())
7717  );
7718  }
7719  $data = array();
7720  while ($row = $ilDB->fetchAssoc($result))
7721  {
7722  $data[$row['active_id']] = $row;
7723  }
7724  foreach ($data as $index => $participant)
7725  {
7726  if (strlen(trim($participant["firstname"].$participant["lastname"])) == 0)
7727  {
7728  $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7729  }
7730  }
7731  return $data;
7732  }
7733 
7734  public function getTestParticipantsForManualScoring($filter = NULL)
7735  {
7736  global $ilDB;
7737 
7738  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7740  if (count($scoring) == 0) return array();
7741 
7742  $participants =& $this->getTestParticipants();
7743  $filtered_participants = array();
7744  foreach ($participants as $active_id => $participant)
7745  {
7746  $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7747 
7748  $queryString = "
7749  SELECT tst_test_result.manual
7750 
7751  FROM tst_test_result
7752 
7753  INNER JOIN qpl_questions
7754  ON tst_test_result.question_fi = qpl_questions.question_id
7755 
7756  WHERE tst_test_result.active_fi = %s
7757  AND $qstType_IN_manScoreableQstTypes
7758  ";
7759 
7760  $result = $ilDB->queryF(
7761  $queryString, array("integer"), array($active_id)
7762  );
7763 
7764  $count = $result->numRows();
7765 
7766  if ($count > 0)
7767  {
7768  switch ($filter)
7769  {
7770  case 1: // only active users
7771  if ($participant->active) $filtered_participants[$active_id] = $participant;
7772  break;
7773  case 2: // only inactive users
7774  if (!$participant->active) $filtered_participants[$active_id] = $participant;
7775  break;
7776  case 3: // all users
7777  $filtered_participants[$active_id] = $participant;
7778  break;
7779  case 4:
7780  // already scored participants
7781  //$found = 0;
7782  //while ($row = $ilDB->fetchAssoc($result))
7783  //{
7784  // if ($row["manual"]) $found++;
7785  //}
7786  //if ($found == $count)
7787  //{
7788  //$filtered_participants[$active_id] = $participant;
7789  //}
7790  //else
7791  //{
7792  $assessmentSetting = new ilSetting("assessment");
7793  $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7794  if ($manscoring_done) $filtered_participants[$active_id] = $participant;
7795  //}
7796  break;
7797  case 5:
7798  // unscored participants
7799  //$found = 0;
7800  //while ($row = $ilDB->fetchAssoc($result))
7801  //{
7802  // if ($row["manual"]) $found++;
7803  //}
7804  //if ($found == 0)
7805  //{
7806  $assessmentSetting = new ilSetting("assessment");
7807  $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7808  if (!$manscoring_done) $filtered_participants[$active_id] = $participant;
7809  //}
7810  break;
7811  case 6:
7812  // partially scored participants
7813  $found = 0;
7814  while ($row = $ilDB->fetchAssoc($result))
7815  {
7816  if ($row["manual"]) $found++;
7817  }
7818  if (($found > 0) && ($found < $count)) $filtered_participants[$active_id] = $participant;
7819  break;
7820  default:
7821  $filtered_participants[$active_id] = $participant;
7822  break;
7823  }
7824  }
7825  }
7826  return $filtered_participants;
7827  }
7828 
7836  function &getUserData($ids)
7837  {
7838  global $ilDB;
7839 
7840  if (!is_array($ids) || count($ids) ==0) return array();
7841 
7842  if ($this->getAnonymity())
7843  {
7844  $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",
7845  array('text', 'text', 'text'),
7846  array("", $this->lng->txt("anonymous"), "")
7847  );
7848  }
7849  else
7850  {
7851  $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");
7852  }
7853 
7854  $result_array = array();
7855  while ($row = $ilDB->fetchAssoc($result))
7856  {
7857  $result_array[$row["usr_id"]]= $row;
7858  }
7859  return $result_array;
7860  }
7861 
7862  function &getGroupData($ids)
7863  {
7864  if (!is_array($ids) || count($ids) ==0) return array();
7865  $result = array();
7866  foreach ($ids as $ref_id)
7867  {
7868  $obj_id = ilObject::_lookupObjId($ref_id);
7869  $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7870  }
7871  return $result;
7872  }
7873 
7874  function &getRoleData($ids)
7875  {
7876  if (!is_array($ids) || count($ids) ==0) return array();
7877  $result = array();
7878  foreach ($ids as $obj_id)
7879  {
7880  $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7881  }
7882  return $result;
7883  }
7884 
7885 
7892  function inviteGroup($group_id)
7893  {
7894  include_once "./Modules/Group/classes/class.ilObjGroup.php";
7895  $group = new ilObjGroup($group_id);
7896  $members = $group->getGroupMemberIds();
7897  include_once './Services/User/classes/class.ilObjUser.php';
7898  foreach ($members as $user_id)
7899  {
7900  $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7901  }
7902  }
7903 
7910  function inviteRole($role_id)
7911  {
7912  global $rbacreview;
7913  $members = $rbacreview->assignedUsers($role_id,"usr_id");
7914  include_once './Services/User/classes/class.ilObjUser.php';
7915  foreach ($members as $user_id)
7916  {
7917  $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7918  }
7919  }
7920 
7921 
7922 
7929  function disinviteUser($user_id)
7930  {
7931  global $ilDB;
7932 
7933  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7934  array('integer', 'integer'),
7935  array($this->getTestId(), $user_id)
7936  );
7937  }
7938 
7945  function inviteUser($user_id, $client_ip="")
7946  {
7947  global $ilDB;
7948 
7949  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7950  array('integer', 'integer'),
7951  array($this->getTestId(), $user_id)
7952  );
7953  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7954  array('integer', 'integer', 'text', 'integer'),
7955  array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : NULL, time())
7956  );
7957  }
7958 
7959 
7960  function setClientIP($user_id, $client_ip)
7961  {
7962  global $ilDB;
7963 
7964  $affectedRows = $ilDB->manipulateF("UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7965  array('text', 'integer', 'integer', 'integer'),
7966  array((strlen($client_ip)) ? $client_ip : NULL, time(), $this->getTestId(), $user_id)
7967  );
7968  }
7969 
7975  function _getSolvedQuestions($active_id, $question_fi = null)
7976  {
7977  global $ilDB;
7978  if (is_numeric($question_fi))
7979  {
7980  $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7981  array('integer', 'integer'),
7982  array($active_id, $question_fi)
7983  );
7984  }
7985  else
7986  {
7987  $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7988  array('integer'),
7989  array($active_id)
7990  );
7991  }
7992  $result_array = array();
7993  while ($row = $ilDB->fetchAssoc($result))
7994  {
7995  $result_array[$row["question_fi"]]= $row;
7996  }
7997  return $result_array;
7998  }
7999 
8000 
8004  function setQuestionSetSolved($value, $question_id, $user_id)
8005  {
8006  global $ilDB;
8007 
8008  $active_id = $this->getActiveIdOfUser($user_id);
8009  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
8010  array('integer', 'integer'),
8011  array($active_id, $question_id)
8012  );
8013  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
8014  array('integer', 'integer', 'integer'),
8015  array($value, $question_id, $active_id)
8016  );
8017  }
8018 
8022  function isTestFinished($active_id)
8023  {
8024  global $ilDB;
8025 
8026  $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
8027  array('integer', 'integer'),
8028  array($active_id, 1)
8029  );
8030  return $result->numRows() == 1;
8031  }
8032 
8036  function isActiveTestSubmitted($user_id = null)
8037  {
8038  global $ilUser;
8039  global $ilDB;
8040 
8041  if (!is_numeric($user_id))
8042  $user_id = $ilUser->getId();
8043 
8044  $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
8045  array('integer', 'integer', 'integer'),
8046  array($this->getTestId(), $user_id, 1)
8047  );
8048  return $result->numRows() == 1;
8049  }
8050 
8055  {
8056  return $this->getNrOfTries() != 0;
8057  }
8058 
8059 
8065  function isNrOfTriesReached($tries)
8066  {
8067  return $tries >= (int) $this->getNrOfTries();
8068  }
8069 
8070 
8079  function getAllTestResults($participants, $prepareForCSV = true)
8080  {
8081  $results = array();
8082  $row = array(
8083  "user_id" => $this->lng->txt("user_id"),
8084  "matriculation" => $this->lng->txt("matriculation"),
8085  "lastname" => $this->lng->txt("lastname"),
8086  "firstname" => $this->lng->txt("firstname"),
8087  "login" =>$this->lng->txt("login"),
8088  "reached_points" => $this->lng->txt("tst_reached_points"),
8089  "max_points" => $this->lng->txt("tst_maximum_points"),
8090  "percent_value" => $this->lng->txt("tst_percent_solved"),
8091  "mark" => $this->lng->txt("tst_mark"),
8092  "ects" => $this->lng->txt("ects_grade")
8093  );
8094  $results[] = $row;
8095  if (count($participants))
8096  {
8097  if($this->getECTSOutput())
8098  {
8099  $passed_array =& $this->getTotalPointsPassedArray();
8100  }
8101  foreach ($participants as $active_id => $user_rec)
8102  {
8103  $row = array();
8104  $reached_points = 0;
8105  $max_points = 0;
8106  foreach ($this->questions as $value)
8107  {
8108  $question =& ilObjTest::_instanciateQuestion($value);
8109  if (is_object($question))
8110  {
8111  $max_points += $question->getMaximumPoints();
8112  $reached_points += $question->getReachedPoints($active_id);
8113  }
8114  }
8115  if ($max_points > 0)
8116  {
8117  $percentvalue = $reached_points / $max_points;
8118  if ($percentvalue < 0) $percentvalue = 0.0;
8119  }
8120  else
8121  {
8122  $percentvalue = 0;
8123  }
8124  $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
8125  $passed = "";
8126  if ($mark_obj)
8127  {
8128  $mark = $mark_obj->getOfficialName();
8129  $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
8130  }
8131  if ($this->getAnonymity())
8132  {
8133  $user_rec['firstname'] = "";
8134  $user_rec['lastname'] = $this->lng->txt("anonymous");
8135  }
8136  $row = array(
8137  "user_id"=>$user_rec['usr_id'],
8138  "matriculation" => $user_rec['matriculation'],
8139  "lastname" => $user_rec['lastname'],
8140  "firstname" => $user_rec['firstname'],
8141  "login"=>$user_rec['login'],
8142  "reached_points" => $reached_points,
8143  "max_points" => $max_points,
8144  "percent_value" => $percentvalue,
8145  "mark" => $mark,
8146  "ects" => $ects_mark
8147  );
8148  $results[] = $prepareForCSV ? $this->processCSVRow ($row, true) : $row;
8149  }
8150  }
8151  return $results;
8152  }
8153 
8164  function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
8165  {
8166  $resultarray = array();
8167  foreach ($row as $rowindex => $entry)
8168  {
8169  $surround = FALSE;
8170  if ($quoteAll)
8171  {
8172  $surround = TRUE;
8173  }
8174  if (strpos($entry, "\"") !== FALSE)
8175  {
8176  $entry = str_replace("\"", "\"\"", $entry);
8177  $surround = TRUE;
8178  }
8179  if (strpos($entry, $separator) !== FALSE)
8180  {
8181  $surround = TRUE;
8182  }
8183  // replace all CR LF with LF (for Excel for Windows compatibility
8184  $entry = str_replace(chr(13).chr(10), chr(10), $entry);
8185 
8186  if ($surround)
8187  {
8188  $entry = "\"" . $entry . "\"";
8189  }
8190 
8191  $resultarray[$rowindex] = $entry;
8192  }
8193  return $resultarray;
8194  }
8195 
8204  function _getPass($active_id)
8205  {
8206  global $ilDB;
8207  $result = $ilDB->queryF("SELECT tries FROM tst_active WHERE active_id = %s",
8208  array('integer'),
8209  array($active_id)
8210  );
8211  if ($result->numRows())
8212  {
8213  $row = $ilDB->fetchAssoc($result);
8214  return $row["tries"];
8215  }
8216  else
8217  {
8218  return 0;
8219  }
8220  }
8221 
8231  function _getMaxPass($active_id)
8232  {
8233  global $ilDB;
8234  $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_pass_result WHERE active_fi = %s",
8235  array('integer'),
8236  array($active_id)
8237  );
8238  if ($result->numRows())
8239  {
8240  $row = $ilDB->fetchAssoc($result);
8241  $max = $row["maxpass"];
8242  }
8243  else
8244  {
8245  $max = NULL;
8246  }
8247  return $max;
8248  }
8249 
8260  function _getBestPass($active_id)
8261  {
8262  global $ilDB;
8263 
8264  $result = $ilDB->queryF("SELECT * FROM tst_pass_result WHERE active_fi = %s",
8265  array('integer'),
8266  array($active_id)
8267  );
8268  if ($result->numRows())
8269  {
8270  $bestrow = null;
8271  $bestfactor = 0;
8272  while ($row = $ilDB->fetchAssoc($result))
8273  {
8274  if($row["maxpoints"] > 0)
8275  {
8276  $factor = $row["points"] / $row["maxpoints"];
8277  }
8278  else
8279  {
8280  $factor = 0;
8281  }
8282 
8283  if($factor > $bestfactor)
8284  {
8285  $bestrow = $row;
8286  $bestfactor = $factor;
8287  }
8288  }
8289  if (is_array($bestrow))
8290  {
8291  return $bestrow["pass"];
8292  }
8293  else
8294  {
8295  return 0;
8296  }
8297  }
8298  else
8299  {
8300  return 0;
8301  }
8302  }
8303 
8312  function _getResultPass($active_id)
8313  {
8314  $counted_pass = NULL;
8315  if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS)
8316  {
8317  $counted_pass = ilObjTest::_getBestPass($active_id);
8318  }
8319  else
8320  {
8321  $counted_pass = ilObjTest::_getMaxPass($active_id);
8322  }
8323  return $counted_pass;
8324  }
8325 
8335  function getAnsweredQuestionCount($active_id, $pass = NULL)
8336  {
8337  if( $this->isDynamicTest() )
8338  {
8339  global $tree, $ilDB, $lng, $ilPluginAdmin;
8340 
8341  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
8342  $testSessionFactory = new ilTestSessionFactory($this);
8343  $testSession = $testSessionFactory->getSession($active_id);
8344 
8345  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
8346  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
8347  $testSequence = $testSequenceFactory->getSequence($testSession);
8348 
8349  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
8350  $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
8351  $dynamicQuestionSetConfig->loadFromDb();
8352 
8353  $testSequence->loadFromDb($dynamicQuestionSetConfig);
8354  $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
8355 
8356  return $testSequence->getTrackedQuestionCount();
8357  }
8358 
8359  if ($this->isRandomTest())
8360  {
8361  $this->loadQuestions($active_id, $pass);
8362  }
8363  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
8364  $workedthrough = 0;
8365  foreach ($this->questions as $value)
8366  {
8367  if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
8368  {
8369  $workedthrough += 1;
8370  }
8371  }
8372  return $workedthrough;
8373  }
8374 
8384  function getPassFinishDate($active_id, $pass)
8385  {
8386  global $ilDB;
8387 
8388  if (is_null($pass))
8389  {
8390  $pass = 0;
8391  }
8392 
8393  $query = "
8394  SELECT tst_pass_result.tstamp pass_res_tstamp,
8395  tst_test_result.tstamp quest_res_tstamp
8396 
8397  FROM tst_pass_result
8398 
8399  LEFT JOIN tst_test_result
8400  ON tst_test_result.active_fi = tst_pass_result.active_fi
8401  AND tst_test_result.pass = tst_pass_result.pass
8402 
8403  WHERE tst_pass_result.active_fi = %s
8404  AND tst_pass_result.pass = %s
8405 
8406  ORDER BY tst_test_result.tstamp DESC
8407  ";
8408 
8409  $result = $ilDB->queryF($query,
8410  array('integer', 'integer'),
8411  array($active_id, $pass)
8412  );
8413 
8414  while( $row = $ilDB->fetchAssoc($result) )
8415  {
8416  if( $row['qres_tstamp'] )
8417  {
8418  return $row['quest_res_tstamp'];
8419  }
8420 
8421  return $row['pass_res_tstamp'];
8422  }
8423 
8424  return 0;
8425  }
8426 
8435  function isExecutable($testSession, $user_id, $allowPassIncrease = FALSE)
8436  {
8437  $result = array(
8438  "executable" => true,
8439  "errormessage" => ""
8440  );
8441  if (!$this->startingTimeReached())
8442  {
8443  $result["executable"] = false;
8444  $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getStartingTime(), IL_CAL_TIMESTAMP)));
8445  return $result;
8446  }
8447  if ($this->endingTimeReached())
8448  {
8449  $result["executable"] = false;
8450  $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilDatePresentation::formatDate(new ilDateTime($this->getEndingTime(), IL_CAL_TIMESTAMP)));
8451  return $result;
8452  }
8453 
8454  $active_id = $this->getActiveIdOfUser($user_id);
8455 
8456  if ($this->getEnableProcessingTime())
8457  {
8458  if ($active_id > 0)
8459  {
8460  $starting_time = $this->getStartingTimeOfUser($active_id);
8461  if ($starting_time !== FALSE)
8462  {
8463  if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8464  {
8465  if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > ($this->_getPass($active_id)+1))))
8466  {
8467  // a test pass was quitted because the maximum processing time was reached, but the time
8468  // will be resetted for future passes, so if there are more passes allowed, the participant may
8469  // start the test again.
8470  // This code block is only called when $allowPassIncrease is TRUE which only happens when
8471  // the test info page is opened. Otherwise this will lead to unexpected results!
8472  $testSession->increasePass();
8473  $testSession->setLastSequence(0);
8474  $testSession->saveToDb();
8475  }
8476  else
8477  {
8478  $result["executable"] = false;
8479  $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8480  }
8481  return $result;
8482  }
8483  }
8484  }
8485  }
8486 
8487  if ($this->hasNrOfTriesRestriction() && ($active_id > 0))
8488  {
8489  require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8490  $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8491  $testPassesSelector->setActiveId($active_id);
8492  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8493 
8494  $closedPasses = $testPassesSelector->getClosedPasses();
8495 
8496  if( count($closedPasses) >= $this->getNrOfTries() )
8497  {
8498  $result["executable"] = false;
8499  $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8500  return $result;
8501  }
8502  }
8503 
8504  return $result;
8505  }
8506 
8513  function canViewResults()
8514  {
8515  $result = true;
8516  if ($this->getScoreReporting() == 4) return false;
8517  if ($this->getReportingDate())
8518  {
8519  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8520  {
8521  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8522  $now = mktime();
8523  if ($now < $epoch_time)
8524  {
8525  $result = false;
8526  }
8527  }
8528  }
8529  return $result;
8530  }
8531 
8532  function canShowTestResults($testSession, $user_id)
8533  {
8534  $active_id = $this->getActiveIdOfUser($user_id);
8535  if ($active_id > 0)
8536  {
8537  $starting_time = $this->getStartingTimeOfUser($active_id);
8538  }
8539  $notimeleft = FALSE;
8540  if ($starting_time !== FALSE)
8541  {
8542  if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8543  {
8544  $notimeleft = TRUE;
8545  }
8546  }
8547  $result = TRUE;
8548  if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
8549  {
8550  $result = FALSE;
8551  }
8552  if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
8553  $result = $result & $this->canViewResults();
8554  return $result;
8555  }
8556 
8564  function getStartingTimeOfUser($active_id, $pass = null)
8565  {
8566  global $ilDB;
8567 
8568  if ($active_id < 1) return FALSE;
8569  if($pass === null)
8570  {
8571  $pass = ($this->getResetProcessingTime()) ? $this->_getPass($active_id) : 0;
8572  }
8573  $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",
8574  array('integer', 'integer'),
8575  array($active_id, $pass)
8576  );
8577  if ($result->numRows())
8578  {
8579  $row = $ilDB->fetchAssoc($result);
8580  if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
8581  {
8582  return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8583  }
8584  else
8585  {
8586  return mktime();
8587  }
8588  }
8589  else
8590  {
8591  return mktime();
8592  }
8593  }
8594 
8604  {
8605  if ($this->getEnableProcessingTime())
8606  {
8607  $processing_time = $this->getProcessingTimeInSeconds($active_id);
8608  $now = mktime();
8609  if ($now > ($starting_time + $processing_time))
8610  {
8611  return TRUE;
8612  }
8613  else
8614  {
8615  return FALSE;
8616  }
8617  }
8618  else
8619  {
8620  return FALSE;
8621  }
8622  }
8623 
8624  function &getTestQuestions()
8625  {
8626  global $ilDB;
8627 
8628  $query = "
8629  SELECT questions.*,
8630  questtypes.type_tag,
8631  tstquest.sequence,
8632  tstquest.obligatory,
8633  origquest.obj_fi orig_obj_fi
8634 
8635  FROM qpl_questions questions
8636 
8637  INNER JOIN qpl_qst_type questtypes
8638  ON questtypes.question_type_id = questions.question_type_fi
8639 
8640  INNER JOIN tst_test_question tstquest
8641  ON tstquest.question_fi = questions.question_id
8642 
8643  LEFT JOIN qpl_questions origquest
8644  ON origquest.question_id = questions.original_id
8645 
8646  WHERE tstquest.test_fi = %s
8647 
8648  ORDER BY tstquest.sequence
8649  ";
8650 
8651  $query_result = $ilDB->queryF(
8652  $query, array('integer'), array($this->getTestId())
8653  );
8654 
8655  $questions = array();
8656 
8657  while ($row = $ilDB->fetchAssoc($query_result))
8658  {
8659  $question = $row;
8660 
8661  $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8662 
8663  $questions[] = $question;
8664  }
8665 
8666  return $questions;
8667  }
8668 
8672  public function getPotentialRandomTestQuestions()
8673  {
8677  global $ilDB;
8678 
8679  $query = "
8680  SELECT questions.*,
8681  questtypes.type_tag,
8682  origquest.obj_fi orig_obj_fi
8683 
8684  FROM qpl_questions questions
8685 
8686  INNER JOIN qpl_qst_type questtypes
8687  ON questtypes.question_type_id = questions.question_type_fi
8688 
8689  INNER JOIN tst_rnd_cpy tstquest
8690  ON tstquest.qst_fi = questions.question_id
8691 
8692  LEFT JOIN qpl_questions origquest
8693  ON origquest.question_id = questions.original_id
8694 
8695  WHERE tstquest.tst_fi = %s
8696  ";
8697 
8698  $query_result = $ilDB->queryF(
8699  $query, array('integer'), array($this->getTestId())
8700  );
8701 
8702  $questions = array();
8703 
8704  while ($row = $ilDB->fetchAssoc($query_result))
8705  {
8706  $question = $row;
8707 
8708  $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8709 
8710  $questions[] = $question;
8711  }
8712 
8713  return $questions;
8714  }
8715 
8723  {
8724  return ($this->shuffle_questions) ? 1 : 0;
8725  }
8726 
8733  function setShuffleQuestions($a_shuffle)
8734  {
8735  $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8736  }
8737 
8751  {
8752  return ($this->show_summary) ? $this->show_summary : 0;
8753  }
8754 
8767  function setListOfQuestionsSettings($a_value = 0)
8768  {
8769  $this->show_summary = $a_value;
8770  }
8771 
8779  {
8780  if (($this->show_summary & 1) > 0)
8781  {
8782  return TRUE;
8783  }
8784  else
8785  {
8786  return FALSE;
8787  }
8788  }
8789 
8796  function setListOfQuestions($a_value = TRUE)
8797  {
8798  if ($a_value)
8799  {
8800  $this->show_summary = 1;
8801  }
8802  else
8803  {
8804  $this->show_summary = 0;
8805  }
8806  }
8807 
8815  {
8816  if (($this->show_summary & 2) > 0)
8817  {
8818  return TRUE;
8819  }
8820  else
8821  {
8822  return FALSE;
8823  }
8824  }
8825 
8832  function setListOfQuestionsStart($a_value = TRUE)
8833  {
8834  if ($a_value && $this->getListOfQuestions())
8835  {
8836  $this->show_summary = $this->show_summary | 2;
8837  }
8838  if (!$a_value && $this->getListOfQuestions())
8839  {
8840  if ($this->getListOfQuestionsStart())
8841  {
8842  $this->show_summary = $this->show_summary ^ 2;
8843  }
8844  }
8845  }
8846 
8854  {
8855  if (($this->show_summary & 4) > 0)
8856  {
8857  return TRUE;
8858  }
8859  else
8860  {
8861  return FALSE;
8862  }
8863  }
8864 
8871  function setListOfQuestionsEnd($a_value = TRUE)
8872  {
8873  if ($a_value && $this->getListOfQuestions())
8874  {
8875  $this->show_summary = $this->show_summary | 4;
8876  }
8877  if (!$a_value && $this->getListOfQuestions())
8878  {
8879  if ($this->getListOfQuestionsEnd())
8880  {
8881  $this->show_summary = $this->show_summary ^ 4;
8882  }
8883  }
8884  }
8885 
8893  {
8894  if (($this->show_summary & 8) > 0)
8895  {
8896  return TRUE;
8897  }
8898  else
8899  {
8900  return FALSE;
8901  }
8902  }
8903 
8910  function setListOfQuestionsDescription($a_value = TRUE)
8911  {
8912  if ($a_value && $this->getListOfQuestions())
8913  {
8914  $this->show_summary = $this->show_summary | 8;
8915  }
8916  if (!$a_value && $this->getListOfQuestions())
8917  {
8918  if ($this->getListOfQuestionsDescription())
8919  {
8920  $this->show_summary = $this->show_summary ^ 8;
8921  }
8922  }
8923  }
8924 
8932  {
8933  return ($this->results_presentation) ? $this->results_presentation : 0;
8934  }
8935 
8943  {
8944  if (($this->results_presentation & 1) > 0)
8945  {
8946  return TRUE;
8947  }
8948  else
8949  {
8950  return FALSE;
8951  }
8952  }
8953 
8961  {
8962  if (($this->results_presentation & 2) > 0)
8963  {
8964  return TRUE;
8965  }
8966  else
8967  {
8968  return FALSE;
8969  }
8970  }
8971 
8979  {
8980  if (($this->results_presentation & 4) > 0)
8981  {
8982  return TRUE;
8983  }
8984  else
8985  {
8986  return FALSE;
8987  }
8988  }
8989 
8997  {
8998  if (($this->results_presentation & 8) > 0)
8999  {
9000  return TRUE;
9001  }
9002  else
9003  {
9004  return FALSE;
9005  }
9006  }
9007 
9015  {
9016  if (($this->results_presentation & 16) > 0)
9017  {
9018  return TRUE;
9019  }
9020  else
9021  {
9022  return FALSE;
9023  }
9024  }
9025 
9033  {
9034  if (($this->results_presentation & 32) > 0)
9035  {
9036  return TRUE;
9037  }
9038  else
9039  {
9040  return FALSE;
9041  }
9042  }
9043 
9049  {
9050  if (($this->results_presentation & 64) > 0)
9051  {
9052  return TRUE;
9053  }
9054  else
9055  {
9056  return FALSE;
9057  }
9058  }
9059 
9065  {
9066  if(($this->results_presentation & 128) > 0)
9067  {
9068  return TRUE;
9069  }
9070  else
9071  {
9072  return FALSE;
9073  }
9074  }
9075 
9082  function setResultsPresentation($a_results_presentation = 3)
9083  {
9084  $this->results_presentation = $a_results_presentation;
9085  }
9086 
9095  function setShowPassDetails($a_details = 1)
9096  {
9097  if ($a_details)
9098  {
9099  $this->results_presentation = $this->results_presentation | 1;
9100  }
9101  else
9102  {
9103  if ($this->getShowPassDetails())
9104  {
9105  $this->results_presentation = $this->results_presentation ^ 1;
9106  }
9107  }
9108  }
9109 
9116  function setShowSolutionDetails($a_details = 1)
9117  {
9118  if ($a_details)
9119  {
9120  $this->results_presentation = $this->results_presentation | 2;
9121  }
9122  else
9123  {
9124  if ($this->getShowSolutionDetails())
9125  {
9126  $this->results_presentation = $this->results_presentation ^ 2;
9127  }
9128  }
9129  }
9130 
9137  function canShowSolutionPrintview($user_id = NULL)
9138  {
9139  return $this->getShowSolutionPrintview();
9140  }
9141 
9148  function setShowSolutionPrintview($a_printview = 1)
9149  {
9150  if ($a_printview)
9151  {
9152  $this->results_presentation = $this->results_presentation | 4;
9153  }
9154  else
9155  {
9156  if ($this->getShowSolutionPrintview())
9157  {
9158  $this->results_presentation = $this->results_presentation ^ 4;
9159  }
9160  }
9161  }
9162 
9169  function setShowSolutionFeedback($a_feedback = TRUE)
9170  {
9171  if ($a_feedback)
9172  {
9173  $this->results_presentation = $this->results_presentation | 8;
9174  }
9175  else
9176  {
9177  if ($this->getShowSolutionFeedback())
9178  {
9179  $this->results_presentation = $this->results_presentation ^ 8;
9180  }
9181  }
9182  }
9183 
9190  function setShowSolutionAnswersOnly($a_full = TRUE)
9191  {
9192  if ($a_full)
9193  {
9194  $this->results_presentation = $this->results_presentation | 16;
9195  }
9196  else
9197  {
9198  if ($this->getShowSolutionAnswersOnly())
9199  {
9200  $this->results_presentation = $this->results_presentation ^ 16;
9201  }
9202  }
9203  }
9204 
9211  function setShowSolutionSignature($a_signature = FALSE)
9212  {
9213  if ($a_signature)
9214  {
9215  $this->results_presentation = $this->results_presentation | 32;
9216  }
9217  else
9218  {
9219  if ($this->getShowSolutionSignature())
9220  {
9221  $this->results_presentation = $this->results_presentation ^ 32;
9222  }
9223  }
9224  }
9225 
9232  function setShowSolutionSuggested($a_solution = FALSE)
9233  {
9234  if ($a_solution)
9235  {
9236  $this->results_presentation = $this->results_presentation | 64;
9237  }
9238  else
9239  {
9240  if ($this->getShowSolutionSuggested())
9241  {
9242  $this->results_presentation = $this->results_presentation ^ 64;
9243  }
9244  }
9245  }
9246 
9252  public function setShowSolutionListComparison($a_comparison = FALSE)
9253  {
9254  if($a_comparison)
9255  {
9256  $this->results_presentation = $this->results_presentation | 128;
9257  }
9258  else
9259  {
9260  if($this->getShowSolutionListComparison())
9261  {
9262  $this->results_presentation = $this->results_presentation ^ 128;
9263  }
9264  }
9265  }
9266 
9270  public static function _getUserIdFromActiveId($active_id)
9271  {
9272  global $ilDB;
9273  $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
9274  array('integer'),
9275  array($active_id)
9276  );
9277  if ($result->numRows())
9278  {
9279  $row = $ilDB->fetchAssoc($result);
9280  return $row["user_fi"];
9281  }
9282  else
9283  {
9284  return -1;
9285  }
9286  }
9287 
9291  public function isLimitUsersEnabled()
9292  {
9293  return $this->limitUsersEnabled;
9294  }
9295 
9300  {
9301  $this->limitUsersEnabled = $limitUsersEnabled;
9302  }
9303 
9304  public function getAllowedUsers()
9305  {
9306  return ($this->allowedUsers) ? $this->allowedUsers : 0;
9307  }
9308 
9309  public function setAllowedUsers($a_allowed_users)
9310  {
9311  $this->allowedUsers = $a_allowed_users;
9312  }
9313 
9314  public function getAllowedUsersTimeGap()
9315  {
9316  return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
9317  }
9318 
9319  public function setAllowedUsersTimeGap($a_allowed_users_time_gap)
9320  {
9321  $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
9322  }
9323 
9325  {
9326  global $ilDB;
9327 
9328  $nr_of_users = $this->getAllowedUsers();
9329  $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
9330  if (($nr_of_users > 0) && ($time_gap > 0))
9331  {
9332  $now = mktime();
9333  $time_border = $now - $time_gap;
9334  $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
9335  $query = "
9336  SELECT DISTINCT tst_times.active_fi
9337  FROM tst_times
9338  INNER JOIN tst_active
9339  ON tst_times.active_fi = tst_active.active_id
9340  AND (
9341  tst_times.pass > tst_active.last_finished_pass OR tst_active.last_finished_pass IS NULL
9342  )
9343  WHERE tst_times.tstamp > %s
9344  AND tst_active.test_fi = %s
9345  ";
9346  $result = $ilDB->queryF($query, array('integer', 'integer'), array($time_border, $this->getTestId()));
9347  if ($result->numRows() >= $nr_of_users)
9348  {
9349  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
9351  {
9352  $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
9353  }
9354  return FALSE;
9355  }
9356  else
9357  {
9358  return TRUE;
9359  }
9360  }
9361  return TRUE;
9362  }
9363 
9364  function _getLastAccess($active_id)
9365  {
9366  global $ilDB;
9367 
9368  $result = $ilDB->queryF("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
9369  array('integer'),
9370  array($active_id)
9371  );
9372  if ($result->numRows())
9373  {
9374  $row = $ilDB->fetchAssoc($result);
9375  return $row["finished"];
9376  }
9377  return "";
9378  }
9379 
9387  function isHTML($a_text)
9388  {
9389  if (preg_match("/<[^>]*?>/", $a_text))
9390  {
9391  return TRUE;
9392  }
9393  else
9394  {
9395  return FALSE;
9396  }
9397  }
9398 
9406  function QTIMaterialToString($a_material)
9407  {
9408  $result = "";
9409  for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
9410  {
9411  $material = $a_material->getMaterial($i);
9412  if (strcmp($material["type"], "mattext") == 0)
9413  {
9414  $result .= $material["material"]->getContent();
9415  }
9416  if (strcmp($material["type"], "matimage") == 0)
9417  {
9418  $matimage = $material["material"];
9419  if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
9420  {
9421  // import an mediaobject which was inserted using tiny mce
9422  if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
9423  array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
9424  }
9425  }
9426  }
9427  global $ilLog;
9428  $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
9429  return $result;
9430  }
9431 
9440  function addQTIMaterial(&$a_xml_writer, $a_material)
9441  {
9442  include_once "./Services/RTE/classes/class.ilRTE.php";
9443  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9444 
9445  $a_xml_writer->xmlStartTag("material");
9446  $attrs = array(
9447  "texttype" => "text/plain"
9448  );
9449  if ($this->isHTML($a_material))
9450  {
9451  $attrs["texttype"] = "text/xhtml";
9452  }
9453  $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9454 
9455  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9456  foreach ($mobs as $mob)
9457  {
9458  $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9459  if (strpos($a_material, "mm_$mob") !== FALSE)
9460  {
9461  if (ilObjMediaObject::_exists($mob))
9462  {
9463  $mob_obj =& new ilObjMediaObject($mob);
9464  $imgattrs = array(
9465  "label" => $moblabel,
9466  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9467  );
9468  }
9469  $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
9470  }
9471  }
9472  $a_xml_writer->xmlEndTag("material");
9473  }
9474 
9481  function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE, $omitNl2BrWhenTextArea = false)
9482  {
9483  include_once "./Services/Utilities/classes/class.ilUtil.php";
9484  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output, $omitNl2BrWhenTextArea);
9485  }
9486 
9493  function saveCertificateVisibility($a_value)
9494  {
9495  global $ilDB;
9496 
9497  $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9498  array('text', 'integer', 'integer'),
9499  array($a_value, time(), $this->getTestId())
9500  );
9501  }
9502 
9510  {
9511  return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9512  }
9513 
9520  function setCertificateVisibility($a_value)
9521  {
9522  $this->certificate_visibility = $a_value;
9523  }
9524 
9531  function getAnonymity()
9532  {
9533  return ($this->anonymity) ? 1 : 0;
9534  }
9535 
9542  function setAnonymity($a_value = 0)
9543  {
9544  switch ($a_value)
9545  {
9546  case 1:
9547  $this->anonymity = 1;
9548  break;
9549  default:
9550  $this->anonymity = 0;
9551  break;
9552  }
9553  }
9554 
9561  function getShowCancel()
9562  {
9563  return ($this->show_cancel) ? 1 : 0;
9564  }
9565 
9572  function setShowCancel($a_value = 1)
9573  {
9574  switch ($a_value)
9575  {
9576  case 1:
9577  $this->show_cancel = 1;
9578  break;
9579  default:
9580  $this->show_cancel = 0;
9581  break;
9582  }
9583  }
9584 
9591  function getShowMarker()
9592  {
9593  return ($this->show_marker) ? 1 : 0;
9594  }
9595 
9602  function setShowMarker($a_value = 1)
9603  {
9604  switch ($a_value)
9605  {
9606  case 1:
9607  $this->show_marker = 1;
9608  break;
9609  default:
9610  $this->show_marker = 0;
9611  break;
9612  }
9613  }
9614 
9622  {
9623  return ($this->fixed_participants) ? 1 : 0;
9624  }
9625 
9632  function setFixedParticipants($a_value = 1)
9633  {
9634  switch ($a_value)
9635  {
9636  case 1:
9637  $this->fixed_participants = 1;
9638  break;
9639  default:
9640  $this->fixed_participants = 0;
9641  break;
9642  }
9643  }
9644 
9652  function _lookupAnonymity($a_obj_id)
9653  {
9654  global $ilDB;
9655 
9656  $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9657  array('integer'),
9658  array($a_obj_id)
9659  );
9660  while($row = $ilDB->fetchAssoc($result))
9661  {
9662  return $row['anonymity'];
9663  }
9664  return 0;
9665  }
9666 
9673  public static function lookupQuestionSetTypeByActiveId($active_id)
9674  {
9675  global $ilDB;
9676 
9677  $query = "
9678  SELECT tst_tests.question_set_type
9679  FROM tst_active
9680  INNER JOIN tst_tests
9681  ON tst_active.test_fi = tst_tests.test_id
9682  WHERE tst_active.active_id = %s
9683  ";
9684 
9685  $res = $ilDB->queryF( $query, array('integer'), array($active_id) );
9686 
9687  while($row = $ilDB->fetchAssoc($res))
9688  {
9689  return $row['question_set_type'];
9690  }
9691 
9692  return null;
9693  }
9694 
9703  function _lookupRandomTestFromActiveId($active_id)
9704  {
9705  throw new Exception(__METHOD__.' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9706 
9707  global $ilDB;
9708 
9709  $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",
9710  array('integer'),
9711  array($active_id)
9712  );
9713  while($row = $ilDB->fetchAssoc($result))
9714  {
9715  return $row['random_test'];
9716  }
9717  return 0;
9718  }
9719 
9730  function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
9731  {
9732  if ($this->getAnonymity() && !$overwrite_anonymity)
9733  {
9734  return $this->lng->txt("anonymous") . $suffix;
9735  }
9736  else
9737  {
9738  include_once './Services/User/classes/class.ilObjUser.php';
9739  $uname = ilObjUser::_lookupName($user_id);
9740  if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
9741  if ($sorted_order)
9742  {
9743  return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9744  }
9745  else
9746  {
9747  return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9748  }
9749  }
9750  }
9751 
9759  function getStartTestLabel($active_id)
9760  {
9761  if ($this->getNrOfTries() == 1)
9762  {
9763  return $this->lng->txt("tst_start_test");
9764  }
9765  $active_pass = $this->_getPass($active_id);
9766  $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9767  if ($res == 0)
9768  {
9769  if ($active_pass == 0)
9770  {
9771  return $this->lng->txt("tst_start_test");
9772  }
9773  else
9774  {
9775  return $this->lng->txt("tst_start_new_test_pass");
9776  }
9777  }
9778  else
9779  {
9780  return $this->lng->txt("tst_resume_test");
9781  }
9782  }
9783 
9789  public function getAvailableDefaults()
9790  {
9795  global $ilDB, $ilUser;
9796 
9797  $result = $ilDB->queryF(
9798  "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9799  array('integer'),
9800  array($ilUser->getId())
9801  );
9802  $defaults = array();
9803  while($row = $ilDB->fetchAssoc($result))
9804  {
9805  $defaults[$row["test_defaults_id"]] = $row;
9806  }
9807  return $defaults;
9808  }
9809 
9817  function &getTestDefaults($test_defaults_id)
9818  {
9819  return self::_getTestDefaults($test_defaults_id);
9820  }
9821 
9822  public static function _getTestDefaults($test_defaults_id)
9823  {
9824  global $ilDB;
9825 
9826  $result = $ilDB->queryF("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9827  array('integer'),
9828  array($test_defaults_id)
9829  );
9830  if ($result->numRows() == 1)
9831  {
9832  $row = $ilDB->fetchAssoc($result);
9833  return $row;
9834  }
9835  else
9836  {
9837  return NULL;
9838  }
9839  }
9840 
9847  function deleteDefaults($test_default_id)
9848  {
9849  global $ilDB;
9850  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9851  array('integer'),
9852  array($test_default_id)
9853  );
9854  }
9855 
9862  function addDefaults($a_name)
9863  {
9864  global $ilDB;
9865  global $ilUser;
9866  $testsettings = array(
9867  "TitleOutput" => $this->getTitleOutput(),
9868  "PassScoring" => $this->getPassScoring(),
9869  "IntroEnabled" => $this->isIntroductionEnabled(),
9870  "Introduction" => $this->getIntroduction(),
9871  "FinalStatement" => $this->getFinalStatement(),
9872  "ShowInfo" => $this->getShowInfo(),
9873  "ForceJS" => $this->getForceJS(),
9874  "CustomStyle" => $this->getCustomStyle(),
9875  "ShowFinalStatement" => $this->getShowFinalStatement(),
9876  "SequenceSettings" => $this->getSequenceSettings(),
9877  "ScoreReporting" => $this->getScoreReporting(),
9878  "ScoreCutting" => $this->getScoreCutting(),
9879  'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9880  'PrintBsWithRes' => (int)$this->isBestSolutionPrintedWithResult(),
9881  "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9882  "AnswerFeedback" => $this->getAnswerFeedback(),
9883  "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9884  "ResultsPresentation" => $this->getResultsPresentation(),
9885  "Anonymity" => $this->getAnonymity(),
9886  "ShowCancel" => $this->getShowCancel(),
9887  "ShowMarker" => $this->getShowMarker(),
9888  "ReportingDate" => $this->getReportingDate(),
9889  "NrOfTries" => $this->getNrOfTries(),
9890  "Shuffle" => $this->getShuffleQuestions(),
9891  "Kiosk" => $this->getKiosk(),
9892  "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9893  "ProcessingTime" => $this->getProcessingTime(),
9894  "EnableProcessingTime" => $this->getEnableProcessingTime(),
9895  "ResetProcessingTime" => $this->getResetProcessingTime(),
9896  "StartingTimeEnabled" => $this->isStartingTimeEnabled(),
9897  "StartingTime" => $this->getStartingTime(),
9898  "EndingTimeEnabled" => $this->isEndingTimeEnabled(),
9899  "EndingTime" => $this->getEndingTime(),
9900  "ECTSOutput" => $this->getECTSOutput(),
9901  "ECTSFX" => $this->getECTSFX(),
9902  "ECTSGrades" => $this->getECTSGrades(),
9903  "questionSetType" => $this->getQuestionSetType(),
9904  "CountSystem" => $this->getCountSystem(),
9905  "MCScoring" => $this->getMCScoring(),
9906  "mailnotification" => $this->getMailNotification(),
9907  "mailnottype" => $this->getMailNotificationType(),
9908  "exportsettings" => $this->getExportSettings(),
9909  "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9910  'obligations_enabled' => (int)$this->areObligationsEnabled(),
9911  'offer_question_hints' => (int)$this->isOfferingQuestionHintsEnabled(),
9912  'pass_deletion_allowed' => (int)$this->isPassDeletionAllowed(),
9913  'enable_examview' => $this->getEnableExamview(),
9914  'show_examview_html' => $this->getShowExamviewHtml(),
9915  'show_examview_pdf' => $this->getShowExamviewPdf(),
9916  'char_selector_availability' => $this->getCharSelectorAvailability(),
9917  'char_selector_definition' => $this->getCharSelectorDefinition(),
9918  'skill_service' => (int)$this->isSkillServiceEnabled(),
9919  'result_tax_filters' => (array)$this->getResultFilterTaxIds(),
9920  'show_grading_status' => (int)$this->isShowGradingStatusEnabled(),
9921  'show_grading_mark' => (int)$this->isShowGradingMarkEnabled(),
9922 
9923  'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
9924  'redirection_mode' => $this->getRedirectionMode(),
9925  'redirection_url' => $this->getRedirectionUrl(),
9926  'sign_submission' => $this->getSignSubmission(),
9927  'autosave' => (int)$this->getAutosave(),
9928  'autosave_ival' => (int)$this->getAutosaveIval(),
9929  'examid_in_test_pass' => (int)$this->isShowExamIdInTestPassEnabled(),
9930  'examid_in_test_res' => (int)$this->isShowExamIdInTestResultsEnabled(),
9931 
9932  'enable_archiving' => (int)$this->getEnableArchiving(),
9933  'password_enabled' => (int)$this->isPasswordEnabled(),
9934  'password' => (string)$this->getPassword(),
9935  'fixed_participants' => $this->getFixedParticipants(),
9936  'limit_users_enabled' => $this->isLimitUsersEnabled(),
9937  'allowedusers' => $this->getAllowedUsers(),
9938  'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9939  'pool_usage' => $this->getPoolUsage(),
9940  'activation_limited' => $this->isActivationLimited(),
9941  'activation_start_time' => $this->getActivationStartingTime(),
9942  'activation_end_time' => $this->getActivationEndingTime(),
9943  'activation_visibility' => $this->getActivationVisibility(),
9944  'highscore_enabled' => $this->getHighscoreEnabled(),
9945  'highscore_anon' => $this->getHighscoreAnon(),
9946  'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9947  'highscore_score' => $this->getHighscoreScore(),
9948  'highscore_percentage' => $this->getHighscorePercentage(),
9949  'highscore_hints' => $this->getHighscoreHints(),
9950  'highscore_wtime' => $this->getHighscoreWTime(),
9951  'highscore_own_table' => $this->getHighscoreOwnTable(),
9952  'highscore_top_table' => $this->getHighscoreTopTable(),
9953  'highscore_top_num' => $this->getHighscoreTopNum(),
9954  'use_previous_answers' => (string)$this->getUsePreviousAnswers()
9955  );
9956 
9957  $next_id = $ilDB->nextId('tst_test_defaults');
9958  $ilDB->insert(
9959  'tst_test_defaults',
9960  array(
9961  'test_defaults_id' => array('integer', $next_id),
9962  'name' => array('text', $a_name),
9963  'user_fi' => array('integer', $ilUser->getId()),
9964  'defaults' => array('clob', serialize($testsettings)),
9965  'marks' => array('clob', serialize($this->mark_schema)),
9966  'tstamp' => array('integer', time())
9967  )
9968  );
9969  }
9970 
9978  public function applyDefaults($test_defaults)
9979  {
9980  $testsettings = unserialize($test_defaults["defaults"]);
9981  include_once "./Modules/Test/classes/class.assMarkSchema.php";
9982  $this->mark_schema = unserialize($test_defaults["marks"]);
9983 
9984  $this->setTitleOutput($testsettings["TitleOutput"]);
9985  $this->setPassScoring($testsettings["PassScoring"]);
9986  $this->setIntroductionEnabled($testsettings["IntroEnabled"]);
9987  $this->setIntroduction($testsettings["Introduction"]);
9988  $this->setFinalStatement($testsettings["FinalStatement"]);
9989  $this->setShowInfo($testsettings["ShowInfo"]);
9990  $this->setForceJS($testsettings["ForceJS"]);
9991  $this->setCustomStyle($testsettings["CustomStyle"]);
9992  $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
9993  $this->setSequenceSettings($testsettings["SequenceSettings"]);
9994  $this->setScoreReporting($testsettings["ScoreReporting"]);
9995  $this->setScoreCutting($testsettings['ScoreCutting']);
9996  $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
9997  $this->setPrintBestSolutionWithResult((bool)$testsettings['PrintBsWithRes']);
9998  $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
9999  $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
10000  $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
10001  $this->setResultsPresentation($testsettings["ResultsPresentation"]);
10002  $this->setAnonymity($testsettings["Anonymity"]);
10003  $this->setShowCancel($testsettings["ShowCancel"]);
10004  $this->setShuffleQuestions($testsettings["Shuffle"]);
10005  $this->setShowMarker($testsettings["ShowMarker"]);
10006  $this->setReportingDate($testsettings["ReportingDate"]);
10007  $this->setNrOfTries($testsettings["NrOfTries"]);
10008  $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
10009  $this->setRedirectionMode($testsettings['redirection_mode']);
10010  $this->setRedirectionUrl($testsettings['redirection_url']);
10011  $this->setProcessingTime($testsettings["ProcessingTime"]);
10012  $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
10013  $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
10014  $this->setStartingTimeEnabled($testsettings["StartingTimeEnabled"]);
10015  $this->setStartingTime($testsettings["StartingTime"]);
10016  $this->setKiosk($testsettings["Kiosk"]);
10017  $this->setEndingTimeEnabled($testsettings["EndingTimeEnabled"]);
10018  $this->setEndingTime($testsettings["EndingTime"]);
10019  $this->setECTSOutput($testsettings["ECTSOutput"]);
10020  $this->setECTSFX($testsettings["ECTSFX"]);
10021  $this->setECTSGrades($testsettings["ECTSGrades"]);
10022  if( isset($testsettings["isRandomTest"]) )
10023  {
10024  if( $testsettings["isRandomTest"] )
10025  {
10026  $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
10027  }
10028  else
10029  {
10030  $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
10031  }
10032  }
10033  elseif( isset($testsettings["questionSetType"]) )
10034  {
10035  $this->setQuestionSetType($testsettings["questionSetType"]);
10036  }
10037  $this->setCountSystem($testsettings["CountSystem"]);
10038  $this->setMCScoring($testsettings["MCScoring"]);
10039  $this->setMailNotification($testsettings["mailnotification"]);
10040  $this->setMailNotificationType($testsettings["mailnottype"]);
10041  $this->setExportSettings($testsettings['exportsettings']);
10042  $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
10043  $this->setObligationsEnabled($testsettings["obligations_enabled"]);
10044  $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
10045  $this->setHighscoreEnabled($testsettings['highscore_enabled']);
10046  $this->setHighscoreAnon($testsettings['highscore_anon']);
10047  $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
10048  $this->setHighscoreScore($testsettings['highscore_score']);
10049  $this->setHighscorePercentage($testsettings['highscore_percentage']);
10050  $this->setHighscoreHints($testsettings['highscore_hints']);
10051  $this->setHighscoreWTime($testsettings['highscore_wtime']);
10052  $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
10053  $this->setHighscoreTopTable($testsettings['highscore_top_table']);
10054  $this->setHighscoreTopNum($testsettings['highscore_top_num']);
10055  $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
10056  if( isset($testsettings['examid_in_kiosk']) )
10057  {
10058  $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
10059  }
10060  else
10061  {
10062  $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
10063  }
10064  if( isset($testsettings['show_exam_id']) )
10065  {
10066  $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
10067  }
10068  else
10069  {
10070  $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
10071  }
10072  $this->setEnableExamview($testsettings['enable_examview']);
10073  $this->setShowExamviewHtml($testsettings['show_examview_html']);
10074  $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
10075  $this->setEnableArchiving($testsettings['enable_archiving']);
10076  $this->setSignSubmission($testsettings['sign_submission']);
10077  $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
10078  $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
10079  $this->setSkillServiceEnabled((bool)$testsettings['skill_service']);
10080  $this->setResultFilterTaxIds((array)$testsettings['result_tax_filters']);
10081  $this->setShowGradingStatusEnabled((bool)$testsettings['show_grading_status']);
10082  $this->setShowGradingMarkEnabled((bool)$testsettings['show_grading_mark']);
10083 
10084  $this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
10085  $this->setRedirectionMode($testsettings['redirection_mode']);
10086  $this->setRedirectionUrl($testsettings['redirection_url']);
10087 
10088  $this->setAutosave($testsettings['autosave']);
10089  $this->setAutosaveIval($testsettings['autosave_ival']);
10090  $this->setShowExamIdInTestResultsEnabled((int)$testsettings['examid_in_test_res']);
10091  $this->setPasswordEnabled($testsettings['password_enabled']);
10092  $this->setPassword($testsettings['password']);
10093  $this->setFixedParticipants($testsettings['fixed_participants'] );
10094  $this->setLimitUsersEnabled($testsettings['limit_users_enabled']);
10095  $this->setAllowedUsers($testsettings['allowedusers']);
10096  $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
10097  $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
10098  $this->setPoolUsage($testsettings['pool_usage']);
10099  $this->setActivationLimited($testsettings['activation_limited']);
10100  $this->setActivationStartingTime($testsettings['activation_start_time']);
10101  $this->setActivationEndingTime($testsettings['activation_end_time']);
10102  $this->setActivationVisibility($testsettings['activation_visibility']);
10103 
10104  $this->saveToDb();
10105 
10106  return true;
10107  }
10108 
10116  function processPrintoutput2FO($print_output)
10117  {
10118  if (extension_loaded("tidy"))
10119  {
10120  $config = array(
10121  "indent" => false,
10122  "output-xml" => true,
10123  "numeric-entities" => true
10124  );
10125  $tidy = new tidy();
10126  $tidy->parseString($print_output, $config, 'utf8');
10127  $tidy->cleanRepair();
10128  $print_output = tidy_get_output($tidy);
10129  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
10130  }
10131  else
10132  {
10133  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
10134  $print_output = str_replace("&otimes;", "X", $print_output);
10135  }
10136  $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
10137 
10138  // additional font support
10139  $xsl = str_replace(
10140  'font-family="Helvetica, unifont"',
10141  'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
10142  $xsl
10143  );
10144 
10145  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
10146  $xh = xslt_create();
10147  $params = array();
10148  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
10149  xslt_error($xh);
10150  xslt_free($xh);
10151  return $output;
10152  }
10153 
10160  public function deliverPDFfromHTML($content, $title = NULL)
10161  {
10162  $content = preg_replace("/href=\".*?\"/", "", $content);
10163  $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", TRUE, TRUE, "Modules/Test");
10164  $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
10165  $printbody->setVariable("ADM_CONTENT", $content);
10166  $printbody->setCurrentBlock("css_file");
10167  $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
10168  $printbody->parseCurrentBlock();
10169  $printbody->setCurrentBlock("css_file");
10170  $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
10171  $printbody->parseCurrentBlock();
10172  $printoutput = $printbody->get();
10173  $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
10174  $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
10175  if (extension_loaded("tidy"))
10176  {
10177  $config = array(
10178  "indent" => false,
10179  "output-xml" => true,
10180  "numeric-entities" => true
10181  );
10182  $tidy = new tidy();
10183  $tidy->parseString($html, $config, 'utf8');
10184  $tidy->cleanRepair();
10185  $html = tidy_get_output($tidy);
10186  $html = preg_replace("/^.*?(<html)/", "\\1", $html);
10187  }
10188  else
10189  {
10190  $html = str_replace("&nbsp;", "&#160;", $html);
10191  $html = str_replace("&otimes;", "X", $html);
10192  }
10193  $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
10194  $this->deliverPDFfromFO($this->processPrintoutput2FO($html), $title);
10195  }
10196 
10203  public function deliverPDFfromFO($fo, $title = null)
10204  {
10205  global $ilLog;
10206 
10207  include_once "./Services/Utilities/classes/class.ilUtil.php";
10208  $fo_file = ilUtil::ilTempnam() . ".fo";
10209  $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
10210 
10211  include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
10212  try
10213  {
10214  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
10215  $filename = (strlen($title)) ? $title : $this->getTitle();
10216  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10217  return true;
10218  }
10219  catch(XML_RPC2_FaultException $e)
10220  {
10221  $ilLog->write(__METHOD__.': '.$e->getMessage());
10222  return false;
10223  }
10224  catch(Exception $e)
10225  {
10226  $ilLog->write(__METHOD__.': '.$e->getMessage());
10227  return false;
10228  }
10229 
10230  /*
10231  include_once "./Services/Transformation/classes/class.ilFO2PDF.php";
10232  $fo2pdf = new ilFO2PDF();
10233  $fo2pdf->setFOString($fo);
10234  $result = $fo2pdf->send();
10235  $filename = (strlen($title)) ? $title : $this->getTitle();
10236  ilUtil::deliverData($result, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
10237  */
10238  }
10239 
10249  static function getManualFeedback($active_id, $question_id, $pass)
10250  {
10251  global $ilDB;
10252  $feedback = "";
10253  $result = $ilDB->queryF("SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10254  array('integer', 'integer', 'integer'),
10255  array($active_id, $question_id, $pass)
10256  );
10257  if ($result->numRows())
10258  {
10259  $row = $ilDB->fetchAssoc($result);
10260  include_once("./Services/RTE/classes/class.ilRTE.php");
10261  $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
10262  }
10263  return $feedback;
10264  }
10265 
10276  function saveManualFeedback($active_id, $question_id, $pass, $feedback)
10277  {
10278  global $ilDB;
10279 
10280  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
10281  array('integer', 'integer', 'integer'),
10282  array($active_id, $question_id, $pass)
10283  );
10284 
10285  if (strlen($feedback))
10286  {
10287  $next_id = $ilDB->nextId('tst_manual_fb');
10289  $result = $ilDB->insert('tst_manual_fb', array(
10290  'manual_feedback_id' => array( 'integer', $next_id ),
10291  'active_fi' => array( 'integer', $active_id ),
10292  'question_fi' => array( 'integer', $question_id ),
10293  'pass' => array( 'integer', $pass),
10294  'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0) ),
10295  'tstamp' => array( 'integer', time() ),
10296  )
10297  );
10298  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
10300  {
10301  global $lng, $ilUser;
10302  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
10303  $username = ilObjTestAccess::_getParticipantData($active_id);
10304  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10305  $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
10306  }
10307  }
10308  if (PEAR::isError($result))
10309  {
10310  global $ilias;
10311  $ilias->raiseError($result->getMessage());
10312  }
10313  else
10314  {
10315  return TRUE;
10316  }
10317  }
10318 
10327  {
10328  return TRUE;
10329 
10330 // global $ilUser;
10331 // if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
10332 // if ($this->getForceJS()) return TRUE;
10333 // $assessmentSetting = new ilSetting("assessment");
10334 // return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
10335  }
10336 
10337  function &createTestSequence($active_id, $pass, $shuffle)
10338  {
10339  include_once "./Modules/Test/classes/class.ilTestSequence.php";
10340  $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10341  }
10342 
10348  public function setTestId($a_id)
10349  {
10350  $this->test_id = $a_id;
10351  }
10352 
10361  function getDetailedTestResults($participants)
10362  {
10363  $results = array();
10364  if (count($participants))
10365  {
10366  foreach ($participants as $active_id => $user_rec)
10367  {
10368  $row = array();
10369  $reached_points = 0;
10370  $max_points = 0;
10371  foreach ($this->questions as $value)
10372  {
10373  $question =& ilObjTest::_instanciateQuestion($value);
10374  if (is_object($question))
10375  {
10376  $max_points += $question->getMaximumPoints();
10377  $reached_points += $question->getReachedPoints($active_id);
10378  if ($max_points > 0)
10379  {
10380  $percentvalue = $reached_points / $max_points;
10381  if ($percentvalue < 0) $percentvalue = 0.0;
10382  }
10383  else
10384  {
10385  $percentvalue = 0;
10386  }
10387  if ($this->getAnonymity())
10388  {
10389  $user_rec['firstname'] = "";
10390  $user_rec['lastname'] = $this->lng->txt("anonymous");
10391  }
10392  $row = array(
10393  "user_id"=>$user_rec['usr_id'],
10394  "matriculation" => $user_rec['matriculation'],
10395  "lastname" => $user_rec['lastname'],
10396  "firstname" => $user_rec['firstname'],
10397  "login"=>$user_rec['login'],
10398  "question_id" => $question->getId(),
10399  "question_title" => $question->getTitle(),
10400  "reached_points" => $reached_points,
10401  "max_points" => $max_points
10402  );
10403  $results[] = $row;
10404  }
10405  }
10406  }
10407  }
10408  return $results;
10409  }
10410 
10415  {
10416  global $ilDB;
10417 
10418  $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",
10419  array('integer'),
10420  array($a_q_id)
10421  );
10422  $rec = $ilDB->fetchAssoc($result);
10423  return $rec["obj_id"];
10424  }
10425 
10432  function isPluginActive($a_pname)
10433  {
10434  global $ilPluginAdmin;
10435  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname))
10436  {
10437  return TRUE;
10438  }
10439  else
10440  {
10441  return FALSE;
10442  }
10443  }
10444 
10445  public function getPassed($active_id)
10446  {
10447  global $ilDB;
10448 
10449  $result = $ilDB->queryF("SELECT passed FROM tst_result_cache WHERE active_fi = %s",
10450  array('integer'),
10451  array($active_id)
10452  );
10453  if ($result->numRows())
10454  {
10455  $row = $ilDB->fetchAssoc($result);
10456  return $row['passed'];
10457  }
10458  else
10459  {
10460  $counted_pass = ilObjTest::_getResultPass($active_id);
10461  $result_array =& $this->getTestResult($active_id, $counted_pass);
10462  return $result_array["test"]["passed"];
10463  }
10464  }
10465 
10471  function canShowCertificate($testSession, $user_id, $active_id)
10472  {
10473  if ($this->canShowTestResults($testSession, $user_id))
10474  {
10475  include_once "./Services/Certificate/classes/class.ilCertificate.php";
10476  include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
10477  $cert = new ilCertificate(new ilTestCertificateAdapter($this));
10478  if ($cert->isComplete())
10479  {
10480  $vis = $this->getCertificateVisibility();
10481  $showcert = FALSE;
10482  switch ($vis)
10483  {
10484  case 0:
10485  $showcert = TRUE;
10486  break;
10487  case 1:
10488  if ($this->getPassed($active_id))
10489  {
10490  $showcert = TRUE;
10491  }
10492  break;
10493  case 2:
10494  $showcert = FALSE;
10495  break;
10496  }
10497  if ($showcert)
10498  {
10499  return TRUE;
10500  }
10501  else
10502  {
10503  return FALSE;
10504  }
10505  }
10506  else
10507  {
10508  return FALSE;
10509  }
10510  }
10511  else
10512  {
10513  return FALSE;
10514  }
10515  }
10516 
10520  public function getParticipantsForTestAndQuestion($test_id, $question_id)
10521  {
10523  global $ilDB;
10524 
10525  $query = "
10526  SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10527  FROM tst_test_result, tst_active, qpl_questions
10528  WHERE tst_active.active_id = tst_test_result.active_fi
10529  AND tst_active.test_fi = %s
10530  AND tst_test_result.question_fi = qpl_questions.question_id
10531  AND tst_test_result.question_fi = %s";
10532 
10533  $result = $ilDB->queryF($query,
10534  array('integer', 'integer'),
10535  array($test_id, $question_id)
10536  );
10537  $foundusers = array();
10539  while ($row = $ilDB->fetchAssoc($result))
10540  {
10541  if (!array_key_exists($row["active_fi"], $foundusers))
10542  {
10543  $foundusers[$row["active_fi"]] = array();
10544  }
10545  array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10546  }
10547  return $foundusers;
10548  }
10549 
10555  public function getAggregatedResultsData()
10556  {
10557  $data =& $this->getCompleteEvaluationData();
10558  $foundParticipants =& $data->getParticipants();
10559  $results = array("overview" => array(), "questions" => array());
10560  if (count($foundParticipants))
10561  {
10562  $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10563  $total_finished = $this->evalTotalFinished();
10564  $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10565  $average_time = $this->evalTotalStartedAverageTime();
10566  $diff_seconds = $average_time;
10567  $diff_hours = floor($diff_seconds/3600);
10568  $diff_seconds -= $diff_hours * 3600;
10569  $diff_minutes = floor($diff_seconds/60);
10570  $diff_seconds -= $diff_minutes * 60;
10571  $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10572  $total_passed = 0;
10573  $total_passed_reached = 0;
10574  $total_passed_max = 0;
10575  $total_passed_time = 0;
10576  foreach ($foundParticipants as $userdata)
10577  {
10578  if ($userdata->getPassed())
10579  {
10580  $total_passed++;
10581  $total_passed_reached += $userdata->getReached();
10582  $total_passed_max += $userdata->getMaxpoints();
10583  $total_passed_time += $userdata->getTimeOfWork();
10584  }
10585  }
10586  $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10587  $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10588  $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10589  $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10590  $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);
10591  $average_time = $average_passed_time;
10592  $diff_seconds = $average_time;
10593  $diff_hours = floor($diff_seconds/3600);
10594  $diff_seconds -= $diff_hours * 3600;
10595  $diff_minutes = floor($diff_seconds/60);
10596  $diff_seconds -= $diff_minutes * 60;
10597  $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10598  }
10599 
10600  foreach ($data->getQuestionTitles() as $question_id => $question_title)
10601  {
10602  $answered = 0;
10603  $reached = 0;
10604  $max = 0;
10605  foreach ($foundParticipants as $userdata)
10606  {
10607  for ($i = 0; $i <= $userdata->getLastPass(); $i++)
10608  {
10609  if (is_object($userdata->getPass($i)))
10610  {
10611  $question =& $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10612  if (is_array($question))
10613  {
10614  $answered++;
10615  $reached += $question["reached"];
10616  $max += $question["points"];
10617  }
10618  }
10619  }
10620  }
10621  $percent = $max ? $reached/$max * 100.0 : 0;
10622  $counter++;
10623  $results["questions"][$question_id] = array(
10624  $question_title,
10625  sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10626  sprintf("%.2f", $percent) . "%",
10627  $answered,
10628  sprintf("%.2f", $answered ? $reached / $answered : 0),
10629  sprintf("%.2f", $answered ? $max / $answered : 0),
10630  $percent / 100.0
10631  );
10632  }
10633  return $results;
10634  }
10635 
10639  function getXMLZip()
10640  {
10641  include_once("./Modules/Test/classes/class.ilTestExport.php");
10642  $test_exp = new ilTestExport($this, "xml");
10643  return $test_exp->buildExportFile();
10644  }
10645 
10649  public function getMailNotification()
10650  {
10651  return $this->mailnotification;
10652  }
10653 
10659  public function setMailNotification($a_notification)
10660  {
10661  $this->mailnotification = $a_notification;
10662  }
10663 
10664  public function sendSimpleNotification($active_id)
10665  {
10666  include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10667 
10668  $mail = new ilTestMailNotification();
10669  $owner_id = $this->getOwner();
10670  $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10671  $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10672  }
10673 
10680  {
10681  include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10682  include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10683  $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(), 'outEvaluation', $this->getAnonymity());
10684  return $table_gui->getSelectedColumns();
10685  }
10686 
10687  public function sendAdvancedNotification($active_id)
10688  {
10689  include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10690 
10691  $mail = new ilTestMailNotification();
10692  $owner_id = $this->getOwner();
10693  $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10694 
10695  include_once "./Modules/Test/classes/class.ilTestExport.php";
10696  $exportObj = new ilTestExport($this, "results");
10697  $file = $exportObj->exportToExcel($deliver = FALSE, 'active_id', $active_id, $passedonly = FALSE);
10698  include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10699  $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10700  $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10701  $file_names[] = "result_" . $active_id . ".xls";
10702 
10703  $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10704 
10705  if(count($file_names))
10706  {
10707  $fd->unlinkFiles($file_names);
10708  unset($fd);
10709  @unlink($file);
10710  }
10711  }
10712 
10713  function createRandomSolutions($number)
10714  {
10715  global $ilDB;
10716 
10717  // 1. get a user
10718  $query = "SELECT usr_id FROM usr_data";
10719  $result = $ilDB->query($query);
10720  while ($data = $ilDB->fetchAssoc($result))
10721  {
10722  $activequery = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10723  $ilDB->quote($this->getTestId()),
10724  $ilDB->quote($data['usr_id'])
10725  );
10726  $activeresult = $ilDB->query($activequery);
10727  if ($activeresult->numRows() == 0)
10728  {
10729  $user_id = $data['usr_id'];
10730  if ($user_id != 13)
10731  {
10732  include_once "./Modules/Test/classes/class.ilTestSession.php";
10733  $testSession = FALSE;
10734  $testSession = new ilTestSession();
10735  $testSession->setRefId($this->getRefId());
10736  $testSession->setTestId($this->getTestId());
10737  $testSession->setUserId($user_id);
10738  $testSession->saveToDb();
10739  $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10740  $nr_of_passes = rand(1, $passes);
10741  $active_id = $testSession->getActiveId();
10742  for ($pass = 0; $pass < $nr_of_passes; $pass++)
10743  {
10744  include_once "./Modules/Test/classes/class.ilTestSequence.php";
10745  $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10746  if (!$testSequence->hasSequence())
10747  {
10748  $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10749  $testSequence->saveToDb();
10750  }
10751  for ($seq = 1; $seq <= count($this->questions); $seq++)
10752  {
10753  $question_id = $testSequence->getQuestionForSequence($seq);
10754  $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10755  $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10756  }
10757  if ($pass < $nr_of_passes - 1)
10758  {
10759  $testSession->increasePass();
10760  $testSession->setLastSequence(0);
10761  $testSession->saveToDb();
10762  }
10763  else
10764  {
10765  $testSession->setSubmitted(1);
10766  $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10767  $testSession->saveToDb();
10768  }
10769  }
10770  $number--;
10771  if ($number == 0) return;
10772  }
10773  }
10774  }
10775  }
10776 
10777  public function getResultsForActiveId($active_id)
10778  {
10779  global $ilDB;
10780 
10781  $query = "
10782  SELECT *
10783  FROM tst_result_cache
10784  WHERE active_fi = %s
10785  ";
10786 
10787  $result = $ilDB->queryF(
10788  $query, array('integer'), array($active_id)
10789  );
10790 
10791  if( !$result->numRows() )
10792  {
10793  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10794 
10796 
10797  $query = "
10798  SELECT *
10799  FROM tst_result_cache
10800  WHERE active_fi = %s
10801  ";
10802 
10803  $result = $ilDB->queryF(
10804  $query, array('integer'), array($active_id)
10805  );
10806  }
10807 
10808  $row = $ilDB->fetchAssoc($result);
10809 
10810  return $row;
10811 
10812  }
10813 
10814  public function getMailNotificationType()
10815  {
10816  if ($this->mailnottype == 1)
10817  {
10818  return $this->mailnottype;
10819  }
10820  else
10821  {
10822  return 0;
10823  }
10824  }
10825 
10826  public function setMailNotificationType($a_type)
10827  {
10828  if ($a_type == 1)
10829  {
10830  $this->mailnottype = 1;
10831  }
10832  else
10833  {
10834  $this->mailnottype = 0;
10835  }
10836  }
10837 
10838  public function getExportSettings()
10839  {
10840  if ($this->exportsettings)
10841  {
10842  return $this->exportsettings;
10843  }
10844  else
10845  {
10846  return 0;
10847  }
10848  }
10849 
10850  public function setExportSettings($a_settings)
10851  {
10852  if ($a_settings)
10853  {
10854  $this->exportsettings = $a_settings;
10855  }
10856  else
10857  {
10858  $this->exportsettings = 0;
10859  }
10860  }
10861 
10863  {
10864  if (($this->exportsettings & 1) > 0)
10865  {
10866  return true;
10867  }
10868  else
10869  {
10870  return false;
10871  }
10872  }
10873 
10874  public function setExportSettingsSingleChoiceShort($a_settings)
10875  {
10876  if ($a_settings)
10877  {
10878  $this->exportsettings = $this->exportsettings | 1;
10879  }
10880  else
10881  {
10883  {
10884  $this->exportsettings = $this->exportsettings ^ 1;
10885  }
10886  }
10887  }
10888 
10889  public function getEnabledViewMode() {
10890  return $this->enabled_view_mode;
10891  }
10892 
10893  public function setEnabledViewMode($mode) {
10894  $this->enabled_view_mode = $mode;
10895  }
10896 
10898  $this->template_id = (int)$template_id;
10899  }
10900 
10901  function getTemplate() {
10902  return $this->template_id;
10903  }
10904 
10905  public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
10906  $new_array = array();
10907  $position = 1;
10908 
10909  $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10910  $types = array('integer');
10911  $values = array($this->getTestId());
10912 
10913  $new_question_id += 1;
10914 
10915  global $ilDB;
10916  $inserted = false;
10917  $res = $ilDB->queryF($query, $types, $values);
10918  while($row = $ilDB->fetchAssoc($res)) {
10919 
10920  $qid = $row['question_fi'];
10921 
10922  if ($qid == $new_question_id) {
10923  continue;
10924  }
10925  else if ($qid == $previous_question_id) {
10926  $new_array[$position++] = $qid;
10927  $new_array[$position++] = $new_question_id;
10928  $inserted = true;
10929  }
10930  else {
10931  $new_array[$position++] = $qid;
10932  }
10933  }
10934 
10935  $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10936  $update_types = array('integer', 'integer', 'integer');
10937 
10938  foreach($new_array as $position => $qid) {
10939  $ilDB->manipulateF(
10940  $update_query,
10941  $update_types,
10942  $vals = array(
10943  $position,
10944  $this->getTestId(),
10945  $qid
10946  )
10947  );
10948  }
10949  }
10950 
10952  {
10953  if (is_array($options))
10954  {
10955  $this->setGenericAnswerFeedback( in_array('instant_feedback_generic', $options) ? 1 : 0);
10956  $this->setSpecificAnswerFeedback( in_array('instant_feedback_specific', $options) ? 1 : 0);
10957  $this->setAnswerFeedbackPoints( in_array('instant_feedback_points', $options) ? 1 : 0);
10958  $this->setInstantFeedbackSolution( in_array('instant_feedback_solution', $options) ? 1 : 0);
10959  $this->setInstantFeedbackAnswerFixationEnabled( in_array('instant_feedback_answer_fixation', $options) ? true : false);
10960  }
10961  else
10962  {
10963  $this->setGenericAnswerFeedback(0);
10964  $this->setSpecificAnswerFeedback(0);
10965  $this->setAnswerFeedbackPoints(0);
10966  $this->setInstantFeedbackSolution(0);
10968  }
10969  }
10970 
10972  $setter = array(
10973  'pass_details' => 'setShowPassDetails',
10974  'solution_details' => 'setShowSolutionDetails',
10975  'solution_printview' => 'setShowSolutionPrintview',
10976  'solution_feedback' => 'setShowSolutionFeedback',
10977  'solution_answers_only' => 'setShowSolutionAnswersOnly',
10978  'solution_signature' => 'setShowSolutionSignature',
10979  'solution_suggested' => 'setShowSolutionSuggested',
10980  );
10981  foreach($setter as $key => $setter) {
10982  if (in_array($key, $options)) {
10983  $this->$setter(1);
10984  }
10985  else {
10986  $this->$setter(0);
10987  }
10988  }
10989  }
10990 
10991  public function getPoolUsage() {
10992  return (boolean) $this->poolUsage;
10993  }
10994 
10995  public function setPoolUsage($usage) {
10996  $this->poolUsage = (boolean)$usage;
10997  }
10998 
10999  public function setQuestionOrderAndObligations($orders, $obligations)
11000  {
11001  global $ilDB;
11002 
11003  asort($orders);
11004 
11005  $i = 0;
11006 
11007  foreach($orders as $id => $position)
11008  {
11009  $i++;
11010 
11011  $obligatory = (
11012  isset($obligations[$id]) && $obligations[$id] ? 1 : 0
11013  );
11014 
11015  $query = "
11016  UPDATE tst_test_question
11017  SET sequence = %s,
11018  obligatory = %s
11019  WHERE question_fi = %s
11020  ";
11021 
11022  $ilDB->manipulateF(
11023  $query, array('integer', 'integer', 'integer'), array($i, $obligatory, $id)
11024  );
11025  }
11026 
11027  $this->loadQuestions();
11028  }
11029 
11030  public function moveQuestionAfter($question_to_move, $question_before) {
11031  global $ilDB;
11032  //var_dump(func_get_args());
11033  if ($question_before) {
11034  $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
11035  $types = array('integer');
11036  $values = array($question_before);
11037  $rset = $ilDB->queryF($query, $types, $values);
11038  }
11039 
11040  if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
11041  $row = array(
11042  'sequence' => 0,
11043  'test_fi' => $this->getTestId(),
11044  );
11045  }
11046 
11047  $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
11048  $types = array('integer', 'integer');
11049  $values = array($row['sequence'], $row['test_fi']);
11050  $ilDB->manipulateF($update, $types, $values);
11051 
11052  $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
11053  $types = array('integer', 'integer');
11054  $values = array($row['sequence'] + 1, $question_to_move);
11055  $ilDB->manipulateF($update, $types, $values);
11056 
11057  }
11058 
11060  {
11061  global $ilDB;
11062 
11063  $questions = $this->getQuestionTitlesAndIndexes();
11064 
11065  $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
11066 
11067  $query = "
11068  SELECT count(q1.question_id) cnt
11069 
11070  FROM qpl_questions q1
11071 
11072  INNER JOIN qpl_questions q2
11073  ON q2.question_id = q1.original_id
11074 
11075  WHERE $IN_questions
11076  AND q1.obj_fi = q2.obj_fi
11077  ";
11078 
11079  $rset = $ilDB->query($query);
11080 
11081  $row = $ilDB->fetchAssoc($rset);
11082 
11083  return $row['cnt'] > 0;
11084  }
11085 
11092  public static function _lookupFinishedUserTests($a_user_id)
11093  {
11094  global $ilDB;
11095 
11096  $result = $ilDB->queryF("SELECT test_fi,MAX(pass) AS pass FROM tst_active".
11097  " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)".
11098  " WHERE user_fi=%s".
11099  " GROUP BY test_fi",
11100  array('integer', 'integer'),
11101  array($a_user_id, 1)
11102  );
11103  $all = array();
11104  while($row = $ilDB->fetchAssoc($result))
11105  {
11106  $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
11107  $all[$obj_id] = (bool)$row["pass"];
11108  }
11109  return $all;
11110  }
11111  public function getQuestions()
11112  {
11113  return $this->questions;
11114  }
11115 
11116  public function isOnline()
11117  {
11118  return $this->online;
11119  }
11120 
11121  public function setOnline($a_online = true)
11122  {
11123  $this->online = (bool)$a_online;
11124  }
11125 
11126  public function setPrintBestSolutionWithResult($status)
11127  {
11128  $this->print_best_solution_with_result = (bool) $status;
11129  }
11130 
11132  {
11134  }
11135 
11142  {
11144  }
11145 
11152  {
11153  $this->offeringQuestionHintsEnabled = (bool)$offeringQuestionHintsEnabled;
11154  }
11155 
11156  function setActivationVisibility($a_value)
11157  {
11158  $this->activation_visibility = (bool) $a_value;
11159  }
11160 
11162  {
11164  }
11165 
11167  {
11168  return (bool)$this->activation_limited;
11169  }
11170 
11171  function setActivationLimited($a_value)
11172  {
11173  $this->activation_limited = (bool)$a_value;
11174  }
11175 
11176  /* GET/SET for highscore feature */
11177 
11183  public function setHighscoreEnabled($a_enabled)
11184  {
11185  $this->_highscore_enabled = (bool)$a_enabled;
11186  }
11187 
11193  public function getHighscoreEnabled()
11194  {
11195  return (bool) $this->_highscore_enabled;
11196  }
11197 
11205  public function setHighscoreAnon($a_anon)
11206  {
11207  $this->_highscore_anon = (bool)$a_anon;
11208  }
11209 
11219  public function getHighscoreAnon()
11220  {
11221  return (bool) $this->_highscore_anon;
11222  }
11223 
11232  public function isHighscoreAnon()
11233  {
11234  if ($this->getAnonymity() == 1)
11235  {
11236  return true;
11237  }
11238  else
11239  {
11240  return (bool)$this->getHighscoreAnon();
11241  }
11242  }
11243 
11249  public function setHighscoreAchievedTS($a_achieved_ts)
11250  {
11251  $this->_highscore_achieved_ts = (bool)$a_achieved_ts;
11252  }
11253 
11259  public function getHighscoreAchievedTS()
11260  {
11261  return (bool) $this->_highscore_achieved_ts;
11262  }
11263 
11269  public function setHighscoreScore($a_score)
11270  {
11271  $this->_highscore_score = (bool)$a_score;
11272  }
11273 
11279  public function getHighscoreScore()
11280  {
11281  return (bool) $this->_highscore_score;
11282  }
11283 
11289  public function setHighscorePercentage($a_percentage)
11290  {
11291  $this->_highscore_percentage = (bool)$a_percentage;
11292  }
11293 
11299  public function getHighscorePercentage()
11300  {
11301  return (bool) $this->_highscore_percentage;
11302  }
11303 
11309  public function setHighscoreHints($a_hints)
11310  {
11311  $this->_highscore_hints = (bool)$a_hints;
11312  }
11313 
11319  public function getHighscoreHints()
11320  {
11321  return (bool) $this->_highscore_hints;
11322  }
11323 
11329  public function setHighscoreWTime($a_wtime)
11330  {
11331  $this->_highscore_wtime = (bool)$a_wtime;
11332  }
11333 
11339  public function getHighscoreWTime()
11340  {
11341  return (bool) $this->_highscore_wtime;
11342  }
11343 
11349  public function setHighscoreOwnTable($a_own_table)
11350  {
11351  $this->_highscore_own_table = (bool)$a_own_table;
11352  }
11353 
11359  public function getHighscoreOwnTable()
11360  {
11361  return (bool) $this->_highscore_own_table;
11362  }
11363 
11369  public function setHighscoreTopTable($a_top_table)
11370  {
11371  $this->_highscore_top_table = (bool)$a_top_table;
11372  }
11373 
11379  public function getHighscoreTopTable()
11380  {
11381  return (bool) $this->_highscore_top_table;
11382  }
11383 
11390  public function setHighscoreTopNum($a_top_num)
11391  {
11392  $this->_highscore_top_num = (int)$a_top_num;
11393  }
11394 
11403  public function getHighscoreTopNum($a_retval = 10)
11404  {
11405  $retval = $a_retval;
11406  if ( (int) $this->_highscore_top_num != 0)
11407  {
11408  $retval = $this->_highscore_top_num;
11409  }
11410 
11411  return $retval;
11412  }
11413 
11417  public function getHighscoreMode()
11418  {
11419  switch(true)
11420  {
11421  case $this->getHighscoreOwnTable() && $this->getHighscoreTopTable():
11422  return self::HIGHSCORE_SHOW_ALL_TABLES;
11423  break;
11424 
11425  case $this->getHighscoreTopTable():
11426  return self::HIGHSCORE_SHOW_TOP_TABLE;
11427  break;
11428 
11429  case $this->getHighscoreOwnTable():
11430  default:
11431  return self::HIGHSCORE_SHOW_OWN_TABLE;
11432  break;
11433  }
11434  }
11435 
11439  public function setHighscoreMode($mode)
11440  {
11441  switch($mode)
11442  {
11443  case self::HIGHSCORE_SHOW_ALL_TABLES:
11444  $this->setHighscoreTopTable(1);
11445  $this->setHighscoreOwnTable(1);
11446  break;
11447 
11448  case self::HIGHSCORE_SHOW_TOP_TABLE:
11449  $this->setHighscoreTopTable(1);
11450  $this->setHighscoreOwnTable(0);
11451  break;
11452 
11453  case self::HIGHSCORE_SHOW_OWN_TABLE:
11454  default:
11455  $this->setHighscoreTopTable(0);
11456  $this->setHighscoreOwnTable(1);
11457  break;
11458  }
11459  }
11460  /* End GET/SET for highscore feature*/
11461 
11462  public function setSpecificAnswerFeedback($specific_answer_feedback)
11463  {
11464  switch ($specific_answer_feedback)
11465  {
11466  case 1:
11467  $this->specific_answer_feedback = 1;
11468  break;
11469  default:
11470  $this->specific_answer_feedback = 0;
11471  break;
11472  }
11473  }
11474 
11475  public function getSpecificAnswerFeedback()
11476  {
11477  switch ($this->specific_answer_feedback)
11478  {
11479  case 1:
11480  return 1;
11481  default:
11482  return 0;
11483  }
11484  }
11485 
11492  {
11493  $this->obligationsEnabled = (bool)$obligationsEnabled;
11494  }
11495 
11501  public function areObligationsEnabled()
11502  {
11503  return (bool)$this->obligationsEnabled;
11504  }
11505 
11512  public static function isQuestionObligationPossible($questionId)
11513  {
11514  require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11515 
11516  $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11517 
11518  assQuestion::_includeClass($classConcreteQuestion, 0);
11519 
11520  // static binder is not at work yet (in PHP < 5.3)
11521  //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11522  $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11523 
11524  return $obligationPossible;
11525  }
11526 
11533  public static function isQuestionObligatory($question_id)
11534  {
11535  global $ilDB;
11536 
11537  $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11538 
11539  if( $row = $ilDB->fetchAssoc($rset) )
11540  {
11541  return (bool) $row['obligatory'];
11542  }
11543 
11544  return false;
11545  }
11546 
11559  public static function allObligationsAnswered($test_id, $active_id, $pass)
11560  {
11561  global $ilDB;
11562 
11563  $rset = $ilDB->queryF(
11564  'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11565  array('integer', 'integer'),
11566  array($active_id, $pass)
11567  );
11568 
11569  if( $row = $ilDB->fetchAssoc($rset) )
11570  {
11571  return (bool)$row['obligations_answered'];
11572  }
11573 
11574  return !self::hasObligations($test_id);
11575  }
11576 
11585  public static function hasObligations($test_id)
11586  {
11587  global $ilDB;
11588 
11589  $rset = $ilDB->queryF(
11590  'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11591  array('integer'), array($test_id)
11592  );
11593 
11594  $row = $ilDB->fetchAssoc($rset);
11595 
11596  return (bool)$row['cnt'] > 0;
11597  }
11598 
11599  public function setAutosave($autosave)
11600  {
11601  $this->autosave = $autosave;
11602  }
11603 
11604  public function getAutosave()
11605  {
11606  return $this->autosave;
11607  }
11608 
11610  {
11611  $this->autosave_ival = $autosave_ival;
11612  }
11613 
11614  public function getAutosaveIval()
11615  {
11616  return $this->autosave_ival;
11617  }
11618 
11624  public function isPassDeletionAllowed()
11625  {
11627  }
11628 
11635  {
11636  $this->passDeletionAllowed = (bool)$passDeletionAllowed;
11637  }
11638 
11639  #region Examview / PDF Examview
11640 
11644  {
11645  $this->show_examview_html = $show_examview_html;
11646  }
11647 
11651  public function getShowExamviewHtml()
11652  {
11654  }
11655 
11660  {
11661  $this->show_examview_pdf = $show_examview_pdf;
11662  }
11663 
11667  public function getShowExamviewPdf()
11668  {
11669  return $this->show_examview_pdf;
11670  }
11671 
11676  {
11677  $this->enable_examview = $enable_examview;
11678  }
11679 
11683  public function getEnableExamview()
11684  {
11685  return $this->enable_examview;
11686  }
11687 
11688  #endregion
11689 
11691  {
11692  $this->activation_starting_time = $starting_time;
11693  }
11694 
11696  {
11697  $this->activation_ending_time = $ending_time;
11698  }
11699 
11701  {
11702  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
11703  }
11704 
11706  {
11707  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
11708  }
11709 
11711  {
11712  global $ilDB;
11713 
11714  $times = array();
11715  $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");
11716  while ($row = $ilDB->fetchAssoc($result))
11717  {
11718  $times[$row['active_fi']] = $row['started'];
11719  }
11720  return $times;
11721  }
11722 
11724  {
11725  global $ilDB;
11726 
11727  $times = array();
11728  $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",
11729  array('integer'),
11730  array($this->getTestId())
11731  );
11732  while ($row = $ilDB->fetchAssoc($result))
11733  {
11734  $times[$row['active_fi']] = $row['additionaltime'];
11735  }
11736  return $times;
11737  }
11738 
11739  public function getExtraTime($active_id)
11740  {
11741  global $ilDB;
11742 
11743  $result = $ilDB->queryF("SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11744  array('integer'),
11745  array($active_id)
11746  );
11747  if ($result->numRows() > 0)
11748  {
11749  $row = $ilDB->fetchAssoc($result);
11750  return $row['additionaltime'];
11751  }
11752  return 0;
11753  }
11754 
11755  public function addExtraTime($active_id, $minutes)
11756  {
11757  global $ilDB;
11758 
11759  $participants = array();
11760  if ($active_id == 0)
11761  {
11762  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
11763  array('integer'),
11764  array($this->getTestId())
11765  );
11766  while ($row = $ilDB->fetchAssoc($result))
11767  {
11768  array_push($participants, $row['active_id']);
11769  }
11770  }
11771  else
11772  {
11773  array_push($participants, $active_id);
11774  }
11775  foreach ($participants as $active_id)
11776  {
11777  $result = $ilDB->queryF("SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11778  array('integer'),
11779  array($active_id)
11780  );
11781  if ($result->numRows() > 0)
11782  {
11783  $ilDB->manipulateF("DELETE FROM tst_addtime WHERE active_fi = %s",
11784  array('integer'),
11785  array($active_id)
11786  );
11787  }
11788 
11789  $ilDB->manipulateF("UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11790  array('integer','integer','timestamp','integer'),
11791  array(0, 0, NULL, $active_id)
11792  );
11793 
11794  $ilDB->manipulateF("INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11795  array('integer','integer','integer'),
11796  array($active_id, $minutes, time())
11797  );
11798 
11799  require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11801  {
11802  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11803  }
11804  }
11805  }
11806 
11813  {
11814  $this->enable_archiving = $enable_archiving;
11815  return $this;
11816  }
11817 
11821  public function getEnableArchiving()
11822  {
11823  return $this->enable_archiving;
11824  }
11825 
11826  public function getMaxPassOfTest()
11827  {
11831  global $ilDB;
11832 
11833  $query = '
11834  SELECT MAX(tst_pass_result.pass) + 1 max_res
11835  FROM tst_pass_result
11836  INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11837  WHERE test_fi = '.$ilDB->quote($this->getTestId(), 'integer').'
11838  ';
11839  $res = $ilDB->query($query);
11840  $data = $ilDB->fetchAssoc($res);
11841  return (int)$data['max_res'];
11842  }
11843 
11849  public function lookupExamId($active_id, $pass)
11850  {
11852  global $ilDB, $ilSetting;
11853 
11854  $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11855  $exam_id_result = $ilDB->queryF( $exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ) );
11856  if ($ilDB->numRows( $exam_id_result ) == 1)
11857  {
11858  $exam_id_row = $ilDB->fetchAssoc( $exam_id_result );
11859 
11860  if ($exam_id_row['exam_id'] != null)
11861  {
11862  return $exam_id_row['exam_id'];
11863  }
11864  }
11865 
11866  return null;
11867  }
11868 
11875  public static function buildExamId($active_id, $pass, $test_obj_id = null)
11876  {
11878  global $ilSetting;
11879 
11880  $inst_id = $ilSetting->get( 'inst_id', null );
11881 
11882  if($test_obj_id === null)
11883  {
11884  $obj_id = self::_getObjectIDFromActiveID($active_id);
11885  }
11886  else
11887  {
11888  $obj_id = $test_obj_id;
11889  }
11890 
11891  $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11892 
11893  return $examId;
11894  }
11895 
11897  {
11898  $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11899  }
11900 
11902  {
11904  }
11905 
11910  {
11911  $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11912  }
11913 
11918  {
11920  }
11921 
11926  {
11927  $this->sign_submission = $sign_submission;
11928  }
11929 
11933  public function getSignSubmission()
11934  {
11935  return $this->sign_submission;
11936  }
11937 
11941  public function setCharSelectorAvailability($availability)
11942  {
11943  $this->char_selector_availability = (int) $availability;
11944  }
11945 
11950  {
11951  return (int) $this->char_selector_availability;
11952  }
11953 
11957  public function setCharSelectorDefinition($definition = '')
11958  {
11959  $this->char_selector_definition = $definition;
11960  }
11961 
11965  public function getCharSelectorDefinition()
11966  {
11968  }
11969 
11970 
11977  {
11978  $this->questionSetType = $questionSetType;
11979  }
11980 
11986  public function getQuestionSetType()
11987  {
11988  return $this->questionSetType;
11989  }
11990 
11998  public static function lookupQuestionSetType($objId)
11999  {
12000  global $ilDB;
12001 
12002  $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
12003 
12004  $res = $ilDB->queryF($query, array('integer'), array($objId));
12005 
12006  $questionSetType = null;
12007 
12008  while( $row = $ilDB->fetchAssoc($res) )
12009  {
12010  $questionSetType = $row['question_set_type'];
12011  }
12012 
12013  return $questionSetType;
12014  }
12015 
12021  public function isFixedTest()
12022  {
12023  return $this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED;
12024  }
12025 
12031  public function isRandomTest()
12032  {
12033  return $this->getQuestionSetType() == self::QUESTION_SET_TYPE_RANDOM;
12034  }
12035 
12041  public function isDynamicTest()
12042  {
12043  return $this->getQuestionSetType() == self::QUESTION_SET_TYPE_DYNAMIC;
12044  }
12045 
12053  public static function _lookupRandomTest($a_obj_id)
12054  {
12055  return self::lookupQuestionSetType($a_obj_id) == self::QUESTION_SET_TYPE_RANDOM;
12056  }
12057 
12059  {
12060  switch( $questionSetType )
12061  {
12063  return $lng->txt('tst_question_set_type_fixed');
12064 
12066  return $lng->txt('tst_question_set_type_random');
12067 
12069  return $lng->txt('tst_question_set_type_dynamic');
12070  }
12071 
12072  throw new ilTestException('invalid question set type value given: '.$questionSetType);
12073  }
12074 
12075  public function participantDataExist()
12076  {
12077  if( $this->participantDataExist === null )
12078  {
12079  $this->participantDataExist = (bool)$this->evalTotalPersons();
12080  }
12081 
12083  }
12084 
12085  public function isScoreReportingAvailable()
12086  {
12087  if ($this->getScoreReporting() == 4)
12088  {
12089  return false;
12090  }
12091 
12092  if ($this->getScoreReporting() == 3 && $this->getReportingDate() > time())
12093  {
12094  return false;
12095  }
12096 
12097  return true;
12098  }
12099 
12100  public function recalculateScores($preserve_manscoring = false)
12101  {
12102  require_once 'class.ilTestScoring.php';
12103  $scoring = new ilTestScoring($this);
12104  $scoring->setPreserveManualScores($preserve_manscoring);
12105  $scoring->recalculateSolutions();
12106  }
12107 
12108  public static function getPoolQuestionChangeListeners(ilDB $db, $poolObjId)
12109  {
12110  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
12111 
12112  $questionChangeListeners = array(
12114  );
12115 
12116  return $questionChangeListeners;
12117  }
12118 
12119  public static function getTestObjIdsWithActiveForUserId($userId)
12120  {
12121  global $ilDB;
12122 
12123  $query = "
12124  SELECT obj_fi
12125  FROM tst_active
12126  INNER JOIN tst_tests
12127  ON test_id = test_fi
12128  WHERE user_fi = %s
12129  ";
12130 
12131  $res = $ilDB->queryF($query, array('integer'), array($userId));
12132 
12133  $objIds = array();
12134 
12135  while( $row = $ilDB->fetchAssoc($res) )
12136  {
12137  $objIds[] = (int)$row['obj_fi'];
12138  }
12139 
12140  return $objIds;
12141  }
12142 
12144  {
12145  $this->skillServiceEnabled = $skillServiceEnabled;
12146  }
12147 
12148  public function isSkillServiceEnabled()
12149  {
12151  }
12152 
12154  {
12155  $this->resultFilterTaxIds = $resultFilterTaxIds;
12156  }
12157 
12158  public function getResultFilterTaxIds()
12159  {
12161  }
12162 
12164  {
12165  if( !$this->isSkillServiceEnabled() )
12166  {
12167  return false;
12168  }
12169 
12170  if( !self::isSkillManagementGloballyActivated() )
12171  {
12172  return false;
12173  }
12174 
12175  return true;
12176  }
12177 
12179 
12180  public static function isSkillManagementGloballyActivated()
12181  {
12182  if( self::$isSkillManagementGloballyActivated === null )
12183  {
12184  include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
12185  $skmgSet = new ilSkillManagementSettings();
12186 
12187  self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
12188  }
12189 
12190  return self::$isSkillManagementGloballyActivated;
12191  }
12192 
12194  {
12195  $this->showGradingStatusEnabled = $showGradingStatusEnabled;
12196  }
12197 
12198  public function isShowGradingStatusEnabled()
12199  {
12201  }
12202 
12204  {
12205  $this->showGradingMarkEnabled = $showGradingMarkEnabled;
12206  }
12207 
12208 
12209  public function isShowGradingMarkEnabled()
12210  {
12212  }
12213 
12215  {
12216  $this->instantFeedbackAnswerFixationEnabled = $instantFeedbackAnswerFixationEnabled;
12217  }
12218 
12220  {
12222  }
12223 
12224  public static function ensureParticipantsLastActivePassFinished($testObjId, $userId, $a_force_new_run = FALSE)
12225  {
12226  global $ilDB, $lng, $ilPluginAdmin;
12227 
12228  /* @var ilObjTest $testOBJ */
12229 
12230  $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12231 
12232  $activeId = $testOBJ->getActiveIdOfUser($userId);
12233 
12234  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12235  $testSessionFactory = new ilTestSessionFactory($testOBJ);
12236 
12237  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12238  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12239 
12240  $testSession = $testSessionFactory->getSession($activeId);
12241  $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $testSession->getPass());
12242  $testSequence->loadFromDb();
12243 
12244  // begin-patch lok changed smeyer
12245  if($a_force_new_run)
12246  {
12247  if( $testSequence->hasSequence() )
12248  {
12249  $testSession->increasePass();
12250  }
12251  $testSession->setLastSequence(0);
12252  $testSession->saveToDb();
12253  }
12254  // end-patch lok
12255  }
12256 
12257  public static function isParticipantsLastPassActive($testObjId, $userId)
12258  {
12259  global $ilDB, $lng, $ilPluginAdmin;
12260 
12261  /* @var ilObjTest $testOBJ */
12262 
12263  $testOBJ = ilObjectFactory::getInstanceByRefId($testObjId,false);
12264 
12265 
12266  $activeId = $testOBJ->getActiveIdOfUser($userId);
12267 
12268  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
12269  $testSessionFactory = new ilTestSessionFactory($testOBJ);
12270  // Added temporarily bugfix smeyer
12271  $testSessionFactory->reset();
12272 
12273  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
12274  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $testOBJ);
12275 
12276  $testSession = $testSessionFactory->getSession($activeId);
12277  $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $testSession->getPass());
12278  $testSequence->loadFromDb();
12279 
12280  return $testSequence->hasSequence();
12281  }
12282 
12286  public function isTestFinalBroken()
12287  {
12288  return $this->testFinalBroken;
12289  }
12290 
12295  {
12296  $this->testFinalBroken = $testFinalBroken;
12297  }
12298 }
< a tabindex="-1" style="border-style: none;" href="#" title="Refresh Image" onclick="document.getElementById('siimage').src = './securimage_show.php?sid=' + Math.random(); this.blur(); return false">< img src="./images/refresh.png" alt="Reload Image" height="32" width="32" onclick="this.blur()" align="bottom" border="0"/></a >< br/>< strong > Enter Code *if($_SERVER['REQUEST_METHOD']=='POST' &&@ $_POST['do']=='contact') $_SESSION['ctform']['success']
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)
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.
& 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.
_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.
removeAllTestEditings($question_id="")
Removes all references to the question in executed tests in case the question has been changed...
& 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.
loadFromDb()
loads the question set config for current test from the database
setResultFilterTaxIds($resultFilterTaxIds)
& _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
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.
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.
canShowTestResults($testSession, $user_id)
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.
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.
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
$GLOBALS['ct_recipient']
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.
_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.
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.
removeTestResultsForUser($user_id)
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()
static isParticipantsLastPassActive($testObjId, $userId)
deleteRequestsByQuestionIds($questionIds)
Deletes all hint requests relating to a question included in given question ids.
_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.
setEnableProcessingTime($enable=0)
Sets the processing time enabled or disabled.
_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.
static ilTempnam()
Create a temporary file in an ILIAS writable directory.
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
& getTestResult($active_id, $pass=NULL, $ordered_sequence=FALSE)
Calculates the results of a test for a given user and returns an array with all test results...
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
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.
& 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
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.
read($a_force_db=false)
read object data from db into object
setSequenceSettings($sequence_settings=0)
SEQUENCE SETTING = POSTPONING ENABLED !!
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)
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.