00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00035 require_once "./classes/class.ilObject.php";
00036 require_once "./assessment/classes/class.assMarkSchema.php";
00037 require_once "./classes/class.ilMetaData.php";
00038 require_once "./assessment/classes/class.assQuestion.php";
00039 require_once "./assessment/classes/class.assClozeTest.php";
00040 require_once "./assessment/classes/class.assImagemapQuestion.php";
00041 require_once "./assessment/classes/class.assJavaApplet.php";
00042 require_once "./assessment/classes/class.assMatchingQuestion.php";
00043 require_once "./assessment/classes/class.assMultipleChoice.php";
00044 require_once "./assessment/classes/class.assOrderingQuestion.php";
00045 require_once "./classes/class.ilObjAssessmentFolder.php";
00046
00047 define("TEST_FIXED_SEQUENCE", 0);
00048 define("TEST_POSTPONE", 1);
00049
00050 define("REPORT_AFTER_QUESTION", 0);
00051 define("REPORT_AFTER_TEST", 1);
00052
00053 define("TYPE_ASSESSMENT", "1");
00054 define("TYPE_SELF_ASSESSMENT", "2");
00055 define("TYPE_NAVIGATION_CONTROLLING", "3");
00056
00057 class ilObjTest extends ilObject
00058 {
00066 var $test_id;
00067
00076 var $author;
00077
00085 var $metadata;
00086
00094 var $questions;
00095
00104 var $introduction;
00105
00113 var $mark_schema;
00114
00124 var $sequence_settings;
00125
00137 var $score_reporting;
00138
00149 var $reporting_date;
00150
00158 var $evaluation_data;
00159
00167 var $test_type;
00168
00177 var $nr_of_tries;
00178
00186 var $processing_time;
00187
00195 var $enable_processing_time;
00196
00204 var $starting_time;
00205
00213 var $ending_time;
00214
00222 var $ects_output;
00223
00231 var $ects_fx;
00232
00243 var $test_types;
00244
00252 var $ects_grades;
00253
00263 var $random_test;
00264
00272 var $random_question_count;
00273
00280 function ilObjTest($a_id = 0,$a_call_by_reference = true)
00281 {
00282 global $ilUser;
00283 $this->type = "tst";
00284 $this->mark_schema = new ASS_MarkSchema();
00285
00286 $this->retrieveTestTypes();
00287 $this->test_id = -1;
00288 $this->author = $ilUser->fullname;
00289 $this->introduction = "";
00290 $this->questions = array();
00291 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00292 $this->score_reporting = REPORT_AFTER_TEST;
00293 $this->reporting_date = "";
00294 $this->nr_of_tries = 0;
00295 $this->starting_time = "";
00296 $this->ending_time = "";
00297 $this->processing_time = "00:00:00";
00298 $this->enable_processing_time = "0";
00299 $this->test_type = TYPE_ASSESSMENT;
00300 $this->ects_output = 0;
00301 $this->ects_fx = "";
00302 $this->random_test = 0;
00303 $this->random_question_count = "";
00304 global $lng;
00305 $lng->loadLanguageModule("assessment");
00306 $this->mark_schema->create_simple_schema($lng->txt("failed_short"), $lng->txt("failed_official"), 0, 0, $lng->txt("passed_short"), $lng->txt("passed_official"), 50, 1);
00307 $this->ects_grades = array(
00308 "A" => 90,
00309 "B" => 65,
00310 "C" => 35,
00311 "D" => 10,
00312 "E" => 0
00313 );
00314 if ($a_id == 0)
00315 {
00316 $new_meta =& new ilMetaData();
00317 $this->assignMetaData($new_meta);
00318 }
00319 $this->ilObject($a_id, $a_call_by_reference);
00320 }
00321
00325 function create($a_upload = false)
00326 {
00327 parent::create();
00328 if (!$a_upload)
00329 {
00330 $this->meta_data->setId($this->getId());
00331 $this->meta_data->setType($this->getType());
00332 $this->meta_data->setTitle($this->getTitle());
00333 $this->meta_data->setDescription($this->getDescription());
00334 $this->meta_data->setObject($this);
00335 $this->meta_data->create();
00336 }
00337 }
00338
00345 function update()
00346 {
00347 if (!parent::update())
00348 {
00349 return false;
00350 }
00351
00352
00353
00354 return true;
00355 }
00356
00365 function createReference() {
00366 $result = parent::createReference();
00367 $this->saveToDb();
00368 return $result;
00369 }
00370
00376 function getCallingScript()
00377 {
00378 return "test.php";
00379 }
00380
00386 function read($a_force_db = false)
00387 {
00388 parent::read($a_force_db);
00389 $this->loadFromDb();
00390 $this->meta_data =& new ilMetaData($this->getType(), $this->getId());
00391 }
00392
00400 function ilClone($a_parent_ref)
00401 {
00402 global $rbacadmin;
00403
00404
00405 $new_ref_id = parent::ilClone($a_parent_ref);
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 return $new_ref_id;
00421 }
00422
00429 function delete()
00430 {
00431
00432 if (!parent::delete())
00433 {
00434 return false;
00435 }
00436
00437
00438 $this->deleteTest();
00439
00440 return true;
00441 }
00442
00450 function deleteTest()
00451 {
00452 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00453 $this->ilias->db->quote($this->getTestId())
00454 );
00455 $result = $this->ilias->db->query($query);
00456 $active_array = array();
00457 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00458 {
00459 array_push($active_array, $row["active_id"]);
00460 }
00461
00462 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00463 $this->ilias->db->quote($this->getTestId())
00464 );
00465 $result = $this->ilias->db->query($query);
00466
00467 if (count($active_array))
00468 {
00469 foreach ($active_array as $active_id)
00470 {
00471 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00472 $this->ilias->db->quote($active_id)
00473 );
00474 $result = $this->ilias->db->query($query);
00475 }
00476 }
00477
00478 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00479 $this->ilias->db->quote($this->getTestId())
00480 );
00481 $result = $this->ilias->db->query($query);
00482
00483 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00484 $this->ilias->db->quote($this->getTestId())
00485 );
00486 $result = $this->ilias->db->query($query);
00487 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00488 {
00489 $this->removeQuestion($row->question_fi);
00490 }
00491
00492 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00493 $this->ilias->db->quote($this->getTestId())
00494 );
00495 $result = $this->ilias->db->query($query);
00496
00497 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00498 $this->ilias->db->quote($this->getTestId())
00499 );
00500 $result = $this->ilias->db->query($query);
00501
00502 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
00503 $this->ilias->db->quote($this->getTestId())
00504 );
00505 $result = $this->ilias->db->query($query);
00506
00507 $this->removeAllTestEditings();
00508
00509 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00510 $this->ilias->db->quote($this->getTestId())
00511 );
00512 $result = $this->ilias->db->query($query);
00513
00514
00515 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00516 $directory = $tst_data_dir."/tst_".$this->getId();
00517 if (is_dir($directory))
00518 {
00519 $directory = escapeshellarg($directory);
00520 exec("rm -rf $directory");
00521 }
00522 }
00523
00533 function initDefaultRoles()
00534 {
00535 global $rbacadmin;
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 return $roles ? $roles : array();
00548 }
00549
00563 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00564 {
00565 global $tree;
00566
00567 switch ($a_event)
00568 {
00569 case "link":
00570
00571
00572
00573
00574 break;
00575
00576 case "cut":
00577
00578
00579
00580 break;
00581
00582 case "copy":
00583
00584
00585
00586
00587 break;
00588
00589 case "paste":
00590
00591
00592
00593 break;
00594
00595 case "new":
00596
00597
00598
00599 break;
00600 }
00601
00602
00603 if ($a_node_id==$_GET["ref_id"])
00604 {
00605 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00606 $parent_type = $parent_obj->getType();
00607 if($parent_type == $this->getType())
00608 {
00609 $a_node_id = (int) $tree->getParentId($a_node_id);
00610 }
00611 }
00612
00613 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00614 }
00615
00621 function createExportDirectory()
00622 {
00623 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00624 ilUtil::makeDir($tst_data_dir);
00625 if(!is_writable($tst_data_dir))
00626 {
00627 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00628 .") not writeable.",$this->ilias->error_obj->FATAL);
00629 }
00630
00631
00632 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00633 ilUtil::makeDir($tst_dir);
00634 if(!@is_dir($tst_dir))
00635 {
00636 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->FATAL);
00637 }
00638
00639 $export_dir = $tst_dir."/export";
00640 ilUtil::makeDir($export_dir);
00641 if(!@is_dir($export_dir))
00642 {
00643 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->FATAL);
00644 }
00645 }
00646
00654 function getExportDirectory()
00655 {
00656 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00657
00658 return $export_dir;
00659 }
00660
00669 function getExportFiles($dir)
00670 {
00671
00672 if (!@is_dir($dir) or
00673 !is_writeable($dir))
00674 {
00675 return array();
00676 }
00677
00678
00679 $dir = dir($dir);
00680
00681
00682 $file = array();
00683
00684
00685 while ($entry = $dir->read())
00686 {
00687 if ($entry != "." and
00688 $entry != ".." and
00689 substr($entry, -4) == ".zip" and
00690 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test_)*[0-9]+\.zip\$", $entry))
00691 {
00692 $file[] = $entry;
00693 }
00694 }
00695
00696
00697 $dir->close();
00698
00699
00700 sort ($file);
00701 reset ($file);
00702
00703 return $file;
00704 }
00705
00711 function createImportDirectory()
00712 {
00713 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00714 ilUtil::makeDir($tst_data_dir);
00715
00716 if(!is_writable($tst_data_dir))
00717 {
00718 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00719 .") not writeable.",$this->ilias->error_obj->FATAL);
00720 }
00721
00722
00723 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00724 ilUtil::makeDir($tst_dir);
00725 if(!@is_dir($tst_dir))
00726 {
00727 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->FATAL);
00728 }
00729
00730
00731 $import_dir = $tst_dir."/import";
00732 ilUtil::makeDir($import_dir);
00733 if(!@is_dir($import_dir))
00734 {
00735 $this->ilias->raiseError("Creation of Import Directory failed.",$this->ilias->error_obj->FATAL);
00736 }
00737 }
00738
00747 function getImportDirectory()
00748 {
00749 $import_dir = ilUtil::getDataDir()."/tst_data".
00750 "/tst_".$this->getId()."/import";
00751 if(@is_dir($import_dir))
00752 {
00753 return $import_dir;
00754 }
00755 else
00756 {
00757 return false;
00758 }
00759 }
00760
00761
00771 function retrieveTestTypes()
00772 {
00773 global $ilDB;
00774
00775 $this->test_types = array();
00776 $query = "SELECT * FROM tst_test_type ORDER BY test_type_id";
00777 $result = $ilDB->query($query);
00778 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00779 {
00780 $this->test_types[$row->test_type_id] = $row->type_tag;
00781 }
00782 }
00783
00793 function testTitleExists($title)
00794 {
00795 $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00796 $this->ilias->db->quote($title),
00797 $this->ilias->db->quote("tst")
00798 );
00799 $result = $this->ilias->db->query($query);
00800 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00801 if ($result->numRows() == 1) {
00802 return TRUE;
00803 }
00804 }
00805 return FALSE;
00806 }
00807
00815 function duplicate()
00816 {
00817 $clone = $this;
00818 $clone->set_id(-1);
00819 $counter = 2;
00820 while ($this->testTitleExists($this->get_title() . " ($counter)")) {
00821 $counter++;
00822 }
00823 $clone->set_title($this->get_title() . " ($counter)");
00824 $clone->set_owner($this->ilias->account->id);
00825 $clone->setAuthor($this->ilias->account->fullname);
00826 $clone->saveToDb($this->ilias->db);
00827
00828 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi = %s",
00829 $this->ilias->db->quote($this->getId())
00830 );
00831 $result = $this->ilias->db->query($query);
00832 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00833 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
00834 $this->ilias->db->quote($clone->getId()),
00835 $this->ilias->db->quote($data->question_fi),
00836 $this->ilias->db->quote($data->sequence)
00837 );
00838 $insert_result = $this->ilias->db->query($query);
00839 }
00840 }
00841
00850 function isComplete()
00851 {
00852 if (($this->getTitle()) and ($this->author) and (count($this->mark_schema->mark_steps)) and (count($this->questions)))
00853 {
00854 return true;
00855 }
00856 else
00857 {
00858 if ($this->isRandomTest())
00859 {
00860 $arr = $this->getRandomQuestionpools();
00861 if (count($arr) && ($this->getRandomQuestionCount() > 0))
00862 {
00863 return true;
00864 }
00865 $count = 0;
00866 foreach ($arr as $array)
00867 {
00868 $count += $array["count"];
00869 }
00870 if ($count)
00871 {
00872 return true;
00873 }
00874 }
00875 return false;
00876 }
00877 }
00878
00887 function _isComplete($obj_id)
00888 {
00889 $test = new ilObjTest($obj_id, false);
00890 $test->loadFromDb();
00891 if (($test->getTitle()) and ($test->author) and (count($test->mark_schema->mark_steps)) and (count($test->questions)))
00892 {
00893 return true;
00894 }
00895 else
00896 {
00897 return false;
00898 }
00899 }
00900
00908 function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
00909 {
00910 global $ilDB;
00911 if ($this->test_id > 0) {
00912 $fx_support = preg_replace("/,/", ".", $fx_support);
00913 if (preg_match("/\d+/", $fx_support))
00914 {
00915 $fx_support = $fx_support;
00916 }
00917 else
00918 {
00919 $fx_support = "NULL";
00920 }
00921 $query = sprintf("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",
00922 $ilDB->quote("$ects_output"),
00923 $ilDB->quote($ects_a . ""),
00924 $ilDB->quote($ects_b . ""),
00925 $ilDB->quote($ects_c . ""),
00926 $ilDB->quote($ects_d . ""),
00927 $ilDB->quote($ects_e . ""),
00928 $fx_support,
00929 $this->getTestId()
00930 );
00931 $result = $ilDB->query($query);
00932 $this->ects_output = $ects_output;
00933 $this->ects_fx = $fx_support;
00934 }
00935 }
00936
00944 function saveCompleteStatus()
00945 {
00946 global $ilias;
00947
00948 $db =& $ilias->db;
00949 $complete = 0;
00950 if ($this->isComplete()) {
00951 $complete = 1;
00952 }
00953 if ($this->test_id > 0) {
00954 $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
00955 $db->quote("$complete"),
00956 $db->quote($this->test_id)
00957 );
00958 $result = $db->query($query);
00959 }
00960 }
00961
00970 function saveToDb($properties_only = FALSE)
00971 {
00972 global $ilias;
00973 $db =& $ilias->db;
00974 $complete = 0;
00975 if ($this->isComplete()) {
00976 $complete = 1;
00977 }
00978 $ects_fx = "NULL";
00979 if (preg_match("/\d+/", $this->ects_fx))
00980 {
00981 $ects_fx = $this->ects_fx;
00982 }
00983 $random_question_count = "NULL";
00984 if ($this->random_question_count > 0)
00985 {
00986 $random_question_count = $this->ilias->db->quote($this->random_question_count . "");
00987 }
00988 if ($this->test_id == -1) {
00989
00990 $now = getdate();
00991 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00992 $query = sprintf("INSERT INTO tst_tests (test_id, obj_fi, author, test_type_fi, introduction, sequence_settings, score_reporting, nr_of_tries, processing_time, enable_processing_time, reporting_date, starting_time, ending_time, complete, ects_output, ects_a, ects_b, ects_c, ects_d, ects_e, ects_fx, random_test, random_question_count, created, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00993 $db->quote($this->getId() . ""),
00994 $db->quote($this->author . ""),
00995 $db->quote($this->test_type . ""),
00996 $db->quote($this->introduction . ""),
00997 $db->quote($this->sequence_settings . ""),
00998 $db->quote($this->score_reporting . ""),
00999 $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01000 $db->quote($this->processing_time . ""),
01001 $db->quote("$this->enable_processing_time"),
01002 $db->quote($this->reporting_date . ""),
01003 $db->quote($this->starting_time . ""),
01004 $db->quote($this->ending_time . ""),
01005 $db->quote("$complete"),
01006 $db->quote($this->ects_output . ""),
01007 $db->quote($this->ects_grades["A"] . ""),
01008 $db->quote($this->ects_grades["B"] . ""),
01009 $db->quote($this->ects_grades["C"] . ""),
01010 $db->quote($this->ects_grades["D"] . ""),
01011 $db->quote($this->ects_grades["E"] . ""),
01012 $ects_fx,
01013 $db->quote(sprintf("%d", $this->random_test) . ""),
01014 $random_question_count,
01015 $db->quote($created)
01016 );
01017 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01018 {
01019 $this->logAction($this->lng->txt("log_create_new_test"));
01020 }
01021 $result = $db->query($query);
01022 if ($result == DB_OK) {
01023 $this->test_id = $this->ilias->db->getLastInsertId();
01024 }
01025 } else {
01026
01027 $oldrow = array();
01028 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01029 {
01030 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01031 $db->quote($this->test_id)
01032 );
01033 $result = $db->query($query);
01034 if ($result->numRows() == 1)
01035 {
01036 $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01037 }
01038 }
01039 $query = sprintf("UPDATE tst_tests SET author = %s, test_type_fi = %s, introduction = %s, sequence_settings = %s, score_reporting = %s, nr_of_tries = %s, processing_time = %s, enable_processing_time = %s, reporting_date = %s, starting_time = %s, ending_time = %s, ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s, random_test = %s, complete = %s WHERE test_id = %s",
01040 $db->quote($this->author . ""),
01041 $db->quote($this->test_type . ""),
01042 $db->quote($this->introduction . ""),
01043 $db->quote($this->sequence_settings . ""),
01044 $db->quote($this->score_reporting . ""),
01045 $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01046 $db->quote($this->processing_time . ""),
01047 $db->quote("$this->enable_processing_time"),
01048 $db->quote($this->reporting_date . ""),
01049 $db->quote($this->starting_time . ""),
01050 $db->quote($this->ending_time . ""),
01051 $db->quote($this->ects_output . ""),
01052 $db->quote($this->ects_grades["A"] . ""),
01053 $db->quote($this->ects_grades["B"] . ""),
01054 $db->quote($this->ects_grades["C"] . ""),
01055 $db->quote($this->ects_grades["D"] . ""),
01056 $db->quote($this->ects_grades["E"] . ""),
01057 $ects_fx,
01058 $db->quote(sprintf("%d", $this->random_test) . ""),
01059 $db->quote("$complete"),
01060 $db->quote($this->test_id)
01061 );
01062 $result = $db->query($query);
01063 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01064 {
01065 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01066 $db->quote($this->test_id)
01067 );
01068 $logresult = $db->query($query);
01069 $newrow = array();
01070 if ($logresult->numRows() == 1)
01071 {
01072 $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01073 }
01074 $changed_fields = array();
01075 foreach ($oldrow as $key => $value)
01076 {
01077 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01078 {
01079 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01080 }
01081 }
01082 $changes = join($changed_fields, ", ");
01083 if (count($changed_fields) == 0)
01084 {
01085 $changes = $this->lng->txt("log_no_test_fields_changed");
01086 }
01087 $this->logAction($this->lng->txt("log_modified_test") . " [".$changes."]");
01088 }
01089 }
01090 if (!$properties_only)
01091 {
01092 if ($result == DB_OK) {
01093 if (!$this->isRandomTest())
01094 {
01095 $this->saveQuestionsToDb();
01096 }
01097 $this->mark_schema->saveToDb($this->test_id);
01098 }
01099 }
01100 }
01101
01110 function saveQuestionsToDb()
01111 {
01112 $oldquestions = array();
01113 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01114 {
01115 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01116 $this->ilias->db->quote($this->getTestId())
01117 );
01118 $result = $this->ilias->db->query($query);
01119 if ($result->numRows() > 0)
01120 {
01121 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01122 {
01123 array_push($oldquestions, $row["question_fi"]);
01124 }
01125 }
01126 }
01127
01128
01129 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01130 $this->ilias->db->quote($this->getTestId())
01131 );
01132 $result = $this->ilias->db->query($query);
01133
01134 foreach ($this->questions as $key => $value) {
01135 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01136 $this->ilias->db->quote($this->getTestId() . ""),
01137 $this->ilias->db->quote($value . ""),
01138 $this->ilias->db->quote($key . "")
01139 );
01140 $result = $this->ilias->db->query($query);
01141 }
01142 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01143 {
01144 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01145 $this->ilias->db->quote($this->getTestId())
01146 );
01147 $result = $this->ilias->db->query($query);
01148 $newquestions = array();
01149 if ($result->numRows() > 0)
01150 {
01151 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01152 {
01153 array_push($newquestions, $row["question_fi"]);
01154 }
01155 }
01156 foreach ($oldquestions as $index => $question_id)
01157 {
01158 if (strcmp($newquestions[$index], $question_id) != 0)
01159 {
01160 $pos = array_search($question_id, $newquestions);
01161 if ($pos === FALSE)
01162 {
01163 $this->logAction($this->lng->txt("log_question_removed"), $question_id);
01164 }
01165 else
01166 {
01167 $this->logAction($this->lng->txt("log_question_position_changed") . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01168 }
01169 }
01170 }
01171 foreach ($newquestions as $index => $question_id)
01172 {
01173 if (array_search($question_id, $oldquestions) === FALSE)
01174 {
01175 $this->logAction($this->lng->txt("log_question_added") . ": " . ($index+1), $question_id);
01176 }
01177 }
01178 }
01179 }
01180
01189 function saveRandomQuestion($question_id)
01190 {
01191 global $ilUser;
01192
01193 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE test_fi = %s AND user_fi = %s",
01194 $this->ilias->db->quote($this->getTestId() . ""),
01195 $this->ilias->db->quote($ilUser->id . "")
01196 );
01197 $result = $this->ilias->db->query($query);
01198
01199 $query = sprintf("INSERT INTO tst_test_random_question (test_random_question_id, test_fi, user_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
01200 $this->ilias->db->quote($this->getTestId() . ""),
01201 $this->ilias->db->quote($ilUser->id . ""),
01202 $this->ilias->db->quote($question_id . ""),
01203 $this->ilias->db->quote(($result->numRows()+1) . "")
01204 );
01205 $result = $this->ilias->db->query($query);
01206 }
01207
01216 function saveRandomQuestionCount($total_questions = "NULL")
01217 {
01218 if (strcmp($total_questions, "NULL") != 0)
01219 {
01220 $total_questions = $this->ilias->db->quote($total_questions);
01221 }
01222 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01223 $total_questions,
01224 $this->ilias->db->quote($this->getTestId() . "")
01225 );
01226 $result = $this->ilias->db->query($query);
01227 }
01228
01238 function saveRandomQuestionpools($qpl_array)
01239 {
01240
01241 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01242 $this->ilias->db->quote($this->getTestId())
01243 );
01244 $result = $this->ilias->db->query($query);
01245
01246 foreach ($qpl_array as $key => $value) {
01247 if ($value["qpl"] > -1)
01248 {
01249 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01250 if ($value["count"] > $count)
01251 {
01252 $value["count"] = $count;
01253 }
01254 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01255 $this->ilias->db->quote($this->getTestId() . ""),
01256 $this->ilias->db->quote($value["qpl"] . ""),
01257 $this->ilias->db->quote(sprintf("%d", $value["count"]) . "")
01258 );
01259 $result = $this->ilias->db->query($query);
01260 }
01261 }
01262 }
01263
01273 function &getRandomQuestionpools()
01274 {
01275 $qpls = array();
01276 $counter = 0;
01277 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
01278 $this->ilias->db->quote($this->getTestId() . "")
01279 );
01280 $result = $this->ilias->db->query($query);
01281 if ($result->numRows())
01282 {
01283 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01284 {
01285 $qpls[$counter] = array(
01286 "index" => $counter,
01287 "count" => $row["num_of_q"],
01288 "qpl" => $row["questionpool_fi"]
01289 );
01290 $counter++;
01291 }
01292 }
01293 return $qpls;
01294 }
01295
01305 function loadFromDb()
01306 {
01307 $db = $this->ilias->db;
01308
01309 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01310 $db->quote($this->getId())
01311 );
01312 $result = $db->query($query);
01313 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01314 {
01315 if ($result->numRows() == 1)
01316 {
01317 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01318 $this->test_id = $data->test_id;
01319 $this->author = $data->author;
01320 $this->test_type = $data->test_type_fi;
01321 $this->introduction = $data->introduction;
01322 $this->sequence_settings = $data->sequence_settings;
01323 $this->score_reporting = $data->score_reporting;
01324 $this->nr_of_tries = $data->nr_of_tries;
01325 $this->processing_time = $data->processing_time;
01326 $this->enable_processing_time = $data->enable_processing_time;
01327 $this->reporting_date = $data->reporting_date;
01328 $this->starting_time = $data->starting_time;
01329 $this->ending_time = $data->ending_time;
01330 $this->ects_output = $data->ects_output;
01331 $this->ects_grades = array(
01332 "A" => $data->ects_a,
01333 "B" => $data->ects_b,
01334 "C" => $data->ects_c,
01335 "D" => $data->ects_d,
01336 "E" => $data->ects_e
01337 );
01338 $this->ects_fx = $data->ects_fx;
01339 $this->random_test = $data->random_test;
01340 $this->random_question_count = $data->random_question_count;
01341 $this->mark_schema->flush();
01342 $this->mark_schema->loadFromDb($this->test_id);
01343 $this->loadQuestions();
01344 }
01345 }
01346 }
01347
01356 function loadQuestions($user_id = "")
01357 {
01358 global $ilUser;
01359
01360 $db = $this->ilias->db;
01361 $this->questions = array();
01362 if (strcmp($user_id, "") == 0)
01363 {
01364 $user_id = $ilUser->id;
01365 }
01366 if ($this->isRandomTest())
01367 {
01368 $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.test_fi = %s AND tst_test_random_question.user_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi ORDER BY sequence",
01369 $db->quote($this->test_id . ""),
01370 $db->quote($user_id . "")
01371 );
01372 }
01373 else
01374 {
01375 $query = sprintf("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",
01376 $db->quote($this->test_id . "")
01377 );
01378 }
01379 $result = $db->query($query);
01380 $index = 1;
01381 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01382 $this->questions[$index++] = $data->question_fi;
01383 }
01384 }
01385
01395 function setAuthor($author = "")
01396 {
01397 $this->author = $author;
01398 }
01399
01409 function setIntroduction($introduction = "")
01410 {
01411 $this->introduction = $introduction;
01412 }
01413
01423 function getAuthor()
01424 {
01425 return $this->author;
01426 }
01427
01437 function isRandomTest()
01438 {
01439 return $this->random_test;
01440 }
01441
01451 function getRandomQuestionCount()
01452 {
01453 return $this->random_question_count;
01454 }
01455
01465 function getIntroduction()
01466 {
01467 return $this->introduction;
01468 }
01469
01479 function getTestId()
01480 {
01481 return $this->test_id;
01482 }
01483
01493 function setSequenceSettings($sequence_settings = 0)
01494 {
01495 $this->sequence_settings = $sequence_settings;
01496 }
01497
01507 function setTestType($type = TYPE_ASSESSMENT)
01508 {
01509 $this->test_type = $type;
01510 }
01511
01521 function setScoreReporting($score_reporting = 0)
01522 {
01523 $this->score_reporting = $score_reporting;
01524 }
01525
01535 function setRandomTest($a_random_test = 0)
01536 {
01537 $this->random_test = $a_random_test;
01538 }
01539
01549 function setRandomQuestionCount($a_random_question_count = "")
01550 {
01551 $this->random_question_count = $a_random_question_count;
01552 }
01553
01563 function setReportingDate($reporting_date)
01564 {
01565 if (!$reporting_date)
01566 {
01567 $this->reporting_date = "";
01568 $this->ects_output = 0;
01569 }
01570 else
01571 {
01572 $this->reporting_date = $reporting_date;
01573 $this->score_reporting = REPORT_AFTER_TEST;
01574 }
01575 }
01576
01586 function getSequenceSettings()
01587 {
01588 return $this->sequence_settings;
01589 }
01590
01600 function getScoreReporting()
01601 {
01602 return $this->score_reporting;
01603 }
01604
01614 function getTestType()
01615 {
01616 return $this->test_type;
01617 }
01618
01628 function getReportingDate()
01629 {
01630 return $this->reporting_date;
01631 }
01632
01642 function getNrOfTries()
01643 {
01644 return $this->nr_of_tries;
01645 }
01646
01656 function getProcessingTime()
01657 {
01658 return $this->processing_time;
01659 }
01660
01670 function getProcessingTimeInSeconds()
01671 {
01672 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
01673 {
01674 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
01675 }
01676 else
01677 {
01678 return 0;
01679 }
01680 }
01681
01691 function getEnableProcessingTime()
01692 {
01693 return $this->enable_processing_time;
01694 }
01695
01705 function getStartingTime()
01706 {
01707 return $this->starting_time;
01708 }
01709
01719 function getEndingTime()
01720 {
01721 return $this->ending_time;
01722 }
01723
01733 function setNrOfTries($nr_of_tries = 0)
01734 {
01735 $this->nr_of_tries = $nr_of_tries;
01736 }
01737
01747 function setProcessingTime($processing_time = "00:00:00")
01748 {
01749 $this->processing_time = $processing_time;
01750 }
01751
01761 function setEnableProcessingTime($enable = 0)
01762 {
01763 if ($enable) {
01764 $this->enable_processing_time = "1";
01765 } else {
01766 $this->enable_processing_time = "0";
01767 }
01768 }
01769
01779 function setStartingTime($starting_time = "")
01780 {
01781 $this->starting_time = $starting_time;
01782 }
01783
01793 function setEndingTime($ending_time = "")
01794 {
01795 $this->ending_time = $ending_time;
01796 }
01797
01807 function removeQuestion($question_id)
01808 {
01809 $question = new ASS_Question();
01810 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01811 {
01812 $this->logAction($this->lng->txt("log_question_removed"), $question_id);
01813 }
01814 $question->delete($question_id);
01815 $this->removeAllTestEditings($question_id);
01816 $this->loadQuestions();
01817 $this->saveQuestionsToDb();
01818 }
01819
01827 function clearEvalSelectedUsers()
01828 {
01829 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s",
01830 $this->ilias->db->quote($this->getTestId())
01831 );
01832 $result = $this->ilias->db->query($query);
01833 }
01834
01842 function clearEvalSelectedGroups()
01843 {
01844 $query = sprintf("DELETE FROM tst_eval_groups WHERE test_fi = %s",
01845 $this->ilias->db->quote($this->getTestId())
01846 );
01847 $result = $this->ilias->db->query($query);
01848 }
01849
01861 function removeAllTestEditings($question_id = "")
01862 {
01863
01864 $this->deleteActiveTests();
01865
01866 $this->clearEvalSelectedUsers();
01867 $this->clearEvalSelectedGroups();
01868
01869
01870 if ($question_id) {
01871 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND question_fi = %s",
01872 $this->ilias->db->quote($this->getTestId()),
01873 $this->ilias->db->quote($question_id)
01874 );
01875 } else {
01876 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s",
01877 $this->ilias->db->quote($this->getTestId())
01878 );
01879 }
01880 $result = $this->ilias->db->query($query);
01881 if ($this->isRandomTest())
01882 {
01883 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
01884 $this->ilias->db->quote($this->getTestId())
01885 );
01886 $result = $this->ilias->db->query($query);
01887 }
01888 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01889 {
01890 $this->logAction($this->lng->txt("log_user_data_removed"));
01891 }
01892 }
01893
01902 function deleteActiveTests()
01903 {
01904 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
01905 $this->ilias->db->quote($this->getTestId())
01906 );
01907 $result = $this->ilias->db->query($query);
01908 }
01909
01920 function deleteResults($user_id = "")
01921 {
01922 if ($user_id) {
01923 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND user_fi = %s",
01924 $this->ilias->db->quote($this->getTestId()),
01925 $this->ilias->db->quote($user_id)
01926 );
01927 $result = $this->ilias->db->query($query);
01928 $sequence_arr = array_flip($this->questions);
01929 $sequence = join($sequence_arr, ",");
01930 $query = sprintf("UPDATE tst_active SET sequence = %s, lastindex = %s WHERE test_fi = %s and user_fi = %s",
01931 $this->ilias->db->quote($sequence),
01932 $this->ilias->db->quote("1"),
01933 $this->ilias->db->quote($this->getTestId()),
01934 $this->ilias->db->quote($user_id)
01935 );
01936 $result = $this->ilias->db->query($query);
01937 }
01938 }
01939
01949 function questionMoveUp($question_id)
01950 {
01951
01952 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
01953 $this->ilias->db->quote($this->getTestId()),
01954 $this->ilias->db->quote($question_id)
01955 );
01956 $result = $this->ilias->db->query($query);
01957 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01958 if ($data->sequence > 1) {
01959
01960 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
01961 $this->ilias->db->quote($this->getTestId()),
01962 $this->ilias->db->quote($data->sequence - 1)
01963 );
01964 $result = $this->ilias->db->query($query);
01965 $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
01966
01967 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
01968 $this->ilias->db->quote($data->sequence),
01969 $this->ilias->db->quote($data_previous->test_question_id)
01970 );
01971 $result = $this->ilias->db->query($query);
01972
01973 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
01974 $this->ilias->db->quote($data->sequence - 1),
01975 $this->ilias->db->quote($data->test_question_id)
01976 );
01977 $result = $this->ilias->db->query($query);
01978 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01979 {
01980 $this->logAction($this->lng->txt("log_question_position_changed") . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
01981 }
01982 }
01983 $this->loadQuestions();
01984 }
01985
01995 function questionMoveDown($question_id)
01996 {
01997
01998 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
01999 $this->ilias->db->quote($this->getTestId()),
02000 $this->ilias->db->quote($question_id)
02001 );
02002 $result = $this->ilias->db->query($query);
02003 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02004 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
02005 $this->ilias->db->quote($this->getTestId()),
02006 $this->ilias->db->quote($data->sequence + 1)
02007 );
02008 $result = $this->ilias->db->query($query);
02009 if ($result->numRows() == 1)
02010 {
02011
02012 $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
02013
02014 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02015 $this->ilias->db->quote($data->sequence),
02016 $this->ilias->db->quote($data_next->test_question_id)
02017 );
02018 $result = $this->ilias->db->query($query);
02019
02020 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02021 $this->ilias->db->quote($data->sequence + 1),
02022 $this->ilias->db->quote($data->test_question_id)
02023 );
02024 $result = $this->ilias->db->query($query);
02025 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02026 {
02027 $this->logAction($this->lng->txt("log_question_position_changed") . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
02028 }
02029 }
02030 $this->loadQuestions();
02031 }
02032
02042 function duplicateQuestionForTest($question_id)
02043 {
02044 global $ilUser;
02045
02046 $question =& ilObjTest::_instanciateQuestion($question_id);
02047 $duplicate_id = $question->duplicate(true);
02048
02049 return $duplicate_id;
02050 }
02051
02060 function insertQuestion($question_id)
02061 {
02062 $duplicate_id = $this->duplicateQuestionForTest($question_id);
02063
02064
02065 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
02066 $this->ilias->db->quote($this->getTestId())
02067 );
02068 $result = $this->ilias->db->query($query);
02069 $sequence = 1;
02070
02071 if ($result->numRows() == 1)
02072 {
02073 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02074 $sequence = $data->seq + 1;
02075 }
02076
02077 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02078 $this->ilias->db->quote($this->getTestId()),
02079 $this->ilias->db->quote($duplicate_id),
02080 $this->ilias->db->quote($sequence)
02081 );
02082 $result = $this->ilias->db->query($query);
02083 if ($result != DB_OK)
02084 {
02085
02086 }
02087 else
02088 {
02089 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02090 {
02091 $this->logAction($this->lng->txt("log_question_added") . ": " . $sequence, $duplicate_id);
02092 }
02093 }
02094
02095 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
02096 $this->ilias->db->quote($this->getTestId())
02097 );
02098 $result = $this->ilias->db->query($query);
02099 $this->loadQuestions();
02100 $this->saveCompleteStatus();
02101 }
02102
02112 function getQuestionTitle($sequence)
02113 {
02114 global $ilUser;
02115 if ($ilUser->id > 0)
02116 {
02117 $active = $this->getActiveTestUser($ilUser->id);
02118 $seq = split(",", $active->sequence);
02119 $query = sprintf("SELECT title from qpl_questions WHERE question_id = %s",
02120 $this->ilias->db->quote($this->questions[$seq[$sequence-1]])
02121 );
02122 }
02123 else
02124 {
02125 $query = sprintf("SELECT title from qpl_questions WHERE question_id = %s",
02126 $this->ilias->db->quote($this->questions[$sequence])
02127 );
02128 }
02129 $result = $this->ilias->db->query($query);
02130 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02131 return $row->title;
02132 }
02133
02144 function getQuestionDataset($question_id)
02145 {
02146 $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
02147 $this->ilias->db->quote("$question_id")
02148 );
02149 $result = $this->ilias->db->query($query);
02150 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02151 return $row;
02152 }
02153
02162 function &get_qpl_titles()
02163 {
02164 global $rbacsystem;
02165
02166 $qpl_titles = array();
02167
02168 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl'";
02169 $result = $this->ilias->db->query($query);
02170 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02171 {
02172 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
02173 {
02174 $qpl_titles["$row->obj_id"] = $row->title;
02175 }
02176 }
02177 return $qpl_titles;
02178 }
02179
02188 function &getExistingQuestions()
02189 {
02190 global $ilUser;
02191 $existing_questions = array();
02192 if ($this->isRandomTest())
02193 {
02194 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.test_fi = %s AND tst_test_random_question.user_fi = %s AND tst_test_random_question.question_fi = qpl_questions.question_id",
02195 $this->ilias->db->quote($this->getTestId() . ""),
02196 $this->ilias->db->quote($ilUser->id . "")
02197 );
02198 }
02199 else
02200 {
02201 $query = sprintf("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",
02202 $this->ilias->db->quote($this->getTestId())
02203 );
02204 }
02205 $result = $this->ilias->db->query($query);
02206 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
02207 array_push($existing_questions, $data->original_id);
02208 }
02209 return $existing_questions;
02210 }
02211
02221 function getQuestionType($question_id)
02222 {
02223 if ($question_id < 1)
02224 return -1;
02225 $query = sprintf("SELECT type_tag FROM qpl_questions, qpl_question_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
02226 $this->ilias->db->quote($question_id)
02227 );
02228 $result = $this->ilias->db->query($query);
02229 if ($result->numRows() == 1) {
02230 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02231 return $data->type_tag;
02232 } else {
02233 return "";
02234 }
02235 }
02236
02245 function startWorkingTime ($user_id)
02246 {
02247 $result = "";
02248 if (!($result = $this->getActiveTestUser($user_id))) {
02249 $this->setActiveTestUser();
02250 $result = $this->getActiveTestUser($user_id);
02251 }
02252 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02253 $this->ilias->db->quote($result->active_id),
02254 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02255 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S"))
02256 );
02257 $result = $this->ilias->db->query($q);
02258 return $this->ilias->db->getLastInsertId();
02259 }
02260
02269 function updateWorkingTime($times_id)
02270 {
02271 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
02272 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02273 $this->ilias->db->quote($times_id)
02274 );
02275 $result = $this->ilias->db->query($q);
02276 }
02277
02287 function getQuestionIdFromActiveUserSequence($sequence)
02288 {
02289 $active = $this->getActiveTestUser();
02290 $sequence_array = split(",", $active->sequence);
02291 return $this->questions[$sequence_array[$sequence-1]];
02292 }
02293
02302 function &getAllQuestionsForActiveUser()
02303 {
02304 $result_array = array();
02305 $active = $this->getActiveTestUser();
02306 $sequence_array = split(",", $active->sequence);
02307 $all_questions = &$this->getAllQuestions();
02308 $worked_questions = &$this->getWorkedQuestions();
02309 foreach ($sequence_array as $sequence)
02310 {
02311 if (in_array($this->questions[$sequence], $worked_questions))
02312 {
02313 $all_questions[$this->questions[$sequence]]["worked"] = 1;
02314 }
02315 else
02316 {
02317 $all_questions[$this->questions[$sequence]]["worked"] = 0;
02318 }
02319 array_push($result_array, $all_questions[$this->questions[$sequence]]);
02320 }
02321 return $result_array;
02322 }
02323
02332 function &getWorkedQuestions()
02333 {
02334 global $ilUser;
02335 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s GROUP BY question_fi",
02336 $this->ilias->db->quote($ilUser->id),
02337 $this->ilias->db->quote($this->getTestId())
02338 );
02339 $result = $this->ilias->db->query($query);
02340 $result_array = array();
02341 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02342 {
02343 array_push($result_array, $row->question_fi);
02344 }
02345 return $result_array;
02346 }
02347
02356 function &getAllQuestions()
02357 {
02358 global $ilUser;
02359
02360 if ($this->isRandomTest())
02361 {
02362 $query = sprintf("SELECT qpl_questions.* FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.user_fi = %s AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")",
02363 $this->ilias->db->quote($ilUser->id . "")
02364 );
02365 }
02366 else
02367 {
02368 $query = "SELECT qpl_questions.* FROM qpl_questions, tst_test_question WHERE tst_test_question.question_fi = qpl_questions.question_id AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")";
02369 }
02370 $result = $this->ilias->db->query($query);
02371 $result_array = array();
02372 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
02373 {
02374 $result_array[$row["question_id"]] = $row;
02375 }
02376 return $result_array;
02377 }
02378
02388 function getActiveTestUser($user_id = "")
02389 {
02390 global $ilDB;
02391 global $ilUser;
02392
02393 $db =& $ilDB->db;
02394 if (!$user_id) {
02395 $user_id = $ilUser->id;
02396 }
02397 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
02398 $db->quote($user_id),
02399 $db->quote($this->test_id)
02400 );
02401
02402 $result = $db->query($query);
02403 if ($result->numRows()) {
02404 return $result->fetchRow(DB_FETCHMODE_OBJECT);
02405 } else {
02406 return "";
02407 }
02408 }
02409
02420 function _getActiveTestUser($user_id = "", $test_id = "") {
02421 global $ilDB;
02422 global $ilUser;
02423
02424 $db =& $ilDB->db;
02425 if (!$user_id) {
02426 $user_id = $ilUser->id;
02427 }
02428 if (!$test_id)
02429 {
02430 return "";
02431 }
02432 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
02433 $db->quote($user_id),
02434 $db->quote($test_id)
02435 );
02436
02437 $result = $db->query($query);
02438 if ($result->numRows()) {
02439 return $result->fetchRow(DB_FETCHMODE_OBJECT);
02440 } else {
02441 return "";
02442 }
02443 }
02444
02457 function setActiveTestUser($lastindex = 1, $postpone = "", $addTries = false)
02458 {
02459 global $ilDB;
02460 global $ilUser;
02461
02462 $db =& $ilDB->db;
02463 $old_active = $this->getActiveTestUser();
02464 if ($old_active) {
02465 $sequence = $old_active->sequence;
02466 $postponed = $old_active->postponed;
02467 if ($postpone) {
02468 $sequence_array = split(",", $sequence);
02469 $postpone_sequence = $sequence_array[$postpone-1];
02470 $question_id = $this->questions[$postpone_sequence];
02471 unset($sequence_array[$postpone-1]);
02472 array_push($sequence_array, $postpone_sequence);
02473 $sequence = join(",", $sequence_array);
02474 $postponed .= ",$question_id";
02475 $postponed = preg_replace("/^,/", "", $postponed);
02476 }
02477 $tries = $old_active->tries;
02478 if ($addTries) {
02479 $tries++;
02480 }
02481 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
02482 $db->quote($lastindex),
02483 $db->quote($sequence),
02484 $db->quote($postponed),
02485 $db->quote($tries),
02486 $db->quote($ilUser->id),
02487 $db->quote($this->test_id)
02488 );
02489 } else {
02490 $sequence_arr = array_flip($this->questions);
02491 $sequence = join($sequence_arr, ",");
02492 $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
02493 $db->quote($ilUser->id),
02494 $db->quote($this->test_id),
02495 $db->quote($sequence),
02496 $db->quote(""),
02497 $db->quote($lastindex),
02498 $db->quote(0)
02499 );
02500 }
02501 $db->query($query);
02502 }
02503
02513 function &getTestResult($user_id)
02514 {
02515
02516 if ($this->isRandomTest())
02517 {
02518 $this->loadQuestions($user_id);
02519 }
02520 $add_parameter = "?ref_id=$this->ref_id&cmd=run";
02521 $total_max_points = 0;
02522 $total_reached_points = 0;
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533 $key = 1;
02534 $result_array = array();
02535 foreach ($this->questions as $value)
02536 {
02537
02538
02539 $question =& ilObjTest::_instanciateQuestion($value);
02540
02541 if (is_object($question))
02542 {
02543 $max_points = $question->getMaximumPoints();
02544 $total_max_points += $max_points;
02545 $reached_points = $question->getReachedPoints($user_id, $this->getTestId());
02546 $total_reached_points += $reached_points;
02547 if ($max_points > 0)
02548 {
02549 $percentvalue = $reached_points / $max_points;
02550 }
02551 else
02552 {
02553 $percentvalue = 0;
02554 }
02555 if (count($question->suggested_solutions) == 1)
02556 {
02557 $solution_array = $question->getSuggestedSolution(0);
02558 $href = ASS_Question::_getInternalLinkHref($solution_array["internal_link"]);
02559 }
02560 elseif (count($question->suggested_solutions) > 1)
02561 {
02562 $href = "see_details_for_further_information";
02563 }
02564 else
02565 {
02566 $href = "";
02567 }
02568 $row = array(
02569 "nr" => "$key",
02570 "title" => "<a href=\"" . $this->getCallingScript() . "$add_parameter&evaluation=" . $question->getId() . "\">" . $question->getTitle() . "</a>",
02571 "max" => sprintf("%d", $max_points),
02572 "reached" => sprintf("%d", $reached_points),
02573 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
02574 "solution" => $href,
02575 "type" => $question->getQuestionType(),
02576 "qid" => $question->getId()
02577 );
02578 array_push($result_array, $row);
02579 $key++;
02580 }
02581 }
02582 $result_array["test"]["total_max_points"] = $total_max_points;
02583 $result_array["test"]["total_reached_points"] = $total_reached_points;
02584 if ((!$total_reached_points) or (!$total_max_points))
02585 {
02586 $percentage = 0.0;
02587 }
02588 else
02589 {
02590 $percentage = ($total_reached_points / $total_max_points) * 100.0;
02591 }
02592 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
02593 $passed = "";
02594 if ($mark_obj)
02595 {
02596 if ($mark_obj->get_passed())
02597 {
02598 $passed = 1;
02599 }
02600 else
02601 {
02602 $passed = 0;
02603 }
02604 }
02605 $result_array["test"]["passed"] = $passed;
02606 return $result_array;
02607 }
02608
02618 function &_getTestResult($user_id, $test_obj_id)
02619 {
02620 $test = new ilObjTest($test_obj_id, false);
02621 $test->loadFromDb();
02622 $result =& $test->getTestResult($user_id);
02623 return $result;
02624 }
02625
02638 function _checkCondition($a_exc_id,$a_operator,$a_value)
02639 {
02640 global $ilias;
02641
02642 switch($a_operator)
02643 {
02644 case 'passed':
02645 $result = ilObjTest::_getTestResult($ilias->account->getId(), $a_exc_id);
02646 if ($result["test"]["passed"])
02647 {
02648 return true;
02649 }
02650 else
02651 {
02652 return false;
02653 }
02654 break;
02655 default:
02656 return true;
02657 }
02658 return true;
02659 }
02660
02661
02672 function &_getMark($user_id, $test_obj_id)
02673 {
02674 $test = new ilObjTest($test_obj_id, false);
02675 $test->loadFromDb();
02676 $result =& $test->getTestResult($user_id);
02677 if ($result["test"]["total_max_points"] == 0)
02678 {
02679 $pct = 0;
02680 }
02681 else
02682 {
02683 $pct = ($result["test"]["total_reached_points"] / $result["test"]["total_max_points"]) * 100.0;
02684 }
02685 $mark = $test->mark_schema->get_matching_mark($pct);
02686 return $mark;
02687 }
02688
02694 function assignMetaData(&$a_meta_data)
02695 {
02696 $this->meta_data =& $a_meta_data;
02697 }
02698
02704 function &getMetaData()
02705 {
02706 return $this->meta_data;
02707 }
02708
02712 function initMeta()
02713 {
02714 if (!is_object($this->meta_data))
02715 {
02716 if ($this->getId())
02717 {
02718 $new_meta =& new ilMetaData($this->getType(), $this->getId());
02719 }
02720 else
02721 {
02722 $new_meta =& new ilMetaData();
02723 }
02724 $this->assignMetaData($new_meta);
02725 }
02726 }
02727
02736 function evalTotalPersons()
02737 {
02738 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
02739 $this->ilias->db->quote($this->getTestId())
02740 );
02741 $result = $this->ilias->db->query($q);
02742 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02743 return $row->total;
02744 }
02745
02754 function canViewResults()
02755 {
02756 $result = true;
02757 if ($this->getTestType() == TYPE_ASSESSMENT)
02758 {
02759 if ($this->getReportingDate())
02760 {
02761 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches);
02762 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02763 $now = mktime();
02764 if ($now < $epoch_time)
02765 {
02766 $result = false;
02767 }
02768 }
02769 }
02770 return $result;
02771 }
02772
02781 function evalLoadStatisticalSettings($user_id)
02782 {
02783 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
02784 $this->ilias->db->quote("$user_id")
02785 );
02786 $result = $this->ilias->db->query($q);
02787 if (!$result->numRows())
02788 {
02789 $row = array(
02790 "qworkedthrough" => "1",
02791 "pworkedthrough" => "1",
02792 "timeofwork" => "1",
02793 "atimeofwork" => "1",
02794 "firstvisit" => "1",
02795 "lastvisit" => "1",
02796 "resultspoints" => "1",
02797 "resultsmarks" => "1",
02798 "distancemedian" => "1"
02799 );
02800 }
02801 else
02802 {
02803 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02804 unset($row["eval_settings_id"]);
02805 }
02806 return $row;
02807 }
02808
02817 function evalSaveStatisticalSettings($settings_array, $user_id)
02818 {
02819 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
02820 $this->ilias->db->quote("$user_id")
02821 );
02822 $result = $this->ilias->db->query($q);
02823 if ($result->numRows() > 0)
02824 {
02825 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02826 }
02827 $update = $row["eval_settings_id"];
02828 if (!$update) {
02829 $q = sprintf("INSERT INTO tst_eval_settings ".
02830 "(eval_settings_id, user_fi, qworkedthrough, pworkedthrough, timeofwork, atimeofwork, firstvisit, " .
02831 "lastvisit, resultspoints, resultsmarks, distancemedian, TIMESTAMP) VALUES " .
02832 "(NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
02833 $this->ilias->db->quote("$user_id"),
02834 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
02835 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
02836 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
02837 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
02838 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
02839 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
02840 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
02841 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
02842 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"]))
02843 );
02844 }
02845 else
02846 {
02847 $q = sprintf("UPDATE tst_eval_settings SET ".
02848 "qworkedthrough = %s, pworkedthrough = %s, timeofwork = %s, atimeofwork = %s, firstvisit = %s, " .
02849 "lastvisit = %s, resultspoints = %s, resultsmarks = %s, distancemedian = %s " .
02850 "WHERE eval_settings_id = %s",
02851 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
02852 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
02853 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
02854 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
02855 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
02856 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
02857 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
02858 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
02859 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"])),
02860 $this->ilias->db->quote("$update")
02861 );
02862 }
02863 $result = $this->ilias->db->query($q);
02864 }
02865
02874 function getCompleteWorkingTime($user_id)
02875 {
02876 $q = sprintf("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",
02877 $this->ilias->db->quote($this->getTestId()),
02878 $this->ilias->db->quote($user_id)
02879 );
02880 $result = $this->ilias->db->query($q);
02881 $time = 0;
02882 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02883 {
02884 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
02885 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02886 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
02887 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02888 $time += ($epoch_2 - $epoch_1);
02889 }
02890 return $time;
02891 }
02892
02901 function &evalStatistical($user_id)
02902 {
02903
02904
02905 $test_result =& $this->getTestResult($user_id);
02906 $q = sprintf("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",
02907 $this->ilias->db->quote($this->getTestId()),
02908 $this->ilias->db->quote($user_id)
02909 );
02910 $result = $this->ilias->db->query($q);
02911 $times = array();
02912 $first_visit = "";
02913 $last_visit = "";
02914 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
02915 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
02916 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02917 if (!$first_visit) {
02918 $first_visit = $epoch_1;
02919 }
02920 if ($epoch_1 < $first_visit) {
02921 $first_visit = $epoch_1;
02922 }
02923 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
02924 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02925 if (!$last_visit) {
02926 $last_visit = $epoch_2;
02927 }
02928 if ($epoch_2 > $last_visit) {
02929 $last_visit = $epoch_2;
02930 }
02931 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
02932 }
02933 $max_time = 0;
02934 foreach ($times as $key => $value) {
02935 $max_time += $value;
02936 }
02937 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"])) {
02938 $percentage = 0.0;
02939 } else {
02940 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
02941 }
02942 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
02943 $first_date = getdate($first_visit);
02944 $last_date = getdate($last_visit);
02945 $qworkedthrough = 0;
02946 $query_worked_through = sprintf("SELECT DISTINCT(question_fi) FROM tst_solutions WHERE user_fi = %s AND test_fi = %s",
02947 $this->ilias->db->quote("$user_id"),
02948 $this->ilias->db->quote($this->getTestId())
02949 );
02950 $worked_through_result = $this->ilias->db->query($query_worked_through);
02951 if (!$worked_through_result->numRows())
02952 {
02953 $atimeofwork = 0;
02954 }
02955 else
02956 {
02957 $atimeofwork = $max_time / $worked_through_result->numRows();
02958 }
02959 $result_mark = "";
02960 $passed = "";
02961 if ($mark_obj)
02962 {
02963 $result_mark = $mark_obj->get_short_name();
02964 if ($mark_obj->get_passed())
02965 {
02966 $passed = 1;
02967 }
02968 else
02969 {
02970 $passed = 0;
02971 }
02972 }
02973 $result_array = array(
02974 "qworkedthrough" => $worked_through_result->numRows(),
02975 "qmax" => count($this->questions),
02976 "pworkedthrough" => ($worked_through_result->numRows()) / count($this->questions),
02977 "timeofwork" => $max_time,
02978 "atimeofwork" => $atimeofwork,
02979 "firstvisit" => $first_date,
02980 "lastvisit" => $last_date,
02981 "resultspoints" => $test_result["test"]["total_reached_points"],
02982 "maxpoints" => $test_result["test"]["total_max_points"],
02983 "resultsmarks" => $result_mark,
02984 "passed" => $passed,
02985 "distancemedian" => "0"
02986 );
02987 foreach ($test_result as $key => $value)
02988 {
02989 if (preg_match("/\d+/", $key))
02990 {
02991 $result_array[$key] = $value;
02992 }
02993 }
02994 return $result_array;
02995 }
02996
03006 function &getTotalPointsArray()
03007 {
03008 $totalpoints_array = array();
03009 $all_users =& $this->evalTotalPersonsArray();
03010 foreach ($all_users as $user_id => $user_name)
03011 {
03012 $test_result =& $this->getTestResult($user_id);
03013 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03014 }
03015 return $totalpoints_array;
03016 }
03017
03027 function &getTotalPointsPassedArray()
03028 {
03029 $totalpoints_array = array();
03030 $all_users =& $this->evalTotalPersonsArray();
03031 foreach ($all_users as $user_id => $user_name)
03032 {
03033 $test_result =& $this->getTestResult($user_id);
03034 $reached = $test_result["test"]["total_reached_points"];
03035 $total = $test_result["test"]["total_max_points"];
03036 $percentage = $reached/$total;
03037 $mark = $this->mark_schema->get_matching_mark($percentage*100.0);
03038 if ($mark)
03039 {
03040 if ($mark->get_passed())
03041 {
03042 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03043 }
03044 }
03045 }
03046 return $totalpoints_array;
03047 }
03048
03057 function &evalTotalPersonsArray()
03058 {
03059 $q = sprintf("SELECT tst_active.user_fi, usr_data.firstname, usr_data.lastname FROM tst_active, usr_data WHERE tst_active.test_fi = %s AND tst_active.user_fi = usr_data.usr_id",
03060 $this->ilias->db->quote($this->getTestId())
03061 );
03062 $result = $this->ilias->db->query($q);
03063 $persons_array = array();
03064 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03065 {
03066 $persons_array[$row->user_fi] = trim("$row->firstname $row->lastname");
03067 }
03068 return $persons_array;
03069 }
03070
03079 function evalTotalFinished()
03080 {
03081 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
03082 $this->ilias->db->quote($this->getTestId())
03083 );
03084 $result = $this->ilias->db->query($q);
03085 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03086 return $row->total;
03087 }
03088
03098 function evalTotalFinishedPassed()
03099 {
03100 $q = sprintf("SELECT * FROM tst_active WHERE test_fi = %s AND tries > 0",
03101 $this->ilias->db->quote($this->getTestId())
03102 );
03103 $result = $this->ilias->db->query($q);
03104 $points = array();
03105 $passed_tests = 0;
03106 $failed_tests = 0;
03107 $maximum_points = 0;
03108 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03109 {
03110 $res =& $this->getTestResult($row->user_fi);
03111 if ((!$res["test"]["total_reached_points"]) or (!$res["test"]["total_max_points"]))
03112 {
03113 $percentage = 0.0;
03114 }
03115 else
03116 {
03117 $percentage = ($res["test"]["total_reached_points"] / $res["test"]["total_max_points"]) * 100.0;
03118 }
03119 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03120 $maximum_points = $res["test"]["total_max_points"];
03121 if ($mark_obj)
03122 {
03123 if ($mark_obj->get_passed()) {
03124 $passed_tests++;
03125 array_push($points, $res["test"]["total_reached_points"]);
03126 }
03127 else
03128 {
03129 $failed_tests++;
03130 }
03131 }
03132 }
03133 $reached_points = 0;
03134 $counter = 0;
03135 foreach ($points as $key => $value)
03136 {
03137 $reached_points += $value;
03138 $counter++;
03139 }
03140 if ($counter)
03141 {
03142 $average_points = round($reached_points / $counter);
03143 }
03144 else
03145 {
03146 $average_points = 0;
03147 }
03148 return array(
03149 "total_passed" => $passed_tests,
03150 "total_failed" => $failed_tests,
03151 "average_points" => $average_points,
03152 "maximum_points" => $maximum_points
03153 );
03154 }
03155
03164 function evalTotalFinishedAverageTime()
03165 {
03166 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.tries > 0 AND tst_active.active_id = tst_times.active_fi",
03167 $this->ilias->db->quote($this->getTestId())
03168 );
03169 $result = $this->ilias->db->query($q);
03170 $times = array();
03171 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03172 {
03173 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03174 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03175 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03176 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03177 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03178 }
03179 $max_time = 0;
03180 $counter = 0;
03181 foreach ($times as $key => $value)
03182 {
03183 $max_time += $value;
03184 $counter++;
03185 }
03186 if ($counter)
03187 {
03188 $average_time = round($max_time / $counter);
03189 }
03190 else
03191 {
03192 $average_time = 0;
03193 }
03194 return $average_time;
03195 }
03196
03205 function &getForbiddenQuestionpools()
03206 {
03207 global $rbacsystem;
03208
03209 $forbidden_pools = array();
03210 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl'";
03211 $result = $this->ilias->db->query($query);
03212 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03213 {
03214 if (!$rbacsystem->checkAccess("write", $row->ref_id) || (!$this->_hasUntrashedReference($row->obj_id)))
03215 {
03216 array_push($forbidden_pools, $row->obj_id);
03217 }
03218 }
03219 return $forbidden_pools;
03220 }
03221
03230 function &getAvailableQuestionpools($use_object_id = false)
03231 {
03232 global $rbacsystem;
03233
03234 $result_array = array();
03235 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl' ORDER BY object_data.title";
03236 $result = $this->ilias->db->query($query);
03237 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03238 {
03239 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03240 {
03241 if ($use_object_id)
03242 {
03243 $result_array[$row->obj_id] = $row->title;
03244 }
03245 else
03246 {
03247 $result_array[$row->ref_id] = $row->title;
03248 }
03249 }
03250 }
03251 return $result_array;
03252 }
03253
03262 function getEstimatedWorkingTime()
03263 {
03264 $time_in_seconds = 0;
03265 foreach ($this->questions as $question_id) {
03266 $question =& ilObjTest::_instanciateQuestion($question_id);
03267 $est_time = $question->getEstimatedWorkingTime();
03268 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
03269 }
03270 $hours = (int)($time_in_seconds / 3600) ;
03271 $time_in_seconds = $time_in_seconds - ($hours * 3600);
03272 $minutes = (int)($time_in_seconds / 60);
03273 $time_in_seconds = $time_in_seconds - ($minutes * 60);
03274 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
03275 return $result;
03276 }
03277
03290 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "")
03291 {
03292 global $rbacsystem;
03293 if ($questionpool != 0)
03294 {
03295
03296 if (!$use_obj_id)
03297 {
03298 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
03299 $this->ilias->db->quote("$questionpool")
03300 );
03301 $result = $this->ilias->db->query($query);
03302 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03303 $questionpool = $row[0];
03304 }
03305 }
03306
03307 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
03308 $this->ilias->db->quote($this->getTestId() . "")
03309 );
03310 $result = $this->ilias->db->query($query);
03311 $original_ids = array();
03312 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
03313 {
03314 if (strcmp($row[0], "") != 0)
03315 {
03316 array_push($original_ids, $row[0]);
03317 }
03318 }
03319 $original_clause = "";
03320 if (count($original_ids))
03321 {
03322 $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
03323 }
03324
03325 $forbidden_pools =& $this->getForbiddenQuestionpools();
03326 $forbidden = "";
03327 $constraint_qpls = "";
03328 if (count($forbidden_pools))
03329 {
03330 $forbidden = " AND qpl_questions.obj_fi NOT IN (" . join($forbidden_pools, ",") . ")";
03331 }
03332 $result_array = array();
03333 if ($questionpool == 0)
03334 {
03335 if (is_array($qpls))
03336 {
03337 if (count($qpls) > 0)
03338 {
03339 $qplidx = array();
03340 foreach ($qpls as $idx => $arr)
03341 {
03342 array_push($qplidx, $arr["qpl"]);
03343 }
03344 $constraint_qpls = " AND qpl_questions.obj_fi IN (" . join($qplidx, ",") . ")";
03345 }
03346 }
03347 $query = "SELECT COUNT(question_id) FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$forbidden$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
03348 }
03349 else
03350 {
03351 $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
03352 $this->ilias->db->quote("$questionpool")
03353 );
03354 }
03355 $result = $this->ilias->db->query($query);
03356 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03357 if (($row[0]) <= $nr_of_questions)
03358 {
03359
03360 if ($questionpool == 0)
03361 {
03362 $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$forbidden$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
03363 }
03364 else
03365 {
03366 $query = sprintf("SELECT question_id FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s AND qpl_questions.complete = '1'$original_clause",
03367 $this->ilias->db->quote("$questionpool")
03368 );
03369 }
03370 $result = $this->ilias->db->query($query);
03371 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
03372 {
03373 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
03374 {
03375 $result_array[$row[0]] = $row[0];
03376 }
03377 }
03378 }
03379 else
03380 {
03381
03382 mt_srand((double)microtime()*1000000);
03383 $random_number = mt_rand(0, $row[0] - 1);
03384 $securitycounter = 500;
03385 while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
03386 {
03387 if ($questionpool == 0)
03388 {
03389 $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$forbidden$constraint_qpls AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1";
03390 }
03391 else
03392 {
03393 $query = sprintf("SELECT question_id FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1",
03394 $this->ilias->db->quote("$questionpool")
03395 );
03396 }
03397 $result = $this->ilias->db->query($query);
03398 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03399 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
03400 {
03401 $result_array[$result_row[0]] = $result_row[0];
03402 }
03403 $random_number = mt_rand(0, $row[0] - 1);
03404 $securitycounter--;
03405 }
03406 }
03407 return $result_array;
03408 }
03409
03418 function getImagePath()
03419 {
03420 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
03421 }
03422
03431 function getImagePathWeb()
03432 {
03433 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
03434 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
03435 }
03436
03447 function &createQuestionGUI($question_type, $question_id = -1)
03448 {
03449 if ((!$question_type) and ($question_id > 0))
03450 {
03451 $question_type = $this->getQuestionType($question_id);
03452 }
03453 switch ($question_type)
03454 {
03455 case "qt_multiple_choice_sr":
03456 $question =& new ASS_MultipleChoiceGUI();
03457 $question->object->set_response(RESPONSE_SINGLE);
03458 break;
03459 case "qt_multiple_choice_mr":
03460 $question =& new ASS_MultipleChoiceGUI();
03461 $question->object->set_response(RESPONSE_MULTIPLE);
03462 break;
03463 case "qt_cloze":
03464 $question =& new ASS_ClozeTestGUI();
03465 break;
03466 case "qt_matching":
03467 $question =& new ASS_MatchingQuestionGUI();
03468 break;
03469 case "qt_ordering":
03470 $question =& new ASS_OrderingQuestionGUI();
03471 break;
03472 case "qt_imagemap":
03473 $question =& new ASS_ImagemapQuestionGUI();
03474 break;
03475 case "qt_javaapplet":
03476 $question =& new ASS_JavaAppletGUI();
03477 break;
03478 case "qt_text":
03479 $question =& new ASS_TextQuestionGUI();
03480 break;
03481 }
03482 if ($question_id > 0)
03483 {
03484 $question->object->loadFromDb($question_id);
03485 }
03486 return $question;
03487 }
03488
03498 function &_instanciateQuestion($question_id)
03499 {
03500 if (strcmp($question_id, "") != 0)
03501 {
03502 $question_type = ASS_Question::_getQuestionType($question_id);
03503 switch ($question_type) {
03504 case "qt_cloze":
03505 $question = new ASS_ClozeTest();
03506 break;
03507 case "qt_matching":
03508 $question = new ASS_MatchingQuestion();
03509 break;
03510 case "qt_ordering":
03511 $question = new ASS_OrderingQuestion();
03512 break;
03513 case "qt_imagemap":
03514 $question = new ASS_ImagemapQuestion();
03515 break;
03516 case "qt_multiple_choice_sr":
03517 case "qt_multiple_choice_mr":
03518 $question = new ASS_MultipleChoice();
03519 break;
03520 case "qt_javaapplet":
03521 $question = new ASS_JavaApplet();
03522 break;
03523 case "qt_text":
03524 $question = new ASS_TextQuestion();
03525 break;
03526 }
03527 $question->loadFromDb($question_id);
03528 return $question;
03529 }
03530 }
03531
03542 function moveQuestions($move_questions, $target_index, $insert_mode)
03543 {
03544 $this->questions = array_values($this->questions);
03545 $array_pos = array_search($target_index, $this->questions);
03546 if ($insert_mode == 0)
03547 {
03548 $part1 = array_slice($this->questions, 0, $array_pos);
03549 $part2 = array_slice($this->questions, $array_pos);
03550 }
03551 else if ($insert_mode == 1)
03552 {
03553 $part1 = array_slice($this->questions, 0, $array_pos + 1);
03554 $part2 = array_slice($this->questions, $array_pos + 1);
03555 }
03556 foreach ($move_questions as $question_id)
03557 {
03558 if (!(array_search($question_id, $part1) === FALSE))
03559 {
03560 unset($part1[array_search($question_id, $part1)]);
03561 }
03562 if (!(array_search($question_id, $part2) === FALSE))
03563 {
03564 unset($part2[array_search($question_id, $part2)]);
03565 }
03566 }
03567 $part1 = array_values($part1);
03568 $part2 = array_values($part2);
03569 $new_array = array_values(array_merge($part1, $move_questions, $part2));
03570 $this->questions = array();
03571 $counter = 1;
03572 foreach ($new_array as $question_id)
03573 {
03574 $this->questions[$counter] = $question_id;
03575 $counter++;
03576 }
03577 $this->saveQuestionsToDb();
03578 }
03579
03580
03590 function startingTimeReached()
03591 {
03592 if ($this->getTestType() == TYPE_ASSESSMENT)
03593 {
03594 if ($this->getStartingTime())
03595 {
03596 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches);
03597 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03598 $now = mktime();
03599 if ($now < $epoch_time)
03600 {
03601
03602 return false;
03603 }
03604 }
03605 }
03606 return true;
03607 }
03608
03618 function endingTimeReached()
03619 {
03620 if ($this->getTestType() == TYPE_ASSESSMENT)
03621 {
03622 if ($this->getEndingTime())
03623 {
03624 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches);
03625 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03626 $now = mktime();
03627 if ($now > $epoch_time)
03628 {
03629
03630 return true;
03631 }
03632 }
03633 }
03634 return false;
03635 }
03636
03644 function getQuestionsTable($sortoptions, $filter_text, $sel_filter_type, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
03645 {
03646 global $ilUser;
03647 $where = "";
03648 if (strlen($filter_text) > 0) {
03649 switch($sel_filter_type) {
03650 case "title":
03651 $where = " AND qpl_questions.title LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
03652 break;
03653 case "comment":
03654 $where = " AND qpl_questions.comment LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
03655 break;
03656 case "author":
03657 $where = " AND qpl_questions.author LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
03658 break;
03659 }
03660 }
03661
03662 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
03663 {
03664 $where .= " AND qpl_question_type.type_tag = " . $this->ilias->db->quote($filter_question_type);
03665 }
03666
03667 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
03668 {
03669 $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
03670 }
03671
03672
03673 $order = "";
03674 $images = array();
03675 if (count($sortoptions)) {
03676 foreach ($sortoptions as $key => $value) {
03677 switch($key) {
03678 case "title":
03679 $order = " ORDER BY title $value";
03680 $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03681 break;
03682 case "comment":
03683 $order = " ORDER BY comment $value";
03684 $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03685 break;
03686 case "type":
03687 $order = " ORDER BY question_type_id $value";
03688 $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03689 break;
03690 case "author":
03691 $order = " ORDER BY author $value";
03692 $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03693 break;
03694 case "created":
03695 $order = " ORDER BY created $value";
03696 $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03697 break;
03698 case "updated":
03699 $order = " ORDER BY TIMESTAMP $value";
03700 $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03701 break;
03702 case "qpl":
03703 $order = " ORDER BY obj_fi $value";
03704 $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
03705 break;
03706 }
03707 }
03708 }
03709 $maxentries = $ilUser->prefs["hits_per_page"];
03710 if ($maxentries < 1)
03711 {
03712 $maxentries = 9999;
03713 }
03714 $forbidden_pools =& $this->getForbiddenQuestionpools();
03715 $forbidden = "";
03716 if (count($forbidden_pools))
03717 {
03718 $forbidden = " AND qpl_questions.obj_fi NOT IN (" . join($forbidden_pools, ",") . ")";
03719 }
03720 if ($completeonly)
03721 {
03722 $forbidden .= " AND qpl_questions.complete = " . $this->ilias->db->quote("1");
03723 }
03724
03725
03726 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
03727 $this->ilias->db->quote($this->getTestId() . "")
03728 );
03729 $result = $this->ilias->db->query($query);
03730 $original_ids = array();
03731 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
03732 {
03733 if (strcmp($row[0], "") != 0)
03734 {
03735 array_push($original_ids, $row[0]);
03736 }
03737 }
03738 $original_clause = " ISNULL(qpl_questions.original_id)";
03739 if (count($original_ids))
03740 {
03741 $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
03742 }
03743
03744 $query = "SELECT qpl_questions.question_id FROM qpl_questions, qpl_question_type WHERE $original_clause$forbidden AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
03745 $query_result = $this->ilias->db->query($query);
03746 $max = $query_result->numRows();
03747 if ($startrow > $max -1)
03748 {
03749 $startrow = $max - ($max % $maxentries);
03750 }
03751 else if ($startrow < 0)
03752 {
03753 $startrow = 0;
03754 }
03755 $limit = " LIMIT $startrow, $maxentries";
03756 $query = "SELECT qpl_questions.*, qpl_question_type.type_tag, object_reference.ref_id FROM qpl_questions, qpl_question_type, object_reference WHERE $original_clause AND qpl_questions.obj_fi = object_reference.obj_id$forbidden AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
03757 $query_result = $this->ilias->db->query($query);
03758 $rows = array();
03759 if ($query_result->numRows())
03760 {
03761 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
03762 {
03763 array_push($rows, $row);
03764 }
03765 }
03766 $nextrow = $startrow + $maxentries;
03767 if ($nextrow > $max - 1)
03768 {
03769 $nextrow = $startrow;
03770 }
03771 $prevrow = $startrow - $maxentries;
03772 if ($prevrow < 0)
03773 {
03774 $prevrow = 0;
03775 }
03776 return array(
03777 "rows" => $rows,
03778 "images" => $images,
03779 "startrow" => $startrow,
03780 "nextrow" => $nextrow,
03781 "prevrow" => $prevrow,
03782 "step" => $maxentries,
03783 "rowcount" => $max
03784 );
03785 }
03786
03796 function _getTestType($test_id)
03797 {
03798 global $ilDB;
03799
03800 $result = "";
03801 $query = sprintf("SELECT tst_test_type.type_tag FROM tst_test_type, tst_tests WHERE tst_test_type.test_type_id = tst_tests.test_type_fi AND tst_tests.test_id = %s",
03802 $ilDB->quote($test_id)
03803 );
03804 $query_result = $ilDB->query($query);
03805 if ($query_result->numRows())
03806 {
03807 $row = $query_result->fetchRow(DB_FETCHMODE_ASSOC);
03808 $result = $row["type_tag"];
03809 }
03810 return $result;
03811 }
03812
03821 function &_getQuestiontypes()
03822 {
03823 global $ilDB;
03824
03825 $questiontypes = array();
03826 $query = "SELECT * FROM qpl_question_type ORDER BY type_tag";
03827 $query_result = $ilDB->query($query);
03828 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
03829 {
03830 array_push($questiontypes, $row["type_tag"]);
03831 }
03832 return $questiontypes;
03833 }
03834
03843 function to_xml()
03844 {
03845 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
03846 $domxml = domxml_open_mem($xml_header);
03847 $root = $domxml->document_element();
03848
03849 $qtiAssessment = $domxml->create_element("assessment");
03850 $qtiAssessment->set_attribute("ident", "il_".IL_INST_ID."_tst_".$this->getTestId());
03851 $qtiAssessment->set_attribute("title", $this->getTitle());
03852
03853
03854 $qtiComment = $domxml->create_element("qticomment");
03855 $qtiCommentText = $domxml->create_text_node($this->getDescription());
03856 $qtiComment->append_child($qtiCommentText);
03857 $qtiAssessment->append_child($qtiComment);
03858 $qtiComment = $domxml->create_element("qticomment");
03859 $qtiCommentText = $domxml->create_text_node("ILIAS Version=".$this->ilias->getSetting("ilias_version"));
03860 $qtiComment->append_child($qtiCommentText);
03861 $qtiAssessment->append_child($qtiComment);
03862 $qtiComment = $domxml->create_element("qticomment");
03863 $qtiCommentText = $domxml->create_text_node("Author=".$this->getAuthor());
03864 $qtiComment->append_child($qtiCommentText);
03865 $qtiAssessment->append_child($qtiComment);
03866
03867 if ($this->enable_processing_time)
03868 {
03869 $qtiDuration = $domxml->create_element("duration");
03870 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
03871 $qtiDurationText = $domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
03872 $qtiDuration->append_child($qtiDurationText);
03873 $qtiAssessment->append_child($qtiDuration);
03874 }
03875
03876 $qtiAssessmentcontrol = $domxml->create_element("assessmentcontrol");
03877 $qtiAssessmentcontrol->set_attribute("solutionswitch", sprintf("%d", $this->getScoreReporting()));
03878 $qtiAssessment->append_child($qtiAssessmentcontrol);
03879
03880 $qtiObjectives = $domxml->create_element("objectives");
03881 $qtiMaterial = $domxml->create_element("material");
03882 $qtiMaterial->set_attribute("label", "introduction");
03883 $qtiMatText = $domxml->create_element("mattext");
03884 $qtiMatTextText = $domxml->create_text_node($this->getIntroduction());
03885 $qtiMatText->append_child($qtiMatTextText);
03886 $qtiMaterial->append_child($qtiMatText);
03887 $qtiObjectives->append_child($qtiMaterial);
03888 $qtiAssessment->append_child($qtiObjectives);
03889
03890 $qtiMetadata = $domxml->create_element("qtimetadata");
03891
03892 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03893 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03894 $qtiFieldLabelText = $domxml->create_text_node("test_type");
03895 $qtiFieldLabel->append_child($qtiFieldLabelText);
03896 $qtiFieldEntry = $domxml->create_element("fieldentry");
03897 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getTestType()));
03898 $qtiFieldEntry->append_child($qtiFieldEntryText);
03899 $qtiMetadatafield->append_child($qtiFieldLabel);
03900 $qtiMetadatafield->append_child($qtiFieldEntry);
03901 $qtiMetadata->append_child($qtiMetadatafield);
03902
03903 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03904 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03905 $qtiFieldLabelText = $domxml->create_text_node("sequence_settings");
03906 $qtiFieldLabel->append_child($qtiFieldLabelText);
03907 $qtiFieldEntry = $domxml->create_element("fieldentry");
03908 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getSequenceSettings()));
03909 $qtiFieldEntry->append_child($qtiFieldEntryText);
03910 $qtiMetadatafield->append_child($qtiFieldLabel);
03911 $qtiMetadatafield->append_child($qtiFieldEntry);
03912 $qtiMetadata->append_child($qtiMetadatafield);
03913
03914 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03915 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03916 $qtiFieldLabelText = $domxml->create_text_node("author");
03917 $qtiFieldLabel->append_child($qtiFieldLabelText);
03918 $qtiFieldEntry = $domxml->create_element("fieldentry");
03919 $qtiFieldEntryText = $domxml->create_text_node($this->getAuthor());
03920 $qtiFieldEntry->append_child($qtiFieldEntryText);
03921 $qtiMetadatafield->append_child($qtiFieldLabel);
03922 $qtiMetadatafield->append_child($qtiFieldEntry);
03923 $qtiMetadata->append_child($qtiMetadatafield);
03924
03925 if ($this->getReportingDate())
03926 {
03927 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03928 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03929 $qtiFieldLabelText = $domxml->create_text_node("reporting_date");
03930 $qtiFieldLabel->append_child($qtiFieldLabelText);
03931 $qtiFieldEntry = $domxml->create_element("fieldentry");
03932 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
03933 $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
03934 $qtiFieldEntry->append_child($qtiFieldEntryText);
03935 $qtiMetadatafield->append_child($qtiFieldLabel);
03936 $qtiMetadatafield->append_child($qtiFieldEntry);
03937 $qtiMetadata->append_child($qtiMetadatafield);
03938 }
03939
03940 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03941 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03942 $qtiFieldLabelText = $domxml->create_text_node("nr_of_tries");
03943 $qtiFieldLabel->append_child($qtiFieldLabelText);
03944 $qtiFieldEntry = $domxml->create_element("fieldentry");
03945 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getNrOfTries()));
03946 $qtiFieldEntry->append_child($qtiFieldEntryText);
03947 $qtiMetadatafield->append_child($qtiFieldLabel);
03948 $qtiMetadatafield->append_child($qtiFieldEntry);
03949 $qtiMetadata->append_child($qtiMetadatafield);
03950
03951 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03952 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03953 $qtiFieldLabelText = $domxml->create_text_node("random_test");
03954 $qtiFieldLabel->append_child($qtiFieldLabelText);
03955 $qtiFieldEntry = $domxml->create_element("fieldentry");
03956 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->isRandomTest()));
03957 $qtiFieldEntry->append_child($qtiFieldEntryText);
03958 $qtiMetadatafield->append_child($qtiFieldLabel);
03959 $qtiMetadatafield->append_child($qtiFieldEntry);
03960 $qtiMetadata->append_child($qtiMetadatafield);
03961
03962 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03963 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03964 $qtiFieldLabelText = $domxml->create_text_node("random_question_count");
03965 $qtiFieldLabel->append_child($qtiFieldLabelText);
03966 $qtiFieldEntry = $domxml->create_element("fieldentry");
03967 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getRandomQuestionCount()));
03968 $qtiFieldEntry->append_child($qtiFieldEntryText);
03969 $qtiMetadatafield->append_child($qtiFieldLabel);
03970 $qtiMetadatafield->append_child($qtiFieldEntry);
03971 $qtiMetadata->append_child($qtiMetadatafield);
03972
03973 if ($this->getStartingTime())
03974 {
03975 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03976 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03977 $qtiFieldLabelText = $domxml->create_text_node("starting_time");
03978 $qtiFieldLabel->append_child($qtiFieldLabelText);
03979 $qtiFieldEntry = $domxml->create_element("fieldentry");
03980 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
03981 $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
03982 $qtiFieldEntry->append_child($qtiFieldEntryText);
03983 $qtiMetadatafield->append_child($qtiFieldLabel);
03984 $qtiMetadatafield->append_child($qtiFieldEntry);
03985 $qtiMetadata->append_child($qtiMetadatafield);
03986 }
03987
03988 if ($this->getEndingTime())
03989 {
03990 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
03991 $qtiFieldLabel = $domxml->create_element("fieldlabel");
03992 $qtiFieldLabelText = $domxml->create_text_node("ending_time");
03993 $qtiFieldLabel->append_child($qtiFieldLabelText);
03994 $qtiFieldEntry = $domxml->create_element("fieldentry");
03995 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
03996 $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
03997 $qtiFieldEntry->append_child($qtiFieldEntryText);
03998 $qtiMetadatafield->append_child($qtiFieldLabel);
03999 $qtiMetadatafield->append_child($qtiFieldEntry);
04000 $qtiMetadata->append_child($qtiMetadatafield);
04001 }
04002 foreach ($this->mark_schema->mark_steps as $index => $mark)
04003 {
04004
04005 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04006 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04007 $qtiFieldLabelText = $domxml->create_text_node("mark_step_$index");
04008 $qtiFieldLabel->append_child($qtiFieldLabelText);
04009 $qtiFieldEntry = $domxml->create_element("fieldentry");
04010 $qtiFieldEntryText = $domxml->create_text_node(sprintf("<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>", $mark->get_short_name(), $mark->get_official_name(), $mark->get_minimum_level(), $mark->get_passed()));
04011 $qtiFieldEntry->append_child($qtiFieldEntryText);
04012 $qtiMetadatafield->append_child($qtiFieldLabel);
04013 $qtiMetadatafield->append_child($qtiFieldEntry);
04014 $qtiMetadata->append_child($qtiMetadatafield);
04015 }
04016 $qtiAssessment->append_child($qtiMetadata);
04017 $root->append_child($qtiAssessment);
04018 $xml = $domxml->dump_mem(true);
04019 $domxml->free();
04020 foreach ($this->questions as $question_id) {
04021 $question =& ilObjTest::_instanciateQuestion($question_id);
04022 $qti_question = $question->to_xml(false);
04023 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
04024 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
04025 $xml = str_replace("</questestinterop>", "$qti_question</questestinterop>", $xml);
04026 }
04027 return $xml;
04028 }
04029
04036 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
04037 {
04038 global $ilBench;
04039
04040 $this->mob_ids = array();
04041 $this->file_ids = array();
04042
04043 $attrs = array();
04044 $attrs["Type"] = "Test";
04045 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
04046
04047
04048 $this->exportXMLMetaData($a_xml_writer);
04049
04050
04051 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
04052 $ilBench->start("ContentObjectExport", "exportPageObjects");
04053 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
04054 $ilBench->stop("ContentObjectExport", "exportPageObjects");
04055 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
04056
04057
04058 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
04059 $ilBench->start("ContentObjectExport", "exportMediaObjects");
04060 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
04061 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
04062 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
04063
04064
04065 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
04066 $ilBench->start("ContentObjectExport", "exportFileItems");
04067 $this->exportFileItems($a_target_dir, $expLog);
04068 $ilBench->stop("ContentObjectExport", "exportFileItems");
04069 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
04070
04071 $a_xml_writer->xmlEndTag("ContentObject");
04072 }
04073
04080 function exportXMLMetaData(&$a_xml_writer)
04081 {
04082 $nested = new ilNestedSetXML();
04083 $nested->setParameterModifier($this, "modifyExportIdentifier");
04084 $a_xml_writer->appendXML($nested->export($this->getId(),
04085 $this->getType()));
04086 }
04087
04095 function modifyExportIdentifier($a_tag, $a_param, $a_value)
04096 {
04097 if ($a_tag == "Identifier" && $a_param == "Entry")
04098 {
04099 $a_value = ilUtil::insertInstIntoID($a_value);
04100 }
04101
04102 return $a_value;
04103 }
04104
04105
04112 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
04113 {
04114 global $ilBench;
04115
04116 include_once "./content/classes/class.ilLMPageObject.php";
04117
04118 foreach ($this->questions as $question_id)
04119 {
04120 $ilBench->start("ContentObjectExport", "exportPageObject");
04121 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
04122
04123 $attrs = array();
04124 $a_xml_writer->xmlStartTag("PageObject", $attrs);
04125
04126
04127
04128 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
04129 $page_object = new ilPageObject("qpl", $question_id);
04130 $page_object->buildDom();
04131 $page_object->insertInstIntoIDs($a_inst);
04132 $mob_ids = $page_object->collectMediaObjects(false);
04133 $file_ids = $page_object->collectFileItems();
04134 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
04135 $xml = str_replace("&","&", $xml);
04136 $a_xml_writer->appendXML($xml);
04137 $page_object->freeDom();
04138 unset ($page_object);
04139
04140 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
04141
04142
04143 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
04144
04145 foreach($mob_ids as $mob_id)
04146 {
04147 $this->mob_ids[$mob_id] = $mob_id;
04148 }
04149 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
04150
04151
04152 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
04153
04154 foreach($file_ids as $file_id)
04155 {
04156 $this->file_ids[$file_id] = $file_id;
04157 }
04158 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
04159
04160 $a_xml_writer->xmlEndTag("PageObject");
04161
04162
04163 $ilBench->stop("ContentObjectExport", "exportPageObject");
04164
04165
04166 }
04167 }
04168
04175 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
04176 {
04177 include_once("content/classes/Media/class.ilObjMediaObject.php");
04178
04179 foreach ($this->mob_ids as $mob_id)
04180 {
04181 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
04182 $media_obj = new ilObjMediaObject($mob_id);
04183 $media_obj->exportXML($a_xml_writer, $a_inst);
04184 $media_obj->exportFiles($a_target_dir);
04185 unset($media_obj);
04186 }
04187 }
04188
04193 function exportFileItems($a_target_dir, &$expLog)
04194 {
04195 include_once("classes/class.ilObjFile.php");
04196
04197 foreach ($this->file_ids as $file_id)
04198 {
04199 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
04200 $file_obj = new ilObjFile($file_id, false);
04201 $file_obj->export($a_target_dir);
04202 unset($file_obj);
04203 }
04204 }
04205
04214 function from_xml($xml_text)
04215 {
04216 $result = false;
04217 $this->mark_schema->flush();
04218 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
04219 $domxml = domxml_open_mem($xml_text);
04220 if (!empty($domxml))
04221 {
04222 $root = $domxml->document_element();
04223 $this->setTitle($root->get_attribute("title"));
04224 $item = $root;
04225 $itemnodes = $item->child_nodes();
04226 foreach ($itemnodes as $index => $node)
04227 {
04228 switch ($node->node_name())
04229 {
04230 case "qticomment":
04231 $comment = $node->get_content();
04232 if (strpos($comment, "Author=") !== false)
04233 {
04234 $comment = str_replace("Author=", "", $comment);
04235 $this->setAuthor($comment);
04236 }
04237 elseif (strpos($comment, "ILIAS Version=") !== false)
04238 {
04239 }
04240 else
04241 {
04242 $this->setDescription($comment);
04243 }
04244 break;
04245 case "duration":
04246 $iso8601period = $node->get_content();
04247 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04248 {
04249 $this->enable_processing_time = 1;
04250 $this->setProcessingTime(sprintf("%02d:%02d:%02d", $matches[4], $matches[5], $matches[6]));
04251 }
04252 break;
04253 case "assessmentcontrol":
04254 $this->setScoreReporting($node->get_attribute("solutionswitch"));
04255 break;
04256 case "objectives":
04257 $material = $node->first_child();
04258 if (strcmp($material->get_attribute("label"), "introduction") == 0)
04259 {
04260 $mattext = $material->first_child();
04261 $this->setIntroduction($mattext->get_content());
04262 }
04263 break;
04264 case "qtimetadata":
04265 $metadata_fields = $node->child_nodes();
04266 foreach ($metadata_fields as $index => $metadata_field)
04267 {
04268 $fieldlabel = $metadata_field->first_child();
04269 $fieldentry = $fieldlabel->next_sibling();
04270 switch ($fieldlabel->get_content())
04271 {
04272 case "sequence_settings":
04273 $this->setSequenceSettings($fieldentry->get_content());
04274 break;
04275 case "author":
04276 $this->setAuthor($fieldentry->get_content());
04277 break;
04278 case "test_type":
04279 $this->setTestType($fieldentry->get_content());
04280 break;
04281 case "reporting_date":
04282 $iso8601period = $fieldentry->get_content();
04283 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04284 {
04285 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04286 }
04287 break;
04288 case "nr_of_tries":
04289 $this->setNrOfTries($fieldentry->get_content());
04290 break;
04291 case "random_test":
04292 $this->setRandomTest($fieldentry->get_content());
04293 break;
04294 case "random_question_count":
04295 $this->setRandomQuestionCount($fieldentry->get_content());
04296 break;
04297 case "starting_time":
04298 $iso8601period = $fieldentry->get_content();
04299 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04300 {
04301 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04302 }
04303 break;
04304 case "ending_time":
04305 $iso8601period = $fieldentry->get_content();
04306 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04307 {
04308 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04309 }
04310 break;
04311 }
04312 if (preg_match("/mark_step_\d+/", $fieldlabel->get_content()))
04313 {
04314 $xmlmark = $fieldentry->get_content();
04315 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
04316 $mark_short = $matches[1];
04317 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
04318 $mark_official = $matches[1];
04319 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
04320 $mark_percentage = $matches[1];
04321 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
04322 $mark_passed = $matches[1];
04323 $this->mark_schema->add_mark_step($mark_short, $mark_official, $mark_percentage, $mark_passed);
04324 }
04325 }
04326 break;
04327 }
04328 }
04329 $result = true;
04330 }
04331 return $result;
04332 }
04333
04342 function importObject($source, $questionpool_id)
04343 {
04344 $ilias_version = "";
04345 $error = 0;
04346 if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK)
04347 {
04348
04349 $error = 1;
04350 }
04351
04352
04353 if (!$error)
04354 {
04355
04356 $fh = fopen($source, "r");
04357 if (!$fh)
04358 {
04359
04360 $error = 1;
04361 return $error;
04362 }
04363
04364 $xml = fread($fh, filesize($source));
04365 $result = fclose($fh);
04366 if (!$result)
04367 {
04368
04369 $error = 1;
04370 return $error;
04371 }
04372
04373 $assessment_part = "";
04374 if (preg_match("/ILIAS Version\=(\d+)\.(\d+)\.?(\d?)/", $xml, $matches))
04375 {
04376 $major_version = $matches[1];
04377 unset($matches[0]);
04378 $ilias_version = join($matches, ".");
04379 if ($major_version == 2)
04380 {
04381 $this->setTestType(TYPE_SELF_ASSESSMENT);
04382 global $lng;
04383 $lng->loadLanguageModule("assessment");
04384 $this->setTitle($lng->txt("imported_test"));
04385 $assessment_part = $this->to_xml();
04386 if (preg_match("/(<assessment[^>]*>.*?<\/assessment>)/si", $assessment_part, $matches))
04387 {
04388 $assessment_part = $matches[1];
04389 }
04390 }
04391 }
04392
04393 $found_assessment = preg_match("/(<assessment[^>]*>.*?<\/assessment>)/si", $xml, $matches);
04394 if ($found_assessment or $assessment_part)
04395 {
04396 if ((!$found_assessment) and ($assessment_part))
04397 {
04398 $matches[1] = $assessment_part;
04399 }
04400
04401 $succeeded = $this->from_xml($matches[1]);
04402
04403 if (!$succeeded)
04404 {
04405
04406 $error = 1;
04407 return $error;
04408 }
04409 }
04410 else
04411 {
04412
04413 $error = 1;
04414 return $error;
04415 }
04416
04417 $question_counter = 1;
04418
04419 $this->import_mapping = array();
04420
04421 if (preg_match_all("/(<item[^>]*>.*?<\/item>)/si", $xml, $matches))
04422 {
04423
04424 foreach ($matches[1] as $index => $item)
04425 {
04426
04427 if (preg_match("/(<item[^>]*>)/is", $item, $start_tag))
04428 {
04429 if (preg_match("/(ident=\"([^\"]*)\")/is", $start_tag[1], $ident))
04430 {
04431 $ident = $ident[2];
04432 }
04433 }
04434
04435 $question = "";
04436 if (preg_match("/<qticomment>Questiontype\=(.*?)<\/qticomment>/is", $item, $questiontype))
04437 {
04438 switch ($questiontype[1])
04439 {
04440 case CLOZE_TEST_IDENTIFIER:
04441 $question = new ASS_ClozeTest();
04442 break;
04443 case IMAGEMAP_QUESTION_IDENTIFIER:
04444 $question = new ASS_ImagemapQuestion();
04445 break;
04446 case MATCHING_QUESTION_IDENTIFIER:
04447 $question = new ASS_MatchingQuestion();
04448 break;
04449 case MULTIPLE_CHOICE_QUESTION_IDENTIFIER:
04450 $question = new ASS_MultipleChoice();
04451 break;
04452 case ORDERING_QUESTION_IDENTIFIER:
04453 $question = new ASS_OrderingQuestion();
04454 break;
04455 case JAVAAPPLET_QUESTION_IDENTIFIER:
04456 $question = new ASS_JavaApplet();
04457 break;
04458 case TEXT_QUESTION_IDENTIFIER:
04459 $question = new ASS_TextQuestion();
04460 break;
04461 }
04462 if ($question)
04463 {
04464 $question->setObjId($questionpool_id);
04465 if ($question->from_xml("<questestinterop>$item</questestinterop>"))
04466 {
04467 $question->saveToDb();
04468 $q_1_id = $question->getId();
04469 $question_id = $question->duplicate(true);
04470 $this->questions[$question_counter++] = $question_id;
04471 $this->import_mapping[$ident] = array(
04472 "pool" => $q_1_id, "test" => $question_id);
04473 }
04474 else
04475 {
04476 $this->ilias->raiseError($this->lng->txt("error_importing_question"), $this->ilias->error_obj->MESSAGE);
04477 }
04478 }
04479 }
04480 }
04481 }
04482 }
04483
04484 $result = array(
04485 "error" => $error,
04486 "version" => $ilias_version
04487 );
04488 return $result;
04489 }
04490
04495 function getImportMapping()
04496 {
04497 if (!is_array($this->import_mapping))
04498 {
04499 return array();
04500 }
04501 else
04502 {
04503 return $this->import_mapping;
04504 }
04505 }
04506
04507 function getECTSGrade($reached_points, $max_points)
04508 {
04509 require_once "./classes/class.ilStatistics.php";
04510
04511 $passed_statistics = new ilStatistics();
04512 $passed_array =& $this->getTotalPointsPassedArray();
04513 $passed_statistics->setData($passed_array);
04514 $ects_percentiles = array
04515 (
04516 "A" => $passed_statistics->quantile($this->ects_grades["A"]),
04517 "B" => $passed_statistics->quantile($this->ects_grades["B"]),
04518 "C" => $passed_statistics->quantile($this->ects_grades["C"]),
04519 "D" => $passed_statistics->quantile($this->ects_grades["D"]),
04520 "E" => $passed_statistics->quantile($this->ects_grades["E"])
04521 );
04522 if ($reached_points >= $ects_percentiles["A"])
04523 {
04524 return "A";
04525 }
04526 else if ($reached_points >= $ects_percentiles["B"])
04527 {
04528 return "B";
04529 }
04530 else if ($reached_points >= $ects_percentiles["C"])
04531 {
04532 return "C";
04533 }
04534 else if ($reached_points >= $ects_percentiles["D"])
04535 {
04536 return "D";
04537 }
04538 else if ($reached_points >= $ects_percentiles["E"])
04539 {
04540 return "E";
04541 }
04542 else if (strcmp($this->ects_fx, "") != 0)
04543 {
04544 if ($max_points > 0)
04545 {
04546 $percentage = ($reached_points / $max_points) * 100.0;
04547 }
04548 else
04549 {
04550 $percentage = 0.0;
04551 }
04552 if ($percentage >= $this->object->ects_fx)
04553 {
04554 return "FX";
04555 }
04556 else
04557 {
04558 return "F";
04559 }
04560 }
04561 else
04562 {
04563 return "F";
04564 }
04565 }
04566
04567 function checkMarks()
04568 {
04569 return $this->mark_schema->checkMarks();
04570 }
04571
04575 function updateTitleAndDescription()
04576 {
04577 $this->initMeta();
04578 $this->meta_data->updateTitleAndDescription($this->getTitle(), $this->getDescription());
04579 }
04580
04584 function updateMetaData()
04585 {
04586 $this->initMeta();
04587 $this->meta_data->update();
04588 if ($this->meta_data->section != "General")
04589 {
04590 $meta = $this->meta_data->getElement("Title", "General");
04591 $this->meta_data->setTitle($meta[0]["value"]);
04592 $meta = $this->meta_data->getElement("Description", "General");
04593 $this->meta_data->setDescription($meta[0]["value"]);
04594 }
04595 else
04596 {
04597 $this->setTitle($this->meta_data->getTitle());
04598 $this->setDescription($this->meta_data->getDescription());
04599 }
04600 parent::update();
04601 }
04602
04611 function &_getAvailableTests($use_object_id = false)
04612 {
04613 global $rbacsystem;
04614 global $ilDB;
04615
04616 $result_array = array();
04617 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'tst' ORDER BY object_data.title";
04618 $result = $ilDB->query($query);
04619 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04620 {
04621 if ($rbacsystem->checkAccess("write", $row->ref_id) && (ilObject::_hasUntrashedReference($row->obj_id)))
04622 {
04623 if ($use_object_id)
04624 {
04625 $result_array[$row->obj_id] = $row->title;
04626 }
04627 else
04628 {
04629 $result_array[$row->ref_id] = $row->title;
04630 }
04631 }
04632 }
04633 return $result_array;
04634 }
04635
04644 function cloneRandomQuestions($new_id)
04645 {
04646 if ($new_id > 0)
04647 {
04648 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
04649 $this->ilias->db->quote($this->getTestId() . "")
04650 );
04651 $result = $this->ilias->db->query($query);
04652 if ($result->numRows())
04653 {
04654 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04655 {
04656 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
04657 $this->ilias->db->quote($new_id . ""),
04658 $this->ilias->db->quote($row["questionpool_fi"] . ""),
04659 $this->ilias->db->quote($row["num_of_q"] . "")
04660 );
04661 $insertresult = $this->ilias->db->query($query);
04662 }
04663 }
04664 }
04665 }
04666
04667
04675 function _clone($obj_id)
04676 {
04677 $original = new ilObjTest($obj_id, false);
04678 $original->loadFromDb();
04679
04680 $newObj = new ilObjTest();
04681 $newObj->setType("tst");
04682 $counter = 2;
04683 while ($newObj->testTitleExists($newObj->getTitle() . " ($counter)"))
04684 {
04685 $counter++;
04686 }
04687 $newObj->setTitle($original->getTitle() . " ($counter)");
04688 $newObj->setDescription($original->getDescription());
04689 $newObj->create(true);
04690 $newObj->createReference();
04691 $newObj->putInTree($_GET["ref_id"]);
04692 $newObj->setPermissions($_GET["ref_id"]);
04693
04694
04695 $newObj->$author = $original->getAuthor();
04696 $newObj->introduction = $original->getIntroduction();
04697 $newObj->mark_schema = $original->mark_schema;
04698 $newObj->sequence_settings = $original->getSequenceSettings();
04699 $newObj->score_reporting = $original->getScoreReporting();
04700 $newObj->reporting_date = $original->getReportingDate();
04701 $newObj->test_type = $original->getTestType();
04702 $newObj->nr_of_tries = $original->getNrOfTries();
04703 $newObj->processing_time = $original->getProcessingTime();
04704 $newObj->enable_processing_time = $original->getEnableProcessingTime();
04705 $newObj->starting_time = $original->getStartingTime();
04706 $newObj->ending_time = $original->getEndingTime();
04707 $newObj->ects_output = $original->ects_output;
04708 $newObj->ects_fx = $original->ects_fx;
04709 $newObj->ects_grades = $original->ects_grades;
04710 $newObj->random_test = $original->random_test;
04711 $newObj->random_question_count = $original->random_question_count;
04712 $newObj->saveToDb();
04713 if ($original->isRandomTest())
04714 {
04715 $newObj->saveRandomQuestionCount($newObj->random_question_count);
04716 $original->cloneRandomQuestions($newObj->getTestId());
04717 }
04718 else
04719 {
04720
04721 foreach ($original->questions as $key => $question_id)
04722 {
04723 $question = ilObjTest::_instanciateQuestion($question_id);
04724 $newObj->questions[$key] = $question->duplicate();
04725
04726 $original_id = ASS_Question::_getOriginalId($question_id);
04727 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
04728 $question->saveToDb($original_id);
04729 }
04730 }
04731
04732 $newObj->saveToDb();
04733
04734 $meta_data =& new ilMetaData($original->getType(), $original->getId());
04735 include_once("./classes/class.ilNestedSetXML.php");
04736 $nested = new ilNestedSetXML();
04737 $nested->dom = domxml_open_mem($meta_data->nested_obj->dom->dump_mem(0));
04738 $nodes = $nested->getDomContent("//MetaData/General", "Identifier");
04739 if (is_array($nodes))
04740 {
04741 $nodes[0]["Entry"] = "il__" . $newObj->getType() . "_" . $newObj->getId();
04742 $nested->updateDomContent("//MetaData/General", "Identifier", 0, $nodes[0]);
04743 }
04744 $xml = $nested->dom->dump_mem(0);
04745 $nested->import($xml, $newObj->getId(), $newObj->getType());
04746 }
04747
04748 function _getRefIdFromObjId($obj_id)
04749 {
04750 global $ilDB;
04751
04752 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
04753 $ilDB->quote($obj_id)
04754
04755 );
04756 $result = $ilDB->query($query);
04757 if ($result->numRows())
04758 {
04759 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
04760 return $row["ref_id"];
04761 }
04762 return 0;
04763 }
04764
04765 function createRandomSolutionsForAllUsers()
04766 {
04767 global $ilDB;
04768 global $ilUser;
04769
04770 $db =& $ilDB->db;
04771 $sequence_arr = array_flip($this->questions);
04772 $sequence = join($sequence_arr, ",");
04773 require_once("./classes/class.ilObjUser.php");
04774 $logins = ilObjUser::_getAllUserData(array("login"));
04775
04776 foreach ($logins as $login)
04777 {
04778 $user_id = $login["usr_id"];
04779 $old_active = $this->getActiveTestUser($user_id);
04780 if ($old_active) {
04781 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
04782 $db->quote("0"),
04783 $db->quote($sequence),
04784 $db->quote(""),
04785 $db->quote("1"),
04786 $db->quote($user_id),
04787 $db->quote($this->getTestId())
04788 );
04789 } else {
04790 $sequence_arr = array_flip($this->questions);
04791 $sequence = join($sequence_arr, ",");
04792 $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
04793 $db->quote($user_id),
04794 $db->quote($this->getTestId()),
04795 $db->quote($sequence),
04796 $db->quote(""),
04797 $db->quote("0"),
04798 $db->quote("1")
04799 );
04800 }
04801 $db->query($query);
04802 }
04803 foreach ($this->questions as $question_id) {
04804 $question =& ilObjTest::_instanciateQuestion($question_id);
04805 foreach ($logins as $login)
04806 {
04807 $question->createRandomSolution($this->getTestId(), $login["usr_id"]);
04808 }
04809 }
04810 }
04811
04819 function &getEvaluationUsers($user_id)
04820 {
04821 $users = array();
04822 $query = sprintf("SELECT tst_eval_users.user_fi, usr_data.firstname, usr_data.lastname FROM tst_eval_users, usr_data WHERE tst_eval_users.test_fi = %s AND tst_eval_users.evaluator_fi = %s AND tst_eval_users.user_fi = usr_data.usr_id",
04823 $this->ilias->db->quote($this->getTestId() . ""),
04824 $this->ilias->db->quote($user_id . "")
04825 );
04826 $result = $this->ilias->db->query($query);
04827 if ($result->numRows())
04828 {
04829 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04830 {
04831 $users[$row["user_fi"]] = trim($row["firstname"] ." " . $row["lastname"]);
04832 }
04833 }
04834 return $users;
04835 }
04836
04844 function &getEvaluationGroups($user_id)
04845 {
04846 $groups = array();
04847 $query = sprintf("SELECT group_fi FROM tst_eval_groups WHERE test_fi = %s AND evaluator_fi = %s",
04848 $this->ilias->db->quote($this->getTestId() . ""),
04849 $this->ilias->db->quote($user_id . "")
04850 );
04851 $result = $this->ilias->db->query($query);
04852 if ($result->numRows())
04853 {
04854 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04855 {
04856 $groups[$row["group_fi"]] = $row["group_fi"];
04857 }
04858 }
04859 return $groups;
04860 }
04861
04870 function removeSelectedUser($user_id, $evaluator_id)
04871 {
04872 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s AND user_fi = %s AND evaluator_fi = %s",
04873 $this->ilias->db->quote($this->getTestId() . ""),
04874 $this->ilias->db->quote($user_id . ""),
04875 $this->ilias->db->quote($evaluator_id . "")
04876 );
04877 $result = $this->ilias->db->query($query);
04878 }
04879
04888 function addSelectedUser($user_id, $evaluator_id)
04889 {
04890 $query = sprintf("SELECT user_fi FROM tst_eval_users WHERE test_fi = %s AND evaluator_fi = %s AND user_fi = %s",
04891 $this->ilias->db->quote($this->getTestId() . ""),
04892 $this->ilias->db->quote($evaluator_id . ""),
04893 $this->ilias->db->quote($user_id . "")
04894 );
04895 $result = $this->ilias->db->query($query);
04896 if ($result->numRows() < 1)
04897 {
04898 $query = sprintf("INSERT INTO tst_eval_users (eval_users_id, test_fi, evaluator_fi, user_fi, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
04899 $this->ilias->db->quote($this->getTestId() . ""),
04900 $this->ilias->db->quote($evaluator_id . ""),
04901 $this->ilias->db->quote($user_id . "")
04902 );
04903 $result = $this->ilias->db->query($query);
04904 }
04905 }
04906
04915 function removeSelectedGroup($group_id, $evaluator_id)
04916 {
04917 $query = sprintf("DELETE FROM tst_eval_groups WHERE test_fi = %s AND group_fi = %s AND evaluator_fi = %s",
04918 $this->ilias->db->quote($this->getTestId() . ""),
04919 $this->ilias->db->quote($group_id . ""),
04920 $this->ilias->db->quote($evaluator_id . "")
04921 );
04922 $result = $this->ilias->db->query($query);
04923 }
04924
04933 function addSelectedGroup($group_id, $evaluator_id)
04934 {
04935 $query = sprintf("SELECT group_fi FROM tst_eval_groups WHERE test_fi = %s AND evaluator_fi = %s AND group_fi = %s",
04936 $this->ilias->db->quote($this->getTestId() . ""),
04937 $this->ilias->db->quote($evaluator_id . ""),
04938 $this->ilias->db->quote($group_id . "")
04939 );
04940 $result = $this->ilias->db->query($query);
04941 if ($result->numRows() < 1)
04942 {
04943 $query = sprintf("INSERT INTO tst_eval_groups (eval_groups_id, test_fi, evaluator_fi, group_fi, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
04944 $this->ilias->db->quote($this->getTestId() . ""),
04945 $this->ilias->db->quote($evaluator_id . ""),
04946 $this->ilias->db->quote($group_id . "")
04947 );
04948 $result = $this->ilias->db->query($query);
04949 }
04950 }
04951
04960 function getQuestionCount()
04961 {
04962 $num = 0;
04963 if ($this->isRandomTest())
04964 {
04965 if ($this->getRandomQuestionCount())
04966 {
04967 $num = $this->getRandomQuestionCount();
04968 }
04969 else
04970 {
04971 $qpls =& $this->getRandomQuestionpools();
04972 foreach ($qpls as $data)
04973 {
04974 $num += $data["count"];
04975 }
04976 }
04977 }
04978 else
04979 {
04980 $num = count($this->questions);
04981 }
04982 return $num;
04983 }
04984
04993 function _goto($a_target)
04994 {
04995 global $rbacsystem, $ilErr, $lng;
04996
04997 if ($rbacsystem->checkAccess("read", $a_target))
04998 {
04999 ilUtil::redirect("assessment/test.php?cmd=run&ref_id=$a_target");
05000 }
05001 else
05002 {
05003 $ilErr->raiseError($lng->txt("msg_no_perm_read_lm"), $ilErr->FATAL);
05004 }
05005 }
05006
05014 function removeNonRandomTestData()
05015 {
05016
05017 $this->removeAllTestEditings();
05018 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
05019 $this->ilias->db->quote($this->getTestId())
05020 );
05021 $result = $this->ilias->db->query($query);
05022 }
05023
05031 function removeRandomTestData()
05032 {
05033
05034 $this->removeAllTestEditings();
05035 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
05036 $this->ilias->db->quote($this->getTestId())
05037 );
05038 $result = $this->ilias->db->query($query);
05039 }
05040
05050 function logAction($logtext = "", $question_id = "")
05051 {
05052 global $ilUser;
05053
05054 $original_id = "";
05055 if (strcmp($question_id, "") == 0)
05056 {
05057 $question_id = "NULL";
05058 }
05059 else
05060 {
05061 $original_id = ASS_Question::_getOriginalId($question_id);
05062 $question_id = $this->ilias->db->quote($question_id . "");
05063 }
05064 if (strcmp($original_id, "") == 0)
05065 {
05066 $original_id = "NULL";
05067 }
05068 else
05069 {
05070 $original_id = $this->ilias->db->quote($original_id . "");
05071 }
05072 $query = sprintf("INSERT INTO ass_log (ass_log_id, user_fi, obj_fi, logtext, question_fi, original_fi, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
05073 $this->ilias->db->quote($ilUser->id . ""),
05074 $this->ilias->db->quote($this->getId() . ""),
05075 $this->ilias->db->quote($logtext . ""),
05076 $question_id,
05077 $original_id
05078 );
05079 $result = $this->ilias->db->query($query);
05080 }
05081
05091 function _getObjectIDFromTestID($test_id)
05092 {
05093 global $ilDB;
05094 $object_id = FALSE;
05095 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
05096 $ilDB->quote($test_id . "")
05097 );
05098 $result = $ilDB->query($query);
05099 if ($result->numRows())
05100 {
05101 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05102 $object_id = $row["obj_fi"];
05103 }
05104 return $object_id;
05105 }
05106
05116 function _getTestIDFromObjectID($object_id)
05117 {
05118 global $ilDB;
05119 $test_id = FALSE;
05120 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
05121 $ilDB->quote($object_id . "")
05122 );
05123 $result = $ilDB->query($query);
05124 if ($result->numRows())
05125 {
05126 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05127 $test_id = $row["test_id"];
05128 }
05129 return $test_id;
05130 }
05131
05142 function getTextAnswer($user_id, $question_id)
05143 {
05144 $res = "";
05145 if (($user_id) && ($question_id))
05146 {
05147 $query = sprintf("SELECT value1 FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
05148 $this->ilias->db->quote($user_id . ""),
05149 $this->ilias->db->quote($this->getTestId() . ""),
05150 $this->ilias->db->quote($question_id . "")
05151 );
05152 $result = $this->ilias->db->query($query);
05153 if ($result->numRows() == 1)
05154 {
05155 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05156 $res = $row["value1"];
05157 }
05158 }
05159 return $res;
05160 }
05161
05171 function getQuestiontext($question_id)
05172 {
05173 $res = "";
05174 if ($question_id)
05175 {
05176 $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
05177 $this->ilias->db->quote($question_id . "")
05178 );
05179 $result = $this->ilias->db->query($query);
05180 if ($result->numRows() == 1)
05181 {
05182 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05183 $res = $row["question_text"];
05184 }
05185 }
05186 return $res;
05187 }
05188 }
05189 ?>