ILIAS  release_4-4 Revision
All Data Structures Namespaces Files Functions Variables Modules Pages
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 include_once "./Services/Object/classes/class.ilObject.php";
5 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
6 
17 class ilObjTest extends ilObject
18 {
19  #region Properties
20 
24  const QUESTION_SET_TYPE_FIXED = 'FIXED_QUEST_SET';
25 
29  const QUESTION_SET_TYPE_RANDOM = 'RANDOM_QUEST_SET';
30 
34  const QUESTION_SET_TYPE_DYNAMIC = 'DYNAMIC_QUEST_SET';
35 
41  private $questionSetType = self::QUESTION_SET_TYPE_FIXED;
42 
50  protected $_kiosk;
51 
57  var $test_id;
58 
65 
72  var $author;
73 
79  var $metadata;
80 
87 
95 
102 
111 
122 
131 
138 
148 
155 
163 
171 
181 
188 
195 
202 
209 
216 
223 
229  var $ects_fx;
230 
237 
238 
246 
253 
260 
268 
275 
282 
289 
296 
303 
310 
317 
324 
331 
338 
345 
352 
359 
366 
373 
380 
386  private $_showinfo;
387 
393  private $_forcejs;
394 
400  private $_customStyle;
401 
402  protected $mailnotification;
403 
404  protected $mailnottype;
405 
406  protected $exportsettings;
407 
408  protected $poolUsage;
409 
410  private $template_id;
411 
417  private $online = null;
418 
423 
430 
436  private $obligationsEnabled = null;
437 
439 
441 
443 
444  protected $autosave;
445 
446  protected $autosave_ival;
447 
454  private $passDeletionAllowed = null;
455 
461  private $participantDataExist = null;
462 
464  protected $enable_examview;
465 
468 
471 
473  protected $enable_archiving;
474 
478  private $redirection_mode = 0;
479 
483  private $redirection_url = NULL;
484 
487 
490 
492  protected $sign_submission;
493 
496 
499 
503  protected $testFinalBroken;
504 
505  #endregion
506 
515  public function __construct($a_id = 0,$a_call_by_reference = true)
516  {
517  global $ilUser, $lng;
518  $this->type = "tst";
519 
520  $lng->loadLanguageModule("assessment");
521  // Defaults:
522  include_once "./Modules/Test/classes/class.assMarkSchema.php";
523  $this->mark_schema = new ASS_MarkSchema();
524  $this->mark_schema->createSimpleSchema(
525  $lng->txt("failed_short"),
526  $lng->txt("failed_official"),
527  0,
528  0,
529  $lng->txt("passed_short"),
530  $lng->txt("passed_official"),
531  50,
532  1
533  );
534 
535  $this->test_id = -1;
536  $this->author = $ilUser->fullname;
537  $this->introduction = "";
538  $this->questions = array();
539  $this->sequence_settings = TEST_FIXED_SEQUENCE;
540  $this->score_reporting = REPORT_AFTER_TEST;
541  $this->instant_verification = 0;
542  $this->answer_feedback_points = 0;
543  $this->reporting_date = "";
544  $this->nr_of_tries = 0;
545  $this->_kiosk = 0;
546  $this->use_previous_answers = 1;
547  $this->title_output = 0;
548  $this->starting_time = "";
549  $this->ending_time = "";
550  $this->processing_time = "00:00:00";
551  $this->enable_processing_time = "0";
552  $this->reset_processing_time = 0;
553  $this->ects_output = 0;
554  $this->ects_fx = NULL;
555  $this->shuffle_questions = FALSE;
556  $this->mailnottype = 0;
557  $this->exportsettings = 0;
558  $this->show_summary = 8;
559  $this->count_system = COUNT_PARTIAL_SOLUTIONS;
560  $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
561  $this->score_cutting = SCORE_CUT_QUESTION;
562  $this->pass_scoring = SCORE_LAST_PASS;
563  $this->answer_feedback = 0;
564  $this->password = "";
565  $this->certificate_visibility = 0;
566  $this->allowedUsers = "";
567  $this->_showfinalstatement = FALSE;
568  $this->_finalstatement = "";
569  $this->_showinfo = TRUE;
570  $this->_forcejs = FALSE;
571  $this->_customStyle = "";
572  $this->allowedUsersTimeGap = "";
573  $this->anonymity = 0;
574  $this->show_cancel = 0;
575  $this->show_marker = 0;
576  $this->fixed_participants = 0;
577  $this->setShowPassDetails(TRUE);
578  $this->setShowSolutionDetails(TRUE);
579  $this->setShowSolutionAnswersOnly(FALSE);
580  $this->setShowSolutionSignature(FALSE);
581  $this->testSession = FALSE;
582  $this->testSequence = FALSE;
583  $this->mailnotification = 0;
584  $this->poolUsage = 1;
585 
586  $this->ects_grades = array(
587  "A" => 90,
588  "B" => 65,
589  "C" => 35,
590  "D" => 10,
591  "E" => 0
592  );
593 
594  $this->autosave = FALSE;
595  $this->autosave_ival = 30000;
596 
597  $this->enable_examview = false;
598  $this->show_examview_html = false;
599  $this->show_examview_pdf = false;
600  $this->enable_archiving = false;
601 
602  $this->express_mode = false;
603  $this->template_id = '';
604  $this->redirection_mode = 0;
605  $this->redirection_url = NULL;
606  $this->show_exam_id_in_test_pass_enabled = false;
607  $this->show_exam_id_in_test_results_enabled = false;
608  $this->sign_submission = false;
609  $this->char_selector_availability = 0;
610  $this->char_selector_definition = null;
611 
612  $this->testFinalBroken = false;
613 
614  $this->ilObject($a_id, $a_call_by_reference);
615  }
616 
620  function create($a_upload = false)
621  {
622  parent::create();
623 
624  // meta data will be created by
625  // import parser
626  if (!$a_upload)
627  {
628  $this->createMetaData();
629  }
630  }
631 
638  function update()
639  {
640  if (!parent::update())
641  {
642  return false;
643  }
644 
645  // put here object specific stuff
646 
647  return true;
648  }
649 
655  function read($a_force_db = false)
656  {
657  parent::read($a_force_db);
658  $this->loadFromDb();
659  }
660 
661 
668  function delete()
669  {
670  // always call parent delete function first!!
671  if (!parent::delete())
672  {
673  return false;
674  }
675 
676  // delet meta data
677  $this->deleteMetaData();
678 
679  //put here your module specific stuff
680  $this->deleteTest();
681 
682  return true;
683  }
684 
690  function deleteTest()
691  {
692  global $tree, $ilDB, $ilPluginAdmin;
693 
694  // first of all remove all test editings, because the delete statements used for this
695  // contain a subquery for active ids, that are deleted in the next steps
696  $this->removeAllTestEditings();
697 
698  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
699  array('integer'),
700  array($this->getTestId())
701  );
702  $active_array = array();
703  while ($row = $ilDB->fetchAssoc($result))
704  {
705  array_push($active_array, $row["active_id"]);
706  }
707 
708  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
709  array('integer'),
710  array($this->getTestId())
711  );
712 
713  if (count($active_array))
714  {
715  foreach ($active_array as $active_id)
716  {
717  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_times WHERE active_fi = %s",
718  array('integer'),
719  array($active_id)
720  );
721 
722  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
723  array('integer'),
724  array($active_id)
725  );
726  }
727  }
728 
729  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_mark WHERE test_fi = %s",
730  array('integer'),
731  array($this->getTestId())
732  );
733 
734  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_tests WHERE test_id = %s",
735  array('integer'),
736  array($this->getTestId())
737  );
738 
739  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
740  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
741  $testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
742 
743  // delete export files
744  include_once "./Services/Utilities/classes/class.ilUtil.php";
745  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
746  $directory = $tst_data_dir."/tst_".$this->getId();
747  if (is_dir($directory))
748  {
749  include_once "./Services/Utilities/classes/class.ilUtil.php";
750  ilUtil::delDir($directory);
751  }
752  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
753  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
754  // remaining usages are not in text anymore -> delete them
755  // and media objects (note: delete method of ilObjMediaObject
756  // checks whether object is used in another context; if yes,
757  // the object is not deleted!)
758  foreach($mobs as $mob)
759  {
760  ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
761  if (ilObjMediaObject::_exists($mob))
762  {
763  $mob_obj =& new ilObjMediaObject($mob);
764  $mob_obj->delete();
765  }
766  }
767  }
768 
778  function initDefaultRoles()
779  {
780  global $rbacadmin;
781  return array();
782  }
783 
797  function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
798  {
799  global $tree;
800 
801  switch ($a_event)
802  {
803  case "link":
804 
805  //var_dump("<pre>",$a_params,"</pre>");
806  //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
807  //exit;
808  break;
809 
810  case "cut":
811 
812  //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
813  //exit;
814  break;
815 
816  case "copy":
817 
818  //var_dump("<pre>",$a_params,"</pre>");
819  //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
820  //exit;
821  break;
822 
823  case "paste":
824 
825  //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
826  //exit;
827  break;
828 
829  case "new":
830 
831  //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
832  //exit;
833  break;
834  }
835 
836  // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
837  if ($a_node_id==$_GET["ref_id"])
838  {
839  $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
840  $parent_type = $parent_obj->getType();
841  if ($parent_type == $this->getType())
842  {
843  $a_node_id = (int) $tree->getParentId($a_node_id);
844  }
845  }
846 
847  parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
848  }
849 
856  {
857  include_once "./Services/Utilities/classes/class.ilUtil.php";
858  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
859  ilUtil::makeDir($tst_data_dir);
860  if (!is_writable($tst_data_dir))
861  {
862  $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
863  .") not writeable.",$this->ilias->error_obj->MESSAGE);
864  }
865 
866  // create learning module directory (data_dir/lm_data/lm_<id>)
867  $tst_dir = $tst_data_dir."/tst_".$this->getId();
868  ilUtil::makeDir($tst_dir);
869  if (!@is_dir($tst_dir))
870  {
871  $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
872  }
873  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
874  $export_dir = $tst_dir."/export";
875  ilUtil::makeDir($export_dir);
876  if (!@is_dir($export_dir))
877  {
878  $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
879  }
880  }
881 
888  {
889  include_once "./Services/Utilities/classes/class.ilUtil.php";
890  $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
891  return $export_dir;
892  }
893 
900  function getExportFiles($dir)
901  {
902  // quit if import dir not available
903  if(!@is_dir($dir) || !is_writeable($dir))
904  {
905  return array();
906  }
907 
908  $files = array();
909  foreach(new DirectoryIterator($dir) as $file)
910  {
914  if($file->isDir())
915  {
916  continue;
917  }
918 
919  $files[] = $file->getBasename();
920  }
921 
922  sort($files);
923 
924  return $files;
925  }
926 
930  function _setImportDirectory($a_import_dir = null)
931  {
932  if (strlen($a_import_dir))
933  {
934  $_SESSION["tst_import_dir"] = $a_import_dir;
935  }
936  else
937  {
938  unset($_SESSION["tst_import_dir"]);
939  }
940  }
941 
949  {
950  if (strlen($_SESSION["tst_import_dir"]))
951  {
952  return $_SESSION["tst_import_dir"];
953  }
954  return null;
955  }
956 
958  {
960  }
961 
968  {
969  global $ilias;
970  include_once "./Services/Utilities/classes/class.ilUtil.php";
971  $tst_data_dir = ilUtil::getDataDir()."/tst_data";
972  ilUtil::makeDir($tst_data_dir);
973 
974  if (!is_writable($tst_data_dir))
975  {
976  $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
977  .") not writeable.",$this->ilias->error_obj->FATAL);
978  }
979 
980  // create test directory (data_dir/tst_data/tst_import)
981  $tst_dir = $tst_data_dir."/tst_import";
982  ilUtil::makeDir($tst_dir);
983  if (!@is_dir($tst_dir))
984  {
985  $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
986  }
987  return $tst_dir;
988  }
989 
997  {
998  global $ilDB;
999 
1000  $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",
1001  array('integer'),
1002  array($this->getTestId())
1003  );
1004  $hasSC = false;
1005  while ($row = $ilDB->fetchAssoc($result))
1006  {
1007  if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1008  {
1009  $hasSC = true;
1010  }
1011  }
1012  return $hasSC;
1013  }
1014 
1022  {
1023  global $ilDB;
1024 
1025  $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",
1026  array('integer'),
1027  array($this->getTestId())
1028  );
1029  if ($result->numRows() == 1)
1030  {
1031  $row = $ilDB->fetchAssoc($result);
1032  if (strcmp($row['foundtypes'], 'assSingleChoice') == 0)
1033  {
1034  return TRUE;
1035  }
1036  else
1037  {
1038  return false;
1039  }
1040  }
1041  return FALSE;
1042  }
1043 
1051  {
1052  global $ilDB;
1053 
1054  if (!$this->hasSingleChoiceQuestions()) return false;
1055 
1056  $result = $ilDB->queryF("
1057  SELECT DISTINCT(qpl_qst_sc.shuffle) foundshuffles
1058  FROM qpl_questions,
1059  qpl_qst_sc,
1060  tst_test_result,
1061  qpl_qst_type,
1062  tst_active
1063  WHERE tst_test_result.question_fi = qpl_questions.question_id
1064  AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id
1065  AND tst_test_result.active_fi = tst_active.active_id
1066  AND qpl_questions.question_id = qpl_qst_sc.question_fi
1067  AND tst_active.test_fi = %s
1068  AND qpl_qst_type.type_tag = %s
1069  ",
1070  array('integer', 'text'),
1071  array($this->getTestId(), 'assSingleChoice')
1072  );
1073  if ($result->numRows() == 1)
1074  {
1075  $row = $ilDB->fetchAssoc($result);
1076  return ($row['foundshuffles'] == 0);
1077  }
1078  return FALSE;
1079  }
1080 
1087  final public function isComplete(ilTestQuestionSetConfig $testQuestionSetConfig)
1088  {
1089  if( !count($this->mark_schema->mark_steps) )
1090  {
1091  return false;
1092  }
1093 
1094  if( !$testQuestionSetConfig->isQuestionSetConfigured() )
1095  {
1096  return false;
1097  }
1098 
1099  return true;
1100  }
1101 
1108  function _isComplete($obj_id)
1109  {
1110  global $tree, $ilDB, $ilPluginAdmin;
1111 
1112  $test = new ilObjTest($obj_id, false);
1113  $test->loadFromDb();
1114 
1115  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1116  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $test);
1117 
1118  return $test->isComplete( $testQuestionSetConfigFactory->getQuestionSetConfig() );
1119  }
1120 
1126  function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
1127  {
1128  global $ilDB;
1129  if ($this->test_id > 0)
1130  {
1131  $fx_support = preg_replace("/,/", ".", $fx_support);
1132  if (preg_match("/\d+/", $fx_support))
1133  {
1134  $fx_support = $fx_support;
1135  }
1136  else
1137  {
1138  $fx_support = NULL;
1139  }
1140  $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s WHERE test_id = %s",
1141  array('text','float','float','float','float','float','float','integer'),
1142  array($ects_output, $ects_a, $ects_b, $ects_c, $ects_d, $ects_e, $fx_support, $this->getTestId())
1143  );
1144  $this->ects_output = $ects_output;
1145  $this->ects_fx = $fx_support;
1146  }
1147  }
1148 
1154  function saveCompleteStatus(ilTestQuestionSetConfig $testQuestionSetConfig)
1155  {
1156  global $ilDB;
1157 
1158  $complete = 0;
1159  if ($this->isComplete($testQuestionSetConfig))
1160  {
1161  $complete = 1;
1162  }
1163  if ($this->test_id > 0)
1164  {
1165  $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
1166  array('text','integer'),
1167  array($complete, $this->test_id)
1168  );
1169  }
1170  }
1171 
1177  function getAllRTEContent()
1178  {
1179  $result = array();
1180  array_push($result, $this->getIntroduction());
1181  array_push($result, $this->getFinalStatement());
1182  return $result;
1183  }
1184 
1191  {
1192  include_once("./Services/RTE/classes/class.ilRTE.php");
1193  $completecontent = "";
1194  foreach ($this->getAllRTEContent() as $content)
1195  {
1196  $completecontent .= $content;
1197  }
1198  ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
1199  $this->getId());
1200  }
1201 
1207  public function saveToDb($properties_only = FALSE)
1208  {
1209  global $tree, $ilDB, $ilPluginAdmin;
1210 
1211  // moved online_status to ilObjectActivation (see below)
1212 
1213  // cleanup RTE images
1214  $this->cleanupMediaobjectUsage();
1215 
1216  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
1217  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
1218  $testQuestionSetConfig = $testQuestionSetConfigFactory->getQuestionSetConfig();
1219 
1220  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1221  if ($this->test_id == -1)
1222  {
1223  // Create new dataset
1224  $next_id = $ilDB->nextId('tst_tests');
1225 
1226  $ilDB->insert('tst_tests', array(
1227  'test_id' => array('integer', $next_id),
1228  'obj_fi' => array('integer', $this->getId()),
1229  'author' => array('text', $this->getAuthor()),
1230  'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1231  'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1232  'showinfo' => array('integer', $this->getShowInfo()),
1233  'forcejs' => array('integer', $this->getForceJS()),
1234  'customstyle' => array('text', $this->getCustomStyle()),
1235  'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1236  'sequence_settings' => array('integer', $this->getSequenceSettings()),
1237  'score_reporting' => array('integer', $this->getScoreReporting()),
1238  'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1239  'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1240  'answer_feedback' => array('text', $this->getAnswerFeedback()),
1241  'anonymity' => array('text', $this->getAnonymity()),
1242  'show_cancel' => array('text', $this->getShowCancel()),
1243  'show_marker' => array('integer', $this->getShowMarker()),
1244  'fixed_participants' => array('text', $this->getFixedParticipants()),
1245  'nr_of_tries' => array('integer', $this->getNrOfTries()),
1246  'kiosk' => array('integer', $this->getKiosk()),
1247  'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1248  'title_output' => array('text', $this->getTitleOutput()),
1249  'processing_time' => array('text', $this->getProcessingTime()),
1250  'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1251  'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1252  'reporting_date' => array('text', $this->getReportingDate()),
1253  'starting_time' => array('text', $this->getStartingTime()),
1254  'ending_time' => array('text', $this->getEndingTime()),
1255  'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1256  'ects_output' => array('text', $this->getECTSOutput()),
1257  'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1258  'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1259  'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1260  'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1261  'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1262  'ects_fx' => array('float', $this->getECTSFX()),
1263  'count_system' => array('text', $this->getCountSystem()),
1264  'mc_scoring' => array('text', $this->getMCScoring()),
1265  'score_cutting' => array('text', $this->getScoreCutting()),
1266  'pass_scoring' => array('text', $this->getPassScoring()),
1267  'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1268  'results_presentation' => array('integer', $this->getResultsPresentation()),
1269  'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1270  'password' => array('text', $this->getPassword()),
1271  'allowedusers' => array('integer', $this->getAllowedUsers()),
1272  'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1273  'mailnottype' => array('integer', $this->getMailNotificationType()),
1274  'exportsettings' => array('integer', $this->getExportSettings()),
1275  'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1276  'mailnotification' => array('integer', $this->getMailNotification()),
1277  'created' => array('integer', time()),
1278  'tstamp' => array('integer', time()),
1279  'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1280  'template_id' => array('integer', $this->getTemplate()),
1281  'pool_usage' => array('integer', $this->getPoolUsage()),
1282  'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1283  'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1284  'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1285  'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1286  'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1287  'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1288  'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1289  'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1290  'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1291  'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1292  'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1293  'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1294  'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1295  'online_status' => array('integer', (int)$this->isOnline()),
1296  'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1297  'autosave' => array('integer', (int)$this->getAutosave()),
1298  'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1299  'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1300  'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1301  'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1302  'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1303  'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1304  'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1305  'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1306  'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1307  'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1308  'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1309  'question_set_type' => array('text', $this->getQuestionSetType()),
1310  'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1311  'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1312  'broken' => array('integer', (int)$this->isTestFinalBroken())
1313  ));
1314 
1315  $this->test_id = $next_id;
1316 
1318  {
1319  $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
1320  }
1321  }
1322  else
1323  {
1324  // Modify existing dataset
1325  $oldrow = array();
1327  {
1328  $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1329  array('integer'),
1330  array($this->test_id)
1331  );
1332  if ($result->numRows() == 1)
1333  {
1334  $oldrow = $ilDB->fetchAssoc($result);
1335  }
1336  }
1337 
1338  $ilDB->update('tst_tests',
1339  array(
1340  'author' => array('text', $this->getAuthor()),
1341  'introduction' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
1342  'finalstatement' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getFinalStatement(), 0)),
1343  'showinfo' => array('integer', $this->getShowInfo()),
1344  'forcejs' => array('integer', $this->getForceJS()),
1345  'customstyle' => array('text', $this->getCustomStyle()),
1346  'showfinalstatement' => array('integer', $this->getShowFinalStatement()),
1347  'sequence_settings' => array('integer', $this->getSequenceSettings()),
1348  'score_reporting' => array('integer', $this->getScoreReporting()),
1349  'instant_verification' => array('text', $this->getInstantFeedbackSolution()),
1350  'answer_feedback_points' => array('text', $this->getAnswerFeedbackPoints()),
1351  'answer_feedback' => array('text', $this->getGenericAnswerFeedback()),
1352  'anonymity' => array('text', $this->getAnonymity()),
1353  'show_cancel' => array('text', $this->getShowCancel()),
1354  'show_marker' => array('integer', $this->getShowMarker()),
1355  'fixed_participants' => array('text', $this->getFixedParticipants()),
1356  'nr_of_tries' => array('integer', $this->getNrOfTries()),
1357  'kiosk' => array('integer', $this->getKiosk()),
1358  'use_previous_answers' => array('text', $this->getUsePreviousAnswers()),
1359  'title_output' => array('text', $this->getTitleOutput()),
1360  'processing_time' => array('text', $this->getProcessingTime()),
1361  'enable_processing_time' => array('text', $this->getEnableProcessingTime()),
1362  'reset_processing_time' => array('integer', $this->getResetProcessingTime()),
1363  'reporting_date' => array('text', $this->getReportingDate()),
1364  'starting_time' => array('text', $this->getStartingTime()),
1365  'ending_time' => array('text', $this->getEndingTime()),
1366  'complete' => array('text', $this->isComplete($testQuestionSetConfig)),
1367  'ects_output' => array('text', $this->getECTSOutput()),
1368  'ects_a' => array('float', strlen($this->ects_grades["A"]) ? $this->ects_grades["A"] : NULL),
1369  'ects_b' => array('float', strlen($this->ects_grades["B"]) ? $this->ects_grades["B"] : NULL),
1370  'ects_c' => array('float', strlen($this->ects_grades["C"]) ? $this->ects_grades["C"] : NULL),
1371  'ects_d' => array('float', strlen($this->ects_grades["D"]) ? $this->ects_grades["D"] : NULL),
1372  'ects_e' => array('float', strlen($this->ects_grades["E"]) ? $this->ects_grades["E"] : NULL),
1373  'ects_fx' => array('float', $this->getECTSFX()),
1374  'count_system' => array('text', $this->getCountSystem()),
1375  'mc_scoring' => array('text', $this->getMCScoring()),
1376  'score_cutting' => array('text', $this->getScoreCutting()),
1377  'pass_scoring' => array('text', $this->getPassScoring()),
1378  'shuffle_questions' => array('text', $this->getShuffleQuestions()),
1379  'results_presentation' => array('integer', $this->getResultsPresentation()),
1380  'show_summary' => array('integer', $this->getListOfQuestionsSettings()),
1381  'password' => array('text', $this->getPassword()),
1382  'allowedusers' => array('integer', $this->getAllowedUsers()),
1383  'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1384  'mailnottype' => array('integer', $this->getMailNotificationType()),
1385  'exportsettings' => array('integer', $this->getExportSettings()),
1386  'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1387  'alloweduserstimegap' => array('integer', $this->getAllowedUsersTimeGap()),
1388  'certificate_visibility' => array('text', $this->getCertificateVisibility()),
1389  'mailnotification' => array('integer', $this->getMailNotification()),
1390  'tstamp' => array('integer', time()),
1391  'enabled_view_mode' => array('text', $this->getEnabledViewMode()),
1392  'template_id' => array('integer', $this->getTemplate()),
1393  'pool_usage' => array('integer', $this->getPoolUsage()),
1394  'print_bs_with_res' => array('integer', (int)$this->isBestSolutionPrintedWithResult()),
1395  'obligations_enabled' => array('integer', (int)$this->areObligationsEnabled()),
1396  'offer_question_hints' => array('integer', (int)$this->isOfferingQuestionHintsEnabled()),
1397  'highscore_enabled' => array('integer', (int)$this->getHighscoreEnabled()),
1398  'highscore_anon' => array('integer', (int)$this->getHighscoreAnon()),
1399  'highscore_achieved_ts' => array('integer', (int)$this->getHighscoreAchievedTS()),
1400  'highscore_score' => array('integer', (int)$this->getHighscoreScore()),
1401  'highscore_percentage' => array('integer', (int)$this->getHighscorePercentage()),
1402  'highscore_hints' => array('integer', (int)$this->getHighscoreHints()),
1403  'highscore_wtime' => array('integer', (int)$this->getHighscoreWTime()),
1404  'highscore_own_table' => array('integer', (int)$this->getHighscoreOwnTable()),
1405  'highscore_top_table' => array('integer', (int)$this->getHighscoreTopTable()),
1406  'highscore_top_num' => array('integer', (int)$this->getHighscoreTopNum()),
1407  'online_status' => array('integer', (int)$this->isOnline()),
1408  'specific_feedback' => array('integer', (int)$this->getSpecificAnswerFeedback()),
1409  'autosave' => array('integer', (int)$this->getAutosave()),
1410  'autosave_ival' => array('integer', (int)$this->getAutosaveIval()),
1411  'pass_deletion_allowed' => array('integer', (int)$this->isPassDeletionAllowed()),
1412  'enable_examview' => array('integer', (int)$this->getEnableExamview()),
1413  'show_examview_html' => array('integer', (int)$this->getShowExamviewHtml()),
1414  'show_examview_pdf' => array('integer', (int)$this->getShowExamviewPdf()),
1415  'redirection_mode' => array('integer', (int)$this->getRedirectionMode()),
1416  'redirection_url' => array('text', (string)$this->getRedirectionUrl()),
1417  'enable_archiving' => array('integer', (int)$this->getEnableArchiving()),
1418  'examid_in_test_pass' => array('integer', (int)$this->isShowExamIdInTestPassEnabled()),
1419  'examid_in_test_res' => array('integer', (int)$this->isShowExamIdInTestResultsEnabled()),
1420  'sign_submission' => array('integer', (int)$this->getSignSubmission()),
1421  'question_set_type' => array('text', $this->getQuestionSetType()),
1422  'char_selector_availability' => array('integer', (int)$this->getCharSelectorAvailability()),
1423  'char_selector_definition' => array('text', (string)$this->getCharSelectorDefinition()),
1424  'broken' => array('integer', (int)$this->isTestFinalBroken())
1425  ),
1426  array(
1427  'test_id' => array('integer', (int)$this->getTestId())
1428  )
1429  );
1430 
1431  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1433  {
1434  $logresult = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
1435  array('integer'),
1436  array($this->getTestId())
1437  );
1438  $newrow = array();
1439  if ($logresult->numRows() == 1)
1440  {
1441  $newrow = $ilDB->fetchAssoc($logresult);
1442  }
1443  $changed_fields = array();
1444  foreach ($oldrow as $key => $value)
1445  {
1446  if (strcmp($oldrow[$key], $newrow[$key]) != 0)
1447  {
1448  array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
1449  }
1450  }
1451  $changes = join($changed_fields, ", ");
1452  if (count($changed_fields) > 0)
1453  {
1454  $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
1455  }
1456  }
1457  if ($this->evalTotalPersons() > 0)
1458  {
1459  // reset the finished status of participants if the nr of test passes did change
1460  if ($this->getNrOfTries() > 0)
1461  {
1462  // set all unfinished tests with nr of passes >= allowed passes finished
1463  $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = %s",
1464  array('integer', 'integer', 'integer'),
1465  array($this->getTestId(), $this->getNrOfTries(), 0)
1466  );
1467  while ($row = $ilDB->fetchAssoc($aresult))
1468  {
1469  $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1470  array('integer', 'timestamp', 'integer'),
1471  array(1, date('Y-m-d H:i:s'), $row["active_id"])
1472  );
1473  }
1474 
1475  // set all finished tests with nr of passes < allowed passes not finished
1476  $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = %s",
1477  array('integer', 'integer', 'integer'),
1478  array($this->getTestId(), $this->getNrOfTries()-1, 1)
1479  );
1480  while ($row = $ilDB->fetchAssoc($aresult))
1481  {
1482  $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1483  array('integer', 'timestamp', 'integer'),
1484  array(0, NULL, $row["active_id"])
1485  );
1486  }
1487  }
1488  else
1489  {
1490  // set all finished tests with nr of passes >= allowed passes not finished
1491  $aresult = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = %s",
1492  array('integer', 'integer'),
1493  array($this->getTestId(), 1)
1494  );
1495  while ($row = $ilDB->fetchAssoc($aresult))
1496  {
1497  $ilDB->manipulateF("UPDATE tst_active SET submitted = %s, submittimestamp = %s WHERE active_id = %s",
1498  array('integer', 'timestamp', 'integer'),
1499  array(0, NULL, $row["active_id"])
1500  );
1501  }
1502  }
1503  }
1504  }
1505 
1506  // moved activation to ilObjectActivation
1507  if($this->ref_id)
1508  {
1509  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1510  ilObjectActivation::getItem($this->ref_id);
1511 
1512  $item = new ilObjectActivation;
1513  if(!$this->isActivationLimited())
1514  {
1516  }
1517  else
1518  {
1519  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1520  $item->setTimingStart($this->getActivationStartingTime());
1521  $item->setTimingEnd($this->getActivationEndingTime());
1522  $item->toggleVisible($this->getActivationVisibility());
1523  }
1524 
1525  $item->update($this->ref_id);
1526  }
1527 
1528  if (!$properties_only)
1529  {
1530  if (PEAR::isError($result))
1531  {
1532  global $ilias;
1533  $ilias->raiseError($result->getMessage());
1534  }
1535  else
1536  {
1537  if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
1538  {
1539  $this->saveQuestionsToDb();
1540  }
1541  $this->mark_schema->saveToDb($this->test_id);
1542  }
1543  }
1544  }
1545 
1553  {
1554  global $ilDB;
1555 
1556  $oldquestions = array();
1557  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1559  {
1560  $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1561  array('integer'),
1562  array($this->getTestId())
1563  );
1564  if ($result->numRows() > 0)
1565  {
1566  while ($row = $ilDB->fetchAssoc($result))
1567  {
1568  array_push($oldquestions, $row["question_fi"]);
1569  }
1570  }
1571  }
1572  // workaround for lost obligations
1573  // this method is called if a question is removed
1574  $currentQuestionsObligationsQuery = 'SELECT question_fi, obligatory FROM tst_test_question WHERE test_fi = %s';
1575  $rset = $ilDB->queryF($currentQuestionsObligationsQuery, array('integer'), array($this->getTestId()));
1576  while ($row = $ilDB->fetchAssoc($rset)) {
1577  $obligatoryQuestionState[$row['question_fi']] = $row['obligatory'];
1578  }
1579  // delete existing category relations
1580  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_question WHERE test_fi = %s",
1581  array('integer'),
1582  array($this->getTestId())
1583  );
1584  // create new category relations
1585  foreach ($this->questions as $key => $value)
1586  {
1587  // workaround for import witout obligations information
1588  if( !isset($obligatoryQuestionState[$value]) || is_null($obligatoryQuestionState[$value]) )
1589  {
1590  $obligatoryQuestionState[$value] = 0;
1591  }
1592 
1593  // insert question
1594  $next_id = $ilDB->nextId('tst_test_question');
1595  $ilDB->insert('tst_test_question', array(
1596  'test_question_id' => array('integer', $next_id),
1597  'test_fi' => array('integer', $this->getTestId()),
1598  'question_fi' => array('integer', $value),
1599  'sequence' => array('integer', $key),
1600  'obligatory' => array('integer', $obligatoryQuestionState[$value]),
1601  'tstamp' => array('integer', time())
1602  ));
1603  }
1604  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1606  {
1607  $result = $ilDB->queryF("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
1608  array('integer'),
1609  array($this->getTestId())
1610  );
1611  $newquestions = array();
1612  if ($result->numRows() > 0)
1613  {
1614  while ($row = $ilDB->fetchAssoc($result))
1615  {
1616  array_push($newquestions, $row["question_fi"]);
1617  }
1618  }
1619  foreach ($oldquestions as $index => $question_id)
1620  {
1621  if (strcmp($newquestions[$index], $question_id) != 0)
1622  {
1623  $pos = array_search($question_id, $newquestions);
1624  if ($pos === FALSE)
1625  {
1626  $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
1627  }
1628  else
1629  {
1630  $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
1631  }
1632  }
1633  }
1634  foreach ($newquestions as $index => $question_id)
1635  {
1636  if (array_search($question_id, $oldquestions) === FALSE)
1637  {
1638  $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
1639  }
1640  }
1641  }
1642  }
1643 
1649  protected function isNewRandomTest()
1650  {
1651  global $ilDB;
1652  $result = $ilDB->queryF('SELECT copy_id FROM tst_rnd_cpy WHERE tst_fi = %s',
1653  array('integer'),
1654  array($this->getTestId())
1655  );
1656  return $result->numRows() > 0;
1657  }
1658 
1671  function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
1672  {
1673  global $rbacsystem;
1674  global $ilDB;
1675 
1676  // retrieve object id instead of ref id if necessary
1677  if (($questionpool != 0) && (!$use_obj_id)) $questionpool = ilObject::_lookupObjId($questionpool);
1678 
1679  // get original ids of all existing questions in the test
1680  $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",
1681  array("integer"),
1682  array($this->getTestId())
1683  );
1684  $original_ids = array();
1685  $paramtypes = array();
1686  $paramvalues = array();
1687  while ($row = $ilDB->fetchAssoc($result))
1688  {
1689  array_push($original_ids, $row['original_id']);
1690  }
1691 
1692  $available = "";
1693  // get a list of all available questionpools
1694  if (($questionpool == 0) && (!is_array($qpls)))
1695  {
1696  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1697  $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())));
1698  if (count($available_pools))
1699  {
1700  $available = " AND " . $ilDB->in('obj_fi', $available_pools, false, 'integer');
1701  }
1702  else
1703  {
1704  return array();
1705  }
1706  }
1707 
1708  $constraint_qpls = "";
1709  $result_array = array();
1710  if ($questionpool == 0)
1711  {
1712  if (is_array($qpls))
1713  {
1714  if (count($qpls) > 0)
1715  {
1716  $constraint_qpls = " AND " . $ilDB->in('obj_fi', $qpls, false, 'integer');
1717  }
1718  }
1719  }
1720 
1721  $original_clause = "";
1722  if (count($original_ids))
1723  {
1724  $original_clause = " AND " . $ilDB->in('question_id', $original_ids, true, 'integer');
1725  }
1726 
1727  if ($questionpool == 0)
1728  {
1729  $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",
1730  array('integer', 'text'),
1731  array(0, "1")
1732  );
1733  }
1734  else
1735  {
1736  $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",
1737  array('integer','integer', 'text'),
1738  array($questionpool, 0, "1")
1739  );
1740  }
1741  $found_ids = array();
1742  while ($row = $ilDB->fetchAssoc($result))
1743  {
1744  array_push($found_ids, $row['question_id']);
1745  }
1746  $nr_of_questions = ($nr_of_questions > count($found_ids)) ? count($found_ids) : $nr_of_questions;
1747  if ($nr_of_questions == 0) return array();
1748  $rand_keys = array_rand($found_ids, $nr_of_questions);
1749  $result = array();
1750  if (is_array($rand_keys))
1751  {
1752  foreach ($rand_keys as $key)
1753  {
1754  $result[$found_ids[$key]] = $found_ids[$key];
1755  }
1756  }
1757  else
1758  {
1759  $result[$found_ids[$rand_keys]] = $found_ids[$rand_keys];
1760  }
1761  return $result;
1762  }
1763 
1771  function getNrOfResultsForPass($active_id, $pass)
1772  {
1773  global $ilDB;
1774 
1775  $result = $ilDB->queryF("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
1776  array('integer','integer'),
1777  array($active_id, $pass)
1778  );
1779  return $result->numRows();
1780  }
1781 
1792  function hasRandomQuestionsForPass($active_id, $pass)
1793  {
1794  global $ilDB;
1795  $result = $ilDB->queryF("SELECT test_random_question_id FROM tst_test_rnd_qst WHERE active_fi = %s AND pass = %s",
1796  array('integer','integer'),
1797  array($active_id, $pass)
1798  );
1799  return ($result->numRows() > 0) ? true : false;
1800  }
1801 
1805  public function loadFromDb()
1806  {
1807  global $ilDB;
1808 
1809  $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE obj_fi = %s",
1810  array('integer'),
1811  array($this->getId())
1812  );
1813  if ($result->numRows() == 1)
1814  {
1815  $data = $ilDB->fetchObject($result);
1816  $this->setTestId($data->test_id);
1817  if (strlen($this->getAuthor()) == 0)
1818  {
1819  $this->saveAuthorToMetadata($data->author);
1820  }
1821  $this->setAuthor($data->author);
1822  include_once("./Services/RTE/classes/class.ilRTE.php");
1823  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($data->introduction, 1));
1824  $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc($data->finalstatement, 1));
1825  $this->setShowInfo($data->showinfo);
1826  $this->setForceJS($data->forcejs);
1827  $this->setCustomStyle($data->customstyle);
1828  $this->setShowFinalStatement($data->showfinalstatement);
1829  $this->setSequenceSettings($data->sequence_settings);
1830  $this->setScoreReporting($data->score_reporting);
1831  $this->setInstantFeedbackSolution($data->instant_verification);
1832  $this->setAnswerFeedbackPoints($data->answer_feedback_points);
1833  $this->setAnswerFeedback($data->answer_feedback);
1834  $this->setAnonymity($data->anonymity);
1835  $this->setShowCancel($data->show_cancel);
1836  $this->setShowMarker($data->show_marker);
1837  $this->setFixedParticipants($data->fixed_participants);
1838  $this->setNrOfTries($data->nr_of_tries);
1839  $this->setKiosk($data->kiosk);
1840  $this->setUsePreviousAnswers($data->use_previous_answers);
1841  $this->setRedirectionMode($data->redirection_mode);
1842  $this->setRedirectionUrl($data->redirection_url);
1843  $this->setTitleOutput($data->title_output);
1844  $this->setProcessingTime($data->processing_time);
1845  $this->setEnableProcessingTime($data->enable_processing_time);
1846  $this->setResetProcessingTime($data->reset_processing_time);
1847  $this->setReportingDate($data->reporting_date);
1848  $this->setShuffleQuestions($data->shuffle_questions);
1849  $this->setResultsPresentation($data->results_presentation);
1850  $this->setStartingTime($data->starting_time);
1851  $this->setEndingTime($data->ending_time);
1852  $this->setListOfQuestionsSettings($data->show_summary);
1853  $this->setECTSOutput($data->ects_output);
1854  $this->setECTSGrades(
1855  array(
1856  "A" => $data->ects_a,
1857  "B" => $data->ects_b,
1858  "C" => $data->ects_c,
1859  "D" => $data->ects_d,
1860  "E" => $data->ects_e
1861  )
1862  );
1863  $this->setECTSFX($data->ects_fx);
1864  $this->mark_schema->flush();
1865  $this->mark_schema->loadFromDb($this->getTestId());
1866  $this->setCountSystem($data->count_system);
1867  $this->setMCScoring($data->mc_scoring);
1868  $this->setMailNotification($data->mailnotification);
1869  $this->setMailNotificationType($data->mailnottype);
1870  $this->setExportSettings($data->exportsettings);
1871  $this->setScoreCutting($data->score_cutting);
1872  $this->setPassword($data->password);
1873  $this->setAllowedUsers($data->allowedusers);
1874  $this->setAllowedUsersTimeGap($data->alloweduserstimegap);
1875  $this->setPassScoring($data->pass_scoring);
1876  $this->setObligationsEnabled($data->obligations_enabled);
1877  $this->setOfferingQuestionHintsEnabled($data->offer_question_hints);
1878  $this->setCertificateVisibility($data->certificate_visibility);
1879  $this->setEnabledViewMode($data->enabled_view_mode);
1880  $this->setTemplate($data->template_id);
1881  $this->setPoolUsage($data->pool_usage);
1882  $this->setPrintBestSolutionWithResult((bool) $data->print_bs_with_res);
1883  $this->setHighscoreEnabled((bool) $data->highscore_enabled);
1884  $this->setHighscoreAnon((bool) $data->highscore_anon);
1885  $this->setHighscoreAchievedTS((bool) $data->highscore_achieved_ts);
1886  $this->setHighscoreScore((bool) $data->highscore_score);
1887  $this->setHighscorePercentage((bool) $data->highscore_percentage);
1888  $this->setHighscoreHints((bool) $data->highscore_hints);
1889  $this->setHighscoreWTime((bool) $data->highscore_wtime);
1890  $this->setHighscoreOwnTable((bool) $data->highscore_own_table);
1891  $this->setHighscoreTopTable((bool) $data->highscore_top_table);
1892  $this->setHighscoreTopNum((int) $data->highscore_top_num);
1893  $this->setOnline((bool) $data->online_status);
1894  $this->setSpecificAnswerFeedback((int) $data->specific_feedback);
1895  $this->setAutosave((bool)$data->autosave);
1896  $this->setAutosaveIval((int)$data->autosave_ival);
1897  $this->setPassDeletionAllowed($data->pass_deletion_allowed);
1898  $this->setEnableExamview((bool)$data->enable_examview);
1899  $this->setShowExamviewHtml((bool)$data->show_examview_html);
1900  $this->setShowExamviewPdf((bool)$data->show_examview_pdf);
1901  $this->setEnableArchiving((bool)$data->enable_archiving);
1902  $this->setShowExamIdInTestPassEnabled( (bool)$data->examid_in_test_pass);
1903  $this->setShowExamIdInTestResultsEnabled( (bool)$data->examid_in_test_res);
1904  $this->setSignSubmission( (bool)$data->sign_submission );
1905  $this->setQuestionSetType($data->question_set_type);
1906  $this->setCharSelectorAvailability((int)$data->char_selector_availability);
1907  $this->setCharSelectorDefinition($data->char_selector_definition);
1908  $this->setTestFinalBroken((bool)$data->broken);
1909  $this->loadQuestions();
1910  }
1911 
1912  // moved activation to ilObjectActivation
1913  if($this->ref_id)
1914  {
1915  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1916  $activation = ilObjectActivation::getItem($this->ref_id);
1917  switch($activation["timing_type"])
1918  {
1920  $this->setActivationLimited(true);
1921  $this->setActivationStartingTime($activation["timing_start"]);
1922  $this->setActivationEndingTime($activation["timing_end"]);
1923  $this->setActivationVisibility($activation["visible"]);
1924  break;
1925 
1926  default:
1927  $this->setActivationLimited(false);
1928  break;
1929  }
1930  }
1931  }
1932 
1939 function loadQuestions($active_id = "", $pass = NULL)
1940 {
1941  global $ilUser;
1942  global $ilDB;
1943 
1944  $this->questions = array();
1945  if (strcmp($active_id, "") == 0)
1946  {
1947  $active_id = $this->getActiveIdOfUser($ilUser->getId());
1948  }
1949  if ($this->isRandomTest())
1950  {
1951  if (is_null($pass))
1952  {
1953  $pass = $this->_getPass($active_id);
1954  }
1955  $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",
1956  array('integer', 'integer'),
1957  array($active_id, $pass)
1958  );
1959  // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
1960  // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
1961  // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
1962  // no questions are present for a newer pass.
1963  if ($result->numRows() == 0)
1964  {
1965  $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",
1966  array('integer'),
1967  array($active_id)
1968  );
1969  }
1970  }
1971  else
1972  {
1973  $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",
1974  array('integer'),
1975  array($this->test_id)
1976  );
1977  }
1978  $index = 1;
1979  while ($data = $ilDB->fetchAssoc($result))
1980  {
1981  $this->questions[$index++] = $data["question_fi"];
1982  }
1983 }
1984 
1992  function setIntroduction($introduction = "")
1993  {
1994  $this->introduction = $introduction;
1995  }
1996 
2004  public function setFinalStatement($a_statement = "")
2005  {
2006  $this->_finalstatement = $a_statement;
2007  }
2008 
2016  public function setShowInfo($a_info = 1)
2017  {
2018  $this->_showinfo = ($a_info) ? 1 : 0;
2019  }
2020 
2028  public function setForceJS($a_js = 1)
2029  {
2030  $this->_forcejs = ($a_js) ? 1 : 0;
2031  }
2032 
2040  public function setCustomStyle($a_customStyle = NULL)
2041  {
2042  $this->_customStyle = $a_customStyle;
2043  }
2044 
2052  public function getCustomStyle()
2053  {
2054  return (strlen($this->_customStyle)) ? $this->_customStyle : NULL;
2055  }
2056 
2064  public function getCustomStyles()
2065  {
2066  $css_path = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2067  $css_path = str_replace("ta.css", "customstyles", $css_path) . "/";
2068  $customstyles = array();
2069  if (is_dir($css_path))
2070  {
2071  $results = array();
2072  include_once "./Services/Utilities/classes/class.ilFileUtils.php";
2074  if (is_array($results["file"]))
2075  {
2076  foreach ($results["file"] as $filename)
2077  {
2078  if (strpos($filename, ".css"))
2079  {
2080  array_push($customstyles, $filename);
2081  }
2082  }
2083  }
2084  }
2085  return $customstyles;
2086  }
2087 
2095  public function getTestStyleLocation($mode = "output")
2096  {
2097  if (strlen($this->getCustomStyle()))
2098  {
2099  $default = ilUtil::getStyleSheetLocation("filesystem", "ta.css", "Modules/Test");
2100  $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $default);
2101  if (file_exists($custom))
2102  {
2103  $custom = ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2104  $custom = str_replace("ta.css", "customstyles/" . $this->getCustomStyle(), $custom);
2105  return $custom;
2106  }
2107  else
2108  {
2109  return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2110  }
2111  }
2112  else
2113  {
2114  return ilUtil::getStyleSheetLocation($mode, "ta.css", "Modules/Test");
2115  }
2116  }
2117 
2125  public function setShowFinalStatement($show = 0)
2126  {
2127  $this->_showfinalstatement = ($show) ? 1 : 0;
2128  }
2129 
2136  public function getIntroduction()
2137  {
2138  return (strlen($this->introduction)) ? $this->introduction : NULL;
2139  }
2140 
2147  public function getFinalStatement()
2148  {
2149  return (strlen($this->_finalstatement)) ? $this->_finalstatement : NULL;
2150  }
2151 
2159  public function getShowInfo()
2160  {
2161  return ($this->_showinfo) ? 1 : 0;
2162  }
2163 
2171  public function getForceJS()
2172  {
2173  return ($this->_forcejs) ? 1 : 0;
2174  }
2175 
2183  public function getShowFinalStatement()
2184  {
2185  return ($this->_showfinalstatement) ? 1 : 0;
2186  }
2187 
2195  function getTestId()
2196  {
2197  return $this->test_id;
2198  }
2199 
2207  function getECTSOutput()
2208  {
2209  return ($this->ects_output) ? 1 : 0;
2210  }
2211 
2219  function setECTSOutput($a_ects_output)
2220  {
2221  $this->ects_output = $a_ects_output ? 1 : 0;
2222  }
2223 
2231  function getECTSFX()
2232  {
2233  return (strlen($this->ects_fx)) ? $this->ects_fx : NULL;
2234  }
2235 
2243  function setECTSFX($a_ects_fx)
2244  {
2245  $this->ects_fx = $a_ects_fx;
2246  }
2247 
2255  function &getECTSGrades()
2256  {
2257  return $this->ects_grades;
2258  }
2259 
2267  function setECTSGrades($a_ects_grades)
2268  {
2269  if (is_array($a_ects_grades))
2270  {
2271  $this->ects_grades = $a_ects_grades;
2272  }
2273  }
2274 
2282  function setSequenceSettings($sequence_settings = 0)
2283  {
2284  $this->sequence_settings = $sequence_settings;
2285  }
2286 
2294  function setScoreReporting($score_reporting = 0)
2295  {
2296  $this->score_reporting = $score_reporting;
2297  }
2298 
2306  function setInstantFeedbackSolution($instant_feedback = 0)
2307  {
2308  switch ($instant_feedback)
2309  {
2310  case 1:
2311  $this->instant_verification = 1;
2312  break;
2313  default:
2314  $this->instant_verification = 0;
2315  break;
2316  }
2317  }
2318 
2326 function setAnswerFeedback($answer_feedback = 0)
2327 {
2328  switch ($answer_feedback)
2329  {
2330  case 1:
2331  $this->answer_feedback = 1;
2332  break;
2333  default:
2334  $this->answer_feedback = 0;
2335  break;
2336  }
2337 }
2338 
2345 function setGenericAnswerFeedback($generic_answer_feedback = 0)
2346 {
2347  switch ($generic_answer_feedback)
2348  {
2349  case 1:
2350  $this->answer_feedback = 1;
2351  break;
2352  default:
2353  $this->answer_feedback = 0;
2354  break;
2355  }
2356 }
2357 
2365  function setAnswerFeedbackPoints($answer_feedback_points = 0)
2366  {
2367  switch ($answer_feedback_points)
2368  {
2369  case 1:
2370  $this->answer_feedback_points = 1;
2371  break;
2372  default:
2373  $this->answer_feedback_points = 0;
2374  break;
2375  }
2376  }
2377 
2385  function setReportingDate($reporting_date)
2386  {
2387  if (!$reporting_date)
2388  {
2389  $this->reporting_date = "";
2390  $this->ects_output = 0;
2391  }
2392  else
2393  {
2394  $this->reporting_date = $reporting_date;
2395  }
2396  }
2397 
2407  {
2408  return ($this->sequence_settings) ? $this->sequence_settings : 0;
2409  }
2410 
2419  {
2420  return ($this->score_reporting) ? $this->score_reporting : 0;
2421  }
2422 
2431  {
2432  return ($this->instant_verification) ? $this->instant_verification : 0;
2433  }
2434 
2443  public function getAnswerFeedback()
2444  {
2445  return ($this->answer_feedback) ? $this->answer_feedback : 0;
2446  }
2447 
2456  public function getGenericAnswerFeedback()
2457  {
2458  return ($this->answer_feedback) ? $this->answer_feedback : 0;
2459  }
2460 
2469 {
2470  return ($this->answer_feedback_points) ? $this->answer_feedback_points : 0;
2471 }
2472 
2480  function getCountSystem()
2481  {
2482  return ($this->count_system) ? $this->count_system : 0;
2483  }
2484 
2492  function _getCountSystem($active_id)
2493  {
2494  global $ilDB;
2495  $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",
2496  array('integer'),
2497  array($active_id)
2498  );
2499  if ($result->numRows())
2500  {
2501  $row = $ilDB->fetchAssoc($result);
2502  return $row["count_system"];
2503  }
2504  return FALSE;
2505  }
2506 
2514  function getMCScoring()
2515  {
2516  return ($this->mc_scoring) ? $this->mc_scoring : 0;
2517  }
2518 
2526  function getScoreCutting()
2527  {
2528  return ($this->score_cutting) ? $this->score_cutting : 0;
2529  }
2530 
2538  function getPassword()
2539  {
2540  return (strlen($this->password)) ? $this->password : NULL;
2541  }
2542 
2550  function getPassScoring()
2551  {
2552  return ($this->pass_scoring) ? $this->pass_scoring : 0;
2553  }
2554 
2562  function _getPassScoring($active_id)
2563  {
2564  global $ilDB;
2565  $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",
2566  array('integer'),
2567  array($active_id)
2568  );
2569  if ($result->numRows())
2570  {
2571  $row = $ilDB->fetchAssoc($result);
2572  return $row["pass_scoring"];
2573  }
2574  return 0;
2575  }
2576 
2584  function _getMCScoring($active_id)
2585  {
2586  global $ilDB;
2587  $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",
2588  array('integer'),
2589  array($active_id)
2590  );
2591  if ($result->numRows())
2592  {
2593  $row = $ilDB->fetchAssoc($result);
2594  return $row["mc_scoring"];
2595  }
2596  return FALSE;
2597  }
2598 
2606  function _getScoreCutting($active_id)
2607  {
2608  global $ilDB;
2609  $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",
2610  array('integer'),
2611  array($active_id)
2612  );
2613  if ($result->numRows())
2614  {
2615  $row = $ilDB->fetchAssoc($result);
2616  return $row["score_cutting"];
2617  }
2618  return FALSE;
2619  }
2620 
2628  function getReportingDate()
2629  {
2630  return (strlen($this->reporting_date)) ? $this->reporting_date : NULL;
2631  }
2632 
2640  function getNrOfTries()
2641  {
2642  return ($this->nr_of_tries) ? $this->nr_of_tries : 0;
2643  }
2644 
2652  function getKiosk()
2653  {
2654  return ($this->_kiosk) ? $this->_kiosk : 0;
2655  }
2656 
2657 
2665  function setKiosk($kiosk = 0)
2666  {
2667  $this->_kiosk = $kiosk;
2668  }
2669 
2677  function getKioskMode()
2678  {
2679  if (($this->_kiosk & 1) > 0)
2680  {
2681  return TRUE;
2682  }
2683  else
2684  {
2685  return FALSE;
2686  }
2687  }
2688 
2696  public function setKioskMode($a_kiosk = FALSE)
2697  {
2698  if ($a_kiosk)
2699  {
2700  $this->_kiosk = $this->_kiosk | 1;
2701  }
2702  else
2703  {
2704  if ($this->getKioskMode())
2705  {
2706  $this->_kiosk = $this->_kiosk ^ 1;
2707  }
2708  }
2709  }
2710 
2718  public function getShowKioskModeTitle()
2719  {
2720  if (($this->_kiosk & 2) > 0)
2721  {
2722  return TRUE;
2723  }
2724  else
2725  {
2726  return FALSE;
2727  }
2728  }
2729 
2736  public function setShowKioskModeTitle($a_title = FALSE)
2737  {
2738  if ($a_title)
2739  {
2740  $this->_kiosk = $this->_kiosk | 2;
2741  }
2742  else
2743  {
2744  if ($this->getShowKioskModeTitle())
2745  {
2746  $this->_kiosk = $this->_kiosk ^ 2;
2747  }
2748  }
2749  }
2750 
2759  {
2760  if (($this->_kiosk & 4) > 0)
2761  {
2762  return TRUE;
2763  }
2764  else
2765  {
2766  return FALSE;
2767  }
2768  }
2769 
2776  public function setShowKioskModeParticipant($a_participant = FALSE)
2777  {
2778  if ($a_participant)
2779  {
2780  $this->_kiosk = $this->_kiosk | 4;
2781  }
2782  else
2783  {
2784  if ($this->getShowKioskModeParticipant())
2785  {
2786  $this->_kiosk = $this->_kiosk ^ 4;
2787  }
2788  }
2789  }
2790 
2799  {
2800  return ($this->use_previous_answers) ? $this->use_previous_answers : 0;
2801  }
2802 
2810  function getTitleOutput()
2811  {
2812  return ($this->title_output) ? $this->title_output : 0;
2813  }
2814 
2823  function _getTitleOutput($active_id)
2824  {
2825  global $ilDB;
2826 
2827  $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",
2828  array('integer'),
2829  array($active_id)
2830  );
2831  if ($result->numRows())
2832  {
2833  $row = $ilDB->fetchAssoc($result);
2834  return $row["title_output"];
2835  }
2836  return 0;
2837  }
2838 
2848  function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
2849  {
2850  global $ilDB;
2851  global $ilUser;
2852 
2853  $use_previous_answers = 1;
2854 
2855  $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",
2856  array("integer"),
2857  array($active_id)
2858  );
2859  if ($result->numRows())
2860  {
2861  $row = $ilDB->fetchAssoc($result);
2862  $use_previous_answers = $row["use_previous_answers"];
2863  }
2864 
2865  if ($use_previous_answers == 1)
2866  {
2867  if ($user_active_user_setting)
2868  {
2869  $res = $ilUser->getPref("tst_use_previous_answers");
2870  if ($res !== FALSE)
2871  {
2872  $use_previous_answers = $res;
2873  }
2874  }
2875  }
2876  return $use_previous_answers;
2877  }
2878 
2887  {
2888  return (strlen($this->processing_time)) ? $this->processing_time : NULL;
2889  }
2890 
2897  public function getProcessingTimeAsArray()
2898  {
2899  if (strlen($this->processing_time))
2900  {
2901  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/is", $this->processing_time, $matches))
2902  {
2903  if ((int)$matches[1]+(int)$matches[2]+(int)$matches[3] == 0)
2904  {
2905  return $this->getEstimatedWorkingTime();
2906  }
2907  else
2908  {
2909  return array(
2910  'hh' => $matches[1],
2911  'mm' => $matches[2],
2912  'ss' => $matches[3],
2913  );
2914  }
2915  }
2916  }
2917  return $this->getEstimatedWorkingTime();
2918  }
2919 
2927  function getProcessingTimeInSeconds($active_id = "")
2928  {
2929  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
2930  {
2931  $extratime = $this->getExtraTime($active_id) * 60;
2932  return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3] + $extratime;
2933  }
2934  else
2935  {
2936  return 0;
2937  }
2938  }
2939 
2948  {
2949  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
2950  {
2951  $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
2952  $now = time();
2953  return $ending - $now;
2954  }
2955  else
2956  {
2957  return 0;
2958  }
2959  }
2960 
2969  {
2970  return ($this->enable_processing_time) ? $this->enable_processing_time : 0;
2971  }
2972 
2981  {
2982  return ($this->reset_processing_time) ? $this->reset_processing_time : 0;
2983  }
2984 
2992  function getStartingTime()
2993  {
2994  return (strlen($this->starting_time)) ? $this->starting_time : NULL;
2995  }
2996 
3004  function getEndingTime()
3005  {
3006  return (strlen($this->ending_time)) ? $this->ending_time : NULL;
3007  }
3008 
3016  function setNrOfTries($nr_of_tries = 0)
3017  {
3018  $this->nr_of_tries = $nr_of_tries;
3019  }
3020 
3028  function setUsePreviousAnswers($use_previous_answers = 1)
3029  {
3030  if ($use_previous_answers)
3031  {
3032  $this->use_previous_answers = 1;
3033  }
3034  else
3035  {
3036  $this->use_previous_answers = 0;
3037  }
3038  }
3039 
3041  {
3042  $this->redirection_mode = $redirection_mode;
3043  }
3045  {
3046  return $this->redirection_mode;
3047  }
3049  {
3050  $this->redirection_url = $redirection_url;
3051  }
3053  {
3054  return $this->redirection_url;
3055  }
3056 
3064  function setTitleOutput($title_output = 0)
3065  {
3066  switch ($title_output)
3067  {
3068  case 1:
3069  $this->title_output = 1;
3070  break;
3071  case 2:
3072  $this->title_output = 2;
3073  break;
3074  default:
3075  $this->title_output = 0;
3076  break;
3077  }
3078  }
3079 
3087  function setProcessingTime($processing_time = "00:00:00")
3088  {
3089  $this->processing_time = $processing_time;
3090  }
3091 
3099  function setEnableProcessingTime($enable = 0)
3100  {
3101  if ($enable) {
3102  $this->enable_processing_time = "1";
3103  } else {
3104  $this->enable_processing_time = "0";
3105  }
3106  }
3107 
3115  function setResetProcessingTime($reset = 0)
3116  {
3117  if ($reset)
3118  {
3119  $this->reset_processing_time = 1;
3120  }
3121  else
3122  {
3123  $this->reset_processing_time = 0;
3124  }
3125  }
3126 
3134  function setStartingTime($starting_time = NULL)
3135  {
3136  $this->starting_time = $starting_time;
3137  }
3138 
3146  function setEndingTime($ending_time = NULL)
3147  {
3148  $this->ending_time = $ending_time;
3149  }
3150 
3158  function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
3159  {
3160  $this->count_system = $a_count_system;
3161  }
3162 
3170  function setPassword($a_password = NULL)
3171  {
3172  $this->password = $a_password;
3173  }
3174 
3182  function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
3183  {
3184  $this->score_cutting = $a_score_cutting;
3185  }
3186 
3195  {
3196  $this->mc_scoring = $a_mc_scoring;
3197  }
3198 
3206  function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
3207  {
3208  switch ($a_pass_scoring)
3209  {
3210  case SCORE_BEST_PASS:
3211  $this->pass_scoring = SCORE_BEST_PASS;
3212  break;
3213  default:
3214  $this->pass_scoring = SCORE_LAST_PASS;
3215  break;
3216  }
3217  }
3218 
3226  function removeQuestion($question_id)
3227  {
3228  $question =& ilObjTest::_instanciateQuestion($question_id);
3229  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3231  {
3232  $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
3233  }
3234  $question->delete($question_id);
3235  $this->removeAllTestEditings($question_id);
3236  $this->loadQuestions();
3237  $this->saveQuestionsToDb();
3238  }
3239 
3247  public function removeAllTestEditings($question_id = "")
3248  {
3249  global $ilDB;
3250 
3251  // remove the question from tst_solutions
3252  if ($question_id)
3253  {
3254  $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",
3255  array('integer','integer'),
3256  array($this->getTestId(), $question_id)
3257  );
3258  $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",
3259  array('integer','integer'),
3260  array($this->getTestId(), $question_id)
3261  );
3262  $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",
3263  array('integer','integer'),
3264  array($this->getTestId(), $question_id)
3265  );
3266  $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)",
3267  array('integer'),
3268  array($this->getTestId())
3269  );
3270 
3271  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3273  }
3274  else
3275  {
3276  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE tst_solutions.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3277  array('integer'),
3278  array($this->getTestId())
3279  );
3280  $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)",
3281  array('integer'),
3282  array($this->getTestId())
3283  );
3284  $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)",
3285  array('integer'),
3286  array($this->getTestId())
3287  );
3288  $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)",
3289  array('integer'),
3290  array($this->getTestId())
3291  );
3292 
3293  $query = "SELECT active_id FROM tst_active WHERE test_fi = %s";
3294  $res = $ilDB->queryF($query, array('integer'), array($this->getTestId()));
3295  $activeIds = array();
3296  while( $row = $ilDB->fetchAssoc($res) )
3297  {
3298  $activeIds[] = $row['active_id'];
3299  }
3300 
3301  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3303 
3304  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3306  {
3307  $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
3308  }
3309  }
3310 
3311  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE tst_sequence.active_fi IN (SELECT active_id FROM tst_active WHERE test_fi = %s)",
3312  array('integer'),
3313  array($this->getTestId())
3314  );
3315 
3316  if ($this->isRandomTest())
3317  {
3318  $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)",
3319  array('integer'),
3320  array($this->getTestId())
3321  );
3322  }
3323 
3324  // remove test_active entries, because test has changed
3325  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3326  array('integer'),
3327  array($this->getTestId())
3328  );
3329 
3330  // remove saved user passwords
3331  $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE keyword = %s",
3332  array('text'),
3333  array("tst_password_".$this->getTestId())
3334  );
3335 
3336  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3337  // remove file uploads
3338  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId()))
3339  {
3340  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId());
3341  }
3342  }
3343 
3344  public function removeTestResults(ilTestParticipantData $participantData)
3345  {
3346  if( count($participantData->getAnonymousActiveIds()) )
3347  {
3348  $this->removeTestResultsByActiveIds($participantData->getAnonymousActiveIds());
3349  }
3350 
3351  if( count($participantData->getUserIds()) )
3352  {
3353  /* @var ilTestLP $testLP */
3354  require_once 'Services/Object/classes/class.ilObjectLP.php';
3355  $testLP = ilObjectLP::getInstance($this->getId());
3356  $testLP->resetLPDataForUserIds($participantData->getUserIds(), false);
3357  }
3358 
3359  if( count($participantData->getActiveIds()) )
3360  {
3361  $this->removeTestActives($participantData->getActiveIds());
3362  }
3363  }
3364 
3365  public function removeTestResultsByUserIds($userIds)
3366  {
3367  global $ilDB, $lng;
3368 
3369  require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
3370  $participantData = new ilTestParticipantData($ilDB, $lng);
3371  $participantData->setUserIds($userIds);
3372  $participantData->load($this->getTestId());
3373 
3374  $IN_userIds = $ilDB->in('usr_id', $participantData->getUserIds(), false, 'integer');
3375  $ilDB->manipulateF("DELETE FROM usr_pref WHERE $IN_userIds AND keyword = %s",
3376  array('text'), array("tst_password_".$this->getTestId())
3377  );
3378 
3379  if( count($participantData->getActiveIds()) )
3380  {
3381  $this->removeTestResultsByActiveIds($participantData->getActiveIds());
3382  }
3383  }
3384 
3385  public function removeTestResultsByActiveIds($activeIds)
3386  {
3387  global $ilDB;
3388 
3389  $IN_activeIds = $ilDB->in('active_fi', $activeIds, false, 'integer');
3390 
3391  $ilDB->manipulate("DELETE FROM tst_solutions WHERE $IN_activeIds");
3392  $ilDB->manipulate("DELETE FROM tst_qst_solved WHERE $IN_activeIds");
3393  $ilDB->manipulate("DELETE FROM tst_test_result WHERE $IN_activeIds");
3394  $ilDB->manipulate("DELETE FROM tst_pass_result WHERE $IN_activeIds");
3395  $ilDB->manipulate("DELETE FROM tst_result_cache WHERE $IN_activeIds");
3396  $ilDB->manipulate("DELETE FROM tst_sequence WHERE $IN_activeIds");
3397 
3398  if( $this->isRandomTest() )
3399  {
3400  $ilDB->manipulate("DELETE FROM tst_test_rnd_qst WHERE $IN_activeIds");
3401  }
3402  elseif( $this->isDynamicTest() )
3403  {
3404  $ilDB->manipulate("DELETE FROM tst_seq_qst_tracking WHERE $IN_activeIds");
3405  $ilDB->manipulate("DELETE FROM tst_seq_qst_answstatus WHERE $IN_activeIds");
3406  $ilDB->manipulate("DELETE FROM tst_seq_qst_postponed WHERE $IN_activeIds");
3407  $ilDB->manipulate("DELETE FROM tst_seq_qst_checked WHERE $IN_activeIds");
3408  }
3409 
3410  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3411 
3412  foreach ($activeIds as $active_id)
3413  {
3414  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3415  // remove file uploads
3416  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3417  {
3418  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3419  }
3420 
3422  {
3423  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3424  }
3425  }
3426 
3427  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3429  }
3430 
3431  public function removeTestActives($activeIds)
3432  {
3433  global $ilDB;
3434 
3435  $IN_activeIds = $ilDB->in('active_id', $activeIds, false, 'integer');
3436  $ilDB->manipulate("DELETE FROM tst_active WHERE $IN_activeIds");
3437  }
3438 
3439  function removeTestResultsForUser($user_id)
3440  {
3441  global $ilDB;
3442 
3443  $active_id = $this->getActiveIdOfUser($user_id);
3444 
3445  // remove the question from tst_solutions
3446  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s",
3447  array('integer'),
3448  array($active_id)
3449  );
3450  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s",
3451  array('integer'),
3452  array($active_id)
3453  );
3454  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_result WHERE active_fi = %s",
3455  array('integer'),
3456  array($active_id)
3457  );
3458  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_pass_result WHERE active_fi = %s",
3459  array('integer'),
3460  array($active_id)
3461  );
3462 
3463  if ($this->isRandomTest())
3464  {
3465  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_rnd_qst WHERE active_fi = %s",
3466  array('integer'),
3467  array($active_id)
3468  );
3469  }
3470 
3471  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3473  {
3474  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
3475  }
3476 
3477  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s",
3478  array('integer'),
3479  array($active_id)
3480  );
3481 
3482  // remove test_active entry
3483  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE active_id = %s",
3484  array('integer'),
3485  array($active_id)
3486  );
3487 
3488  // remove saved user password
3489  if ($user_id > 0)
3490  {
3491  $affectedRows = $ilDB->manipulateF("DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s",
3492  array('integer', 'text'),
3493  array($user_id, "tst_password_".$this->getTestId())
3494  );
3495  }
3496 
3497  // TODO: this shouldn't be here since it is question stuff and should be modular but there's no other solution yet
3498  // remove file uploads
3499  if (@is_dir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id"))
3500  {
3501  ilUtil::delDir(CLIENT_WEB_DIR . "/assessment/tst_" . $this->getTestId() . "/$active_id");
3502  }
3503 
3504  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
3506  }
3507 
3515  function questionMoveUp($question_id)
3516  {
3517  global $ilDB;
3518 
3519  // Move a question up in sequence
3520  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3521  array('integer', 'integer'),
3522  array($this->getTestId(), $question_id)
3523  );
3524  $data = $ilDB->fetchObject($result);
3525  if ($data->sequence > 1)
3526  {
3527  // OK, it's not the top question, so move it up
3528  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3529  array('integer','integer'),
3530  array($this->getTestId(), $data->sequence - 1)
3531  );
3532  $data_previous = $ilDB->fetchObject($result);
3533  // change previous dataset
3534  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3535  array('integer','integer'),
3536  array($data->sequence, $data_previous->test_question_id)
3537  );
3538  // move actual dataset up
3539  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3540  array('integer','integer'),
3541  array($data->sequence - 1, $data->test_question_id)
3542  );
3543  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3545  {
3546  $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
3547  }
3548  }
3549  $this->loadQuestions();
3550  }
3551 
3559  function questionMoveDown($question_id)
3560  {
3561  global $ilDB;
3562 
3563  // Move a question down in sequence
3564  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
3565  array('integer','integer'),
3566  array($this->getTestId(), $question_id)
3567  );
3568  $data = $ilDB->fetchObject($result);
3569  $result = $ilDB->queryF("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
3570  array('integer','integer'),
3571  array($this->getTestId(), $data->sequence + 1)
3572  );
3573  if ($result->numRows() == 1)
3574  {
3575  // OK, it's not the last question, so move it down
3576  $data_next = $ilDB->fetchObject($result);
3577  // change next dataset
3578  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3579  array('integer','integer'),
3580  array($data->sequence, $data_next->test_question_id)
3581  );
3582  // move actual dataset down
3583  $affectedRows = $ilDB->manipulateF("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
3584  array('integer','integer'),
3585  array($data->sequence + 1, $data->test_question_id)
3586  );
3587  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3589  {
3590  $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
3591  }
3592  }
3593  $this->loadQuestions();
3594  }
3595 
3603  function duplicateQuestionForTest($question_id)
3604  {
3605  global $ilUser;
3606  $question =& ilObjTest::_instanciateQuestion($question_id);
3607  $duplicate_id = $question->duplicate(true, null, null, null, $this->getId());
3608 
3609  return $duplicate_id;
3610  }
3611 
3620  public function insertQuestion(ilTestQuestionSetConfig $testQuestionSetConfig, $question_id, $linkOnly = false)
3621  {
3622  global $ilDB;
3623 #var_dump($question_id);
3624  if ($linkOnly)
3625  {
3626  $duplicate_id = $question_id;
3627  }
3628  else
3629  {
3630  $duplicate_id = $this->duplicateQuestionForTest($question_id);
3631  }
3632 
3633  // get maximum sequence index in test
3634  $result = $ilDB->queryF("SELECT MAX(sequence) seq FROM tst_test_question WHERE test_fi=%s",
3635  array('integer'),
3636  array($this->getTestId())
3637  );
3638  $sequence = 1;
3639 
3640  if ($result->numRows() == 1)
3641  {
3642  $data = $ilDB->fetchObject($result);
3643  $sequence = $data->seq + 1;
3644  }
3645 
3646  $next_id = $ilDB->nextId('tst_test_question');
3647  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
3648  array('integer', 'integer','integer','integer','integer'),
3649  array($next_id, $this->getTestId(), $duplicate_id, $sequence, time())
3650  );
3651  if ($affectedRows == 1)
3652  {
3653  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3655  {
3656  $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
3657  }
3658  }
3659  // remove test_active entries, because test has changed
3660  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_active WHERE test_fi = %s",
3661  array('integer'),
3662  array($this->getTestId())
3663  );
3664  $this->loadQuestions();
3665  $this->saveCompleteStatus($testQuestionSetConfig);
3666  return $duplicate_id;
3667  }
3668 
3676  function &getQuestionTitles()
3677  {
3678  $titles = array();
3679  if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3680  {
3681  global $ilDB;
3682  $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",
3683  array('integer'),
3684  array($this->getTestId())
3685  );
3686  while ($row = $ilDB->fetchAssoc($result))
3687  {
3688  array_push($titles, $row["title"]);
3689  }
3690  }
3691  return $titles;
3692  }
3693 
3702  {
3703  $titles = array();
3704  if ($this->getQuestionSetType() == self::QUESTION_SET_TYPE_FIXED)
3705  {
3706  global $ilDB;
3707  $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",
3708  array('integer'),
3709  array($this->getTestId())
3710  );
3711  while ($row = $ilDB->fetchAssoc($result))
3712  {
3713  $titles[$row['question_id']] = $row["title"];
3714  }
3715  }
3716  return $titles;
3717  }
3718 
3728  {
3729  if ($this->getTitleOutput() == 2)
3730  {
3731  return $this->lng->txt("ass_question");
3732  }
3733  else
3734  {
3735  return $title;
3736  }
3737  }
3738 
3747  function getQuestionDataset($question_id)
3748  {
3749  global $ilDB;
3750 
3751  $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",
3752  array('integer'),
3753  array($question_id)
3754  );
3755  $row = $ilDB->fetchObject($result);
3756  return $row;
3757  }
3758 
3765  function &getExistingQuestions($pass = NULL)
3766  {
3767  global $ilUser;
3768  global $ilDB;
3769 
3770  $existing_questions = array();
3771  $active_id = $this->getActiveIdOfUser($ilUser->getId());
3772  if ($this->isRandomTest())
3773  {
3774  if (is_null($pass)) $pass = 0;
3775  $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",
3776  array('integer','integer'),
3777  array($active_id, $pass)
3778  );
3779  }
3780  else
3781  {
3782  $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",
3783  array('integer'),
3784  array($this->getTestId())
3785  );
3786  }
3787  while ($data = $ilDB->fetchObject($result))
3788  {
3789  if( $data->original_id === null )
3790  {
3791  continue;
3792  }
3793 
3794  array_push($existing_questions, $data->original_id);
3795  }
3796  return $existing_questions;
3797  }
3798 
3806  function getQuestionType($question_id)
3807  {
3808  global $ilDB;
3809 
3810  if ($question_id < 1) return -1;
3811  $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",
3812  array('integer'),
3813  array($question_id)
3814  );
3815  if ($result->numRows() == 1)
3816  {
3817  $data = $ilDB->fetchObject($result);
3818  return $data->type_tag;
3819  }
3820  else
3821  {
3822  return "";
3823  }
3824  }
3825 
3832  function startWorkingTime($active_id, $pass)
3833  {
3834  global $ilDB;
3835 
3836  $next_id = $ilDB->nextId('tst_times');
3837  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
3838  array('integer', 'integer', 'timestamp', 'timestamp', 'integer', 'integer'),
3839  array($next_id, $active_id, strftime("%Y-%m-%d %H:%M:%S"), strftime("%Y-%m-%d %H:%M:%S"), $pass, time())
3840  );
3841  return $next_id;
3842  }
3843 
3850  function updateWorkingTime($times_id)
3851  {
3852  global $ilDB;
3853 
3854  $affectedRows = $ilDB->manipulateF("UPDATE tst_times SET finished = %s, tstamp = %s WHERE times_id = %s",
3855  array('timestamp', 'integer', 'integer'),
3856  array(strftime("%Y-%m-%d %H:%M:%S"), time(), $times_id)
3857  );
3858  }
3859 
3866  function &getWorkedQuestions($active_id, $pass = NULL)
3867  {
3868  global $ilUser;
3869  global $ilDB;
3870 
3871  if (is_null($pass))
3872  {
3873  $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3874  array('integer','integer'),
3875  array($active_id, 0)
3876  );
3877  }
3878  else
3879  {
3880  $result = $ilDB->queryF("SELECT question_fi FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
3881  array('integer','integer'),
3882  array($active_id, $pass)
3883  );
3884  }
3885  $result_array = array();
3886  while ($row = $ilDB->fetchAssoc($result))
3887  {
3888  array_push($result_array, $row["question_fi"]);
3889  }
3890  return $result_array;
3891  }
3892 
3901  function isTestFinishedToViewResults($active_id, $currentpass)
3902  {
3903  $num = $this->getPassFinishDate($active_id, $currentpass);
3904  return ((($currentpass > 0) && ($num == 0)) || $this->isTestFinished($active_id)) ? true : false;
3905  }
3906 
3913  function &getAllQuestions($pass = NULL)
3914  {
3915  global $ilUser;
3916  global $ilDB;
3917 
3918  $result_array = array();
3919  if ($this->isRandomTest())
3920  {
3921  $active_id = $this->getActiveIdOfUser($ilUser->getId());
3922  $this->loadQuestions($active_id, $pass);
3923  if (count($this->questions) == 0) return $result_array;
3924  if (is_null($pass))
3925  {
3926  $pass = $this->_getPass($active_id);
3927  }
3928  $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'),
3929  array('integer','integer'),
3930  array($active_id, $pass)
3931  );
3932  }
3933  else
3934  {
3935  if (count($this->questions) == 0) return $result_array;
3936  $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'));
3937  }
3938  while ($row = $ilDB->fetchAssoc($result))
3939  {
3940  $result_array[$row["question_id"]] = $row;
3941  }
3942  return $result_array;
3943  }
3944 
3953  function getActiveIdOfUser($user_id = "", $anonymous_id = "")
3954  {
3955  global $ilDB;
3956  global $ilUser;
3957 
3958  if (!$user_id) $user_id = $ilUser->getId();
3959  if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
3960  {
3961  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3962  array('integer','integer','text'),
3963  array($user_id, $this->test_id, $_SESSION["tst_access_code"][$this->getTestId()])
3964  );
3965  }
3966  else if (strlen($anonymous_id))
3967  {
3968  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
3969  array('integer','integer','text'),
3970  array($user_id, $this->test_id, $anonymous_id)
3971  );
3972  }
3973  else
3974  {
3975  if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
3976  {
3977  return NULL;
3978  }
3979  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
3980  array('integer','integer'),
3981  array($user_id, $this->test_id)
3982  );
3983  }
3984  if ($result->numRows())
3985  {
3986  $row = $ilDB->fetchAssoc($result);
3987  return $row["active_id"];
3988  }
3989  else
3990  {
3991  return 0;
3992  }
3993  }
3994 
4003  function _getActiveIdOfUser($user_id = "", $test_id = "")
4004  {
4005  global $ilDB;
4006  global $ilUser;
4007 
4008  if (!$user_id) {
4009  $user_id = $ilUser->id;
4010  }
4011  if (!$test_id)
4012  {
4013  return "";
4014  }
4015  $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
4016  array('integer', 'integer'),
4017  array($user_id, $test_id)
4018  );
4019  if ($result->numRows())
4020  {
4021  $row = $ilDB->fetchAssoc($result);
4022  return $row["active_id"];
4023  }
4024  else
4025  {
4026  return "";
4027  }
4028  }
4029 
4036  function pcArrayShuffle($array)
4037  {
4038  $keys = array_keys($array);
4039  shuffle($keys);
4040  $result = array();
4041  foreach ($keys as $key)
4042  {
4043  $result[$key] = $array[$key];
4044  }
4045  return $result;
4046  }
4047 
4055  function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE)
4056  {
4057  global $tree, $ilDB, $lng, $ilPluginAdmin;
4058 
4059  $results = $this->getResultsForActiveId($active_id);
4060 
4061  if( is_null($pass) )
4062  {
4063  $pass = $results['pass'];
4064  }
4065 
4066  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
4067  $testSessionFactory = new ilTestSessionFactory($this);
4068  $testSession = $testSessionFactory->getSession($active_id);
4069 
4070  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
4071  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
4072  $testSequence = $testSequenceFactory->getSequenceByPass($testSession, $pass);
4073 
4074  if( $this->isDynamicTest() )
4075  {
4076  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
4077  $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
4078  $dynamicQuestionSetConfig->loadFromDb();
4079 
4080  $testSequence->loadFromDb($dynamicQuestionSetConfig);
4081  $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
4082 
4083  $sequence = $testSequence->getUserSequenceQuestions();
4084  }
4085  else
4086  {
4087  $testSequence->loadFromDb();
4088  $testSequence->loadQuestions();
4089 
4090  if( $ordered_sequence )
4091  {
4092  $sequence = $testSequence->getOrderedSequenceQuestions();
4093  }
4094  else
4095  {
4096  $sequence = $testSequence->getUserSequenceQuestions();
4097  }
4098  }
4099 
4100  $arrResults = array();
4101 
4102  $query = "
4103  SELECT tst_test_result.question_fi,
4104  tst_test_result.points reached,
4105  tst_test_result.hint_count requested_hints,
4106  tst_test_result.hint_points hint_points,
4107  tst_test_result.answered answered
4108 
4109  FROM tst_test_result
4110 
4111  LEFT JOIN tst_solutions
4112  ON tst_solutions.active_fi = tst_test_result.active_fi
4113  AND tst_solutions.question_fi = tst_test_result.question_fi
4114 
4115  WHERE tst_test_result.active_fi = %s
4116  AND tst_test_result.pass = %s
4117  ";
4118 
4119  $solutionresult = $ilDB->queryF(
4120  $query, array('integer', 'integer'), array($active_id, $pass)
4121  );
4122 
4123  while( $row = $ilDB->fetchAssoc($solutionresult) )
4124  {
4125  $arrResults[ $row['question_fi'] ] = $row;
4126  }
4127 
4128  $numWorkedThrough = count($arrResults);
4129 
4130  require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
4131 
4132  $IN_question_ids = $ilDB->in('qpl_questions.question_id', $sequence, false, 'integer');
4133 
4134  $query = "
4135  SELECT qpl_questions.*,
4136  qpl_qst_type.type_tag,
4137  qpl_sol_sug.question_fi has_sug_sol
4138 
4139  FROM qpl_qst_type,
4140  qpl_questions
4141 
4142  LEFT JOIN qpl_sol_sug
4143  ON qpl_sol_sug.question_fi = qpl_questions.question_id
4144 
4145  WHERE qpl_qst_type.question_type_id = qpl_questions.question_type_fi
4146  AND $IN_question_ids
4147  ";
4148 
4149  $result = $ilDB->query($query);
4150 
4151  $unordered = array();
4152 
4153  $key = 1;
4154 
4155  $obligationsAnswered = true;
4156 
4157  while( $row = $ilDB->fetchAssoc($result) )
4158  {
4159  $percentvalue = (
4160  $row['points'] ? $arrResults[ $row['question_id'] ]['reached'] / $row['points'] : 0
4161  );
4162 
4163  if( $percentvalue < 0 ) $percentvalue = 0.0;
4164 
4165  $data = array(
4166  "nr" => "$key",
4167  "title" => ilUtil::prepareFormOutput($row['title']),
4168  "max" => round($row['points'], 2),
4169  "reached" => round($arrResults[$row['question_id']]['reached'],2),
4170  'requested_hints' => $arrResults[$row['question_id']]['requested_hints'],
4171  'hint_points' => $arrResults[$row['question_id']]['hint_points'],
4172  "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
4173  "solution" => ($row['has_sug_sol']) ? assQuestion::_getSuggestedSolutionOutput($row['question_id']) : '',
4174  "type" => $row["type_tag"],
4175  "qid" => $row['question_id'],
4176  "original_id" => $row["original_id"],
4177  "workedthrough" => isset($arrResults[$row['question_id']]) ? 1 : 0,
4178  'answered' => $arrResults[$row['question_id']]['answered']
4179  );
4180 
4181  if( !$arrResults[ $row['question_id'] ]['answered'] )
4182  {
4183  $obligationsAnswered = false;
4184  }
4185 
4186  $unordered[ $row['question_id'] ] = $data;
4187 
4188  $key++;
4189  }
4190 
4191  $pass_max = 0;
4192  $pass_reached = 0;
4193  $pass_requested_hints = 0;
4194  $pass_hint_points = 0;
4195  $key = 1;
4196 
4197  $found = array();
4198 
4199  foreach( $sequence as $qid )
4200  {
4201  // building pass point sums based on prepared data
4202  // for question that exists in users qst sequence
4203  $pass_max += round($unordered[$qid]['max'], 2);
4204  $pass_reached += round($unordered[$qid]['reached'], 2);
4205  $pass_requested_hints += $unordered[$qid]['requested_hints'];
4206  $pass_hint_points += $unordered[$qid]['hint_points'];
4207 
4208  // pickup prepared data for question
4209  // that exists in users qst sequence
4210  $unordered[$qid]['nr'] = $key;
4211  array_push($found, $unordered[$qid]);
4212 
4213  // increment key counter
4214  $key++;
4215  }
4216 
4217  $unordered = null;
4218 
4219  if( $this->getScoreCutting() == 1 )
4220  {
4221  if( $results['reached_points'] < 0 )
4222  {
4223  $results['reached_points'] = 0;
4224  }
4225 
4226  if( $pass_reached < 0 ) $pass_reached = 0;
4227  }
4228 
4229  $found['pass']['total_max_points'] = $pass_max;
4230  $found['pass']['total_reached_points'] = $pass_reached;
4231  $found['pass']['total_requested_hints'] = $pass_requested_hints;
4232  $found['pass']['total_hint_points'] = $pass_hint_points;
4233  $found['pass']['percent'] = ($pass_max > 0) ? $pass_reached / $pass_max : 0;
4234  $found['pass']['obligationsAnswered'] = $obligationsAnswered;
4235  $found['pass']['num_workedthrough'] = $numWorkedThrough;
4236 
4237  $found["test"]["total_max_points"] = $results['max_points'];
4238  $found["test"]["total_reached_points"] = $results['reached_points'];
4239  $found["test"]["total_requested_hints"] = $results['hint_count'];
4240  $found["test"]["total_hint_points"] = $results['hint_points'];
4241  $found["test"]["result_pass"] = $results['pass'];
4242  $found['test']['obligations_answered'] = $results['obligations_answered'];
4243 
4244  if( (!$total_reached_points) or (!$total_max_points) )
4245  {
4246  $percentage = 0.0;
4247  }
4248  else
4249  {
4250  $percentage = ($total_reached_points / $total_max_points) * 100.0;
4251 
4252  if( $percentage < 0 ) $percentage = 0.0;
4253  }
4254 
4255  $found["test"]["passed"] = $results['passed'];
4256 
4257  return $found;
4258  }
4259 
4266  function evalTotalPersons()
4267  {
4268  global $ilDB;
4269 
4270  $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s",
4271  array('integer'),
4272  array($this->getTestId())
4273  );
4274  $row = $ilDB->fetchAssoc($result);
4275  return $row["total"];
4276  }
4277 
4284  function getCompleteWorkingTime($user_id)
4285  {
4286  global $ilDB;
4287 
4288  $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",
4289  array('integer','integer'),
4290  array($this->getTestId(), $user_id)
4291  );
4292  $time = 0;
4293  while ($row = $ilDB->fetchAssoc($result))
4294  {
4295  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4296  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4297  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4298  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4299  $time += ($epoch_2 - $epoch_1);
4300  }
4301  return $time;
4302  }
4303 
4311  {
4312  return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
4313  }
4314 
4323  {
4324  global $ilDB;
4325 
4326  $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",
4327  array('integer'),
4328  array($test_id)
4329  );
4330  $time = 0;
4331  $times = array();
4332  while ($row = $ilDB->fetchAssoc($result))
4333  {
4334  if (!array_key_exists($row["active_fi"], $times))
4335  {
4336  $times[$row["active_fi"]] = 0;
4337  }
4338  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4339  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4340  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4341  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4342  $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
4343  }
4344  return $times;
4345  }
4346 
4354  {
4355  global $ilDB;
4356 
4357  $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",
4358  array('integer','integer'),
4359  array($this->getTestId(), $active_id)
4360  );
4361  $time = 0;
4362  while ($row = $ilDB->fetchAssoc($result))
4363  {
4364  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4365  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4366  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4367  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4368  $time += ($epoch_2 - $epoch_1);
4369  }
4370  return $time;
4371  }
4372 
4380  {
4381  global $ilDB;
4382 
4383  $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s AND pass = %s ORDER BY started",
4384  array('integer','integer'),
4385  array($active_id, $pass)
4386  );
4387  $time = 0;
4388  while ($row = $ilDB->fetchAssoc($result))
4389  {
4390  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4391  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4392  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4393  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4394  $time += ($epoch_2 - $epoch_1);
4395  }
4396  return $time;
4397  }
4398 
4406  function getVisitTimeOfParticipant($active_id)
4407  {
4408  return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
4409  }
4410 
4419  function _getVisitTimeOfParticipant($test_id, $active_id)
4420  {
4421  global $ilDB;
4422 
4423  $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",
4424  array('integer','integer'),
4425  array($test_id, $active_id)
4426  );
4427  $firstvisit = 0;
4428  $lastvisit = 0;
4429  while ($row = $ilDB->fetchAssoc($result))
4430  {
4431  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
4432  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4433  if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
4434  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
4435  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4436  if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
4437  }
4438  return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
4439  }
4440 
4447  function &evalStatistical($active_id)
4448  {
4449  global $ilDB;
4450 // global $ilBench;
4451  $pass = ilObjTest::_getResultPass($active_id);
4452  $test_result =& $this->getTestResult($active_id, $pass);
4453  $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",
4454  array('integer'),
4455  array($active_id)
4456  );
4457  $times = array();
4458  $first_visit = 0;
4459  $last_visit = 0;
4460  while ($row = $ilDB->fetchObject($result))
4461  {
4462  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
4463  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4464  if (!$first_visit) {
4465  $first_visit = $epoch_1;
4466  }
4467  if ($epoch_1 < $first_visit) {
4468  $first_visit = $epoch_1;
4469  }
4470  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
4471  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
4472  if (!$last_visit) {
4473  $last_visit = $epoch_2;
4474  }
4475  if ($epoch_2 > $last_visit) {
4476  $last_visit = $epoch_2;
4477  }
4478  $times[$row->active_fi] += ($epoch_2 - $epoch_1);
4479  }
4480  $max_time = 0;
4481  foreach ($times as $key => $value) {
4482  $max_time += $value;
4483  }
4484  if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
4485  {
4486  $percentage = 0.0;
4487  }
4488  else
4489  {
4490  $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
4491  if ($percentage < 0) $percentage = 0.0;
4492  }
4493  $mark_obj = $this->mark_schema->getMatchingMark($percentage);
4494  $first_date = getdate($first_visit);
4495  $last_date = getdate($last_visit);
4496  $qworkedthrough = 0;
4497  foreach ($test_result as $key => $value)
4498  {
4499  if (preg_match("/\d+/", $key))
4500  {
4501  $qworkedthrough += $value["workedthrough"];
4502  }
4503  }
4504  if (!$qworkedthrough)
4505  {
4506  $atimeofwork = 0;
4507  }
4508  else
4509  {
4510  $atimeofwork = $max_time / $qworkedthrough;
4511  }
4512 
4513  $obligationsAnswered = $test_result["test"]["obligations_answered"];
4514 
4515  $result_mark = "";
4516  $passed = "";
4517 
4518  if ($mark_obj)
4519  {
4520  $result_mark = $mark_obj->getShortName();
4521 
4522  if( $mark_obj->getPassed() && $obligationsAnswered )
4523  {
4524  $passed = 1;
4525  }
4526  else
4527  {
4528  $passed = 0;
4529  }
4530  }
4531  $percent_worked_through = 0;
4532  if (count($this->questions))
4533  {
4534  $percent_worked_through = $qworkedthrough / count($this->questions);
4535  }
4536  $result_array = array(
4537  "qworkedthrough" => $qworkedthrough,
4538  "qmax" => count($this->questions),
4539  "pworkedthrough" => $percent_worked_through,
4540  "timeofwork" => $max_time,
4541  "atimeofwork" => $atimeofwork,
4542  "firstvisit" => $first_date,
4543  "lastvisit" => $last_date,
4544  "resultspoints" => $test_result["test"]["total_reached_points"],
4545  "maxpoints" => $test_result["test"]["total_max_points"],
4546  "resultsmarks" => $result_mark,
4547  "passed" => $passed,
4548  "distancemedian" => "0"
4549  );
4550  foreach ($test_result as $key => $value)
4551  {
4552  if (preg_match("/\d+/", $key))
4553  {
4554  $result_array[$key] = $value;
4555  }
4556  }
4557  return $result_array;
4558  }
4559 
4568  {
4569  $totalpoints_array = array();
4570  $all_users =& $this->evalTotalParticipantsArray();
4571  foreach ($all_users as $active_id => $user_name)
4572  {
4573  $test_result =& $this->getTestResult($active_id);
4574  $reached = $test_result["test"]["total_reached_points"];
4575  $total = $test_result["test"]["total_max_points"];
4576  $percentage = $total != 0 ? $reached/$total : 0;
4577  $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
4578 
4579  $obligationsAnswered = $test_result["test"]["obligations_answered"];
4580 
4581  if ($mark)
4582  {
4583  if( $mark->getPassed() && $obligationsAnswered )
4584  {
4585  array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
4586  }
4587  }
4588  }
4589  return $totalpoints_array;
4590  }
4591 
4597  public function &getParticipants()
4598  {
4599  global $ilDB;
4600  $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",
4601  array('integer'),
4602  array($this->getTestId())
4603  );
4604  $persons_array = array();
4605  while ($row = $ilDB->fetchAssoc($result))
4606  {
4607  $name = $this->lng->txt("unknown");
4608  $fullname = $this->lng->txt("unknown");
4609  $login = "";
4610  if (!$this->getAnonymity())
4611  {
4612  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4613  {
4614  $name = $this->lng->txt("deleted_user");
4615  $fullname = $this->lng->txt("deleted_user");
4616  $login = $this->lng->txt("unknown");
4617  }
4618  else
4619  {
4620  $login = $row["login"];
4621  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4622  {
4623  $name = $this->lng->txt("unknown");
4624  $fullname = $this->lng->txt("unknown");
4625  }
4626  else
4627  {
4628  $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4629  $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
4630  }
4631  }
4632  }
4633  $persons_array[$row["active_id"]] = array(
4634  "name" => $name,
4635  "fullname" => $fullname,
4636  "login" => $login
4637  );
4638  }
4639  return $persons_array;
4640  }
4641 
4648  function &evalTotalPersonsArray($name_sort_order = "asc")
4649  {
4650  global $ilDB;
4651  $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),
4652  array('integer'),
4653  array($this->getTestId())
4654  );
4655  $persons_array = array();
4656  while ($row = $ilDB->fetchAssoc($result))
4657  {
4658  if ($this->getAnonymity())
4659  {
4660  $persons_array[$row["active_id"]] = $this->lng->txt("unknown");
4661  }
4662  else
4663  {
4664  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4665  {
4666  $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
4667  }
4668  else
4669  {
4670  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4671  {
4672  $persons_array[$row["active_id"]] = $row["lastname"];
4673  }
4674  else
4675  {
4676  $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
4677  }
4678  }
4679  }
4680  }
4681  return $persons_array;
4682  }
4683 
4690  function &evalTotalParticipantsArray($name_sort_order = "asc")
4691  {
4692  global $ilDB;
4693  $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),
4694  array('integer'),
4695  array($this->getTestId())
4696  );
4697  $persons_array = array();
4698  while ($row = $ilDB->fetchAssoc($result))
4699  {
4700  if ($this->getAnonymity())
4701  {
4702  $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("unknown"));
4703  }
4704  else
4705  {
4706  if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
4707  {
4708  $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
4709  }
4710  else
4711  {
4712  if ($row["user_fi"] == ANONYMOUS_USER_ID)
4713  {
4714  $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
4715  }
4716  else
4717  {
4718  $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
4719  }
4720  }
4721  }
4722  }
4723  return $persons_array;
4724  }
4725 
4733  {
4734  global $ilDB;
4735 
4736  $result = $ilDB->queryF("SELECT COUNT(active_id) total FROM tst_active WHERE test_fi = %s AND submitted = %s",
4737  array('integer', 'integer'),
4738  array($this->getTestId(), 1)
4739  );
4740  $row = $ilDB->fetchAssoc($result);
4741  return $row["total"];
4742  }
4743 
4750  function &getQuestionsOfTest($active_id)
4751  {
4752  global $ilDB;
4753  if ($this->isRandomTest())
4754  {
4755  $ilDB->setLimit($this->getQuestionCount(), 0);
4756  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4757  "tst_test_rnd_qst.pass, qpl_questions.points " .
4758  "FROM tst_test_rnd_qst, qpl_questions " .
4759  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4760  "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4761  array('integer'),
4762  array($active_id)
4763  );
4764  }
4765  else
4766  {
4767  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4768  "qpl_questions.points " .
4769  "FROM tst_test_question, tst_active, qpl_questions " .
4770  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4771  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4772  array('integer'),
4773  array($active_id)
4774  );
4775  }
4776  $qtest = array();
4777  if ($result->numRows())
4778  {
4779  while ($row = $ilDB->fetchAssoc($result))
4780  {
4781  array_push($qtest, $row);
4782  }
4783  }
4784  return $qtest;
4785  }
4786 
4793  function &getQuestionsOfPass($active_id, $pass)
4794  {
4795  global $ilDB;
4796  if ($this->isRandomTest())
4797  {
4798  $ilDB->setLimit($this->getQuestionCount(), 0);
4799  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, " .
4800  "qpl_questions.points " .
4801  "FROM tst_test_rnd_qst, qpl_questions " .
4802  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4803  "AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s " .
4804  "ORDER BY tst_test_rnd_qst.sequence",
4805  array('integer', 'integer'),
4806  array($active_id, $pass)
4807  );
4808  }
4809  else
4810  {
4811  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4812  "qpl_questions.points " .
4813  "FROM tst_test_question, tst_active, qpl_questions " .
4814  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4815  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
4816  array('integer'),
4817  array($active_id)
4818  );
4819  }
4820  $qpass = array();
4821  if ($result->numRows())
4822  {
4823  while ($row = $ilDB->fetchAssoc($result))
4824  {
4825  array_push($qpass, $row);
4826  }
4827  }
4828  return $qpass;
4829  }
4830 
4832  {
4833  global $ilDB;
4834 
4835  include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
4836  include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
4837  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
4838 
4839  $data = new ilTestEvaluationData($this);
4840 
4841  $query = "
4842  SELECT tst_test_result.*,
4843  qpl_questions.original_id,
4844  qpl_questions.title questiontitle,
4845  qpl_questions.points maxpoints
4846 
4847  FROM tst_test_result, qpl_questions, tst_active
4848 
4849  WHERE tst_active.active_id = tst_test_result.active_fi
4850  AND qpl_questions.question_id = tst_test_result.question_fi
4851  AND tst_active.test_fi = %s
4852 
4853  ORDER BY tst_active.active_id ASC, tst_test_result.pass ASC, tst_test_result.tstamp DESC
4854  ";
4855 
4856  $result = $ilDB->queryF(
4857  $query, array('integer'), array($this->getTestId())
4858  );
4859 
4860  $pass = NULL;
4861  $checked = array();
4862  $datasets = 0;
4863 
4864  while( $row = $ilDB->fetchAssoc($result) )
4865  {
4866  $participantObject = $data->getParticipant($row["active_fi"]);
4867 
4868  if( !($participantObject instanceof ilTestEvaluationUserData) )
4869  {
4870  continue;
4871  }
4872 
4873  $passObject = $participantObject->getPass($row["pass"]);
4874 
4875  if( !($passObject instanceof ilTestEvaluationPassData) )
4876  {
4877  continue;
4878  }
4879 
4880  $passObject->addAnsweredQuestion(
4881  $row["question_fi"], $row["maxpoints"], $row["points"], $row['answered'], null, $row['manual']
4882  );
4883  }
4884 
4885  foreach( array_keys($data->getParticipants()) as $active_id )
4886  {
4887  if( $this->isRandomTest() )
4888  {
4889  for( $testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++ )
4890  {
4891  $ilDB->setLimit($this->getQuestionCount(), 0);
4892  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.sequence, tst_test_rnd_qst.question_fi, qpl_questions.original_id, " .
4893  "tst_test_rnd_qst.pass, qpl_questions.points, qpl_questions.title " .
4894  "FROM tst_test_rnd_qst, qpl_questions " .
4895  "WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id " .
4896  "AND tst_test_rnd_qst.pass = %s " .
4897  "AND tst_test_rnd_qst.active_fi = %s ORDER BY tst_test_rnd_qst.sequence",
4898  array('integer','integer'),
4899  array($testpass, $active_id)
4900  );
4901  if ($result->numRows())
4902  {
4903  while ($row = $ilDB->fetchAssoc($result))
4904  {
4905  $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
4906  $data->getParticipant($active_id)->addQuestion($row["original_id"], $row["question_fi"], $row["points"], $row["sequence"], $tpass);
4907  $data->addQuestionTitle($row["question_fi"], $row["title"]);
4908  }
4909  }
4910  }
4911  }
4912  else
4913  {
4914  $result = $ilDB->queryF("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
4915  "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
4916  "FROM tst_test_question, tst_active, qpl_questions " .
4917  "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
4918  "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
4919  array('integer'),
4920  array($active_id)
4921  );
4922  if ($result->numRows())
4923  {
4924  $questionsbysequence = array();
4925 
4926  while ($row = $ilDB->fetchAssoc($result))
4927  {
4928  $questionsbysequence[$row["sequence"]] = $row;
4929  }
4930 
4931  $seqresult = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s",
4932  array('integer'),
4933  array($active_id)
4934  );
4935 
4936  while ($seqrow = $ilDB->fetchAssoc($seqresult))
4937  {
4938  $questionsequence = unserialize($seqrow["sequence"]);
4939  foreach ($questionsequence as $sidx => $seq)
4940  {
4941  $data->getParticipant($active_id)->addQuestion($questionsbysequence[$seq]["original_id"], $questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
4942  $data->addQuestionTitle($questionsbysequence[$seq]["question_fi"], $questionsbysequence[$seq]["title"]);
4943  }
4944  }
4945  }
4946  }
4947  }
4948 
4949  if ($this->ects_output)
4950  {
4951  $passed_array =& $this->getTotalPointsPassedArray();
4952  }
4953 
4954  foreach( array_keys($data->getParticipants()) as $active_id )
4955  {
4956  $tstUserData = $data->getParticipant($active_id);
4957 
4958  $percentage = $tstUserData->getReachedPointsInPercent();
4959 
4960  $obligationsAnswered = $tstUserData->areObligationsAnswered();
4961 
4962  $mark = $this->mark_schema->getMatchingMark($percentage);
4963 
4964  if (is_object($mark))
4965  {
4966  $tstUserData->setMark($mark->getShortName());
4967  $tstUserData->setMarkOfficial($mark->getOfficialName());
4968 
4969  $tstUserData->setPassed(
4970  $mark->getPassed() && $tstUserData->areObligationsAnswered()
4971  );
4972  }
4973 
4974  if ($this->ects_output)
4975  {
4976  $ects_mark = $this->getECTSGrade(
4977  $passed_array, $tstUserData->getReached(), $tstUserData->getMaxPoints()
4978  );
4979 
4980  $tstUserData->setECTSMark($ects_mark);
4981  }
4982 
4983  $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
4984 
4985  $tstUserData->setFirstVisit($visitingTime["firstvisit"]);
4986  $tstUserData->setLastVisit($visitingTime["lastvisit"]);
4987  }
4988 
4989  return $data;
4990  }
4991 
4993  {
4994  global $ilDB;
4995 
4997 
4998  switch( $questionSetType )
4999  {
5001 
5002  $res = $ilDB->queryF("
5003  SELECT COUNT(qpl_questions.question_id) qcount,
5004  SUM(qpl_questions.points) qsum
5005  FROM tst_active
5006  INNER JOIN tst_tests
5007  ON tst_tests.test_id = tst_active.test_fi
5008  INNER JOIN tst_dyn_quest_set_cfg
5009  ON tst_dyn_quest_set_cfg.test_fi = tst_tests.test_id
5010  INNER JOIN qpl_questions
5011  ON qpl_questions.obj_fi = tst_dyn_quest_set_cfg.source_qpl_fi
5012  AND qpl_questions.original_id IS NULL
5013  AND qpl_questions.complete = %s
5014  WHERE tst_active.active_id = %s
5015  ",
5016  array('integer', 'integer'),
5017  array(1, $active_id)
5018  );
5019 
5020  break;
5021 
5023 
5024  $res = $ilDB->queryF("
5025  SELECT tst_test_rnd_qst.pass,
5026  COUNT(tst_test_rnd_qst.question_fi) qcount,
5027  SUM(qpl_questions.points) qsum
5028 
5029  FROM tst_test_rnd_qst,
5030  qpl_questions
5031 
5032  WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id
5033  AND tst_test_rnd_qst.active_fi = %s
5034  AND pass = %s
5035 
5036  GROUP BY tst_test_rnd_qst.active_fi,
5037  tst_test_rnd_qst.pass
5038  ",
5039  array('integer', 'integer'),
5040  array($active_id, $pass)
5041  );
5042 
5043  break;
5044 
5046 
5047  $res = $ilDB->queryF("
5048  SELECT COUNT(tst_test_question.question_fi) qcount,
5049  SUM(qpl_questions.points) qsum
5050 
5051  FROM tst_test_question,
5052  qpl_questions,
5053  tst_active
5054 
5055  WHERE tst_test_question.question_fi = qpl_questions.question_id
5056  AND tst_test_question.test_fi = tst_active.test_fi
5057  AND tst_active.active_id = %s
5058 
5059  GROUP BY tst_test_question.test_fi
5060  ",
5061  array('integer'),
5062  array($active_id)
5063  );
5064 
5065  break;
5066 
5067  default:
5068 
5069  throw new ilTestException("not supported question set type: $questionSetType");
5070  }
5071 
5072  $row = $ilDB->fetchAssoc($res);
5073 
5074  if( is_array($row) )
5075  {
5076  return array("count" => $row["qcount"], "points" => $row["qsum"]);
5077  }
5078 
5079  return array("count" => 0, "points" => 0);
5080  }
5081 
5082  function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
5083  {
5084  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
5085  include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
5086  include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
5088  if ($withStatistics)
5089  {
5090  $data->calculateStatistics();
5091  }
5092  $data->setFilter($filterby, $filtertext);
5093  return $data;
5094  }
5095 
5103  {
5104  return $this->_evalResultsOverview($this->getTestId());
5105  }
5106 
5113  function &_evalResultsOverview($test_id)
5114  {
5115  global $ilDB;
5116 
5117  $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5118  "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5119  "qpl_questions.points maxpoints " .
5120  "FROM tst_test_result, qpl_questions, tst_active " .
5121  "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5122  "WHERE tst_active.active_id = tst_test_result.active_fi " .
5123  "AND qpl_questions.question_id = tst_test_result.question_fi " .
5124  "AND tst_active.test_fi = %s " .
5125  "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5126  array('integer'),
5127  array($test_id)
5128  );
5129  $overview = array();
5130  while ($row = $ilDB->fetchAssoc($result))
5131  {
5132  if (!array_key_exists($row["active_fi"], $overview))
5133  {
5134  $overview[$row["active_fi"]] = array();
5135  $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5136  $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5137  $overview[$row["active_fi"]]["title"] = $row["title"];
5138  $overview[$row["active_fi"]]["login"] = $row["login"];
5139  $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5140  $overview[$row["active_fi"]]["started"] = $row["started"];
5141  $overview[$row["active_fi"]]["finished"] = $row["finished"];
5142  }
5143  if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5144  {
5145  $overview[$row["active_fi"]][$row["pass"]] = array();
5146  $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5147  $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5148  }
5149  array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5150  $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5151  }
5152  return $overview;
5153  }
5154 
5162  function &evalResultsOverviewOfParticipant($active_id)
5163  {
5164  global $ilDB;
5165 
5166  $result = $ilDB->queryF("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
5167  "tst_test_result.*, qpl_questions.original_id, qpl_questions.title questiontitle, " .
5168  "qpl_questions.points maxpoints " .
5169  "FROM tst_test_result, qpl_questions, tst_active " .
5170  "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
5171  "WHERE tst_active.active_id = tst_test_result.active_fi " .
5172  "AND qpl_questions.question_id = tst_test_result.question_fi " .
5173  "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
5174  "ORDER BY tst_active.active_id, tst_test_result.pass, tst_test_result.tstamp",
5175  array('integer', 'integer'),
5176  array($this->getTestId(), $active_id)
5177  );
5178  $overview = array();
5179  while ($row = $ilDB->fetchAssoc($result))
5180  {
5181  if (!array_key_exists($row["active_fi"], $overview))
5182  {
5183  $overview[$row["active_fi"]] = array();
5184  $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
5185  $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
5186  $overview[$row["active_fi"]]["title"] = $row["title"];
5187  $overview[$row["active_fi"]]["login"] = $row["login"];
5188  $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
5189  $overview[$row["active_fi"]]["started"] = $row["started"];
5190  $overview[$row["active_fi"]]["finished"] = $row["finished"];
5191  }
5192  if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
5193  {
5194  $overview[$row["active_fi"]][$row["pass"]] = array();
5195  $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
5196  $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
5197  }
5198  array_push($overview[$row["active_fi"]][$row["pass"]], $row);
5199  $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
5200  }
5201  return $overview;
5202  }
5203 
5215  function buildName($user_id, $firstname, $lastname, $title)
5216  {
5217  $name = "";
5218  if (strlen($firstname.$lastname.$title) == 0)
5219  {
5220  $name = $this->lng->txt("deleted_user");
5221  }
5222  else
5223  {
5224  if ($user_id == ANONYMOUS_USER_ID)
5225  {
5226  $name = $lastname;
5227  }
5228  else
5229  {
5230  $name = trim($lastname . ", " . $firstname . " " . $title);
5231  }
5232  if ($this->getAnonymity())
5233  {
5234  $name = $this->lng->txt("anonymous");
5235  }
5236  }
5237  return $name;
5238  }
5239 
5252  function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
5253  {
5254  global $lng;
5255  $name = "";
5256  if (strlen($firstname.$lastname.$title) == 0)
5257  {
5258  $name = $lng->txt("deleted_user");
5259  }
5260  else
5261  {
5262  if ($user_id == ANONYMOUS_USER_ID)
5263  {
5264  $name = $lastname;
5265  }
5266  else
5267  {
5268  $name = trim($lastname . ", " . $firstname . " " . $title);
5269  }
5270  if ($is_anonymous)
5271  {
5272  $name = $lng->txt("anonymous");
5273  }
5274  }
5275  return $name;
5276  }
5277 
5285  {
5286  global $ilDB;
5287 
5288  $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",
5289  array('integer'),
5290  array($this->getTestId())
5291  );
5292  $times = array();
5293  while ($row = $ilDB->fetchObject($result))
5294  {
5295  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
5296  $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5297  preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
5298  $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5299  $times[$row->active_fi] += ($epoch_2 - $epoch_1);
5300  }
5301  $max_time = 0;
5302  $counter = 0;
5303  foreach ($times as $key => $value)
5304  {
5305  $max_time += $value;
5306  $counter++;
5307  }
5308  if ($counter)
5309  {
5310  $average_time = round($max_time / $counter);
5311  }
5312  else
5313  {
5314  $average_time = 0;
5315  }
5316  return $average_time;
5317  }
5318 
5325  function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
5326  {
5327  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5328  return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
5329  }
5330 
5338  {
5339  $time_in_seconds = 0;
5340  foreach ($this->questions as $question_id)
5341  {
5342  $question =& ilObjTest::_instanciateQuestion($question_id);
5343  $est_time = $question->getEstimatedWorkingTime();
5344  $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
5345  }
5346  $hours = (int)($time_in_seconds / 3600) ;
5347  $time_in_seconds = $time_in_seconds - ($hours * 3600);
5348  $minutes = (int)($time_in_seconds / 60);
5349  $time_in_seconds = $time_in_seconds - ($minutes * 60);
5350  $result = array("hh" => $hours, "mm" => $minutes, "ss" => $time_in_seconds);
5351  return $result;
5352  }
5353 
5360  function getImagePath()
5361  {
5362  return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
5363  }
5364 
5371  function getImagePathWeb()
5372  {
5373  include_once "./Services/Utilities/classes/class.ilUtil.php";
5374  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
5376  }
5377 
5386  function &createQuestionGUI($question_type, $question_id = -1)
5387  {
5388  if ((!$question_type) and ($question_id > 0))
5389  {
5390  $question_type = $this->getQuestionType($question_id);
5391  }
5392 
5393  if (!strlen($question_type)) return null;
5394 
5395  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5396  assQuestion::_includeClass($question_type, 1);
5397 
5398  $question_type_gui = assQuestion::getGuiClassNameByQuestionType($question_type);
5399  $question = new $question_type_gui();
5400 
5401  $question->object->setObligationsToBeConsidered( $this->areObligationsEnabled() );
5402 
5403  if ($question_id > 0)
5404  {
5405  $question->object->loadFromDb($question_id);
5406 
5407  global $ilCtrl, $ilDB, $ilUser, $lng;
5408 
5409  $feedbackObjectClassname = assQuestion::getFeedbackClassNameByQuestionType($question_type);
5410  $question->object->feedbackOBJ = new $feedbackObjectClassname($question->object, $ilCtrl, $ilDB, $lng);
5411 
5412  $assSettings = new ilSetting('assessment');
5413  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
5414  $processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $ilDB);
5415  $processLockerFactory->setQuestionId($question->object->getId());
5416  $processLockerFactory->setUserId($ilUser->getId());
5417  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
5418  $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
5419  $question->object->setProcessLocker($processLockerFactory->getLocker());
5420  }
5421 
5422  return $question;
5423  }
5424 
5434  function &_instanciateQuestion($question_id)
5435  {
5436  if (strcmp($question_id, "") != 0)
5437  {
5438  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
5439  return assQuestion::_instanciateQuestion($question_id);
5440  }
5441  }
5442 
5451  function moveQuestions($move_questions, $target_index, $insert_mode)
5452  {
5453  $this->questions = array_values($this->questions);
5454  $array_pos = array_search($target_index, $this->questions);
5455  if ($insert_mode == 0)
5456  {
5457  $part1 = array_slice($this->questions, 0, $array_pos);
5458  $part2 = array_slice($this->questions, $array_pos);
5459  }
5460  else if ($insert_mode == 1)
5461  {
5462  $part1 = array_slice($this->questions, 0, $array_pos + 1);
5463  $part2 = array_slice($this->questions, $array_pos + 1);
5464  }
5465  foreach ($move_questions as $question_id)
5466  {
5467  if (!(array_search($question_id, $part1) === FALSE))
5468  {
5469  unset($part1[array_search($question_id, $part1)]);
5470  }
5471  if (!(array_search($question_id, $part2) === FALSE))
5472  {
5473  unset($part2[array_search($question_id, $part2)]);
5474  }
5475  }
5476  $part1 = array_values($part1);
5477  $part2 = array_values($part2);
5478  $new_array = array_values(array_merge($part1, $move_questions, $part2));
5479  $this->questions = array();
5480  $counter = 1;
5481  foreach ($new_array as $question_id)
5482  {
5483  $this->questions[$counter] = $question_id;
5484  $counter++;
5485  }
5486  $this->saveQuestionsToDb();
5487  }
5488 
5489 
5498  {
5499  if ($this->getStartingTime())
5500  {
5501  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
5502  {
5503  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5504  $now = mktime();
5505  if ($now < $epoch_time)
5506  {
5507  // starting time not reached
5508  return false;
5509  }
5510  }
5511  }
5512  return true;
5513  }
5514 
5523  {
5524  if ($this->getEndingTime())
5525  {
5526  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
5527  {
5528  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
5529  $now = mktime();
5530  if ($now > $epoch_time)
5531  {
5532  // ending time reached
5533  return true;
5534  }
5535  }
5536  }
5537  return false;
5538  }
5539 
5545  function getAvailableQuestions($arrFilter, $completeonly = 0)
5546  {
5547  global $ilUser;
5548  global $ilDB;
5549 
5550  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
5551  $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
5552  $available = "";
5553  if (count($available_pools))
5554  {
5555  $available = " AND " . $ilDB->in('qpl_questions.obj_fi', $available_pools, false, 'integer');
5556  }
5557  else
5558  {
5559  return array();
5560  }
5561  if ($completeonly)
5562  {
5563  $available .= " AND qpl_questions.complete = " . $ilDB->quote("1", 'text');
5564  }
5565 
5566  $where = "";
5567  if (is_array($arrFilter))
5568  {
5569  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
5570  {
5571  $where .= " AND " . $ilDB->like('qpl_questions.title', 'text', "%%" . $arrFilter['title'] . "%%");
5572  }
5573  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
5574  {
5575  $where .= " AND " . $ilDB->like('qpl_questions.description', 'text', "%%" . $arrFilter['description'] . "%%");
5576  }
5577  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
5578  {
5579  $where .= " AND " . $ilDB->like('qpl_questions.author', 'text', "%%" . $arrFilter['author'] . "%%");
5580  }
5581  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
5582  {
5583  $where .= " AND qpl_qst_type.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
5584  }
5585  if (array_key_exists('qpl', $arrFilter) && strlen($arrFilter['qpl']))
5586  {
5587  $where .= " AND " . $ilDB->like('object_data.title', 'text', "%%" . $arrFilter['qpl'] . "%%");
5588  }
5589  }
5590 
5591  $original_ids =& $this->getExistingQuestions();
5592  $original_clause = " qpl_questions.original_id IS NULL";
5593  if (count($original_ids))
5594  {
5595  $original_clause = " qpl_questions.original_id IS NULL AND " . $ilDB->in('qpl_questions.question_id', $original_ids, true, 'integer');
5596  }
5597 
5598  $query_result = $ilDB->query(
5599  "SELECT qpl_questions.*, qpl_questions.tstamp, qpl_qst_type.type_tag, qpl_qst_type.plugin, object_data.title qpl " .
5600  "FROM qpl_questions, qpl_qst_type, object_data WHERE $original_clause $available AND " .
5601  "object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.tstamp > 0 AND " .
5602  "qpl_questions.question_type_fi = qpl_qst_type.question_type_id$where");
5603  $rows = array();
5604  $types = $this->getQuestionTypeTranslations();
5605  if ($query_result->numRows())
5606  {
5607  while ($row = $ilDB->fetchAssoc($query_result))
5608  {
5609  $row['ttype'] = $types[$row['type_tag']];
5610  if ($row["plugin"])
5611  {
5612  if ($this->isPluginActive($row["type_tag"]))
5613  {
5614  array_push($rows, $row);
5615  }
5616  }
5617  else
5618  {
5619  array_push($rows, $row);
5620  }
5621  }
5622  }
5623  return $rows;
5624  }
5625 
5626  public function &getQuestionTypeTranslations()
5627  {
5628  global $ilDB;
5629  global $lng;
5630  global $ilLog;
5631  global $ilPluginAdmin;
5632 
5633  $lng->loadLanguageModule("assessment");
5634  $result = $ilDB->query("SELECT * FROM qpl_qst_type");
5635  $types = array();
5636  while ($row = $ilDB->fetchAssoc($result))
5637  {
5638  if ($row["plugin"] == 0)
5639  {
5640  $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
5641  }
5642  else
5643  {
5644  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
5645  foreach ($pl_names as $pl_name)
5646  {
5647  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
5648  if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0)
5649  {
5650  $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
5651  }
5652  }
5653  }
5654  }
5655  ksort($types);
5656  return $types;
5657  }
5658 
5663  public function fromXML(ilQTIAssessment $assessment)
5664  {
5665  unset($_SESSION["import_mob_xhtml"]);
5666 
5667  $this->setDescription($assessment->getComment());
5668  $this->setTitle($assessment->getTitle());
5669 
5670  foreach ($assessment->objectives as $objectives)
5671  {
5672  foreach ($objectives->materials as $material)
5673  {
5674  $this->setIntroduction($this->QTIMaterialToString($material));
5675  }
5676  }
5677 
5678  if(
5679  $assessment->getPresentationMaterial() &&
5680  $assessment->getPresentationMaterial()->getFlowMat(0) &&
5681  $assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)
5682  )
5683  {
5684  $this->setFinalStatement($this->QTIMaterialToString($assessment->getPresentationMaterial()->getFlowMat(0)->getMaterial(0)));
5685  }
5686 
5687  foreach ($assessment->assessmentcontrol as $assessmentcontrol)
5688  {
5689  switch ($assessmentcontrol->getSolutionswitch())
5690  {
5691  case "Yes":
5692  $this->setInstantFeedbackSolution(1);
5693  break;
5694  default:
5695  $this->setInstantFeedbackSolution(0);
5696  break;
5697  }
5698  }
5699 
5700  foreach ($assessment->qtimetadata as $metadata)
5701  {
5702  switch ($metadata["label"])
5703  {
5704  case "test_type":
5705  // for old tests with a test type
5706  $type = $metadata["entry"];
5707  switch ($type)
5708  {
5709  case 1:
5710  // assessment
5711  $this->setAnonymity(1);
5712  break;
5713  case 2:
5714  // self assessment
5715  break;
5716  case 4:
5717  // online exam
5718  $this->setFixedParticipants(1);
5719  $this->setListOfQuestionsSettings(7);
5720  $this->setShowSolutionPrintview(1);
5721  break;
5722  case 5:
5723  // varying random test
5724  break;
5725  }
5726  break;
5727  case "sequence_settings":
5728  $this->setSequenceSettings($metadata["entry"]);
5729  break;
5730  case "author":
5731  $this->setAuthor($metadata["entry"]);
5732  break;
5733  case "nr_of_tries":
5734  $this->setNrOfTries($metadata["entry"]);
5735  break;
5736  case "kiosk":
5737  $this->setKiosk($metadata["entry"]);
5738  break;
5739  case "showfinalstatement":
5740  $this->setShowFinalStatement($metadata["entry"]);
5741  break;
5742  case "showinfo":
5743  $this->setShowInfo($metadata["entry"]);
5744  break;
5745  case "forcejs":
5746  $this->setForceJS($metadata["entry"]);
5747  break;
5748  case "customstyle":
5749  $this->setCustomStyle($metadata["entry"]);
5750  break;
5751 
5752  case "highscore_enabled":
5753  $this->setHighscoreEnabled($metadata["entry"]);
5754  break;
5755 
5756  case "highscore_anon":
5757  $this->setHighscoreAnon($metadata["entry"]);
5758  break;
5759 
5760  case "highscore_achieved_ts":
5761  $this->setHighscoreAchievedTS($metadata["entry"]);
5762  break;
5763 
5764  case "highscore_score":
5765  $this->setHighscoreScore($metadata["entry"]);
5766  break;
5767 
5768  case "highscore_percentage":
5769  $this->setHighscorePercentage($metadata["entry"]);
5770  break;
5771 
5772  case "highscore_hints":
5773  $this->setHighscoreHints($metadata["entry"]);
5774  break;
5775 
5776  case "highscore_wtime":
5777  $this->setHighscoreWTime($metadata["entry"]);
5778  break;
5779 
5780  case "highscore_own_table":
5781  $this->setHighscoreOwnTable($metadata["entry"]);
5782  break;
5783 
5784  case "highscore_top_table":
5785  $this->setHighscoreTopTable($metadata["entry"]);
5786  break;
5787 
5788  case "highscore_top_num":
5789  $this->setHighscoreTopNum($metadata["entry"]);
5790  break;
5791 
5792  case "hide_previous_results":
5793  if ($metadata["entry"] == 0)
5794  {
5795  $this->setUsePreviousAnswers(1);
5796  }
5797  else
5798  {
5799  $this->setUsePreviousAnswers(0);
5800  }
5801  break;
5802  case "use_previous_answers":
5803  $this->setUsePreviousAnswers($metadata["entry"]);
5804  break;
5805  case "answer_feedback":
5806  $this->setAnswerFeedback($metadata["entry"]);
5807  break;
5808  case "hide_title_points":
5809  $this->setTitleOutput($metadata["entry"]);
5810  break;
5811  case "title_output":
5812  $this->setTitleOutput($metadata["entry"]);
5813  break;
5814  case "question_set_type":
5815  $this->setQuestionSetType($metadata["entry"]);
5816  break;
5817  case "random_test":
5818  if( $metadata["entry"] )
5819  {
5820  $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
5821  }
5822  else
5823  {
5824  $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
5825  }
5826  break;
5827  case "results_presentation":
5828  $this->setResultsPresentation($metadata["entry"]);
5829  break;
5830  case "reset_processing_time":
5831  $this->setResetProcessingTime($metadata["entry"]);
5832  break;
5833  case "instant_verification":
5834  $this->setInstantFeedbackSolution($metadata["entry"]);
5835  break;
5836  case "answer_feedback_points":
5837  $this->setAnswerFeedbackPoints($metadata["entry"]);
5838  break;
5839  case "anonymity":
5840  $this->setAnonymity($metadata["entry"]);
5841  break;
5842  case "show_cancel":
5843  $this->setShowCancel($metadata["entry"]);
5844  break;
5845  case "show_marker":
5846  $this->setShowMarker($metadata["entry"]);
5847  break;
5848  case "fixed_participants":
5849  $this->setFixedParticipants($metadata["entry"]);
5850  break;
5851  case "score_reporting":
5852  $this->setScoreReporting($metadata["entry"]);
5853  break;
5854  case "shuffle_questions":
5855  $this->setShuffleQuestions($metadata["entry"]);
5856  break;
5857  case "count_system":
5858  $this->setCountSystem($metadata["entry"]);
5859  break;
5860  case "mc_scoring":
5861  $this->setMCScoring($metadata["entry"]);
5862  break;
5863  case "mailnotification":
5864  $this->setMailNotification($metadata["entry"]);
5865  break;
5866  case "mailnottype":
5867  $this->setMailNotificationType($metadata["entry"]);
5868  break;
5869  case "exportsettings":
5870  $this->setExportSettings($metadata['entry']);
5871  break;
5872  case "score_cutting":
5873  $this->setScoreCutting($metadata["entry"]);
5874  break;
5875  case "password":
5876  $this->setPassword($metadata["entry"]);
5877  break;
5878  case "allowedUsers":
5879  $this->setAllowedUsers($metadata["entry"]);
5880  break;
5881  case "allowedUsersTimeGap":
5882  $this->setAllowedUsersTimeGap($metadata["entry"]);
5883  break;
5884  case "pass_scoring":
5885  $this->setPassScoring($metadata["entry"]);
5886  break;
5887  case "show_summary":
5888  $this->setListOfQuestionsSettings($metadata["entry"]);
5889  break;
5890  case "reporting_date":
5891  $iso8601period = $metadata["entry"];
5892  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
5893  {
5894  $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
5895  }
5896  break;
5897  case 'enable_processing_time':
5898  $this->setEnableProcessingTime($metadata['entry']);
5899  break;
5900  case "processing_time":
5901  $this->setProcessingTime($metadata['entry']);
5902  break;
5903  case "starting_time":
5904  $iso8601period = $metadata["entry"];
5905  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
5906  {
5907  $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
5908  }
5909  break;
5910  case "ending_time":
5911  $iso8601period = $metadata["entry"];
5912  if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
5913  {
5914  $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
5915  }
5916  break;
5917  case "enable_examview":
5918  $this->setEnableExamview($metadata["entry"]);
5919  break;
5920  case 'show_examview_html':
5921  $this->setShowExamviewHtml($metadata['entry']);
5922  break;
5923  case 'show_examview_pdf':
5924  $this->setShowExamviewPdf($metadata['entry']);
5925  break;
5926  case 'redirection_mode':
5927  $this->setRedirectionMode($metadata['entry']);
5928  break;
5929  case 'redirection_url':
5930  $this->setRedirectionUrl($metadata['entry']);
5931  break;
5932  case 'examid_in_kiosk':
5933  case 'examid_in_test_pass':
5934  $this->setShowExamIdInTestPassEnabled($metadata['entry']);
5935  break;
5936  case 'show_exam_id':
5937  case 'examid_in_test_res':
5938  $this->setShowExamIdInTestResultsEnabled($metadata['entry']);
5939  break;
5940  case 'enable_archiving':
5941  $this->setEnableArchiving($metadata['entry']);
5942  break;
5943  case 'sign_submission':
5944  $this->setSignSubmission($metadata['entry']);
5945  break;
5946  case 'char_selector_availability':
5947  $this->setCharSelectorAvailability($metadata['entry']);
5948  break;
5949  case 'char_selector_definition':
5950  $this->setCharSelectorDefinition($metadata['entry']);
5951  break;
5952  case 'activation_limited':
5953  $this->setActivationLimited($metadata['entry']);
5954  break;
5955  case 'activation_start_time':
5956  $this->setActivationStartingTime($metadata['entry']);
5957  break;
5958  case 'activation_end_time':
5959  $this->setActivationEndingTime($metadata['entry']);
5960  break;
5961  case 'activation_visibility':
5962  $this->setActivationVisibility($metadata['entry']);
5963  break;
5964  case 'autosave':
5965  $this->setAutosave($metadata['entry']);
5966  break;
5967  case 'autosave_ival':
5968  $this->setAutosaveIval($metadata['entry']);
5969  break;
5970  case 'offer_question_hints':
5971  $this->setOfferingQuestionHintsEnabled($metadata['entry']);
5972  break;
5973  case 'instant_feedback_specific':
5974  $this->setSpecificAnswerFeedback($metadata['entry']);
5975  break;
5976  case 'obligations_enabled':
5977  $this->setObligationsEnabled($metadata['entry']);
5978  break;
5979  }
5980  if (preg_match("/mark_step_\d+/", $metadata["label"]))
5981  {
5982  $xmlmark = $metadata["entry"];
5983  preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
5984  $mark_short = $matches[1];
5985  preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
5986  $mark_official = $matches[1];
5987  preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
5988  $mark_percentage = $matches[1];
5989  preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
5990  $mark_passed = $matches[1];
5991  $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
5992  }
5993  }
5994  // handle the import of media objects in XHTML code
5995  if (is_array($_SESSION["import_mob_xhtml"]))
5996  {
5997  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
5998  include_once "./Services/RTE/classes/class.ilRTE.php";
5999  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
6000  foreach ($_SESSION["import_mob_xhtml"] as $mob)
6001  {
6002  $importfile = ilObjTest::_getImportDirectory() . '/' . $_SESSION["tst_import_subdir"] . '/' . $mob["uri"];
6003  if (file_exists($importfile))
6004  {
6005  $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
6006  ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
6007  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
6008  $this->setFinalStatement(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getFinalStatement()), 1));
6009  }
6010  else
6011  {
6012  global $ilLog;
6013  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
6014  }
6015  }
6016  $this->saveToDb();
6017  }
6018  }
6019 
6025  public function toXML()
6026  {
6027  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
6028  $a_xml_writer = new ilXmlWriter;
6029  // set xml header
6030  $a_xml_writer->xmlHeader();
6031  $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
6032  $a_xml_writer->xmlStartTag("questestinterop");
6033 
6034  $attrs = array(
6035  "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
6036  "title" => $this->getTitle()
6037  );
6038  $a_xml_writer->xmlStartTag("assessment", $attrs);
6039  // add qti comment
6040  $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
6041 
6042  // add qti duration
6043  if ($this->enable_processing_time)
6044  {
6045  preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
6046  $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
6047  }
6048 
6049  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
6050  $a_xml_writer->xmlStartTag("qtimetadata");
6051  $a_xml_writer->xmlStartTag("qtimetadatafield");
6052  $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
6053  $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
6054  $a_xml_writer->xmlEndTag("qtimetadatafield");
6055 
6056  // anonymity
6057  $a_xml_writer->xmlStartTag("qtimetadatafield");
6058  $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
6059  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
6060  $a_xml_writer->xmlEndTag("qtimetadatafield");
6061 
6062  // question set type (fixed, random, dynamic, ...)
6063  $a_xml_writer->xmlStartTag("qtimetadatafield");
6064  $a_xml_writer->xmlElement("fieldlabel", NULL, "question_set_type");
6065  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getQuestionSetType());
6066  $a_xml_writer->xmlEndTag("qtimetadatafield");
6067 
6068  // sequence settings
6069  $a_xml_writer->xmlStartTag("qtimetadatafield");
6070  $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
6071  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
6072  $a_xml_writer->xmlEndTag("qtimetadatafield");
6073 
6074  // author
6075  $a_xml_writer->xmlStartTag("qtimetadatafield");
6076  $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
6077  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
6078  $a_xml_writer->xmlEndTag("qtimetadatafield");
6079 
6080  // reset processing time
6081  $a_xml_writer->xmlStartTag("qtimetadatafield");
6082  $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
6083  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
6084  $a_xml_writer->xmlEndTag("qtimetadatafield");
6085 
6086  // count system
6087  $a_xml_writer->xmlStartTag("qtimetadatafield");
6088  $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
6089  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
6090  $a_xml_writer->xmlEndTag("qtimetadatafield");
6091 
6092  // multiple choice scoring
6093  $a_xml_writer->xmlStartTag("qtimetadatafield");
6094  $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
6095  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
6096  $a_xml_writer->xmlEndTag("qtimetadatafield");
6097 
6098  // multiple choice scoring
6099  $a_xml_writer->xmlStartTag("qtimetadatafield");
6100  $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
6101  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
6102  $a_xml_writer->xmlEndTag("qtimetadatafield");
6103 
6104  // multiple choice scoring
6105  $a_xml_writer->xmlStartTag("qtimetadatafield");
6106  $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
6107  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
6108  $a_xml_writer->xmlEndTag("qtimetadatafield");
6109 
6110  // allowed users
6111  $a_xml_writer->xmlStartTag("qtimetadatafield");
6112  $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
6113  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
6114  $a_xml_writer->xmlEndTag("qtimetadatafield");
6115 
6116  // allowed users time gap
6117  $a_xml_writer->xmlStartTag("qtimetadatafield");
6118  $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
6119  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
6120  $a_xml_writer->xmlEndTag("qtimetadatafield");
6121 
6122  // pass scoring
6123  $a_xml_writer->xmlStartTag("qtimetadatafield");
6124  $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
6125  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
6126  $a_xml_writer->xmlEndTag("qtimetadatafield");
6127 
6128  // score reporting date
6129  if ($this->getReportingDate())
6130  {
6131  $a_xml_writer->xmlStartTag("qtimetadatafield");
6132  $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
6133  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
6134  $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]));
6135  $a_xml_writer->xmlEndTag("qtimetadatafield");
6136  }
6137  // number of tries
6138  $a_xml_writer->xmlStartTag("qtimetadatafield");
6139  $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
6140  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
6141  $a_xml_writer->xmlEndTag("qtimetadatafield");
6142 
6143  // kiosk
6144  $a_xml_writer->xmlStartTag("qtimetadatafield");
6145  $a_xml_writer->xmlElement("fieldlabel", NULL, "kiosk");
6146  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getKiosk()));
6147  $a_xml_writer->xmlEndTag("qtimetadatafield");
6148 
6149 
6150  //redirection_mode
6151  $a_xml_writer->xmlStartTag('qtimetadatafield');
6152  $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_mode");
6153  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionMode());
6154  $a_xml_writer->xmlEndTag("qtimetadatafield");
6155 
6156  //redirection_url
6157  $a_xml_writer->xmlStartTag('qtimetadatafield');
6158  $a_xml_writer->xmlElement("fieldlabel", NULL, "redirection_url");
6159  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getRedirectionUrl());
6160  $a_xml_writer->xmlEndTag("qtimetadatafield");
6161 
6162  // use previous answers
6163  $a_xml_writer->xmlStartTag("qtimetadatafield");
6164  $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
6165  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
6166  $a_xml_writer->xmlEndTag("qtimetadatafield");
6167 
6168  // hide title points
6169  $a_xml_writer->xmlStartTag("qtimetadatafield");
6170  $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
6171  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
6172  $a_xml_writer->xmlEndTag("qtimetadatafield");
6173 
6174  // results presentation
6175  $a_xml_writer->xmlStartTag("qtimetadatafield");
6176  $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
6177  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
6178  $a_xml_writer->xmlEndTag("qtimetadatafield");
6179 
6180  // examid in test pass
6181  $a_xml_writer->xmlStartTag("qtimetadatafield");
6182  $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_pass");
6183  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestPassEnabled()));
6184  $a_xml_writer->xmlEndTag("qtimetadatafield");
6185 
6186  // examid in kiosk
6187  $a_xml_writer->xmlStartTag("qtimetadatafield");
6188  $a_xml_writer->xmlElement("fieldlabel", NULL, "examid_in_test_res");
6189  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isShowExamIdInTestResultsEnabled()));
6190  $a_xml_writer->xmlEndTag("qtimetadatafield");
6191 
6192  // solution details
6193  $a_xml_writer->xmlStartTag("qtimetadatafield");
6194  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
6195  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
6196  $a_xml_writer->xmlEndTag("qtimetadatafield");
6197 
6198  // solution details
6199  $a_xml_writer->xmlStartTag("qtimetadatafield");
6200  $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
6201  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
6202  $a_xml_writer->xmlEndTag("qtimetadatafield");
6203 
6204  // solution details
6205  $a_xml_writer->xmlStartTag("qtimetadatafield");
6206  $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
6207  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
6208  $a_xml_writer->xmlEndTag("qtimetadatafield");
6209 
6210  // answer specific feedback
6211  $a_xml_writer->xmlStartTag("qtimetadatafield");
6212  $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
6213  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
6214  $a_xml_writer->xmlEndTag("qtimetadatafield");
6215 
6216  // answer specific feedback of reached points
6217  $a_xml_writer->xmlStartTag("qtimetadatafield");
6218  $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
6219  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
6220  $a_xml_writer->xmlEndTag("qtimetadatafield");
6221 
6222  // highscore
6223  $highscore_metadata = array(
6224  'highscore_enabled' => array('value' => $this->getHighscoreEnabled()),
6225  'highscore_anon' => array('value' => $this->getHighscoreAnon()),
6226  'highscore_achieved_ts' => array('value' => $this->getHighscoreAchievedTS()),
6227  'highscore_score' => array('value' => $this->getHighscoreScore()),
6228  'highscore_percentage' => array('value' => $this->getHighscorePercentage()),
6229  'highscore_hints' => array('value' => $this->getHighscoreHints()),
6230  'highscore_wtime' => array('value' => $this->getHighscoreWTime()),
6231  'highscore_own_table' => array('value' => $this->getHighscoreOwnTable()),
6232  'highscore_top_table' => array('value' => $this->getHighscoreTopTable()),
6233  'highscore_top_num' => array('value' => $this->getHighscoreTopNum()),
6234  );
6235  foreach($highscore_metadata as $label => $data)
6236  {
6237  $a_xml_writer->xmlStartTag("qtimetadatafield");
6238  $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
6239  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $data['value']));
6240  $a_xml_writer->xmlEndTag("qtimetadatafield");
6241  }
6242 
6243  // show cancel
6244  $a_xml_writer->xmlStartTag("qtimetadatafield");
6245  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
6246  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
6247  $a_xml_writer->xmlEndTag("qtimetadatafield");
6248 
6249  // show marker
6250  $a_xml_writer->xmlStartTag("qtimetadatafield");
6251  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
6252  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
6253  $a_xml_writer->xmlEndTag("qtimetadatafield");
6254 
6255  // fixed participants
6256  $a_xml_writer->xmlStartTag("qtimetadatafield");
6257  $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
6258  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
6259  $a_xml_writer->xmlEndTag("qtimetadatafield");
6260 
6261  // show final statement
6262  $a_xml_writer->xmlStartTag("qtimetadatafield");
6263  $a_xml_writer->xmlElement("fieldlabel", NULL, "showfinalstatement");
6264  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowFinalStatement()) ? "1" : "0")));
6265  $a_xml_writer->xmlEndTag("qtimetadatafield");
6266 
6267  // show introduction only
6268  $a_xml_writer->xmlStartTag("qtimetadatafield");
6269  $a_xml_writer->xmlElement("fieldlabel", NULL, "showinfo");
6270  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getShowInfo()) ? "1" : "0")));
6271  $a_xml_writer->xmlEndTag("qtimetadatafield");
6272 
6273  // mail notification
6274  $a_xml_writer->xmlStartTag("qtimetadatafield");
6275  $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnotification");
6276  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotification());
6277  $a_xml_writer->xmlEndTag("qtimetadatafield");
6278 
6279  // mail notification type
6280  $a_xml_writer->xmlStartTag("qtimetadatafield");
6281  $a_xml_writer->xmlElement("fieldlabel", NULL, "mailnottype");
6282  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMailNotificationType());
6283  $a_xml_writer->xmlEndTag("qtimetadatafield");
6284 
6285  // export settings
6286  $a_xml_writer->xmlStartTag("qtimetadatafield");
6287  $a_xml_writer->xmlElement("fieldlabel", NULL, "exportsettings");
6288  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getExportSettings());
6289  $a_xml_writer->xmlEndTag("qtimetadatafield");
6290 
6291  // force JavaScript
6292  $a_xml_writer->xmlStartTag("qtimetadatafield");
6293  $a_xml_writer->xmlElement("fieldlabel", NULL, "forcejs");
6294  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", (($this->getForceJS()) ? "1" : "0")));
6295  $a_xml_writer->xmlEndTag("qtimetadatafield");
6296 
6297  // custom style
6298  $a_xml_writer->xmlStartTag("qtimetadatafield");
6299  $a_xml_writer->xmlElement("fieldlabel", NULL, "customstyle");
6300  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCustomStyle());
6301  $a_xml_writer->xmlEndTag("qtimetadatafield");
6302 
6303  // shuffle questions
6304  $a_xml_writer->xmlStartTag("qtimetadatafield");
6305  $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
6306  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
6307  $a_xml_writer->xmlEndTag("qtimetadatafield");
6308 
6309  // processing time
6310  $a_xml_writer->xmlStartTag("qtimetadatafield");
6311  $a_xml_writer->xmlElement("fieldlabel", NULL, "processing_time");
6312  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getProcessingTime());
6313  $a_xml_writer->xmlEndTag("qtimetadatafield");
6314 
6315  // enable_examview
6316  $a_xml_writer->xmlStartTag("qtimetadatafield");
6317  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_examview");
6318  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableExamview());
6319  $a_xml_writer->xmlEndTag("qtimetadatafield");
6320 
6321  // show_examview_html
6322  $a_xml_writer->xmlStartTag("qtimetadatafield");
6323  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_html");
6324  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewHtml());
6325  $a_xml_writer->xmlEndTag("qtimetadatafield");
6326 
6327  // show_examview_pdf
6328  $a_xml_writer->xmlStartTag("qtimetadatafield");
6329  $a_xml_writer->xmlElement("fieldlabel", NULL, "show_examview_pdf");
6330  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getShowExamviewPdf());
6331  $a_xml_writer->xmlEndTag("qtimetadatafield");
6332 
6333  // enable_archiving
6334  $a_xml_writer->xmlStartTag("qtimetadatafield");
6335  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_archiving");
6336  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableArchiving());
6337  $a_xml_writer->xmlEndTag("qtimetadatafield");
6338 
6339  // sign_submission
6340  $a_xml_writer->xmlStartTag("qtimetadatafield");
6341  $a_xml_writer->xmlElement("fieldlabel", NULL, "sign_submission");
6342  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSignSubmission());
6343  $a_xml_writer->xmlEndTag("qtimetadatafield");
6344 
6345  // char_selector_availability
6346  $a_xml_writer->xmlStartTag("qtimetadatafield");
6347  $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_availability");
6348  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getCharSelectorAvailability()));
6349  $a_xml_writer->xmlEndTag("qtimetadatafield");
6350 
6351  // char_selector_definition
6352  $a_xml_writer->xmlStartTag("qtimetadatafield");
6353  $a_xml_writer->xmlElement("fieldlabel", NULL, "char_selector_definition");
6354  $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCharSelectorDefinition());
6355  $a_xml_writer->xmlEndTag("qtimetadatafield");
6356 
6357 
6358  // starting time
6359  if ($this->getStartingTime())
6360  {
6361  $a_xml_writer->xmlStartTag("qtimetadatafield");
6362  $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
6363  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
6364  $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]));
6365  $a_xml_writer->xmlEndTag("qtimetadatafield");
6366  }
6367  // ending time
6368  if ($this->getEndingTime())
6369  {
6370  $a_xml_writer->xmlStartTag("qtimetadatafield");
6371  $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
6372  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
6373  $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]));
6374  $a_xml_writer->xmlEndTag("qtimetadatafield");
6375  }
6376 
6377 
6378  //activation_limited
6379  $a_xml_writer->xmlStartTag("qtimetadatafield");
6380  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_limited");
6381  $a_xml_writer->xmlElement("fieldentry", NULL,(int)$this->isActivationLimited());
6382  $a_xml_writer->xmlEndTag("qtimetadatafield");
6383 
6384  //activation_start_time
6385  $a_xml_writer->xmlStartTag("qtimetadatafield");
6386  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_start_time");
6387  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationStartingTime());
6388  $a_xml_writer->xmlEndTag("qtimetadatafield");
6389 
6390  //activation_end_time
6391  $a_xml_writer->xmlStartTag("qtimetadatafield");
6392  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_end_time");
6393  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationEndingTime());
6394  $a_xml_writer->xmlEndTag("qtimetadatafield");
6395 
6396  //activation_visibility
6397  $a_xml_writer->xmlStartTag("qtimetadatafield");
6398  $a_xml_writer->xmlElement("fieldlabel", NULL, "activation_visibility");
6399  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getActivationVisibility());
6400  $a_xml_writer->xmlEndTag("qtimetadatafield");
6401 
6402  // autosave
6403  $a_xml_writer->xmlStartTag("qtimetadatafield");
6404  $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave");
6405  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosave());
6406  $a_xml_writer->xmlEndTag("qtimetadatafield");
6407 
6408  // autosave_ival
6409  $a_xml_writer->xmlStartTag("qtimetadatafield");
6410  $a_xml_writer->xmlElement("fieldlabel", NULL, "autosave_ival");
6411  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getAutosaveIval());
6412  $a_xml_writer->xmlEndTag("qtimetadatafield");
6413 
6414  //offer_question_hints
6415  $a_xml_writer->xmlStartTag("qtimetadatafield");
6416  $a_xml_writer->xmlElement("fieldlabel", NULL, "offer_question_hints");
6417  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isOfferingQuestionHintsEnabled());
6418  $a_xml_writer->xmlEndTag("qtimetadatafield");
6419 
6420  //instant_feedback_specific
6421  $a_xml_writer->xmlStartTag("qtimetadatafield");
6422  $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_specific");
6423  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getSpecificAnswerFeedback());
6424  $a_xml_writer->xmlEndTag("qtimetadatafield");
6425 
6426  //obligations_enabled
6427  $a_xml_writer->xmlStartTag("qtimetadatafield");
6428  $a_xml_writer->xmlElement("fieldlabel", NULL, "obligations_enabled");
6429  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->areObligationsEnabled());
6430  $a_xml_writer->xmlEndTag("qtimetadatafield");
6431 
6432  //enable_processing_time
6433  $a_xml_writer->xmlStartTag("qtimetadatafield");
6434  $a_xml_writer->xmlElement("fieldlabel", NULL, "enable_processing_time");
6435  $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->getEnableProcessingTime());
6436  $a_xml_writer->xmlEndTag("qtimetadatafield");
6437 
6438  foreach ($this->mark_schema->mark_steps as $index => $mark)
6439  {
6440  // mark steps
6441  $a_xml_writer->xmlStartTag("qtimetadatafield");
6442  $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
6443  $a_xml_writer->xmlElement("fieldentry", NULL, sprintf(
6444  "<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>",
6445  $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()
6446  ));
6447  $a_xml_writer->xmlEndTag("qtimetadatafield");
6448  }
6449  $a_xml_writer->xmlEndTag("qtimetadata");
6450 
6451  // add qti objectives
6452  $a_xml_writer->xmlStartTag("objectives");
6453  $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
6454  $a_xml_writer->xmlEndTag("objectives");
6455 
6456  // add qti assessmentcontrol
6457  if ($this->getInstantFeedbackSolution() == 1)
6458  {
6459  $attrs = array(
6460  "solutionswitch" => "Yes"
6461  );
6462  }
6463  else
6464  {
6465  $attrs = NULL;
6466  }
6467  $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
6468 
6469  if (strlen($this->getFinalStatement()))
6470  {
6471  // add qti presentation_material
6472  $a_xml_writer->xmlStartTag("presentation_material");
6473  $a_xml_writer->xmlStartTag("flow_mat");
6474  $this->addQTIMaterial($a_xml_writer, $this->getFinalStatement());
6475  $a_xml_writer->xmlEndTag("flow_mat");
6476  $a_xml_writer->xmlEndTag("presentation_material");
6477  }
6478 
6479  $attrs = array(
6480  "ident" => "1"
6481  );
6482  $a_xml_writer->xmlElement("section", $attrs, NULL);
6483  $a_xml_writer->xmlEndTag("assessment");
6484  $a_xml_writer->xmlEndTag("questestinterop");
6485 
6486  $xml = $a_xml_writer->xmlDumpMem(FALSE);
6487 
6488  foreach ($this->questions as $question_id)
6489  {
6490  $question =& ilObjTest::_instanciateQuestion($question_id);
6491  $qti_question = $question->toXML(false);
6492  $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
6493  $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
6494  if (strpos($xml, "</section>") !== false)
6495  {
6496  $xml = str_replace("</section>", "$qti_question</section>", $xml);
6497  }
6498  else
6499  {
6500  $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
6501  }
6502  }
6503  return $xml;
6504  }
6505 
6512  function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6513  {
6514  global $ilBench;
6515 
6516  $this->mob_ids = array();
6517  $this->file_ids = array();
6518 
6519  $attrs = array();
6520  $attrs["Type"] = "Test";
6521  $a_xml_writer->xmlStartTag("ContentObject", $attrs);
6522 
6523  // MetaData
6524  $this->exportXMLMetaData($a_xml_writer);
6525 
6526  // PageObjects
6527  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
6528  $ilBench->start("ContentObjectExport", "exportPageObjects");
6529  $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
6530  $ilBench->stop("ContentObjectExport", "exportPageObjects");
6531  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
6532 
6533  // MediaObjects
6534  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
6535  $ilBench->start("ContentObjectExport", "exportMediaObjects");
6536  $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
6537  $ilBench->stop("ContentObjectExport", "exportMediaObjects");
6538  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
6539 
6540  // FileItems
6541  $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
6542  $ilBench->start("ContentObjectExport", "exportFileItems");
6543  $this->exportFileItems($a_target_dir, $expLog);
6544  $ilBench->stop("ContentObjectExport", "exportFileItems");
6545  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
6546 
6547  $a_xml_writer->xmlEndTag("ContentObject");
6548  }
6549 
6556  function exportXMLMetaData(&$a_xml_writer)
6557  {
6558  include_once "./Services/MetaData/classes/class.ilMD2XML.php";
6559  $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
6560  $md2xml->setExportMode(true);
6561  $md2xml->startExport();
6562  $a_xml_writer->appendXML($md2xml->getXML());
6563  }
6564 
6570  function modifyExportIdentifier($a_tag, $a_param, $a_value)
6571  {
6572  if ($a_tag == "Identifier" && $a_param == "Entry")
6573  {
6574  include_once "./Services/Utilities/classes/class.ilUtil.php";
6575  $a_value = ilUtil::insertInstIntoID($a_value);
6576  }
6577 
6578  return $a_value;
6579  }
6580 
6581 
6588  function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
6589  {
6590  global $ilBench;
6591 
6592  include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
6593 
6594  foreach ($this->questions as $question_id)
6595  {
6596  $ilBench->start("ContentObjectExport", "exportPageObject");
6597  $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
6598 
6599  $attrs = array();
6600  $a_xml_writer->xmlStartTag("PageObject", $attrs);
6601 
6602 
6603  // export xml to writer object
6604  $ilBench->start("ContentObjectExport", "exportPageObject_XML");
6605  include_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
6606  $page_object = new ilAssQuestionPage($question_id);
6607  $page_object->buildDom();
6608  $page_object->insertInstIntoIDs($a_inst);
6609  $mob_ids = $page_object->collectMediaObjects(false);
6610  require_once 'Services/COPage/classes/class.ilPCFileList.php';
6611  $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
6612  $xml = $page_object->getXMLFromDom(false, false, false, "", true);
6613  $xml = str_replace("&","&amp;", $xml);
6614  $a_xml_writer->appendXML($xml);
6615  $page_object->freeDom();
6616  unset ($page_object);
6617 
6618  $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
6619 
6620  // collect media objects
6621  $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
6622  //$mob_ids = $page_obj->getMediaObjectIDs();
6623  foreach($mob_ids as $mob_id)
6624  {
6625  $this->mob_ids[$mob_id] = $mob_id;
6626  }
6627  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
6628 
6629  // collect all file items
6630  $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
6631  //$file_ids = $page_obj->getFileItemIds();
6632  foreach($file_ids as $file_id)
6633  {
6634  $this->file_ids[$file_id] = $file_id;
6635  }
6636  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
6637 
6638  $a_xml_writer->xmlEndTag("PageObject");
6639  //unset($page_obj);
6640 
6641  $ilBench->stop("ContentObjectExport", "exportPageObject");
6642 
6643 
6644  }
6645  }
6646 
6653  function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
6654  {
6655  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
6656 
6657  foreach ($this->mob_ids as $mob_id)
6658  {
6659  $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
6660  if (ilObjMediaObject::_exists($mob_id))
6661  {
6662  $media_obj = new ilObjMediaObject($mob_id);
6663  $media_obj->exportXML($a_xml_writer, $a_inst);
6664  $media_obj->exportFiles($a_target_dir);
6665  unset($media_obj);
6666  }
6667  }
6668  }
6669 
6674  function exportFileItems($a_target_dir, &$expLog)
6675  {
6676  include_once "./Modules/File/classes/class.ilObjFile.php";
6677 
6678  foreach ($this->file_ids as $file_id)
6679  {
6680  $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
6681  $file_obj = new ilObjFile($file_id, false);
6682  $file_obj->export($a_target_dir);
6683  unset($file_obj);
6684  }
6685  }
6686 
6691  function getImportMapping()
6692  {
6693  if (!is_array($this->import_mapping))
6694  {
6695  return array();
6696  }
6697  else
6698  {
6699  return $this->import_mapping;
6700  }
6701  }
6702 
6712  function getECTSGrade($passed_array, $reached_points, $max_points)
6713  {
6714  return ilObjTest::_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);
6715  }
6716 
6725  function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
6726  {
6727  include_once "./Modules/Test/classes/class.ilStatistics.php";
6728  // calculate the median
6729  $passed_statistics = new ilStatistics();
6730  $passed_statistics->setData($points_passed);
6731  $ects_percentiles = array
6732  (
6733  "A" => $passed_statistics->quantile($a),
6734  "B" => $passed_statistics->quantile($b),
6735  "C" => $passed_statistics->quantile($c),
6736  "D" => $passed_statistics->quantile($d),
6737  "E" => $passed_statistics->quantile($e)
6738  );
6739  if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
6740  {
6741  return "A";
6742  }
6743  else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
6744  {
6745  return "B";
6746  }
6747  else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
6748  {
6749  return "C";
6750  }
6751  else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
6752  {
6753  return "D";
6754  }
6755  else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
6756  {
6757  return "E";
6758  }
6759  else if (strcmp($fx, "") != 0)
6760  {
6761  if ($max_points > 0)
6762  {
6763  $percentage = ($reached_points / $max_points) * 100.0;
6764  if ($percentage < 0) $percentage = 0.0;
6765  }
6766  else
6767  {
6768  $percentage = 0.0;
6769  }
6770  if ($percentage >= $fx)
6771  {
6772  return "FX";
6773  }
6774  else
6775  {
6776  return "F";
6777  }
6778  }
6779  else
6780  {
6781  return "F";
6782  }
6783  }
6784 
6785  function checkMarks()
6786  {
6787  return $this->mark_schema->checkMarks();
6788  }
6789 
6790  function getMarkSchema()
6791  {
6792  return $this->mark_schema;
6793  }
6794 
6802  function setAuthor($author = "")
6803  {
6804  $this->author = $author;
6805  }
6806 
6816  function saveAuthorToMetadata($a_author = "")
6817  {
6818  $md =& new ilMD($this->getId(), 0, $this->getType());
6819  $md_life =& $md->getLifecycle();
6820  if (!$md_life)
6821  {
6822  if (strlen($a_author) == 0)
6823  {
6824  global $ilUser;
6825  $a_author = $ilUser->getFullname();
6826  }
6827 
6828  $md_life =& $md->addLifecycle();
6829  $md_life->save();
6830  $con =& $md_life->addContribute();
6831  $con->setRole("Author");
6832  $con->save();
6833  $ent =& $con->addEntity();
6834  $ent->setEntity($a_author);
6835  $ent->save();
6836  }
6837  }
6838 
6844  function createMetaData()
6845  {
6846  parent::createMetaData();
6847  $this->saveAuthorToMetadata();
6848  }
6849 
6857  function getAuthor()
6858  {
6859  $author = array();
6860  include_once "./Services/MetaData/classes/class.ilMD.php";
6861  $md =& new ilMD($this->getId(), 0, $this->getType());
6862  $md_life =& $md->getLifecycle();
6863  if ($md_life)
6864  {
6865  $ids =& $md_life->getContributeIds();
6866  foreach ($ids as $id)
6867  {
6868  $md_cont =& $md_life->getContribute($id);
6869  if (strcmp($md_cont->getRole(), "Author") == 0)
6870  {
6871  $entids =& $md_cont->getEntityIds();
6872  foreach ($entids as $entid)
6873  {
6874  $md_ent =& $md_cont->getEntity($entid);
6875  array_push($author, $md_ent->getEntity());
6876  }
6877  }
6878  }
6879  }
6880  return join($author, ",");
6881  }
6882 
6890  function _lookupAuthor($obj_id)
6891  {
6892  $author = array();
6893  include_once "./Services/MetaData/classes/class.ilMD.php";
6894  $md =& new ilMD($obj_id, 0, "tst");
6895  $md_life =& $md->getLifecycle();
6896  if ($md_life)
6897  {
6898  $ids =& $md_life->getContributeIds();
6899  foreach ($ids as $id)
6900  {
6901  $md_cont =& $md_life->getContribute($id);
6902  if (strcmp($md_cont->getRole(), "Author") == 0)
6903  {
6904  $entids =& $md_cont->getEntityIds();
6905  foreach ($entids as $entid)
6906  {
6907  $md_ent =& $md_cont->getEntity($entid);
6908  array_push($author, $md_ent->getEntity());
6909  }
6910  }
6911  }
6912  }
6913  return join($author, ",");
6914  }
6915 
6922  function &_getAvailableTests($use_object_id = FALSE)
6923  {
6924  global $ilUser;
6925  global $ilDB;
6926 
6927  $result_array = array();
6928  $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
6929  if (count($tests))
6930  {
6931  $titles = ilObject::_prepareCloneSelection($tests, "tst");
6932  foreach ($tests as $ref_id)
6933  {
6934  if ($use_object_id)
6935  {
6936  $obj_id = ilObject::_lookupObjId($ref_id);
6937  $result_array[$obj_id] = $titles[$ref_id];
6938  }
6939  else
6940  {
6941  $result_array[$ref_id] = $titles[$ref_id];
6942  }
6943  }
6944  }
6945  return $result_array;
6946  }
6947 
6956  public function cloneObject($a_target_id,$a_copy_id = 0)
6957  {
6958  global $ilLog, $tree, $ilDB, $ilPluginAdmin;
6959 
6960  $this->loadFromDb();
6961 
6962  // Copy settings
6964  $newObj = parent::cloneObject($a_target_id,$a_copy_id);
6965  $this->cloneMetaData($newObj);
6966  $newObj->setAnonymity($this->getAnonymity());
6967  $newObj->setAnswerFeedback($this->getAnswerFeedback());
6968  $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
6969  $newObj->setAuthor($this->getAuthor());
6970  $newObj->setAllowedUsers($this->getAllowedUsers());
6971  $newObj->setAllowedUsersTimeGap($this->getAllowedUsersTimeGap());
6972  $newObj->setCountSystem($this->getCountSystem());
6973  $newObj->setECTSFX($this->getECTSFX());
6974  $newObj->setECTSGrades($this->getECTSGrades());
6975  $newObj->setECTSOutput($this->getECTSOutput());
6976  $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
6977  $newObj->setEndingTime($this->getEndingTime());
6978  $newObj->setFixedParticipants($this->getFixedParticipants());
6979  $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
6980  $newObj->setIntroduction($this->getIntroduction());
6981  $newObj->setFinalStatement($this->getFinalStatement());
6982  $newObj->setShowInfo($this->getShowInfo());
6983  $newObj->setForceJS($this->getForceJS());
6984  $newObj->setCustomStyle($this->getCustomStyle());
6985  $newObj->setKiosk($this->getKiosk());
6986  $newObj->setShowFinalStatement($this->getShowFinalStatement());
6987  $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
6988  $newObj->setMCScoring($this->getMCScoring());
6989  $newObj->setMailNotification($this->getMailNotification());
6990  $newObj->setMailNotificationType($this->getMailNotificationType());
6991  $newObj->setNrOfTries($this->getNrOfTries());
6992  $newObj->setPassScoring($this->getPassScoring());
6993  $newObj->setPassword($this->getPassword());
6994  $newObj->setProcessingTime($this->getProcessingTime());
6995  $newObj->setQuestionSetType($this->getQuestionSetType());
6996  $newObj->setReportingDate($this->getReportingDate());
6997  $newObj->setResetProcessingTime($this->getResetProcessingTime());
6998  $newObj->setResultsPresentation($this->getResultsPresentation());
6999  $newObj->setScoreCutting($this->getScoreCutting());
7000  $newObj->setScoreReporting($this->getScoreReporting());
7001  $newObj->setSequenceSettings($this->getSequenceSettings());
7002  $newObj->setShowCancel($this->getShowCancel());
7003  $newObj->setShowMarker($this->getShowMarker());
7004  $newObj->setShuffleQuestions($this->getShuffleQuestions());
7005  $newObj->setStartingTime($this->getStartingTime());
7006  $newObj->setTitleOutput($this->getTitleOutput());
7007  $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
7008  $newObj->setRedirectionMode($this->getRedirectionMode());
7009  $newObj->setRedirectionUrl($this->getRedirectionUrl());
7010  $newObj->setCertificateVisibility($this->getCertificateVisibility());
7011  $newObj->mark_schema = clone $this->mark_schema;
7012  $newObj->setEnabledViewMode($this->getEnabledViewMode());
7013  $newObj->setTemplate($this->getTemplate());
7014  $newObj->setPoolUsage($this->getPoolUsage());
7015  $newObj->setPrintBestSolutionWithResult($this->isBestSolutionPrintedWithResult());
7016  $newObj->setShowExamIdInTestPassEnabled($this->isShowExamIdInTestPassEnabled());
7017  $newObj->setShowExamIdInTestResultsEnabled($this->isShowExamIdInTestResultsEnabled());
7018  $newObj->setEnableExamView($this->getEnableExamview());
7019  $newObj->setShowExamViewHtml($this->getShowExamviewHtml());
7020  $newObj->setShowExamViewPdf($this->getShowExamviewPdf());
7021  $newObj->setEnableArchiving($this->getEnableArchiving());
7022  $newObj->setSignSubmission($this->getSignSubmission());
7023  $newObj->setCharSelectorAvailability((int)$this->getCharSelectorAvailability());
7024  $newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
7025  $newObj->saveToDb();
7026 
7027  // clone certificate
7028  include_once "./Services/Certificate/classes/class.ilCertificate.php";
7029  include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
7030  $cert = new ilCertificate(new ilTestCertificateAdapter($this));
7031  $newcert = new ilCertificate(new ilTestCertificateAdapter($newObj));
7032  $cert->cloneCertificate($newcert);
7033 
7034  require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
7035  $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory($tree, $ilDB, $ilPluginAdmin, $this);
7036  $testQuestionSetConfigFactory->getQuestionSetConfig()->cloneQuestionSetRelatedData($newObj);
7037 
7038  $newObj->saveToDb();
7039  $newObj->updateMetaData();// #14467
7040  return $newObj;
7041  }
7042 
7049  function getQuestionCount()
7050  {
7051  $num = 0;
7052 
7053  if( $this->isRandomTest() )
7054  {
7055  global $tree, $ilDB, $ilPluginAdmin;
7056 
7057  $questionSetConfig = new ilTestRandomQuestionSetConfig(
7058  $tree, $ilDB, $ilPluginAdmin, $this
7059  );
7060 
7061  $questionSetConfig->loadFromDb();
7062 
7063  if( $questionSetConfig->isQuestionAmountConfigurationModePerPool() )
7064  {
7065  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
7066  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
7067  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
7068 
7069  $srcPoolDefFactory = new ilTestRandomQuestionSetSourcePoolDefinitionFactory($ilDB, $this);
7070  $srcPoolDefList = new ilTestRandomQuestionSetSourcePoolDefinitionList($ilDB, $this, $srcPoolDefFactory);
7071  $srcPoolDefList->loadDefinitions();
7072  $num = ilTestRandomQuestionSetBuilderWithAmountPerPool::getRequiredQuestionAmountForDefinitionList($srcPoolDefList);
7073  }
7074  else
7075  {
7076  $num = $questionSetConfig->getQuestionAmountPerTest();
7077  }
7078  }
7079  else
7080  {
7081  $num = count($this->questions);
7082  }
7083 
7084  return $num;
7085  }
7086 
7094  function logAction($logtext = "", $question_id = "")
7095  {
7096  global $ilUser;
7097 
7098  $original_id = "";
7099  if (strcmp($question_id, "") != 0)
7100  {
7101  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7102  $original_id = assQuestion::_getOriginalId($question_id);
7103  }
7104  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7105  ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
7106  }
7107 
7115  function _getObjectIDFromTestID($test_id)
7116  {
7117  global $ilDB;
7118  $object_id = FALSE;
7119  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
7120  array('integer'),
7121  array($test_id)
7122  );
7123  if ($result->numRows())
7124  {
7125  $row = $ilDB->fetchAssoc($result);
7126  $object_id = $row["obj_fi"];
7127  }
7128  return $object_id;
7129  }
7130 
7138  function _getObjectIDFromActiveID($active_id)
7139  {
7140  global $ilDB;
7141  $object_id = FALSE;
7142  $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",
7143  array('integer'),
7144  array($active_id)
7145  );
7146  if ($result->numRows())
7147  {
7148  $row = $ilDB->fetchAssoc($result);
7149  $object_id = $row["obj_fi"];
7150  }
7151  return $object_id;
7152  }
7153 
7161  function _getTestIDFromObjectID($object_id)
7162  {
7163  global $ilDB;
7164  $test_id = FALSE;
7165  $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
7166  array('integer'),
7167  array($object_id)
7168  );
7169  if ($result->numRows())
7170  {
7171  $row = $ilDB->fetchAssoc($result);
7172  $test_id = $row["test_id"];
7173  }
7174  return $test_id;
7175  }
7176 
7185  function getTextAnswer($active_id, $question_id, $pass = NULL)
7186  {
7187  global $ilDB;
7188 
7189  $res = "";
7190  if (($active_id) && ($question_id))
7191  {
7192  if (is_null($pass))
7193  {
7194  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7195  $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
7196  }
7197  $result = $ilDB->queryF("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
7198  array('integer', 'integer', 'integer'),
7199  array($active_id, $question_id, $pass)
7200  );
7201  if ($result->numRows() == 1)
7202  {
7203  $row = $ilDB->fetchAssoc($result);
7204  $res = $row["value1"];
7205  }
7206  }
7207  return $res;
7208  }
7209 
7217  function getQuestiontext($question_id)
7218  {
7219  global $ilDB;
7220 
7221  $res = "";
7222  if ($question_id)
7223  {
7224  $result = $ilDB->queryF("SELECT question_text FROM qpl_questions WHERE question_id = %s",
7225  array('integer'),
7226  array($question_id)
7227  );
7228  if ($result->numRows() == 1)
7229  {
7230  $row = $ilDB->fetchAssoc($result);
7231  $res = $row["question_text"];
7232  }
7233  }
7234  return $res;
7235  }
7236 
7243  function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
7244  {
7245  global $ilDB;
7246 
7247  $result_array = array();
7248 
7249  if ($this->getAnonymity())
7250  {
7251  if (is_numeric($user_id))
7252  {
7253  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7254  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7255  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7256  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7257  "ORDER BY $order",
7258  array('text', 'text', 'text', 'integer', 'integer'),
7259  array("", $this->lng->txt("unknown"), "", $this->getTestId(), $user_id)
7260  );
7261  }
7262  else
7263  {
7264  $result = $ilDB->queryF("SELECT tst_active.active_id, usr_id, %s login, %s lastname, %s firstname, tst_invited_user.clientip, " .
7265  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7266  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7267  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7268  "ORDER BY $order",
7269  array('text', 'text', 'text', 'integer'),
7270  array("", $this->lng->txt("unknown"), "", $this->getTestId())
7271  );
7272  }
7273  }
7274  else
7275  {
7276  if (is_numeric($user_id))
7277  {
7278  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7279  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7280  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7281  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
7282  "ORDER BY $order",
7283  array('integer', 'integer'),
7284  array($this->getTestId(), $user_id)
7285  );
7286  }
7287  else
7288  {
7289  $result = $ilDB->queryF("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
7290  "tst_active.submitted test_finished, matriculation FROM usr_data, tst_invited_user " .
7291  "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
7292  "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
7293  "ORDER BY $order",
7294  array('integer'),
7295  array($this->getTestId())
7296  );
7297  }
7298  }
7299  $result_array = array();
7300  while ($row = $ilDB->fetchAssoc($result))
7301  {
7302  $result_array[$row['usr_id']]= $row;
7303  }
7304  return $result_array;
7305  }
7306 
7314  {
7315  global $ilDB;
7316 
7317  if ($this->getAnonymity())
7318  {
7319  $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 ".
7320  "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),
7321  array('text', 'text', 'text', 'integer'),
7322  array("", $this->lng->txt("unknown"), "", $this->getTestId())
7323  );
7324  }
7325  else
7326  {
7327  $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 ".
7328  "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),
7329  array('integer'),
7330  array($this->getTestId())
7331  );
7332  }
7333  $data = array();
7334  while ($row = $ilDB->fetchAssoc($result))
7335  {
7336  $data[$row['active_id']] = $row;
7337  }
7338  foreach ($data as $index => $participant)
7339  {
7340  if (strlen(trim($participant["firstname"].$participant["lastname"])) == 0)
7341  {
7342  $data[$index]["lastname"] = $this->lng->txt("deleted_user");
7343  }
7344  }
7345  return $data;
7346  }
7347 
7348  public function getTestParticipantsForManualScoring($filter = NULL)
7349  {
7350  global $ilDB;
7351 
7352  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
7354  if (count($scoring) == 0) return array();
7355 
7356  $participants =& $this->getTestParticipants();
7357  $filtered_participants = array();
7358  foreach ($participants as $active_id => $participant)
7359  {
7360  $qstType_IN_manScoreableQstTypes = $ilDB->in('qpl_questions.question_type_fi', $scoring, false, 'integer');
7361 
7362  $queryString = "
7363  SELECT tst_test_result.manual
7364 
7365  FROM tst_test_result
7366 
7367  INNER JOIN qpl_questions
7368  ON tst_test_result.question_fi = qpl_questions.question_id
7369 
7370  WHERE tst_test_result.active_fi = %s
7371  AND $qstType_IN_manScoreableQstTypes
7372  ";
7373 
7374  $result = $ilDB->queryF(
7375  $queryString, array("integer"), array($active_id)
7376  );
7377 
7378  $count = $result->numRows();
7379 
7380  if ($count > 0)
7381  {
7382  switch ($filter)
7383  {
7384  case 1: // only active users
7385  if ($participant->active) $filtered_participants[$active_id] = $participant;
7386  break;
7387  case 2: // only inactive users
7388  if (!$participant->active) $filtered_participants[$active_id] = $participant;
7389  break;
7390  case 3: // all users
7391  $filtered_participants[$active_id] = $participant;
7392  break;
7393  case 4:
7394  // already scored participants
7395  //$found = 0;
7396  //while ($row = $ilDB->fetchAssoc($result))
7397  //{
7398  // if ($row["manual"]) $found++;
7399  //}
7400  //if ($found == $count)
7401  //{
7402  //$filtered_participants[$active_id] = $participant;
7403  //}
7404  //else
7405  //{
7406  $assessmentSetting = new ilSetting("assessment");
7407  $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7408  if ($manscoring_done) $filtered_participants[$active_id] = $participant;
7409  //}
7410  break;
7411  case 5:
7412  // unscored participants
7413  //$found = 0;
7414  //while ($row = $ilDB->fetchAssoc($result))
7415  //{
7416  // if ($row["manual"]) $found++;
7417  //}
7418  //if ($found == 0)
7419  //{
7420  $assessmentSetting = new ilSetting("assessment");
7421  $manscoring_done = $assessmentSetting->get("manscoring_done_" . $active_id);
7422  if (!$manscoring_done) $filtered_participants[$active_id] = $participant;
7423  //}
7424  break;
7425  case 6:
7426  // partially scored participants
7427  $found = 0;
7428  while ($row = $ilDB->fetchAssoc($result))
7429  {
7430  if ($row["manual"]) $found++;
7431  }
7432  if (($found > 0) && ($found < $count)) $filtered_participants[$active_id] = $participant;
7433  break;
7434  default:
7435  $filtered_participants[$active_id] = $participant;
7436  break;
7437  }
7438  }
7439  }
7440  return $filtered_participants;
7441  }
7442 
7450  function &getUserData($ids)
7451  {
7452  global $ilDB;
7453 
7454  if (!is_array($ids) || count($ids) ==0) return array();
7455 
7456  if ($this->getAnonymity())
7457  {
7458  $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",
7459  array('text', 'text', 'text'),
7460  array("", $this->lng->txt("unknown"), "")
7461  );
7462  }
7463  else
7464  {
7465  $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");
7466  }
7467 
7468  $result_array = array();
7469  while ($row = $ilDB->fetchAssoc($result))
7470  {
7471  $result_array[$row["usr_id"]]= $row;
7472  }
7473  return $result_array;
7474  }
7475 
7476  function &getGroupData($ids)
7477  {
7478  if (!is_array($ids) || count($ids) ==0) return array();
7479  $result = array();
7480  foreach ($ids as $ref_id)
7481  {
7482  $obj_id = ilObject::_lookupObjId($ref_id);
7483  $result[$ref_id] = array("ref_id" => $ref_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7484  }
7485  return $result;
7486  }
7487 
7488  function &getRoleData($ids)
7489  {
7490  if (!is_array($ids) || count($ids) ==0) return array();
7491  $result = array();
7492  foreach ($ids as $obj_id)
7493  {
7494  $result[$obj_id] = array("obj_id" => $obj_id, "title" => ilObject::_lookupTitle($obj_id), "description" => ilObject::_lookupDescription($obj_id));
7495  }
7496  return $result;
7497  }
7498 
7499 
7506  function inviteGroup($group_id)
7507  {
7508  include_once "./Modules/Group/classes/class.ilObjGroup.php";
7509  $group = new ilObjGroup($group_id);
7510  $members = $group->getGroupMemberIds();
7511  include_once './Services/User/classes/class.ilObjUser.php';
7512  foreach ($members as $user_id)
7513  {
7514  $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7515  }
7516  }
7517 
7524  function inviteRole($role_id)
7525  {
7526  global $rbacreview;
7527  $members = $rbacreview->assignedUsers($role_id,"usr_id");
7528  include_once './Services/User/classes/class.ilObjUser.php';
7529  foreach ($members as $user_id)
7530  {
7531  $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
7532  }
7533  }
7534 
7535 
7536 
7543  function disinviteUser($user_id)
7544  {
7545  global $ilDB;
7546 
7547  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7548  array('integer', 'integer'),
7549  array($this->getTestId(), $user_id)
7550  );
7551  }
7552 
7559  function inviteUser($user_id, $client_ip="")
7560  {
7561  global $ilDB;
7562 
7563  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
7564  array('integer', 'integer'),
7565  array($this->getTestId(), $user_id)
7566  );
7567  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_invited_user (test_fi, user_fi, clientip, tstamp) VALUES (%s, %s, %s, %s)",
7568  array('integer', 'integer', 'text', 'integer'),
7569  array($this->getTestId(), $user_id, (strlen($client_ip)) ? $client_ip : NULL, time())
7570  );
7571  }
7572 
7573 
7574  function setClientIP($user_id, $client_ip)
7575  {
7576  global $ilDB;
7577 
7578  $affectedRows = $ilDB->manipulateF("UPDATE tst_invited_user SET clientip = %s, tstamp = %s WHERE test_fi=%s and user_fi=%s",
7579  array('text', 'integer', 'integer', 'integer'),
7580  array((strlen($client_ip)) ? $client_ip : NULL, time(), $this->getTestId(), $user_id)
7581  );
7582  }
7583 
7589  function _getSolvedQuestions($active_id, $question_fi = null)
7590  {
7591  global $ilDB;
7592  if (is_numeric($question_fi))
7593  {
7594  $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s AND question_fi=%s",
7595  array('integer', 'integer'),
7596  array($active_id, $question_fi)
7597  );
7598  }
7599  else
7600  {
7601  $result = $ilDB->queryF("SELECT question_fi, solved FROM tst_qst_solved WHERE active_fi = %s",
7602  array('integer'),
7603  array($active_id)
7604  );
7605  }
7606  $result_array = array();
7607  while ($row = $ilDB->fetchAssoc($result))
7608  {
7609  $result_array[$row["question_fi"]]= $row;
7610  }
7611  return $result_array;
7612  }
7613 
7614 
7618  function setQuestionSetSolved($value, $question_id, $user_id)
7619  {
7620  global $ilDB;
7621 
7622  $active_id = $this->getActiveIdOfUser($user_id);
7623  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_qst_solved WHERE active_fi = %s AND question_fi = %s",
7624  array('integer', 'integer'),
7625  array($active_id, $question_id)
7626  );
7627  $affectedRows = $ilDB->manipulateF("INSERT INTO tst_qst_solved (solved, question_fi, active_fi) VALUES (%s, %s, %s)",
7628  array('integer', 'integer', 'integer'),
7629  array($value, $question_id, $active_id)
7630  );
7631  }
7632 
7636  function isTestFinished($active_id)
7637  {
7638  global $ilDB;
7639 
7640  $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE active_id=%s AND submitted=%s",
7641  array('integer', 'integer'),
7642  array($active_id, 1)
7643  );
7644  return $result->numRows() == 1;
7645  }
7646 
7650  function isActiveTestSubmitted($user_id = null)
7651  {
7652  global $ilUser;
7653  global $ilDB;
7654 
7655  if (!is_numeric($user_id))
7656  $user_id = $ilUser->getId();
7657 
7658  $result = $ilDB->queryF("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=%s",
7659  array('integer', 'integer', 'integer'),
7660  array($this->getTestId(), $user_id, 1)
7661  );
7662  return $result->numRows() == 1;
7663  }
7664 
7669  {
7670  return $this->getNrOfTries() != 0;
7671  }
7672 
7673 
7679  function isNrOfTriesReached($tries)
7680  {
7681  return $tries >= (int) $this->getNrOfTries();
7682  }
7683 
7684 
7693  function getAllTestResults($participants, $prepareForCSV = true)
7694  {
7695  $results = array();
7696  $row = array(
7697  "user_id" => $this->lng->txt("user_id"),
7698  "matriculation" => $this->lng->txt("matriculation"),
7699  "lastname" => $this->lng->txt("lastname"),
7700  "firstname" => $this->lng->txt("firstname"),
7701  "login" =>$this->lng->txt("login"),
7702  "reached_points" => $this->lng->txt("tst_reached_points"),
7703  "max_points" => $this->lng->txt("tst_maximum_points"),
7704  "percent_value" => $this->lng->txt("tst_percent_solved"),
7705  "mark" => $this->lng->txt("tst_mark"),
7706  "ects" => $this->lng->txt("ects_grade")
7707  );
7708  $results[] = $row;
7709  if (count($participants))
7710  {
7711  if ($this->ects_output)
7712  {
7713  $passed_array =& $this->getTotalPointsPassedArray();
7714  }
7715  foreach ($participants as $active_id => $user_rec)
7716  {
7717  $row = array();
7718  $reached_points = 0;
7719  $max_points = 0;
7720  foreach ($this->questions as $value)
7721  {
7722  $question =& ilObjTest::_instanciateQuestion($value);
7723  if (is_object($question))
7724  {
7725  $max_points += $question->getMaximumPoints();
7726  $reached_points += $question->getReachedPoints($active_id);
7727  }
7728  }
7729  if ($max_points > 0)
7730  {
7731  $percentvalue = $reached_points / $max_points;
7732  if ($percentvalue < 0) $percentvalue = 0.0;
7733  }
7734  else
7735  {
7736  $percentvalue = 0;
7737  }
7738  $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
7739  $passed = "";
7740  if ($mark_obj)
7741  {
7742  $mark = $mark_obj->getOfficialName();
7743  $ects_mark = $this->getECTSGrade($passed_array, $reached_points, $max_points);
7744  }
7745  if ($this->getAnonymity())
7746  {
7747  $user_rec['firstname'] = "";
7748  $user_rec['lastname'] = $this->lng->txt("unknown");
7749  }
7750  $row = array(
7751  "user_id"=>$user_rec['usr_id'],
7752  "matriculation" => $user_rec['matriculation'],
7753  "lastname" => $user_rec['lastname'],
7754  "firstname" => $user_rec['firstname'],
7755  "login"=>$user_rec['login'],
7756  "reached_points" => $reached_points,
7757  "max_points" => $max_points,
7758  "percent_value" => $percentvalue,
7759  "mark" => $mark,
7760  "ects" => $ects_mark
7761  );
7762  $results[] = $prepareForCSV ? $this->processCSVRow ($row, true) : $row;
7763  }
7764  }
7765  return $results;
7766  }
7767 
7778  function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
7779  {
7780  $resultarray = array();
7781  foreach ($row as $rowindex => $entry)
7782  {
7783  $surround = FALSE;
7784  if ($quoteAll)
7785  {
7786  $surround = TRUE;
7787  }
7788  if (strpos($entry, "\"") !== FALSE)
7789  {
7790  $entry = str_replace("\"", "\"\"", $entry);
7791  $surround = TRUE;
7792  }
7793  if (strpos($entry, $separator) !== FALSE)
7794  {
7795  $surround = TRUE;
7796  }
7797  // replace all CR LF with LF (for Excel for Windows compatibility
7798  $entry = str_replace(chr(13).chr(10), chr(10), $entry);
7799 
7800  if ($surround)
7801  {
7802  $entry = "\"" . $entry . "\"";
7803  }
7804 
7805  $resultarray[$rowindex] = $entry;
7806  }
7807  return $resultarray;
7808  }
7809 
7818  function _getPass($active_id)
7819  {
7820  global $ilDB;
7821  $result = $ilDB->queryF("SELECT tries FROM tst_active WHERE active_id = %s",
7822  array('integer'),
7823  array($active_id)
7824  );
7825  if ($result->numRows())
7826  {
7827  $row = $ilDB->fetchAssoc($result);
7828  return $row["tries"];
7829  }
7830  else
7831  {
7832  return 0;
7833  }
7834  }
7835 
7845  function _getMaxPass($active_id)
7846  {
7847  global $ilDB;
7848  $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s",
7849  array('integer'),
7850  array($active_id)
7851  );
7852  if ($result->numRows())
7853  {
7854  $row = $ilDB->fetchAssoc($result);
7855  $max = $row["maxpass"];
7856  }
7857  else
7858  {
7859  $max = NULL;
7860  }
7861  return $max;
7862  }
7863 
7874  function _getBestPass($active_id)
7875  {
7876  global $ilDB;
7877 
7878  $result = $ilDB->queryF("SELECT * FROM tst_pass_result WHERE active_fi = %s",
7879  array('integer'),
7880  array($active_id)
7881  );
7882  if ($result->numRows())
7883  {
7884  $bestrow = null;
7885  $bestfactor = 0;
7886  while ($row = $ilDB->fetchAssoc($result))
7887  {
7888  if($row["maxpoints"] > 0)
7889  {
7890  $factor = $row["points"] / $row["maxpoints"];
7891  }
7892  else
7893  {
7894  $factor = 0;
7895  }
7896 
7897  if($factor > $bestfactor)
7898  {
7899  $bestrow = $row;
7900  $bestfactor = $factor;
7901  }
7902  }
7903  if (is_array($bestrow))
7904  {
7905  return $bestrow["pass"];
7906  }
7907  else
7908  {
7909  return 0;
7910  }
7911  }
7912  else
7913  {
7914  return 0;
7915  }
7916  }
7917 
7926  function _getResultPass($active_id)
7927  {
7928  $counted_pass = NULL;
7929  if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS)
7930  {
7931  $counted_pass = ilObjTest::_getBestPass($active_id);
7932  }
7933  else
7934  {
7935  $counted_pass = ilObjTest::_getMaxPass($active_id);
7936  }
7937  return $counted_pass;
7938  }
7939 
7949  function getAnsweredQuestionCount($active_id, $pass = NULL)
7950  {
7951  if( $this->isDynamicTest() )
7952  {
7953  global $tree, $ilDB, $lng, $ilPluginAdmin;
7954 
7955  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
7956  $testSessionFactory = new ilTestSessionFactory($this);
7957  $testSession = $testSessionFactory->getSession($active_id);
7958 
7959  require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php';
7960  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this);
7961  $testSequence = $testSequenceFactory->getSequence($testSession);
7962 
7963  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
7964  $dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this);
7965  $dynamicQuestionSetConfig->loadFromDb();
7966 
7967  $testSequence->loadFromDb($dynamicQuestionSetConfig);
7968  $testSequence->loadQuestions($dynamicQuestionSetConfig, new ilTestDynamicQuestionSetFilterSelection());
7969 
7970  return $testSequence->getTrackedQuestionCount();
7971  }
7972 
7973  if ($this->isRandomTest())
7974  {
7975  $this->loadQuestions($active_id, $pass);
7976  }
7977  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
7978  $workedthrough = 0;
7979  foreach ($this->questions as $value)
7980  {
7981  if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
7982  {
7983  $workedthrough += 1;
7984  }
7985  }
7986  return $workedthrough;
7987  }
7988 
7998  function getPassFinishDate($active_id, $pass)
7999  {
8000  global $ilDB;
8001  if (is_null($pass)) $pass = 0;
8002  $result = $ilDB->queryF("SELECT tst_test_result.tstamp FROM tst_test_result WHERE active_fi = %s AND pass = %s ORDER BY tst_test_result.tstamp DESC",
8003  array('integer', 'integer'),
8004  array($active_id, $pass)
8005  );
8006  if ($result->numRows())
8007  {
8008  $row = $ilDB->fetchAssoc($result);
8009  return $row["tstamp"];
8010  }
8011  else
8012  {
8013  return 0;
8014  }
8015  }
8016 
8025  function isExecutable($testSession, $user_id, $allowPassIncrease = FALSE)
8026  {
8027  $result = array(
8028  "executable" => true,
8029  "errormessage" => ""
8030  );
8031  if (!$this->startingTimeReached())
8032  {
8033  $result["executable"] = false;
8034  $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilFormat::ftimestamp2datetimeDB($this->getStartingTime()));
8035  return $result;
8036  }
8037  if ($this->endingTimeReached())
8038  {
8039  $result["executable"] = false;
8040  $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilFormat::ftimestamp2datetimeDB($this->getEndingTime()));
8041  return $result;
8042  }
8043 
8044  $active_id = $this->getActiveIdOfUser($user_id);
8045 
8046  if ($this->getEnableProcessingTime())
8047  {
8048  if ($active_id > 0)
8049  {
8050  $starting_time = $this->getStartingTimeOfUser($active_id);
8051  if ($starting_time !== FALSE)
8052  {
8053  if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8054  {
8055  if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > ($this->_getPass($active_id)+1))))
8056  {
8057  // a test pass was quitted because the maximum processing time was reached, but the time
8058  // will be resetted for future passes, so if there are more passes allowed, the participant may
8059  // start the test again.
8060  // This code block is only called when $allowPassIncrease is TRUE which only happens when
8061  // the test info page is opened. Otherwise this will lead to unexpected results!
8062  $testSession->increasePass();
8063  $testSession->setLastSequence(0);
8064  $testSession->saveToDb();
8065  }
8066  else
8067  {
8068  $result["executable"] = false;
8069  $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
8070  }
8071  return $result;
8072  }
8073  }
8074  }
8075  }
8076 
8077  if ($this->hasNrOfTriesRestriction() && ($active_id > 0))
8078  {
8079  require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
8080  $testPassesSelector = new ilTestPassesSelector($GLOBALS['ilDB'], $this);
8081  $testPassesSelector->setActiveId($active_id);
8082  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
8083 
8084  $closedPasses = $testPassesSelector->getClosedPasses();
8085 
8086  if( count($closedPasses) >= $this->getNrOfTries() )
8087  {
8088  $result["executable"] = false;
8089  $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
8090  return $result;
8091  }
8092  }
8093 
8094  return $result;
8095  }
8096 
8103  function canViewResults()
8104  {
8105  $result = true;
8106  if ($this->getScoreReporting() == 4) return false;
8107  if ($this->getReportingDate())
8108  {
8109  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8110  {
8111  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8112  $now = mktime();
8113  if ($now < $epoch_time)
8114  {
8115  $result = false;
8116  }
8117  }
8118  }
8119  return $result;
8120  }
8121 
8122  function canShowTestResults($testSession, $user_id)
8123  {
8124  $active_id = $this->getActiveIdOfUser($user_id);
8125  if ($active_id > 0)
8126  {
8127  $starting_time = $this->getStartingTimeOfUser($active_id);
8128  }
8129  $notimeleft = FALSE;
8130  if ($starting_time !== FALSE)
8131  {
8132  if ($this->isMaxProcessingTimeReached($starting_time, $active_id))
8133  {
8134  $notimeleft = TRUE;
8135  }
8136  }
8137  $result = TRUE;
8138  if (!$this->isTestFinishedToViewResults($active_id, $testSession->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
8139  {
8140  $result = FALSE;
8141  }
8142  if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
8143  $result = $result & $this->canViewResults();
8144  return $result;
8145  }
8146 
8147  function canEditMarks()
8148  {
8149  $total = $this->evalTotalPersons();
8150  if ($total > 0)
8151  {
8152  if ($this->getReportingDate())
8153  {
8154  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
8155  {
8156  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8157  $now = mktime();
8158  if ($now < $epoch_time)
8159  {
8160  return true;
8161  }
8162  }
8163  }
8164  return false;
8165  }
8166  else
8167  {
8168  return true;
8169  }
8170  }
8171 
8179  function getStartingTimeOfUser($active_id, $pass = null)
8180  {
8181  global $ilDB;
8182 
8183  if ($active_id < 1) return FALSE;
8184  if($pass === null)
8185  {
8186  $pass = ($this->getResetProcessingTime()) ? $this->_getPass($active_id) : 0;
8187  }
8188  $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",
8189  array('integer', 'integer'),
8190  array($active_id, $pass)
8191  );
8192  if ($result->numRows())
8193  {
8194  $row = $ilDB->fetchAssoc($result);
8195  if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
8196  {
8197  return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
8198  }
8199  else
8200  {
8201  return mktime();
8202  }
8203  }
8204  else
8205  {
8206  return mktime();
8207  }
8208  }
8209 
8218  function isMaxProcessingTimeReached($starting_time, $active_id)
8219  {
8220  if ($this->getEnableProcessingTime())
8221  {
8222  $processing_time = $this->getProcessingTimeInSeconds($active_id);
8223  $now = mktime();
8224  if ($now > ($starting_time + $processing_time))
8225  {
8226  return TRUE;
8227  }
8228  else
8229  {
8230  return FALSE;
8231  }
8232  }
8233  else
8234  {
8235  return FALSE;
8236  }
8237  }
8238 
8239  function &getTestQuestions()
8240  {
8241  global $ilDB;
8242 
8243  $query = "
8244  SELECT questions.*,
8245  questtypes.type_tag,
8246  tstquest.sequence,
8247  tstquest.obligatory,
8248  origquest.obj_fi orig_obj_fi
8249 
8250  FROM qpl_questions questions
8251 
8252  INNER JOIN qpl_qst_type questtypes
8253  ON questtypes.question_type_id = questions.question_type_fi
8254 
8255  INNER JOIN tst_test_question tstquest
8256  ON tstquest.question_fi = questions.question_id
8257 
8258  LEFT JOIN qpl_questions origquest
8259  ON origquest.question_id = questions.original_id
8260 
8261  WHERE tstquest.test_fi = %s
8262 
8263  ORDER BY tstquest.sequence
8264  ";
8265 
8266  $query_result = $ilDB->queryF(
8267  $query, array('integer'), array($this->getTestId())
8268  );
8269 
8270  $questions = array();
8271 
8272  while ($row = $ilDB->fetchAssoc($query_result))
8273  {
8274  $question = $row;
8275 
8276  $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8277 
8278  $questions[] = $question;
8279  }
8280 
8281  return $questions;
8282  }
8283 
8287  public function getPotentialRandomTestQuestions()
8288  {
8292  global $ilDB;
8293 
8294  $query = "
8295  SELECT questions.*,
8296  questtypes.type_tag,
8297  origquest.obj_fi orig_obj_fi
8298 
8299  FROM qpl_questions questions
8300 
8301  INNER JOIN qpl_qst_type questtypes
8302  ON questtypes.question_type_id = questions.question_type_fi
8303 
8304  INNER JOIN tst_rnd_cpy tstquest
8305  ON tstquest.qst_fi = questions.question_id
8306 
8307  LEFT JOIN qpl_questions origquest
8308  ON origquest.question_id = questions.original_id
8309 
8310  WHERE tstquest.tst_fi = %s
8311  ";
8312 
8313  $query_result = $ilDB->queryF(
8314  $query, array('integer'), array($this->getTestId())
8315  );
8316 
8317  $questions = array();
8318 
8319  while ($row = $ilDB->fetchAssoc($query_result))
8320  {
8321  $question = $row;
8322 
8323  $question['obligationPossible'] = self::isQuestionObligationPossible($row['question_id']);
8324 
8325  $questions[] = $question;
8326  }
8327 
8328  return $questions;
8329  }
8330 
8338  {
8339  return ($this->shuffle_questions) ? 1 : 0;
8340  }
8341 
8348  function setShuffleQuestions($a_shuffle)
8349  {
8350  $this->shuffle_questions = ($a_shuffle) ? 1 : 0;
8351  }
8352 
8366  {
8367  return ($this->show_summary) ? $this->show_summary : 0;
8368  }
8369 
8382  function setListOfQuestionsSettings($a_value = 0)
8383  {
8384  $this->show_summary = $a_value;
8385  }
8386 
8394  {
8395  if (($this->show_summary & 1) > 0)
8396  {
8397  return TRUE;
8398  }
8399  else
8400  {
8401  return FALSE;
8402  }
8403  }
8404 
8411  function setListOfQuestions($a_value = TRUE)
8412  {
8413  if ($a_value)
8414  {
8415  $this->show_summary = 1;
8416  }
8417  else
8418  {
8419  $this->show_summary = 0;
8420  }
8421  }
8422 
8430  {
8431  if (($this->show_summary & 2) > 0)
8432  {
8433  return TRUE;
8434  }
8435  else
8436  {
8437  return FALSE;
8438  }
8439  }
8440 
8447  function setListOfQuestionsStart($a_value = TRUE)
8448  {
8449  if ($a_value && $this->getListOfQuestions())
8450  {
8451  $this->show_summary = $this->show_summary | 2;
8452  }
8453  if (!$a_value && $this->getListOfQuestions())
8454  {
8455  if ($this->getListOfQuestionsStart())
8456  {
8457  $this->show_summary = $this->show_summary ^ 2;
8458  }
8459  }
8460  }
8461 
8469  {
8470  if (($this->show_summary & 4) > 0)
8471  {
8472  return TRUE;
8473  }
8474  else
8475  {
8476  return FALSE;
8477  }
8478  }
8479 
8486  function setListOfQuestionsEnd($a_value = TRUE)
8487  {
8488  if ($a_value && $this->getListOfQuestions())
8489  {
8490  $this->show_summary = $this->show_summary | 4;
8491  }
8492  if (!$a_value && $this->getListOfQuestions())
8493  {
8494  if ($this->getListOfQuestionsEnd())
8495  {
8496  $this->show_summary = $this->show_summary ^ 4;
8497  }
8498  }
8499  }
8500 
8508  {
8509  if (($this->show_summary & 8) > 0)
8510  {
8511  return TRUE;
8512  }
8513  else
8514  {
8515  return FALSE;
8516  }
8517  }
8518 
8525  function setListOfQuestionsDescription($a_value = TRUE)
8526  {
8527  if ($a_value && $this->getListOfQuestions())
8528  {
8529  $this->show_summary = $this->show_summary | 8;
8530  }
8531  if (!$a_value && $this->getListOfQuestions())
8532  {
8533  if ($this->getListOfQuestionsDescription())
8534  {
8535  $this->show_summary = $this->show_summary ^ 8;
8536  }
8537  }
8538  }
8539 
8547  {
8548  return ($this->results_presentation) ? $this->results_presentation : 0;
8549  }
8550 
8558  {
8559  if (($this->results_presentation & 1) > 0)
8560  {
8561  return TRUE;
8562  }
8563  else
8564  {
8565  return FALSE;
8566  }
8567  }
8568 
8576  {
8577  if (($this->results_presentation & 2) > 0)
8578  {
8579  return TRUE;
8580  }
8581  else
8582  {
8583  return FALSE;
8584  }
8585  }
8586 
8594  {
8595  if (($this->results_presentation & 4) > 0)
8596  {
8597  return TRUE;
8598  }
8599  else
8600  {
8601  return FALSE;
8602  }
8603  }
8604 
8612  {
8613  if (($this->results_presentation & 8) > 0)
8614  {
8615  return TRUE;
8616  }
8617  else
8618  {
8619  return FALSE;
8620  }
8621  }
8622 
8630  {
8631  if (($this->results_presentation & 16) > 0)
8632  {
8633  return TRUE;
8634  }
8635  else
8636  {
8637  return FALSE;
8638  }
8639  }
8640 
8648  {
8649  if (($this->results_presentation & 32) > 0)
8650  {
8651  return TRUE;
8652  }
8653  else
8654  {
8655  return FALSE;
8656  }
8657  }
8658 
8664  {
8665  if (($this->results_presentation & 64) > 0)
8666  {
8667  return TRUE;
8668  }
8669  else
8670  {
8671  return FALSE;
8672  }
8673  }
8674 
8680  {
8681  if(($this->results_presentation & 128) > 0)
8682  {
8683  return TRUE;
8684  }
8685  else
8686  {
8687  return FALSE;
8688  }
8689  }
8690 
8697  function setResultsPresentation($a_results_presentation = 3)
8698  {
8699  $this->results_presentation = $a_results_presentation;
8700  }
8701 
8710  function setShowPassDetails($a_details = 1)
8711  {
8712  if ($a_details)
8713  {
8714  $this->results_presentation = $this->results_presentation | 1;
8715  }
8716  else
8717  {
8718  if ($this->getShowPassDetails())
8719  {
8720  $this->results_presentation = $this->results_presentation ^ 1;
8721  }
8722  }
8723  }
8724 
8731  function setShowSolutionDetails($a_details = 1)
8732  {
8733  if ($a_details)
8734  {
8735  $this->results_presentation = $this->results_presentation | 2;
8736  }
8737  else
8738  {
8739  if ($this->getShowSolutionDetails())
8740  {
8741  $this->results_presentation = $this->results_presentation ^ 2;
8742  }
8743  }
8744  }
8745 
8752  function canShowSolutionPrintview($user_id = NULL)
8753  {
8754  return $this->getShowSolutionPrintview();
8755  }
8756 
8763  function setShowSolutionPrintview($a_printview = 1)
8764  {
8765  if ($a_printview)
8766  {
8767  $this->results_presentation = $this->results_presentation | 4;
8768  }
8769  else
8770  {
8771  if ($this->getShowSolutionPrintview())
8772  {
8773  $this->results_presentation = $this->results_presentation ^ 4;
8774  }
8775  }
8776  }
8777 
8784  function setShowSolutionFeedback($a_feedback = TRUE)
8785  {
8786  if ($a_feedback)
8787  {
8788  $this->results_presentation = $this->results_presentation | 8;
8789  }
8790  else
8791  {
8792  if ($this->getShowSolutionFeedback())
8793  {
8794  $this->results_presentation = $this->results_presentation ^ 8;
8795  }
8796  }
8797  }
8798 
8805  function setShowSolutionAnswersOnly($a_full = TRUE)
8806  {
8807  if ($a_full)
8808  {
8809  $this->results_presentation = $this->results_presentation | 16;
8810  }
8811  else
8812  {
8813  if ($this->getShowSolutionAnswersOnly())
8814  {
8815  $this->results_presentation = $this->results_presentation ^ 16;
8816  }
8817  }
8818  }
8819 
8826  function setShowSolutionSignature($a_signature = FALSE)
8827  {
8828  if ($a_signature)
8829  {
8830  $this->results_presentation = $this->results_presentation | 32;
8831  }
8832  else
8833  {
8834  if ($this->getShowSolutionSignature())
8835  {
8836  $this->results_presentation = $this->results_presentation ^ 32;
8837  }
8838  }
8839  }
8840 
8847  function setShowSolutionSuggested($a_solution = FALSE)
8848  {
8849  if ($a_solution)
8850  {
8851  $this->results_presentation = $this->results_presentation | 64;
8852  }
8853  else
8854  {
8855  if ($this->getShowSolutionSuggested())
8856  {
8857  $this->results_presentation = $this->results_presentation ^ 64;
8858  }
8859  }
8860  }
8861 
8867  public function setShowSolutionListComparison($a_comparison = FALSE)
8868  {
8869  if($a_comparison)
8870  {
8871  $this->results_presentation = $this->results_presentation | 128;
8872  }
8873  else
8874  {
8875  if($this->getShowSolutionListComparison())
8876  {
8877  $this->results_presentation = $this->results_presentation ^ 128;
8878  }
8879  }
8880  }
8881 
8882  public static function _getUserIdFromActiveId($active_id)
8883  {
8884  global $ilDB;
8885  $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
8886  array('integer'),
8887  array($active_id)
8888  );
8889  if ($result->numRows())
8890  {
8891  $row = $ilDB->fetchAssoc($result);
8892  return $row["user_fi"];
8893  }
8894  else
8895  {
8896  return -1;
8897  }
8898  }
8899 
8900  function getAllowedUsers()
8901  {
8902  return ($this->allowedUsers) ? $this->allowedUsers : 0;
8903  }
8904 
8905  function setAllowedUsers($a_allowed_users)
8906  {
8907  $this->allowedUsers = $a_allowed_users;
8908  }
8909 
8911  {
8912  return ($this->allowedUsersTimeGap) ? $this->allowedUsersTimeGap : 0;
8913  }
8914 
8915  function setAllowedUsersTimeGap($a_allowed_users_time_gap)
8916  {
8917  $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
8918  }
8919 
8921  {
8922  global $ilDB;
8923 
8924  $nr_of_users = $this->getAllowedUsers();
8925  $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
8926  if (($nr_of_users > 0) && ($time_gap > 0))
8927  {
8928  $now = mktime();
8929  $time_border = $now - $time_gap;
8930  $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
8931  $result = $ilDB->queryF("SELECT DISTINCT tst_times.active_fi FROM tst_times, tst_active WHERE tst_times.tstamp > %s AND tst_times.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
8932  array('integer', 'integer'),
8933  array($time_border, $this->getTestId())
8934  );
8935  if ($result->numRows() >= $nr_of_users)
8936  {
8937  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
8939  {
8940  $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
8941  }
8942  return FALSE;
8943  }
8944  else
8945  {
8946  return TRUE;
8947  }
8948  }
8949  return TRUE;
8950  }
8951 
8952  function _getLastAccess($active_id)
8953  {
8954  global $ilDB;
8955 
8956  $result = $ilDB->queryF("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
8957  array('integer'),
8958  array($active_id)
8959  );
8960  if ($result->numRows())
8961  {
8962  $row = $ilDB->fetchAssoc($result);
8963  return $row["finished"];
8964  }
8965  return "";
8966  }
8967 
8975  function isHTML($a_text)
8976  {
8977  if (preg_match("/<[^>]*?>/", $a_text))
8978  {
8979  return TRUE;
8980  }
8981  else
8982  {
8983  return FALSE;
8984  }
8985  }
8986 
8994  function QTIMaterialToString($a_material)
8995  {
8996  $result = "";
8997  for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
8998  {
8999  $material = $a_material->getMaterial($i);
9000  if (strcmp($material["type"], "mattext") == 0)
9001  {
9002  $result .= $material["material"]->getContent();
9003  }
9004  if (strcmp($material["type"], "matimage") == 0)
9005  {
9006  $matimage = $material["material"];
9007  if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
9008  {
9009  // import an mediaobject which was inserted using tiny mce
9010  if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
9011  array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
9012  }
9013  }
9014  }
9015  global $ilLog;
9016  $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
9017  return $result;
9018  }
9019 
9028  function addQTIMaterial(&$a_xml_writer, $a_material)
9029  {
9030  include_once "./Services/RTE/classes/class.ilRTE.php";
9031  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
9032 
9033  $a_xml_writer->xmlStartTag("material");
9034  $attrs = array(
9035  "texttype" => "text/plain"
9036  );
9037  if ($this->isHTML($a_material))
9038  {
9039  $attrs["texttype"] = "text/xhtml";
9040  }
9041  $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
9042 
9043  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
9044  foreach ($mobs as $mob)
9045  {
9046  $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
9047  if (strpos($a_material, "mm_$mob") !== FALSE)
9048  {
9049  if (ilObjMediaObject::_exists($mob))
9050  {
9051  $mob_obj =& new ilObjMediaObject($mob);
9052  $imgattrs = array(
9053  "label" => $moblabel,
9054  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
9055  );
9056  }
9057  $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
9058  }
9059  }
9060  $a_xml_writer->xmlEndTag("material");
9061  }
9062 
9069  function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE)
9070  {
9071  include_once "./Services/Utilities/classes/class.ilUtil.php";
9072  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
9073  }
9074 
9081  function saveCertificateVisibility($a_value)
9082  {
9083  global $ilDB;
9084 
9085  $affectedRows = $ilDB->manipulateF("UPDATE tst_tests SET certificate_visibility = %s, tstamp = %s WHERE test_id = %s",
9086  array('text', 'integer', 'integer'),
9087  array($a_value, time(), $this->getTestId())
9088  );
9089  }
9090 
9098  {
9099  return (strlen($this->certificate_visibility)) ? $this->certificate_visibility : 0;
9100  }
9101 
9108  function setCertificateVisibility($a_value)
9109  {
9110  $this->certificate_visibility = $a_value;
9111  }
9112 
9119  function getAnonymity()
9120  {
9121  return ($this->anonymity) ? 1 : 0;
9122  }
9123 
9130  function setAnonymity($a_value = 0)
9131  {
9132  switch ($a_value)
9133  {
9134  case 1:
9135  $this->anonymity = 1;
9136  break;
9137  default:
9138  $this->anonymity = 0;
9139  break;
9140  }
9141  }
9142 
9149  function getShowCancel()
9150  {
9151  return ($this->show_cancel) ? 1 : 0;
9152  }
9153 
9160  function setShowCancel($a_value = 1)
9161  {
9162  switch ($a_value)
9163  {
9164  case 1:
9165  $this->show_cancel = 1;
9166  break;
9167  default:
9168  $this->show_cancel = 0;
9169  break;
9170  }
9171  }
9172 
9179  function getShowMarker()
9180  {
9181  return ($this->show_marker) ? 1 : 0;
9182  }
9183 
9190  function setShowMarker($a_value = 1)
9191  {
9192  switch ($a_value)
9193  {
9194  case 1:
9195  $this->show_marker = 1;
9196  break;
9197  default:
9198  $this->show_marker = 0;
9199  break;
9200  }
9201  }
9202 
9210  {
9211  return ($this->fixed_participants) ? 1 : 0;
9212  }
9213 
9220  function setFixedParticipants($a_value = 1)
9221  {
9222  switch ($a_value)
9223  {
9224  case 1:
9225  $this->fixed_participants = 1;
9226  break;
9227  default:
9228  $this->fixed_participants = 0;
9229  break;
9230  }
9231  }
9232 
9240  function _lookupAnonymity($a_obj_id)
9241  {
9242  global $ilDB;
9243 
9244  $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE obj_fi = %s",
9245  array('integer'),
9246  array($a_obj_id)
9247  );
9248  while($row = $ilDB->fetchAssoc($result))
9249  {
9250  return $row['anonymity'];
9251  }
9252  return 0;
9253  }
9254 
9261  public static function lookupQuestionSetTypeByActiveId($active_id)
9262  {
9263  global $ilDB;
9264 
9265  $query = "
9266  SELECT tst_tests.question_set_type
9267  FROM tst_active
9268  INNER JOIN tst_tests
9269  ON tst_active.test_fi = tst_tests.test_id
9270  WHERE tst_active.active_id = %s
9271  ";
9272 
9273  $res = $ilDB->queryF( $query, array('integer'), array($active_id) );
9274 
9275  while($row = $ilDB->fetchAssoc($res))
9276  {
9277  return $row['question_set_type'];
9278  }
9279 
9280  return null;
9281  }
9282 
9291  function _lookupRandomTestFromActiveId($active_id)
9292  {
9293  throw new Exception(__METHOD__.' is deprecated ... use ilObjTest::lookupQuestionSetTypeByActiveId() instead!');
9294 
9295  global $ilDB;
9296 
9297  $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",
9298  array('integer'),
9299  array($active_id)
9300  );
9301  while($row = $ilDB->fetchAssoc($result))
9302  {
9303  return $row['random_test'];
9304  }
9305  return 0;
9306  }
9307 
9316  function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
9317  {
9318  if ($this->getAnonymity() && !$overwrite_anonymity)
9319  {
9320  return $this->lng->txt("unknown") . $suffix;
9321  }
9322  else
9323  {
9324  include_once './Services/User/classes/class.ilObjUser.php';
9325  $uname = ilObjUser::_lookupName($user_id);
9326  if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
9327  if ($sorted_order)
9328  {
9329  return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
9330  }
9331  else
9332  {
9333  return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
9334  }
9335  }
9336  }
9337 
9345  function getStartTestLabel($active_id)
9346  {
9347  if ($this->getNrOfTries() == 1)
9348  {
9349  return $this->lng->txt("tst_start_test");
9350  }
9351  $active_pass = $this->_getPass($active_id);
9352  $res = $this->getNrOfResultsForPass($active_id, $active_pass);
9353  if ($res == 0)
9354  {
9355  if ($active_pass == 0)
9356  {
9357  return $this->lng->txt("tst_start_test");
9358  }
9359  else
9360  {
9361  return $this->lng->txt("tst_start_new_test_pass");
9362  }
9363  }
9364  else
9365  {
9366  return $this->lng->txt("tst_resume_test");
9367  }
9368  }
9369 
9375  public function getAvailableDefaults()
9376  {
9381  global $ilDB, $ilUser;
9382 
9383  $result = $ilDB->queryF(
9384  "SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY name ASC",
9385  array('integer'),
9386  array($ilUser->getId())
9387  );
9388  $defaults = array();
9389  while($row = $ilDB->fetchAssoc($result))
9390  {
9391  $defaults[$row["test_defaults_id"]] = $row;
9392  }
9393  return $defaults;
9394  }
9395 
9403  function &getTestDefaults($test_defaults_id)
9404  {
9405  return self::_getTestDefaults($test_defaults_id);
9406  }
9407 
9408  public static function _getTestDefaults($test_defaults_id)
9409  {
9410  global $ilDB;
9411 
9412  $result = $ilDB->queryF("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
9413  array('integer'),
9414  array($test_defaults_id)
9415  );
9416  if ($result->numRows() == 1)
9417  {
9418  $row = $ilDB->fetchAssoc($result);
9419  return $row;
9420  }
9421  else
9422  {
9423  return NULL;
9424  }
9425  }
9426 
9433  function deleteDefaults($test_default_id)
9434  {
9435  global $ilDB;
9436  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
9437  array('integer'),
9438  array($test_default_id)
9439  );
9440  }
9441 
9448  function addDefaults($a_name)
9449  {
9450  global $ilDB;
9451  global $ilUser;
9452  $testsettings = array(
9453  "TitleOutput" => $this->getTitleOutput(),
9454  "PassScoring" => $this->getPassScoring(),
9455  "Introduction" => $this->getIntroduction(),
9456  "FinalStatement" => $this->getFinalStatement(),
9457  "ShowInfo" => $this->getShowInfo(),
9458  "ForceJS" => $this->getForceJS(),
9459  "CustomStyle" => $this->getCustomStyle(),
9460  "ShowFinalStatement" => $this->getShowFinalStatement(),
9461  "SequenceSettings" => $this->getSequenceSettings(),
9462  "ScoreReporting" => $this->getScoreReporting(),
9463  "ScoreCutting" => $this->getScoreCutting(),
9464  'SpecificAnswerFeedback' => $this->getSpecificAnswerFeedback(),
9465  'PrintBsWithRes' => (int)$this->isBestSolutionPrintedWithResult(),
9466  "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
9467  "AnswerFeedback" => $this->getAnswerFeedback(),
9468  "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
9469  "ResultsPresentation" => $this->getResultsPresentation(),
9470  "Anonymity" => $this->getAnonymity(),
9471  "ShowCancel" => $this->getShowCancel(),
9472  "ShowMarker" => $this->getShowMarker(),
9473  "ReportingDate" => $this->getReportingDate(),
9474  "NrOfTries" => $this->getNrOfTries(),
9475  "Shuffle" => $this->getShuffleQuestions(),
9476  "Kiosk" => $this->getKiosk(),
9477  "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
9478  "ProcessingTime" => $this->getProcessingTime(),
9479  "EnableProcessingTime" => $this->getEnableProcessingTime(),
9480  "ResetProcessingTime" => $this->getResetProcessingTime(),
9481  "StartingTime" => $this->getStartingTime(),
9482  "EndingTime" => $this->getEndingTime(),
9483  "ECTSOutput" => $this->getECTSOutput(),
9484  "ECTSFX" => $this->getECTSFX(),
9485  "ECTSGrades" => $this->getECTSGrades(),
9486  "questionSetType" => $this->getQuestionSetType(),
9487  "CountSystem" => $this->getCountSystem(),
9488  "MCScoring" => $this->getMCScoring(),
9489  "mailnotification" => $this->getMailNotification(),
9490  "mailnottype" => $this->getMailNotificationType(),
9491  "exportsettings" => $this->getExportSettings(),
9492  "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings(),
9493  'obligations_enabled' => (int)$this->areObligationsEnabled(),
9494  'offer_question_hints' => (int)$this->isOfferingQuestionHintsEnabled(),
9495  'pass_deletion_allowed' => (int)$this->isPassDeletionAllowed(),
9496  'enable_examview' => $this->getEnableExamview(),
9497  'show_examview_html' => $this->getShowExamviewHtml(),
9498  'show_examview_pdf' => $this->getShowExamviewPdf(),
9499  'char_selector_availability' => $this->getCharSelectorAvailability(),
9500  'char_selector_definition' => $this->getCharSelectorDefinition(),
9501  'redirection_mode' => $this->getRedirectionMode(),
9502  'redirection_url' => $this->getRedirectionUrl(),
9503  'sign_submission' => $this->getSignSubmission(),
9504  'autosave' => (int)$this->getAutosave(),
9505  'autosave_ival' => (int)$this->getAutosaveIval(),
9506  'examid_in_test_pass' => (int)$this->isShowExamIdInTestPassEnabled(),
9507  'examid_in_test_res' => (int)$this->isShowExamIdInTestResultsEnabled(),
9508 
9509  'enable_archiving' => (int)$this->getEnableArchiving(),
9510  'password' => (string)$this->getPassword(),
9511  'fixed_participants' => $this->getFixedParticipants(),
9512  'allowedusers' => $this->getAllowedUsers(),
9513  'alloweduserstimegap' => $this->getAllowedUsersTimeGap(),
9514  'pool_usage' => $this->getPoolUsage(),
9515  'activation_limited' => $this->isActivationLimited(),
9516  'activation_start_time' => $this->getActivationStartingTime(),
9517  'activation_end_time' => $this->getActivationEndingTime(),
9518  'activation_visibility' => $this->getActivationVisibility(),
9519  'highscore_enabled' => $this->getHighscoreEnabled(),
9520  'highscore_anon' => $this->getHighscoreAnon(),
9521  'highscore_achieved_ts' => $this->getHighscoreAchievedTS(),
9522  'highscore_score' => $this->getHighscoreScore(),
9523  'highscore_percentage' => $this->getHighscorePercentage(),
9524  'highscore_hints' => $this->getHighscoreHints(),
9525  'highscore_wtime' => $this->getHighscoreWTime(),
9526  'highscore_own_table' => $this->getHighscoreOwnTable(),
9527  'highscore_top_table' => $this->getHighscoreTopTable(),
9528  'highscore_top_num' => $this->getHighscoreTopNum(),
9529  'use_previous_answers' => (string)$this->getUsePreviousAnswers()
9530  );
9531  $next_id = $ilDB->nextId('tst_test_defaults');
9532  $ilDB->insert(
9533  'tst_test_defaults',
9534  array(
9535  'test_defaults_id' => array('integer', $next_id),
9536  'name' => array('text', $a_name),
9537  'user_fi' => array('integer', $ilUser->getId()),
9538  'defaults' => array('clob', serialize($testsettings)),
9539  'marks' => array('clob', serialize($this->mark_schema)),
9540  'tstamp' => array('integer', time())
9541  )
9542  );
9543  }
9544 
9552  public function applyDefaults($test_defaults)
9553  {
9554  $testsettings = unserialize($test_defaults["defaults"]);
9555  include_once "./Modules/Test/classes/class.assMarkSchema.php";
9556  $this->mark_schema = unserialize($test_defaults["marks"]);
9557 
9558  $this->setTitleOutput($testsettings["TitleOutput"]);
9559  $this->setPassScoring($testsettings["PassScoring"]);
9560  $this->setIntroduction($testsettings["Introduction"]);
9561  $this->setFinalStatement($testsettings["FinalStatement"]);
9562  $this->setShowInfo($testsettings["ShowInfo"]);
9563  $this->setForceJS($testsettings["ForceJS"]);
9564  $this->setCustomStyle($testsettings["CustomStyle"]);
9565  $this->setShowFinalStatement($testsettings["ShowFinalStatement"]);
9566  $this->setSequenceSettings($testsettings["SequenceSettings"]);
9567  $this->setScoreReporting($testsettings["ScoreReporting"]);
9568  $this->setScoreCutting($testsettings['ScoreCutting']);
9569  $this->setSpecificAnswerFeedback($testsettings['SpecificAnswerFeedback']);
9570  $this->setPrintBestSolutionWithResult((bool)$testsettings['PrintBsWithRes']);
9571  $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
9572  $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
9573  $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
9574  $this->setResultsPresentation($testsettings["ResultsPresentation"]);
9575  $this->setAnonymity($testsettings["Anonymity"]);
9576  $this->setShowCancel($testsettings["ShowCancel"]);
9577  $this->setShuffleQuestions($testsettings["Shuffle"]);
9578  $this->setShowMarker($testsettings["ShowMarker"]);
9579  $this->setReportingDate($testsettings["ReportingDate"]);
9580  $this->setNrOfTries($testsettings["NrOfTries"]);
9581  $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
9582  $this->setRedirectionMode($testsettings['redirection_mode']);
9583  $this->setRedirectionUrl($testsettings['redirection_url']);
9584  $this->setProcessingTime($testsettings["ProcessingTime"]);
9585  $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
9586  $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
9587  $this->setStartingTime($testsettings["StartingTime"]);
9588  $this->setKiosk($testsettings["Kiosk"]);
9589  $this->setEndingTime($testsettings["EndingTime"]);
9590  $this->setECTSOutput($testsettings["ECTSOutput"]);
9591  $this->setECTSFX($testsettings["ECTSFX"]);
9592  $this->setECTSGrades($testsettings["ECTSGrades"]);
9593  if( isset($testsettings["isRandomTest"]) )
9594  {
9595  if( $testsettings["isRandomTest"] )
9596  {
9597  $this->setQuestionSetType(self::QUESTION_SET_TYPE_RANDOM);
9598  }
9599  else
9600  {
9601  $this->setQuestionSetType(self::QUESTION_SET_TYPE_FIXED);
9602  }
9603  }
9604  elseif( isset($testsettings["questionSetType"]) )
9605  {
9606  $this->setQuestionSetType($testsettings["questionSetType"]);
9607  }
9608  $this->setCountSystem($testsettings["CountSystem"]);
9609  $this->setMCScoring($testsettings["MCScoring"]);
9610  $this->setMailNotification($testsettings["mailnotification"]);
9611  $this->setMailNotificationType($testsettings["mailnottype"]);
9612  $this->setExportSettings($testsettings['exportsettings']);
9613  $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
9614  $this->setObligationsEnabled($testsettings["obligations_enabled"]);
9615  $this->setOfferingQuestionHintsEnabled($testsettings["offer_question_hints"]);
9616  $this->setHighscoreEnabled($testsettings['highscore_enabled']);
9617  $this->setHighscoreAnon($testsettings['highscore_anon']);
9618  $this->setHighscoreAchievedTS($testsettings['highscore_achieved_ts']);
9619  $this->setHighscoreScore($testsettings['highscore_score']);
9620  $this->setHighscorePercentage($testsettings['highscore_percentage']);
9621  $this->setHighscoreHints($testsettings['highscore_hints']);
9622  $this->setHighscoreWTime($testsettings['highscore_wtime']);
9623  $this->setHighscoreOwnTable($testsettings['highscore_own_table']);
9624  $this->setHighscoreTopTable($testsettings['highscore_top_table']);
9625  $this->setHighscoreTopNum($testsettings['highscore_top_num']);
9626  $this->setPassDeletionAllowed($testsettings['pass_deletion_allowed']);
9627  if( isset($testsettings['examid_in_kiosk']) )
9628  {
9629  $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_kiosk']);
9630  }
9631  else
9632  {
9633  $this->setShowExamIdInTestPassEnabled($testsettings['examid_in_test_pass']);
9634  }
9635  if( isset($testsettings['show_exam_id']) )
9636  {
9637  $this->setShowExamIdInTestResultsEnabled($testsettings['show_exam_id']);
9638  }
9639  else
9640  {
9641  $this->setShowExamIdInTestResultsEnabled($testsettings['examid_in_test_res']);
9642  }
9643  $this->setEnableExamview($testsettings['enable_examview']);
9644  $this->setShowExamviewHtml($testsettings['show_examview_html']);
9645  $this->setShowExamviewPdf($testsettings['show_examview_pdf']);
9646  $this->setEnableArchiving($testsettings['enable_archiving']);
9647  $this->setSignSubmission($testsettings['sign_submission']);
9648  $this->setCharSelectorAvailability($testsettings['char_selector_availability']);
9649  $this->setCharSelectorDefinition($testsettings['char_selector_definition']);
9650 
9651  $this->setRedirectionMode($testsettings['redirection_mode']);
9652  $this->setRedirectionUrl($testsettings['redirection_url']);
9653 
9654  $this->setAutosave($testsettings['autosave']);
9655  $this->setAutosaveIval($testsettings['autosave_ival']);
9656  $this->setShowExamIdInTestResultsEnabled((int)$testsettings['examid_in_test_res']);
9657  $this->setPassword($testsettings['password']);
9658  $this->setFixedParticipants($testsettings['fixed_participants'] );
9659  $this->setAllowedUsers($testsettings['allowedusers']);
9660  $this->setAllowedUsersTimeGap($testsettings['alloweduserstimegap']);
9661  $this->setUsePreviousAnswers($testsettings['use_previous_answers']);
9662  $this->setPoolUsage($testsettings['pool_usage']);
9663  $this->setActivationLimited($testsettings['activation_limited']);
9664  $this->setActivationStartingTime($testsettings['activation_start_time']);
9665  $this->setActivationEndingTime($testsettings['activation_end_time']);
9666  $this->setActivationVisibility($testsettings['activation_visibility']);
9667 
9668  $this->saveToDb();
9669 
9670  return true;
9671  }
9672 
9680  function processPrintoutput2FO($print_output)
9681  {
9682  if (extension_loaded("tidy"))
9683  {
9684  $config = array(
9685  "indent" => false,
9686  "output-xml" => true,
9687  "numeric-entities" => true
9688  );
9689  $tidy = new tidy();
9690  $tidy->parseString($print_output, $config, 'utf8');
9691  $tidy->cleanRepair();
9692  $print_output = tidy_get_output($tidy);
9693  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
9694  }
9695  else
9696  {
9697  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
9698  $print_output = str_replace("&otimes;", "X", $print_output);
9699  }
9700  $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
9701 
9702  // additional font support
9703  $xsl = str_replace(
9704  'font-family="Helvetica, unifont"',
9705  'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
9706  $xsl
9707  );
9708 
9709  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
9710  $xh = xslt_create();
9711  $params = array();
9712  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
9713  xslt_error($xh);
9714  xslt_free($xh);
9715  return $output;
9716  }
9717 
9724  public function deliverPDFfromHTML($content, $title = NULL)
9725  {
9726  $content = preg_replace("/href=\".*?\"/", "", $content);
9727  $printbody = new ilTemplate("tpl.il_as_tst_print_body.html", TRUE, TRUE, "Modules/Test");
9728  $printbody->setVariable("TITLE", ilUtil::prepareFormOutput($this->getTitle()));
9729  $printbody->setVariable("ADM_CONTENT", $content);
9730  $printbody->setCurrentBlock("css_file");
9731  $printbody->setVariable("CSS_FILE", $this->getTestStyleLocation("filesystem"));
9732  $printbody->parseCurrentBlock();
9733  $printbody->setCurrentBlock("css_file");
9734  $printbody->setVariable("CSS_FILE", ilUtil::getStyleSheetLocation("filesystem", "delos.css"));
9735  $printbody->parseCurrentBlock();
9736  $printoutput = $printbody->get();
9737  $html = str_replace("href=\"./", "href=\"" . ILIAS_HTTP_PATH . "/", $printoutput);
9738  $html = preg_replace("/<div id=\"dontprint\">.*?<\\/div>/ims", "", $html);
9739  if (extension_loaded("tidy"))
9740  {
9741  $config = array(
9742  "indent" => false,
9743  "output-xml" => true,
9744  "numeric-entities" => true
9745  );
9746  $tidy = new tidy();
9747  $tidy->parseString($html, $config, 'utf8');
9748  $tidy->cleanRepair();
9749  $html = tidy_get_output($tidy);
9750  $html = preg_replace("/^.*?(<html)/", "\\1", $html);
9751  }
9752  else
9753  {
9754  $html = str_replace("&nbsp;", "&#160;", $html);
9755  $html = str_replace("&otimes;", "X", $html);
9756  }
9757  $html = preg_replace("/src=\".\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
9758  $this->deliverPDFfromFO($this->processPrintoutput2FO($html), $title);
9759  }
9760 
9767  public function deliverPDFfromFO($fo, $title = null)
9768  {
9769  global $ilLog;
9770 
9771  include_once "./Services/Utilities/classes/class.ilUtil.php";
9772  $fo_file = ilUtil::ilTempnam() . ".fo";
9773  $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
9774 
9775  include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
9776  try
9777  {
9778  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
9779  $filename = (strlen($title)) ? $title : $this->getTitle();
9780  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
9781  return true;
9782  }
9783  catch(XML_RPC2_FaultException $e)
9784  {
9785  $ilLog->write(__METHOD__.': '.$e->getMessage());
9786  return false;
9787  }
9788  catch(Exception $e)
9789  {
9790  $ilLog->write(__METHOD__.': '.$e->getMessage());
9791  return false;
9792  }
9793 
9794  /*
9795  include_once "./Services/Transformation/classes/class.ilFO2PDF.php";
9796  $fo2pdf = new ilFO2PDF();
9797  $fo2pdf->setFOString($fo);
9798  $result = $fo2pdf->send();
9799  $filename = (strlen($title)) ? $title : $this->getTitle();
9800  ilUtil::deliverData($result, ilUtil::getASCIIFilename($filename) . ".pdf", "application/pdf", false, true);
9801  */
9802  }
9803 
9813  static function getManualFeedback($active_id, $question_id, $pass)
9814  {
9815  global $ilDB;
9816  $feedback = "";
9817  $result = $ilDB->queryF("SELECT feedback FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
9818  array('integer', 'integer', 'integer'),
9819  array($active_id, $question_id, $pass)
9820  );
9821  if ($result->numRows())
9822  {
9823  $row = $ilDB->fetchAssoc($result);
9824  include_once("./Services/RTE/classes/class.ilRTE.php");
9825  $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
9826  }
9827  return $feedback;
9828  }
9829 
9840  function saveManualFeedback($active_id, $question_id, $pass, $feedback)
9841  {
9842  global $ilDB;
9843 
9844  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_manual_fb WHERE active_fi = %s AND question_fi = %s AND pass = %s",
9845  array('integer', 'integer', 'integer'),
9846  array($active_id, $question_id, $pass)
9847  );
9848 
9849  if (strlen($feedback))
9850  {
9851  $next_id = $ilDB->nextId('tst_manual_fb');
9853  $result = $ilDB->insert('tst_manual_fb', array(
9854  'manual_feedback_id' => array( 'integer', $next_id ),
9855  'active_fi' => array( 'integer', $active_id ),
9856  'question_fi' => array( 'integer', $question_id ),
9857  'pass' => array( 'integer', $pass),
9858  'feedback' => array( 'clob', ilRTE::_replaceMediaObjectImageSrc( $feedback, 0) ),
9859  'tstamp' => array( 'integer', time() ),
9860  )
9861  );
9862  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
9864  {
9865  global $lng, $ilUser;
9866  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
9867  $username = ilObjTestAccess::_getParticipantData($active_id);
9868  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
9869  $this->logAction(sprintf($lng->txtlng("assessment", "log_manual_feedback", ilObjAssessmentFolder::_getLogLanguage()), $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")", $username, assQuestion::_getQuestionTitle($question_id), $feedback));
9870  }
9871  }
9872  if (PEAR::isError($result))
9873  {
9874  global $ilias;
9875  $ilias->raiseError($result->getMessage());
9876  }
9877  else
9878  {
9879  return TRUE;
9880  }
9881  }
9882 
9891  {
9892  global $ilUser;
9893  if (strcmp($_GET["tst_javascript"], "0") == 0) return FALSE;
9894  if ($this->getForceJS()) return TRUE;
9895  $assessmentSetting = new ilSetting("assessment");
9896  return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
9897  }
9898 
9899  function &createTestSequence($active_id, $pass, $shuffle)
9900  {
9901  include_once "./Modules/Test/classes/class.ilTestSequence.php";
9902  $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
9903  }
9904 
9910  public function setTestId($a_id)
9911  {
9912  $this->test_id = $a_id;
9913  }
9914 
9923  function getDetailedTestResults($participants)
9924  {
9925  $results = array();
9926  if (count($participants))
9927  {
9928  foreach ($participants as $active_id => $user_rec)
9929  {
9930  $row = array();
9931  $reached_points = 0;
9932  $max_points = 0;
9933  foreach ($this->questions as $value)
9934  {
9935  $question =& ilObjTest::_instanciateQuestion($value);
9936  if (is_object($question))
9937  {
9938  $max_points += $question->getMaximumPoints();
9939  $reached_points += $question->getReachedPoints($active_id);
9940  if ($max_points > 0)
9941  {
9942  $percentvalue = $reached_points / $max_points;
9943  if ($percentvalue < 0) $percentvalue = 0.0;
9944  }
9945  else
9946  {
9947  $percentvalue = 0;
9948  }
9949  if ($this->getAnonymity())
9950  {
9951  $user_rec['firstname'] = "";
9952  $user_rec['lastname'] = $this->lng->txt("unknown");
9953  }
9954  $row = array(
9955  "user_id"=>$user_rec['usr_id'],
9956  "matriculation" => $user_rec['matriculation'],
9957  "lastname" => $user_rec['lastname'],
9958  "firstname" => $user_rec['firstname'],
9959  "login"=>$user_rec['login'],
9960  "question_id" => $question->getId(),
9961  "question_title" => $question->getTitle(),
9962  "reached_points" => $reached_points,
9963  "max_points" => $max_points
9964  );
9965  $results[] = $row;
9966  }
9967  }
9968  }
9969  }
9970  return $results;
9971  }
9972 
9977  {
9978  global $ilDB;
9979 
9980  $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",
9981  array('integer'),
9982  array($a_q_id)
9983  );
9984  $rec = $ilDB->fetchAssoc($result);
9985  return $rec["obj_id"];
9986  }
9987 
9994  function isPluginActive($a_pname)
9995  {
9996  global $ilPluginAdmin;
9997  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "TestQuestionPool", "qst", $a_pname))
9998  {
9999  return TRUE;
10000  }
10001  else
10002  {
10003  return FALSE;
10004  }
10005  }
10006 
10007  public function getPassed($active_id)
10008  {
10009  global $ilDB;
10010 
10011  $result = $ilDB->queryF("SELECT passed FROM tst_result_cache WHERE active_fi = %s",
10012  array('integer'),
10013  array($active_id)
10014  );
10015  if ($result->numRows())
10016  {
10017  $row = $ilDB->fetchAssoc($result);
10018  return $row['passed'];
10019  }
10020  else
10021  {
10022  $counted_pass = ilObjTest::_getResultPass($active_id);
10023  $result_array =& $this->getTestResult($active_id, $counted_pass);
10024  return $result_array["test"]["passed"];
10025  }
10026  }
10027 
10033  function canShowCertificate($testSession, $user_id, $active_id)
10034  {
10035  if ($this->canShowTestResults($testSession, $user_id))
10036  {
10037  include_once "./Services/Certificate/classes/class.ilCertificate.php";
10038  include_once "./Modules/Test/classes/class.ilTestCertificateAdapter.php";
10039  $cert = new ilCertificate(new ilTestCertificateAdapter($this));
10040  if ($cert->isComplete())
10041  {
10042  $vis = $this->getCertificateVisibility();
10043  $showcert = FALSE;
10044  switch ($vis)
10045  {
10046  case 0:
10047  $showcert = TRUE;
10048  break;
10049  case 1:
10050  if ($this->getPassed($active_id))
10051  {
10052  $showcert = TRUE;
10053  }
10054  break;
10055  case 2:
10056  $showcert = FALSE;
10057  break;
10058  }
10059  if ($showcert)
10060  {
10061  return TRUE;
10062  }
10063  else
10064  {
10065  return FALSE;
10066  }
10067  }
10068  else
10069  {
10070  return FALSE;
10071  }
10072  }
10073  else
10074  {
10075  return FALSE;
10076  }
10077  }
10078 
10082  public function getParticipantsForTestAndQuestion($test_id, $question_id)
10083  {
10085  global $ilDB;
10086 
10087  $query = "
10088  SELECT tst_test_result.active_fi, tst_test_result.question_fi, tst_test_result.pass
10089  FROM tst_test_result, tst_active, qpl_questions
10090  WHERE tst_active.active_id = tst_test_result.active_fi
10091  AND tst_active.test_fi = %s
10092  AND tst_test_result.question_fi = qpl_questions.question_id
10093  AND tst_test_result.question_fi = %s";
10094 
10095  $result = $ilDB->queryF($query,
10096  array('integer', 'integer'),
10097  array($test_id, $question_id)
10098  );
10099  $foundusers = array();
10101  while ($row = $ilDB->fetchAssoc($result))
10102  {
10103  if (!array_key_exists($row["active_fi"], $foundusers))
10104  {
10105  $foundusers[$row["active_fi"]] = array();
10106  }
10107  array_push($foundusers[$row["active_fi"]], array("pass" => $row["pass"], "qid" => $row["question_fi"]));
10108  }
10109  return $foundusers;
10110  }
10111 
10117  public function getAggregatedResultsData()
10118  {
10119  $data =& $this->getCompleteEvaluationData();
10120  $foundParticipants =& $data->getParticipants();
10121  $results = array("overview" => array(), "questions" => array());
10122  if (count($foundParticipants))
10123  {
10124  $results["overview"][$this->lng->txt("tst_eval_total_persons")] = count($foundParticipants);
10125  $total_finished = $this->evalTotalFinished();
10126  $results["overview"][$this->lng->txt("tst_eval_total_finished")] = $total_finished;
10127  $average_time = $this->evalTotalStartedAverageTime();
10128  $diff_seconds = $average_time;
10129  $diff_hours = floor($diff_seconds/3600);
10130  $diff_seconds -= $diff_hours * 3600;
10131  $diff_minutes = floor($diff_seconds/60);
10132  $diff_seconds -= $diff_minutes * 60;
10133  $results["overview"][$this->lng->txt("tst_eval_total_finished_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10134  $total_passed = 0;
10135  $total_passed_reached = 0;
10136  $total_passed_max = 0;
10137  $total_passed_time = 0;
10138  foreach ($foundParticipants as $userdata)
10139  {
10140  if ($userdata->getPassed())
10141  {
10142  $total_passed++;
10143  $total_passed_reached += $userdata->getReached();
10144  $total_passed_max += $userdata->getMaxpoints();
10145  $total_passed_time += $userdata->getTimeOfWork();
10146  }
10147  }
10148  $average_passed_reached = $total_passed ? $total_passed_reached / $total_passed : 0;
10149  $average_passed_max = $total_passed ? $total_passed_max / $total_passed : 0;
10150  $average_passed_time = $total_passed ? $total_passed_time / $total_passed : 0;
10151  $results["overview"][$this->lng->txt("tst_eval_total_passed")] = $total_passed;
10152  $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);
10153  $average_time = $average_passed_time;
10154  $diff_seconds = $average_time;
10155  $diff_hours = floor($diff_seconds/3600);
10156  $diff_seconds -= $diff_hours * 3600;
10157  $diff_minutes = floor($diff_seconds/60);
10158  $diff_seconds -= $diff_minutes * 60;
10159  $results["overview"][$this->lng->txt("tst_eval_total_passed_average_time")] = sprintf("%02d:%02d:%02d", $diff_hours, $diff_minutes, $diff_seconds);
10160  }
10161 
10162  foreach ($data->getQuestionTitles() as $question_id => $question_title)
10163  {
10164  $answered = 0;
10165  $reached = 0;
10166  $max = 0;
10167  foreach ($foundParticipants as $userdata)
10168  {
10169  for ($i = 0; $i <= $userdata->getLastPass(); $i++)
10170  {
10171  if (is_object($userdata->getPass($i)))
10172  {
10173  $question =& $userdata->getPass($i)->getAnsweredQuestionByQuestionId($question_id);
10174  if (is_array($question))
10175  {
10176  $answered++;
10177  $reached += $question["reached"];
10178  $max += $question["points"];
10179  }
10180  }
10181  }
10182  }
10183  $percent = $max ? $reached/$max * 100.0 : 0;
10184  $counter++;
10185  $results["questions"][$question_id] = array(
10186  $question_title,
10187  sprintf("%.2f", $answered ? $reached / $answered : 0) . " " . strtolower($this->lng->txt("of")) . " " . sprintf("%.2f", $answered ? $max / $answered : 0),
10188  sprintf("%.2f", $percent) . "%",
10189  $answered,
10190  sprintf("%.2f", $answered ? $reached / $answered : 0),
10191  sprintf("%.2f", $answered ? $max / $answered : 0),
10192  $percent / 100.0
10193  );
10194  }
10195  return $results;
10196  }
10197 
10201  function getXMLZip()
10202  {
10203  include_once("./Modules/Test/classes/class.ilTestExport.php");
10204  $test_exp = new ilTestExport($this, "xml");
10205  return $test_exp->buildExportFile();
10206  }
10207 
10211  public function getMailNotification()
10212  {
10213  return $this->mailnotification;
10214  }
10215 
10221  public function setMailNotification($a_notification)
10222  {
10223  $this->mailnotification = $a_notification;
10224  }
10225 
10226  public function sendSimpleNotification($active_id)
10227  {
10228  include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10229 
10230  $mail = new ilTestMailNotification();
10231  $owner_id = $this->getOwner();
10232  $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10233  $mail->sendSimpleNotification($owner_id, $this->getTitle(), $usr_data);
10234  }
10235 
10242  {
10243  include_once "./Modules/Test/classes/class.ilObjTestGUI.php";
10244  include_once "./Modules/Test/classes/tables/class.ilEvaluationAllTableGUI.php";
10245  $table_gui = new ilEvaluationAllTableGUI(new ilObjTestGUI(), 'outEvaluation', $this->getAnonymity());
10246  return $table_gui->getSelectedColumns();
10247  }
10248 
10249  public function sendAdvancedNotification($active_id)
10250  {
10251  include_once "./Modules/Test/classes/class.ilTestMailNotification.php";
10252 
10253  $mail = new ilTestMailNotification();
10254  $owner_id = $this->getOwner();
10255  $usr_data = $this->userLookupFullName(ilObjTest::_getUserIdFromActiveId($active_id));
10256 
10257  include_once "./Modules/Test/classes/class.ilTestExport.php";
10258  $exportObj = new ilTestExport($this, "results");
10259  $file = $exportObj->exportToExcel($deliver = FALSE, 'active_id', $active_id, $passedonly = FALSE);
10260  include_once "./Services/Mail/classes/class.ilFileDataMail.php";
10261  $fd = new ilFileDataMail(ANONYMOUS_USER_ID);
10262  $fd->copyAttachmentFile($file, "result_" . $active_id . ".xls");
10263  $file_names[] = "result_" . $active_id . ".xls";
10264 
10265  $mail->sendAdvancedNotification($owner_id, $this->getTitle(), $usr_data, $file_names);
10266 
10267  if(count($file_names))
10268  {
10269  $fd->unlinkFiles($file_names);
10270  unset($fd);
10271  @unlink($file);
10272  }
10273  }
10274 
10275  function createRandomSolutions($number)
10276  {
10277  global $ilDB;
10278 
10279  // 1. get a user
10280  $query = "SELECT usr_id FROM usr_data";
10281  $result = $ilDB->query($query);
10282  while ($data = $ilDB->fetchAssoc($result))
10283  {
10284  $activequery = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
10285  $ilDB->quote($this->getTestId()),
10286  $ilDB->quote($data['usr_id'])
10287  );
10288  $activeresult = $ilDB->query($activequery);
10289  if ($activeresult->numRows() == 0)
10290  {
10291  $user_id = $data['usr_id'];
10292  if ($user_id != 13)
10293  {
10294  include_once "./Modules/Test/classes/class.ilTestSession.php";
10295  $testSession = FALSE;
10296  $testSession = new ilTestSession();
10297  $testSession->setRefId($this->getRefId());
10298  $testSession->setTestId($this->getTestId());
10299  $testSession->setUserId($user_id);
10300  $testSession->saveToDb();
10301  $passes = ($this->getNrOfTries()) ? $this->getNrOfTries() : 10;
10302  $nr_of_passes = rand(1, $passes);
10303  $active_id = $testSession->getActiveId();
10304  for ($pass = 0; $pass < $nr_of_passes; $pass++)
10305  {
10306  include_once "./Modules/Test/classes/class.ilTestSequence.php";
10307  $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
10308  if (!$testSequence->hasSequence())
10309  {
10310  $testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
10311  $testSequence->saveToDb();
10312  }
10313  for ($seq = 1; $seq <= count($this->questions); $seq++)
10314  {
10315  $question_id = $testSequence->getQuestionForSequence($seq);
10316  $objQuestion = ilObjTest::_instanciateQuestion($question_id);
10317  $objQuestion->createRandomSolution($testSession->getActiveId(), $pass);
10318  }
10319  if ($pass < $nr_of_passes - 1)
10320  {
10321  $testSession->increasePass();
10322  $testSession->setLastSequence(0);
10323  $testSession->saveToDb();
10324  }
10325  else
10326  {
10327  $testSession->setSubmitted(1);
10328  $testSession->setSubmittedTimestamp(date('Y-m-d H:i:s'));
10329  $testSession->saveToDb();
10330  }
10331  }
10332  $number--;
10333  if ($number == 0) return;
10334  }
10335  }
10336  }
10337  }
10338 
10339  public function getResultsForActiveId($active_id)
10340  {
10341  global $ilDB;
10342 
10343  $query = "
10344  SELECT *
10345  FROM tst_result_cache
10346  WHERE active_fi = %s
10347  ";
10348 
10349  $result = $ilDB->queryF(
10350  $query, array('integer'), array($active_id)
10351  );
10352 
10353  if( !$result->numRows() )
10354  {
10355  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
10356 
10358 
10359  $query = "
10360  SELECT *
10361  FROM tst_result_cache
10362  WHERE active_fi = %s
10363  ";
10364 
10365  $result = $ilDB->queryF(
10366  $query, array('integer'), array($active_id)
10367  );
10368  }
10369 
10370  $row = $ilDB->fetchAssoc($result);
10371 
10372  return $row;
10373 
10374  }
10375 
10376  public function getMailNotificationType()
10377  {
10378  if ($this->mailnottype == 1)
10379  {
10380  return $this->mailnottype;
10381  }
10382  else
10383  {
10384  return 0;
10385  }
10386  }
10387 
10388  public function setMailNotificationType($a_type)
10389  {
10390  if ($a_type == 1)
10391  {
10392  $this->mailnottype = 1;
10393  }
10394  else
10395  {
10396  $this->mailnottype = 0;
10397  }
10398  }
10399 
10400  public function getExportSettings()
10401  {
10402  if ($this->exportsettings)
10403  {
10404  return $this->exportsettings;
10405  }
10406  else
10407  {
10408  return 0;
10409  }
10410  }
10411 
10412  public function setExportSettings($a_settings)
10413  {
10414  if ($a_settings)
10415  {
10416  $this->exportsettings = $a_settings;
10417  }
10418  else
10419  {
10420  $this->exportsettings = 0;
10421  }
10422  }
10423 
10425  {
10426  if (($this->exportsettings & 1) > 0)
10427  {
10428  return true;
10429  }
10430  else
10431  {
10432  return false;
10433  }
10434  }
10435 
10436  public function setExportSettingsSingleChoiceShort($a_settings)
10437  {
10438  if ($a_settings)
10439  {
10440  $this->exportsettings = $this->exportsettings | 1;
10441  }
10442  else
10443  {
10445  {
10446  $this->exportsettings = $this->exportsettings ^ 1;
10447  }
10448  }
10449  }
10450 
10451  public function getEnabledViewMode() {
10452  return $this->enabled_view_mode;
10453  }
10454 
10455  public function setEnabledViewMode($mode) {
10456  $this->enabled_view_mode = $mode;
10457  }
10458 
10460  $this->template_id = (int)$template_id;
10461  }
10462 
10463  function getTemplate() {
10464  return $this->template_id;
10465  }
10466 
10467  public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
10468  $new_array = array();
10469  $position = 1;
10470 
10471  $query = 'SELECT question_fi FROM tst_test_question WHERE test_fi = %s';
10472  $types = array('integer');
10473  $values = array($this->getTestId());
10474 
10475  $new_question_id += 1;
10476 
10477  global $ilDB;
10478  $inserted = false;
10479  $res = $ilDB->queryF($query, $types, $values);
10480  while($row = $ilDB->fetchAssoc($res)) {
10481 
10482  $qid = $row['question_fi'];
10483 
10484  if ($qid == $new_question_id) {
10485  continue;
10486  }
10487  else if ($qid == $previous_question_id) {
10488  $new_array[$position++] = $qid;
10489  $new_array[$position++] = $new_question_id;
10490  $inserted = true;
10491  }
10492  else {
10493  $new_array[$position++] = $qid;
10494  }
10495  }
10496 
10497  $update_query = 'UPDATE tst_test_question SET sequence = %s WHERE test_fi = %s AND question_fi = %s';
10498  $update_types = array('integer', 'integer', 'integer');
10499 
10500  foreach($new_array as $position => $qid) {
10501  $ilDB->manipulateF(
10502  $update_query,
10503  $update_types,
10504  $vals = array(
10505  $position,
10506  $this->getTestId(),
10507  $qid
10508  )
10509  );
10510  }
10511  }
10512 
10514  if (is_array($options))
10515  {
10516  $this->setGenericAnswerFeedback( in_array('instant_feedback_generic', $options) ? 1 : 0);
10517  $this->setSpecificAnswerFeedback( in_array('instant_feedback_specific', $options) ? 1 : 0);
10518  $this->setAnswerFeedbackPoints( in_array('instant_feedback_points', $options) ? 1 : 0);
10519  $this->setInstantFeedbackSolution( in_array('instant_feedback_solution', $options) ? 1 : 0);
10520  } else {
10521  $this->setGenericAnswerFeedback(0);
10522  $this->setSpecificAnswerFeedback(0);
10523  $this->setAnswerFeedbackPoints(0);
10524  $this->setInstantFeedbackSolution(0);
10525  }
10526  }
10527 
10529  $setter = array(
10530  'pass_details' => 'setShowPassDetails',
10531  'solution_details' => 'setShowSolutionDetails',
10532  'solution_printview' => 'setShowSolutionPrintview',
10533  'solution_feedback' => 'setShowSolutionFeedback',
10534  'solution_answers_only' => 'setShowSolutionAnswersOnly',
10535  'solution_signature' => 'setShowSolutionSignature',
10536  'solution_suggested' => 'setShowSolutionSuggested',
10537  );
10538  foreach($setter as $key => $setter) {
10539  if (in_array($key, $options)) {
10540  $this->$setter(1);
10541  }
10542  else {
10543  $this->$setter(0);
10544  }
10545  }
10546  }
10547 
10548  public function getPoolUsage() {
10549  return (boolean) $this->poolUsage;
10550  }
10551 
10552  public function setPoolUsage($usage) {
10553  $this->poolUsage = (boolean)$usage;
10554  }
10555 
10556  public function setQuestionOrderAndObligations($orders, $obligations)
10557  {
10558  global $ilDB;
10559 
10560  asort($orders);
10561 
10562  $i = 0;
10563 
10564  foreach($orders as $id => $position)
10565  {
10566  $i++;
10567 
10568  $obligatory = (
10569  isset($obligations[$id]) && $obligations[$id] ? 1 : 0
10570  );
10571 
10572  $query = "
10573  UPDATE tst_test_question
10574  SET sequence = %s,
10575  obligatory = %s
10576  WHERE question_fi = %s
10577  ";
10578 
10579  $ilDB->manipulateF(
10580  $query, array('integer', 'integer', 'integer'), array($i, $obligatory, $id)
10581  );
10582  }
10583 
10584  $this->loadQuestions();
10585  }
10586 
10587  public function moveQuestionAfter($question_to_move, $question_before) {
10588  global $ilDB;
10589  //var_dump(func_get_args());
10590  if ($question_before) {
10591  $query = 'SELECT sequence, test_fi FROM tst_test_question WHERE question_fi = %s';
10592  $types = array('integer');
10593  $values = array($question_before);
10594  $rset = $ilDB->queryF($query, $types, $values);
10595  }
10596 
10597  if (!$question_before || ($rset && !($row = $ilDB->fetchAssoc($rset)))) {
10598  $row = array(
10599  'sequence' => 0,
10600  'test_fi' => $this->getTestId(),
10601  );
10602  }
10603 
10604  $update = 'UPDATE tst_test_question SET sequence = sequence + 1 WHERE sequence > %s AND test_fi = %s';
10605  $types = array('integer', 'integer');
10606  $values = array($row['sequence'], $row['test_fi']);
10607  $ilDB->manipulateF($update, $types, $values);
10608 
10609  $update = 'UPDATE tst_test_question SET sequence = %s WHERE question_fi = %s';
10610  $types = array('integer', 'integer');
10611  $values = array($row['sequence'] + 1, $question_to_move);
10612  $ilDB->manipulateF($update, $types, $values);
10613 
10614  }
10615 
10617  {
10618  global $ilDB;
10619 
10620  $questions = $this->getQuestionTitlesAndIndexes();
10621 
10622  $IN_questions = $ilDB->in('q1.question_id', array_keys($questions), false, 'integer');
10623 
10624  $query = "
10625  SELECT count(q1.question_id) cnt
10626 
10627  FROM qpl_questions q1
10628 
10629  INNER JOIN qpl_questions q2
10630  ON q2.question_id = q1.original_id
10631 
10632  WHERE $IN_questions
10633  AND q1.obj_fi = q2.obj_fi
10634  ";
10635 
10636  $rset = $ilDB->query($query);
10637 
10638  $row = $ilDB->fetchAssoc($rset);
10639 
10640  return $row['cnt'] > 0;
10641  }
10642 
10649  public static function _lookupFinishedUserTests($a_user_id)
10650  {
10651  global $ilDB;
10652 
10653  $result = $ilDB->queryF("SELECT test_fi,MAX(pass) AS pass FROM tst_active".
10654  " JOIN tst_pass_result ON (tst_pass_result.active_fi = tst_active.active_id)".
10655  " WHERE user_fi=%s".
10656  " GROUP BY test_fi",
10657  array('integer', 'integer'),
10658  array($a_user_id, 1)
10659  );
10660  $all = array();
10661  while($row = $ilDB->fetchAssoc($result))
10662  {
10663  $obj_id = self::_getObjectIDFromTestID($row["test_fi"]);
10664  $all[$obj_id] = (bool)$row["pass"];
10665  }
10666  return $all;
10667  }
10668  public function getQuestions()
10669  {
10670  return $this->questions;
10671  }
10672 
10673  public function isOnline()
10674  {
10675  return $this->online;
10676  }
10677 
10678  public function setOnline($a_online = true)
10679  {
10680  $this->online = (bool)$a_online;
10681  }
10682 
10683  public function setPrintBestSolutionWithResult($status)
10684  {
10685  $this->print_best_solution_with_result = (bool) $status;
10686  }
10687 
10689  {
10691  }
10692 
10699  {
10701  }
10702 
10709  {
10710  $this->offeringQuestionHintsEnabled = (bool)$offeringQuestionHintsEnabled;
10711  }
10712 
10713  function setActivationVisibility($a_value)
10714  {
10715  $this->activation_visibility = (bool) $a_value;
10716  }
10717 
10719  {
10721  }
10722 
10724  {
10725  return (bool)$this->activation_limited;
10726  }
10727 
10728  function setActivationLimited($a_value)
10729  {
10730  $this->activation_limited = (bool)$a_value;
10731  }
10732 
10733  /* GET/SET for highscore feature */
10734 
10740  public function setHighscoreEnabled($a_enabled)
10741  {
10742  $this->_highscore_enabled = (bool)$a_enabled;
10743  }
10744 
10750  public function getHighscoreEnabled()
10751  {
10752  return (bool) $this->_highscore_enabled;
10753  }
10754 
10762  public function setHighscoreAnon($a_anon)
10763  {
10764  $this->_highscore_anon = (bool)$a_anon;
10765  }
10766 
10776  public function getHighscoreAnon()
10777  {
10778  return (bool) $this->_highscore_anon;
10779  }
10780 
10789  public function isHighscoreAnon()
10790  {
10791  if ($this->getAnonymity() == 1)
10792  {
10793  return true;
10794  }
10795  else
10796  {
10797  return (bool)$this->getHighscoreAnon();
10798  }
10799  }
10800 
10806  public function setHighscoreAchievedTS($a_achieved_ts)
10807  {
10808  $this->_highscore_achieved_ts = (bool)$a_achieved_ts;
10809  }
10810 
10816  public function getHighscoreAchievedTS()
10817  {
10818  return (bool) $this->_highscore_achieved_ts;
10819  }
10820 
10826  public function setHighscoreScore($a_score)
10827  {
10828  $this->_highscore_score = (bool)$a_score;
10829  }
10830 
10836  public function getHighscoreScore()
10837  {
10838  return (bool) $this->_highscore_score;
10839  }
10840 
10846  public function setHighscorePercentage($a_percentage)
10847  {
10848  $this->_highscore_percentage = (bool)$a_percentage;
10849  }
10850 
10856  public function getHighscorePercentage()
10857  {
10858  return (bool) $this->_highscore_percentage;
10859  }
10860 
10866  public function setHighscoreHints($a_hints)
10867  {
10868  $this->_highscore_hints = (bool)$a_hints;
10869  }
10870 
10876  public function getHighscoreHints()
10877  {
10878  return (bool) $this->_highscore_hints;
10879  }
10880 
10886  public function setHighscoreWTime($a_wtime)
10887  {
10888  $this->_highscore_wtime = (bool)$a_wtime;
10889  }
10890 
10896  public function getHighscoreWTime()
10897  {
10898  return (bool) $this->_highscore_wtime;
10899  }
10900 
10906  public function setHighscoreOwnTable($a_own_table)
10907  {
10908  $this->_highscore_own_table = (bool)$a_own_table;
10909  }
10910 
10916  public function getHighscoreOwnTable()
10917  {
10918  return (bool) $this->_highscore_own_table;
10919  }
10920 
10926  public function setHighscoreTopTable($a_top_table)
10927  {
10928  $this->_highscore_top_table = (bool)$a_top_table;
10929  }
10930 
10936  public function getHighscoreTopTable()
10937  {
10938  return (bool) $this->_highscore_top_table;
10939  }
10940 
10947  public function setHighscoreTopNum($a_top_num)
10948  {
10949  $this->_highscore_top_num = (int)$a_top_num;
10950  }
10951 
10960  public function getHighscoreTopNum($a_retval = 10)
10961  {
10962  $retval = $a_retval;
10963  if ( (int) $this->_highscore_top_num != 0)
10964  {
10965  $retval = $this->_highscore_top_num;
10966  }
10967 
10968  return $retval;
10969  }
10970  /* End GET/SET for highscore feature*/
10971 
10972  public function setSpecificAnswerFeedback($specific_answer_feedback)
10973  {
10974  switch ($specific_answer_feedback)
10975  {
10976  case 1:
10977  $this->specific_answer_feedback = 1;
10978  break;
10979  default:
10980  $this->specific_answer_feedback = 0;
10981  break;
10982  }
10983  }
10984 
10985  public function getSpecificAnswerFeedback()
10986  {
10987  switch ($this->specific_answer_feedback)
10988  {
10989  case 1:
10990  return 1;
10991  default:
10992  return 0;
10993  }
10994  }
10995 
11002  {
11003  $this->obligationsEnabled = (bool)$obligationsEnabled;
11004  }
11005 
11011  public function areObligationsEnabled()
11012  {
11013  return (bool)$this->obligationsEnabled;
11014  }
11015 
11022  public static function isQuestionObligationPossible($questionId)
11023  {
11024  require_once('Modules/TestQuestionPool/classes/class.assQuestion.php');
11025 
11026  $classConcreteQuestion = assQuestion::_getQuestionType($questionId);
11027 
11028  assQuestion::_includeClass($classConcreteQuestion, 0);
11029 
11030  // static binder is not at work yet (in PHP < 5.3)
11031  //$obligationPossible = $classConcreteQuestion::isObligationPossible();
11032  $obligationPossible = call_user_func(array($classConcreteQuestion, 'isObligationPossible'), $questionId);
11033 
11034  return $obligationPossible;
11035  }
11036 
11043  public static function isQuestionObligatory($question_id)
11044  {
11045  global $ilDB;
11046 
11047  $rset = $ilDB->queryF('SELECT obligatory FROM tst_test_question WHERE question_fi = %s', array('integer'), array($question_id));
11048 
11049  if( $row = $ilDB->fetchAssoc($rset) )
11050  {
11051  return (bool) $row['obligatory'];
11052  }
11053 
11054  return false;
11055  }
11056 
11069  public static function allObligationsAnswered($test_id, $active_id, $pass)
11070  {
11071  global $ilDB;
11072 
11073  $rset = $ilDB->queryF(
11074  'SELECT obligations_answered FROM tst_pass_result WHERE active_fi = %s AND pass = %s',
11075  array('integer', 'integer'),
11076  array($active_id, $pass)
11077  );
11078 
11079  if( $row = $ilDB->fetchAssoc($rset) )
11080  {
11081  return (bool)$row['obligations_answered'];
11082  }
11083 
11084  return !self::hasObligations($test_id);
11085  }
11086 
11095  public static function hasObligations($test_id)
11096  {
11097  global $ilDB;
11098 
11099  $rset = $ilDB->queryF(
11100  'SELECT count(*) cnt FROM tst_test_question WHERE test_fi = %s AND obligatory = 1',
11101  array('integer'), array($test_id)
11102  );
11103 
11104  $row = $ilDB->fetchAssoc($rset);
11105 
11106  return (bool)$row['cnt'] > 0;
11107  }
11108 
11109  public function setAutosave($autosave)
11110  {
11111  $this->autosave = $autosave;
11112  }
11113 
11114  public function getAutosave()
11115  {
11116  return $this->autosave;
11117  }
11118 
11120  {
11121  $this->autosave_ival = $autosave_ival;
11122  }
11123 
11124  public function getAutosaveIval()
11125  {
11126  return $this->autosave_ival;
11127  }
11128 
11134  public function isPassDeletionAllowed()
11135  {
11137  }
11138 
11145  {
11146  $this->passDeletionAllowed = (bool)$passDeletionAllowed;
11147  }
11148 
11149  #region Examview / PDF Examview
11150 
11154  {
11155  $this->show_examview_html = $show_examview_html;
11156  }
11157 
11161  public function getShowExamviewHtml()
11162  {
11164  }
11165 
11170  {
11171  $this->show_examview_pdf = $show_examview_pdf;
11172  }
11173 
11177  public function getShowExamviewPdf()
11178  {
11179  return $this->show_examview_pdf;
11180  }
11181 
11186  {
11187  $this->enable_examview = $enable_examview;
11188  }
11189 
11193  public function getEnableExamview()
11194  {
11195  return $this->enable_examview;
11196  }
11197 
11198  #endregion
11199 
11200  function setActivationStartingTime($starting_time = NULL)
11201  {
11202  $this->activation_starting_time = $starting_time;
11203  }
11204 
11205  function setActivationEndingTime($ending_time = NULL)
11206  {
11207  $this->activation_ending_time = $ending_time;
11208  }
11209 
11211  {
11212  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
11213  }
11214 
11216  {
11217  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
11218  }
11219 
11221  {
11222  global $ilDB;
11223 
11224  $times = array();
11225  $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");
11226  while ($row = $ilDB->fetchAssoc($result))
11227  {
11228  $times[$row['active_fi']] = $row['started'];
11229  }
11230  return $times;
11231  }
11232 
11234  {
11235  global $ilDB;
11236 
11237  $times = array();
11238  $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",
11239  array('integer'),
11240  array($this->getTestId())
11241  );
11242  while ($row = $ilDB->fetchAssoc($result))
11243  {
11244  $times[$row['active_fi']] = $row['additionaltime'];
11245  }
11246  return $times;
11247  }
11248 
11249  public function getExtraTime($active_id)
11250  {
11251  global $ilDB;
11252 
11253  $result = $ilDB->queryF("SELECT additionaltime FROM tst_addtime WHERE active_fi = %s",
11254  array('integer'),
11255  array($active_id)
11256  );
11257  if ($result->numRows() > 0)
11258  {
11259  $row = $ilDB->fetchAssoc($result);
11260  return $row['additionaltime'];
11261  }
11262  return 0;
11263  }
11264 
11265  public function addExtraTime($active_id, $minutes)
11266  {
11267  global $ilDB;
11268 
11269  $participants = array();
11270  if ($active_id == 0)
11271  {
11272  $result = $ilDB->queryF("SELECT active_id FROM tst_active WHERE test_fi = %s",
11273  array('integer'),
11274  array($this->getTestId())
11275  );
11276  while ($row = $ilDB->fetchAssoc($result))
11277  {
11278  array_push($participants, $row['active_id']);
11279  }
11280  }
11281  else
11282  {
11283  array_push($participants, $active_id);
11284  }
11285  foreach ($participants as $active_id)
11286  {
11287  $result = $ilDB->queryF("SELECT active_fi FROM tst_addtime WHERE active_fi = %s",
11288  array('integer'),
11289  array($active_id)
11290  );
11291  if ($result->numRows() > 0)
11292  {
11293  $ilDB->manipulateF("DELETE FROM tst_addtime WHERE active_fi = %s",
11294  array('integer'),
11295  array($active_id)
11296  );
11297  }
11298 
11299  $ilDB->manipulateF("UPDATE tst_active SET tries = %s, submitted = %s, submittimestamp = %s WHERE active_id = %s",
11300  array('integer','integer','timestamp','integer'),
11301  array(0, 0, NULL, $active_id)
11302  );
11303 
11304  $ilDB->manipulateF("INSERT INTO tst_addtime (active_fi, additionaltime, tstamp) VALUES (%s, %s, %s)",
11305  array('integer','integer','integer'),
11306  array($active_id, $minutes, time())
11307  );
11308 
11309  require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
11311  {
11312  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_added_extratime", ilObjAssessmentFolder::_getLogLanguage()), $minutes, $active_id));
11313  }
11314  }
11315  }
11316 
11323  {
11324  $this->enable_archiving = $enable_archiving;
11325  return $this;
11326  }
11327 
11331  public function getEnableArchiving()
11332  {
11333  return $this->enable_archiving;
11334  }
11335 
11336  public function getMaxPassOfTest()
11337  {
11341  global $ilDB;
11342 
11343  $query = '
11344  SELECT MAX(tst_pass_result.pass) + 1 max_res
11345  FROM tst_pass_result
11346  INNER JOIN tst_active ON tst_active.active_id = tst_pass_result.active_fi
11347  WHERE test_fi = '.$ilDB->quote($this->getTestId(), 'integer').'
11348  ';
11349  $res = $ilDB->query($query);
11350  $data = $ilDB->fetchAssoc($res);
11351  return (int)$data['max_res'];
11352  }
11353 
11359  public function lookupExamId($active_id, $pass)
11360  {
11362  global $ilDB, $ilSetting;
11363 
11364  $exam_id_query = 'SELECT exam_id FROM tst_pass_result WHERE active_fi = %s AND pass = %s';
11365  $exam_id_result = $ilDB->queryF( $exam_id_query, array( 'integer', 'integer' ), array( $active_id, $pass ) );
11366  if ($ilDB->numRows( $exam_id_result ) == 1)
11367  {
11368  $exam_id_row = $ilDB->fetchAssoc( $exam_id_result );
11369 
11370  if ($exam_id_row['exam_id'] != null)
11371  {
11372  return $exam_id_row['exam_id'];
11373  }
11374  }
11375 
11376  return null;
11377  }
11378 
11385  public static function buildExamId($active_id, $pass)
11386  {
11388  global $ilSetting;
11389 
11390  $inst_id = $ilSetting->get( 'inst_id', null );
11391 
11392  $obj_id = self::_getObjectIDFromActiveID($active_id);
11393 
11394  $examId = 'I' . $inst_id . '_T' . $obj_id . '_A' . $active_id . '_P' . $pass;
11395 
11396  return $examId;
11397  }
11398 
11400  {
11401  $this->show_exam_id_in_test_pass_enabled = $show_exam_id_in_test_pass_enabled;
11402  }
11403 
11405  {
11407  }
11408 
11413  {
11414  $this->show_exam_id_in_test_results_enabled = $show_exam_id_in_test_results_enabled;
11415  }
11416 
11421  {
11423  }
11424 
11429  {
11430  $this->sign_submission = $sign_submission;
11431  }
11432 
11436  public function getSignSubmission()
11437  {
11438  return $this->sign_submission;
11439  }
11440 
11444  public function setCharSelectorAvailability($availability)
11445  {
11446  $this->char_selector_availability = (int) $availability;
11447  }
11448 
11453  {
11454  return (int) $this->char_selector_availability;
11455  }
11456 
11460  public function setCharSelectorDefinition($definition = '')
11461  {
11462  $this->char_selector_definition = $definition;
11463  }
11464 
11468  public function getCharSelectorDefinition()
11469  {
11471  }
11472 
11473 
11480  {
11481  $this->questionSetType = $questionSetType;
11482  }
11483 
11489  public function getQuestionSetType()
11490  {
11491  return $this->questionSetType;
11492  }
11493 
11501  public static function lookupQuestionSetType($objId)
11502  {
11503  global $ilDB;
11504 
11505  $query = "SELECT question_set_type FROM tst_tests WHERE obj_fi = %s";
11506 
11507  $res = $ilDB->queryF($query, array('integer'), array($objId));
11508 
11509  $questionSetType = null;
11510 
11511  while( $row = $ilDB->fetchAssoc($res) )
11512  {
11513  $questionSetType = $row['question_set_type'];
11514  }
11515 
11516  return $questionSetType;
11517  }
11518 
11524  public function isRandomTest()
11525  {
11526  return $this->getQuestionSetType() == self::QUESTION_SET_TYPE_RANDOM;
11527  }
11528 
11534  public function isDynamicTest()
11535  {
11536  return $this->getQuestionSetType() == self::QUESTION_SET_TYPE_DYNAMIC;
11537  }
11538 
11546  public static function _lookupRandomTest($a_obj_id)
11547  {
11548  return self::lookupQuestionSetType($a_obj_id) == self::QUESTION_SET_TYPE_RANDOM;
11549  }
11550 
11552  {
11553  switch( $questionSetType )
11554  {
11556  return $lng->txt('tst_question_set_type_fixed');
11557 
11559  return $lng->txt('tst_question_set_type_random');
11560 
11562  return $lng->txt('tst_question_set_type_dynamic');
11563  }
11564 
11565  throw new ilTestException('invalid question set type value given: '.$questionSetType);
11566  }
11567 
11568  public function participantDataExist()
11569  {
11570  if( $this->participantDataExist === null )
11571  {
11572  $this->participantDataExist = (bool)$this->evalTotalPersons();
11573  }
11574 
11576  }
11577 
11578  public function recalculateScores($preserve_manscoring = false)
11579  {
11580  require_once 'class.ilTestScoring.php';
11581  $scoring = new ilTestScoring($this);
11582  $scoring->setPreserveManualScores($preserve_manscoring);
11583  $scoring->recalculateSolutions();
11584  }
11585 
11586  public static function getPoolQuestionChangeListeners(ilDB $db, $poolObjId)
11587  {
11588  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
11589 
11590  $questionChangeListeners = array(
11592  );
11593 
11594  return $questionChangeListeners;
11595  }
11596 
11597  public static function getTestObjIdsWithActiveForUserId($userId)
11598  {
11599  global $ilDB;
11600 
11601  $query = "
11602  SELECT obj_fi
11603  FROM tst_active
11604  INNER JOIN tst_tests
11605  ON test_id = test_fi
11606  WHERE user_fi = %s
11607  ";
11608 
11609  $res = $ilDB->queryF($query, array('integer'), array($userId));
11610 
11611  $objIds = array();
11612 
11613  while( $row = $ilDB->fetchAssoc($res) )
11614  {
11615  $objIds[] = (int)$row['obj_fi'];
11616  }
11617 
11618  return $objIds;
11619  }
11620 
11624  public function isTestFinalBroken()
11625  {
11626  return $this->testFinalBroken;
11627  }
11628 
11633  {
11634  $this->testFinalBroken = $testFinalBroken;
11635  }
11636 }
< 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.
initDefaultRoles()
init default roles settings
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)
Sets the ECTS FX grade.
saveCertificateVisibility($a_value)
Saves the visibility settings of the certificate.
static _lookupName($a_user_id)
lookup user name
xslt_create()
ftimestamp2datetimeDB($aTimestamp)
Timestamp to database datetime.
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.
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.
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()
Indicates if ECTS grades output is presented in this test.
_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.
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
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)
prepareTextareaOutput($txt_output, $prepare_for_latex_output=FALSE)
Prepares a string for a text area output in tests.
setShowPassDetails($a_details=1)
Sets if the pass details should be shown when a test is not finished.
getUnfilteredEvaluationData()
& createQuestionGUI($question_type, $question_id=-1)
Creates a question GUI instance of a given question type.
isShowExamIdInTestPassEnabled()
setQuestionOrderAndObligations($orders, $obligations)
setRedirectionMode($redirection_mode=0)
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
setQuestionSetType($questionSetType)
setter for question set type
Class ilObjTestGUI.
setECTSOutput($a_ects_output)
Enables/Disables ECTS grades output for this test.
_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...
saveECTSStatus($ects_output=0, $fx_support="", $ects_a=90, $ects_b=65, $ects_c=35, $ects_d=10, $ects_e=0)
Saves the ECTS status (output of ECTS grades in a test) to the database.
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.
& _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.
nextId($a_table_name)
Get next ID for an index.
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.
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.
fetchObject($a_set)
Fetch row as object from result set.
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.
_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.
_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.
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
static prepareTextareaOutput($txt_output, $prepare_for_latex_output=FALSE)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
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.
$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
& 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.
_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()
Gets the sequence settings of the ilObjTest object 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.
$mobs
canViewResults()
Returns true, if the test results can be viewed.
setTestFinalBroken($testFinalBroken)
getHighscorePercentage()
Gets if the percentage column should be shown.
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...
xslt_error(&$proc)
exportFileItems($a_target_dir, &$expLog)
export files of file itmes
setCustomStyle($a_customStyle=NULL)
Set the custom style.
setSignSubmission($sign_submission)
fetchAssoc($a_set)
Fetch row as associative array from result set.
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.
addDefaults($a_name)
Adds the defaults of this test to the test defaults.
getCountSystem()
Gets the count system for the calculation of points.
getIntroduction()
Gets the introduction text of the ilObjTest object.
_getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
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.
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.
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.
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.
xslt_process(&$proc, $xml_var, $xslt_var, $dummy, $args, $params, $a_no_warnings=false)
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)
setLimit($a_limit, $a_offset=0)
Set limit and offset for a query.
static deleteRequestsByQuestionIds($questionIds)
Deletes all hint requests relating to a question included in given question ids.
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.
_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.
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
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.
getAnswerFeedbackPoints()
Returns 1 if answer specific feedback as reached points is activated.
setECTSGrades($a_ects_grades)
Sets the ECTS grades.
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.
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.
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()
_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.
setShowSolutionFeedback($a_feedback=TRUE)
Sets if the the feedback should be presented to the user in the solution or not.
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.
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)
static _replaceMediaObjectImageSrc($a_text, $a_direction=0)
replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
setResultsPresentationOptionsByArray($options)
setEnabledViewMode($mode)
getQuestionSetType()
getter for question set type
& getECTSGrades()
Returns the ECTS grades.
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.
while($lm_rec=$ilDB->fetchAssoc($lm_set)) $data
$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.
setShowExamviewHtml($show_examview_html)
global $ilUser
Definition: imgupload.php:15
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.
getCustomStyles()
Return the available custom styles.
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.
_getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
Returns the ECTS grade for a number of reached points.
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.
& evalTotalParticipantsArray($name_sort_order="asc")
Returns all participants who started the test.
$print_best_solution_with_result
setPrintBestSolutionWithResult($status)
getKioskMode()
Returns the kiosk mode.
setMCScoring($a_mc_scoring=SCORE_ZERO_POINTS_WHEN_UNANSWERED)
Sets the multiple choice scoring.
getExportSettingsSingleChoiceShort()
global $ilBench
Definition: ilias.php:18
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()
Returns the ECTS FX grade.
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 insertInstIntoID($a_value)
inserts installation id into ILIAS id
static buildExamId($active_id, $pass)
& 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)
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.
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.
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)
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.
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
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
static deleteRequestsByActiveIds($activeIds)
Deletes all hint requests relating to a testactive included in given active ids.
setSequenceSettings($sequence_settings=0)
Sets the sequence settings of the ilObjTest object.
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)
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.