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
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 require_once "./classes/class.ilSearch.php";
00047
00048
00049 define("TEST_FIXED_SEQUENCE", 0);
00050 define("TEST_POSTPONE", 1);
00051
00052 define("REPORT_AFTER_QUESTION", 0);
00053 define("REPORT_AFTER_TEST", 1);
00054
00055 define("TYPE_ASSESSMENT", "1");
00056 define("TYPE_SELF_ASSESSMENT", "2");
00057 define("TYPE_NAVIGATION_CONTROLLING", "3");
00058 define("TYPE_ONLINE_TEST", "4");
00059
00060 define("INVITATION_OFF",0);
00061 define("INVITATION_ON",1);
00062
00063 define("COUNT_PARTIAL_SOLUTIONS", 0);
00064 define("COUNT_CORRECT_SOLUTIONS", 1);
00065
00066 define("SCORE_ZERO_POINTS_WHEN_UNANSWERED", 0);
00067 define("SCORE_STANDARD_SCORE_SYSTEM", 1);
00068
00069 class ilObjTest extends ilObject
00070 {
00078 var $test_id;
00079
00087 var $invitation = INVITATION_OFF;
00088
00089
00098 var $author;
00099
00107 var $metadata;
00108
00116 var $questions;
00117
00126 var $introduction;
00127
00135 var $mark_schema;
00136
00146 var $sequence_settings;
00147
00159 var $score_reporting;
00160
00171 var $reporting_date;
00172
00180 var $evaluation_data;
00181
00189 var $test_type;
00190
00199 var $nr_of_tries;
00200
00208 var $processing_time;
00209
00217 var $enable_processing_time;
00218
00226 var $starting_time;
00227
00235 var $ending_time;
00236
00244 var $ects_output;
00245
00253 var $ects_fx;
00254
00265 var $test_types;
00266
00274 var $ects_grades;
00275
00285 var $random_test;
00286
00294 var $random_question_count;
00295
00302 var $count_system;
00303
00309 var $mc_scoring;
00310
00317 function ilObjTest($a_id = 0,$a_call_by_reference = true)
00318 {
00319 global $ilUser;
00320 $this->type = "tst";
00321 $this->mark_schema = new ASS_MarkSchema();
00322
00323 $this->retrieveTestTypes();
00324 $this->test_id = -1;
00325 $this->author = $ilUser->fullname;
00326 $this->introduction = "";
00327 $this->questions = array();
00328 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00329 $this->score_reporting = REPORT_AFTER_TEST;
00330 $this->reporting_date = "";
00331 $this->nr_of_tries = 0;
00332 $this->starting_time = "";
00333 $this->ending_time = "";
00334 $this->processing_time = "00:00:00";
00335 $this->enable_processing_time = "0";
00336 $this->test_type = TYPE_ASSESSMENT;
00337 $this->ects_output = 0;
00338 $this->ects_fx = "";
00339 $this->random_test = 0;
00340 $this->random_question_count = "";
00341 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
00342 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
00343 global $lng;
00344 $lng->loadLanguageModule("assessment");
00345 $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);
00346 $this->ects_grades = array(
00347 "A" => 90,
00348 "B" => 65,
00349 "C" => 35,
00350 "D" => 10,
00351 "E" => 0
00352 );
00353
00354
00355
00356
00357
00358
00359
00360 $this->ilObject($a_id, $a_call_by_reference);
00361 }
00362
00366 function create($a_upload = false)
00367 {
00368 parent::create();
00369
00370
00371
00372 if (!$a_upload)
00373 {
00374 $this->createMetaData();
00375 }
00376 }
00377
00384 function update()
00385 {
00386 $this->updateMetaData();
00387 if (!parent::update())
00388 {
00389 return false;
00390 }
00391
00392
00393
00394 return true;
00395 }
00396
00405 function createReference() {
00406 $result = parent::createReference();
00407 $this->saveToDb();
00408 return $result;
00409 }
00410
00416 function getCallingScript()
00417 {
00418 return "test.php";
00419 }
00420
00426 function read($a_force_db = false)
00427 {
00428 parent::read($a_force_db);
00429 $this->loadFromDb();
00430
00431 }
00432
00440 function ilClone($a_parent_ref)
00441 {
00442 global $rbacadmin;
00443
00444
00445 $new_ref_id = parent::ilClone($a_parent_ref);
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 return $new_ref_id;
00461 }
00462
00469 function delete()
00470 {
00471
00472 if (!parent::delete())
00473 {
00474 return false;
00475 }
00476
00477
00478 $this->deleteMetaData();
00479
00480
00481 $this->deleteTest();
00482
00483 return true;
00484 }
00485
00493 function deleteTest()
00494 {
00495 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00496 $this->ilias->db->quote($this->getTestId())
00497 );
00498 $result = $this->ilias->db->query($query);
00499 $active_array = array();
00500 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00501 {
00502 array_push($active_array, $row["active_id"]);
00503 }
00504
00505 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00506 $this->ilias->db->quote($this->getTestId())
00507 );
00508 $result = $this->ilias->db->query($query);
00509
00510 if (count($active_array))
00511 {
00512 foreach ($active_array as $active_id)
00513 {
00514 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00515 $this->ilias->db->quote($active_id)
00516 );
00517 $result = $this->ilias->db->query($query);
00518 }
00519 }
00520
00521 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00522 $this->ilias->db->quote($this->getTestId())
00523 );
00524 $result = $this->ilias->db->query($query);
00525
00526 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00527 $this->ilias->db->quote($this->getTestId())
00528 );
00529 $result = $this->ilias->db->query($query);
00530 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00531 {
00532 $this->removeQuestion($row->question_fi);
00533 }
00534
00535 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00536 $this->ilias->db->quote($this->getTestId())
00537 );
00538 $result = $this->ilias->db->query($query);
00539
00540 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00541 $this->ilias->db->quote($this->getTestId())
00542 );
00543 $result = $this->ilias->db->query($query);
00544
00545 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
00546 $this->ilias->db->quote($this->getTestId())
00547 );
00548 $result = $this->ilias->db->query($query);
00549
00550 $this->removeAllTestEditings();
00551
00552 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00553 $this->ilias->db->quote($this->getTestId())
00554 );
00555 $result = $this->ilias->db->query($query);
00556
00557
00558 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00559 $directory = $tst_data_dir."/tst_".$this->getId();
00560 if (is_dir($directory))
00561 {
00562 $directory = escapeshellarg($directory);
00563 exec("rm -rf $directory");
00564 }
00565 }
00566
00576 function initDefaultRoles()
00577 {
00578 global $rbacadmin;
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 return $roles ? $roles : array();
00591 }
00592
00606 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00607 {
00608 global $tree;
00609
00610 switch ($a_event)
00611 {
00612 case "link":
00613
00614
00615
00616
00617 break;
00618
00619 case "cut":
00620
00621
00622
00623 break;
00624
00625 case "copy":
00626
00627
00628
00629
00630 break;
00631
00632 case "paste":
00633
00634
00635
00636 break;
00637
00638 case "new":
00639
00640
00641
00642 break;
00643 }
00644
00645
00646 if ($a_node_id==$_GET["ref_id"])
00647 {
00648 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00649 $parent_type = $parent_obj->getType();
00650 if($parent_type == $this->getType())
00651 {
00652 $a_node_id = (int) $tree->getParentId($a_node_id);
00653 }
00654 }
00655
00656 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00657 }
00658
00664 function createExportDirectory()
00665 {
00666 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00667 ilUtil::makeDir($tst_data_dir);
00668 if(!is_writable($tst_data_dir))
00669 {
00670 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00671 .") not writeable.",$this->ilias->error_obj->MESSAGE);
00672 }
00673
00674
00675 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00676 ilUtil::makeDir($tst_dir);
00677 if(!@is_dir($tst_dir))
00678 {
00679 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
00680 }
00681
00682 $export_dir = $tst_dir."/export";
00683 ilUtil::makeDir($export_dir);
00684 if(!@is_dir($export_dir))
00685 {
00686 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
00687 }
00688 }
00689
00697 function getExportDirectory()
00698 {
00699 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00700
00701 return $export_dir;
00702 }
00703
00712 function getExportFiles($dir)
00713 {
00714
00715 if (!@is_dir($dir) or
00716 !is_writeable($dir))
00717 {
00718 return array();
00719 }
00720
00721
00722 $dir = dir($dir);
00723
00724
00725 $file = array();
00726
00727
00728 while ($entry = $dir->read())
00729 {
00730 if ($entry != "." and
00731 $entry != ".." and
00732
00733 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test(__results)?__)*[0-9]+\.[a-z]{1,3}\$", $entry))
00734 {
00735 $file[] = $entry;
00736 }
00737 }
00738
00739
00740 $dir->close();
00741
00742
00743 sort ($file);
00744 reset ($file);
00745
00746 return $file;
00747 }
00748
00749
00755 function _createImportDirectory()
00756 {
00757 global $ilias;
00758
00759 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00760 ilUtil::makeDir($tst_data_dir);
00761
00762 if(!is_writable($tst_data_dir))
00763 {
00764 $ilias->raiseError("Test data directory (".$tst_data_dir
00765 .") not writeable.",$ilias->error_obj->FATAL);
00766 }
00767
00768
00769 $tst_dir = $tst_data_dir."/tst_import";
00770 ilUtil::makeDir($tst_dir);
00771 if(!@is_dir($tst_dir))
00772 {
00773 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00774 }
00775 }
00776
00785 function _getImportDirectory()
00786 {
00787 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00788 if(@is_dir($import_dir))
00789 {
00790 return $import_dir;
00791 }
00792 else
00793 {
00794 return false;
00795 }
00796 }
00797
00803 function createImportDirectory()
00804 {
00805 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00806 ilUtil::makeDir($tst_data_dir);
00807
00808 if(!is_writable($tst_data_dir))
00809 {
00810 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00811 .") not writeable.",$this->ilias->error_obj->FATAL);
00812 }
00813
00814
00815 $tst_dir = $tst_data_dir."/tst_import";
00816 ilUtil::makeDir($tst_dir);
00817 if(!@is_dir($tst_dir))
00818 {
00819 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00820 }
00821 }
00822
00831 function getImportDirectory()
00832 {
00833 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00834 if(@is_dir($import_dir))
00835 {
00836 return $import_dir;
00837 }
00838 else
00839 {
00840 return false;
00841 }
00842 }
00843
00844
00854 function retrieveTestTypes()
00855 {
00856 global $ilDB;
00857
00858 $this->test_types = array();
00859 $query = "SELECT * FROM tst_test_type ORDER BY test_type_id";
00860 $result = $ilDB->query($query);
00861 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00862 {
00863 $this->test_types[$row->test_type_id] = $row->type_tag;
00864 }
00865 }
00866
00876 function testTitleExists($title)
00877 {
00878 $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00879 $this->ilias->db->quote($title),
00880 $this->ilias->db->quote("tst")
00881 );
00882 $result = $this->ilias->db->query($query);
00883 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00884 if ($result->numRows() == 1) {
00885 return TRUE;
00886 }
00887 }
00888 return FALSE;
00889 }
00890
00898 function duplicate()
00899 {
00900 $clone = $this;
00901 $clone->set_id(-1);
00902 $counter = 2;
00903 while ($this->testTitleExists($this->get_title() . " ($counter)")) {
00904 $counter++;
00905 }
00906 $clone->set_title($this->get_title() . " ($counter)");
00907 $clone->set_owner($this->ilias->account->id);
00908 $clone->setAuthor($this->ilias->account->fullname);
00909 $clone->saveToDb($this->ilias->db);
00910
00911 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi = %s",
00912 $this->ilias->db->quote($this->getId())
00913 );
00914 $result = $this->ilias->db->query($query);
00915 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00916 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
00917 $this->ilias->db->quote($clone->getId()),
00918 $this->ilias->db->quote($data->question_fi),
00919 $this->ilias->db->quote($data->sequence)
00920 );
00921 $insert_result = $this->ilias->db->query($query);
00922 }
00923 }
00924
00933 function isComplete()
00934 {
00935 if (($this->getTitle()) and ($this->author) and (count($this->mark_schema->mark_steps)) and (count($this->questions)))
00936 {
00937 return true;
00938 }
00939 else
00940 {
00941 if ($this->isRandomTest())
00942 {
00943 $arr = $this->getRandomQuestionpools();
00944 if (count($arr) && ($this->getRandomQuestionCount() > 0))
00945 {
00946 return true;
00947 }
00948 $count = 0;
00949 foreach ($arr as $array)
00950 {
00951 $count += $array["count"];
00952 }
00953 if ($count)
00954 {
00955 return true;
00956 }
00957 }
00958 return false;
00959 }
00960 }
00961
00970 function _isComplete($obj_id)
00971 {
00972 $test = new ilObjTest($obj_id, false);
00973 $test->loadFromDb();
00974 return $test->isComplete();
00975 }
00976
00984 function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
00985 {
00986 global $ilDB;
00987 if ($this->test_id > 0) {
00988 $fx_support = preg_replace("/,/", ".", $fx_support);
00989 if (preg_match("/\d+/", $fx_support))
00990 {
00991 $fx_support = $fx_support;
00992 }
00993 else
00994 {
00995 $fx_support = "NULL";
00996 }
00997 $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",
00998 $ilDB->quote("$ects_output"),
00999 $ilDB->quote($ects_a . ""),
01000 $ilDB->quote($ects_b . ""),
01001 $ilDB->quote($ects_c . ""),
01002 $ilDB->quote($ects_d . ""),
01003 $ilDB->quote($ects_e . ""),
01004 $fx_support,
01005 $this->getTestId()
01006 );
01007 $result = $ilDB->query($query);
01008 $this->ects_output = $ects_output;
01009 $this->ects_fx = $fx_support;
01010 }
01011 }
01012
01020 function saveCompleteStatus()
01021 {
01022 global $ilias;
01023
01024 $db =& $ilias->db;
01025 $complete = 0;
01026 if ($this->isComplete()) {
01027 $complete = 1;
01028 }
01029 if ($this->test_id > 0) {
01030 $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
01031 $db->quote("$complete"),
01032 $db->quote($this->test_id)
01033 );
01034 $result = $db->query($query);
01035 }
01036 }
01037
01046 function saveToDb($properties_only = FALSE)
01047 {
01048 global $ilias;
01049 $db =& $ilias->db;
01050 $complete = 0;
01051 if ($this->isComplete()) {
01052 $complete = 1;
01053 }
01054 $ects_fx = "NULL";
01055 if (preg_match("/\d+/", $this->ects_fx))
01056 {
01057 $ects_fx = $this->ects_fx;
01058 }
01059 $random_question_count = "NULL";
01060 if ($this->random_question_count > 0)
01061 {
01062 $random_question_count = $this->ilias->db->quote($this->random_question_count . "");
01063 }
01064 if ($this->test_id == -1) {
01065
01066 $now = getdate();
01067 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
01068 $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, count_system, mc_scoring, 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, %s, %s, NULL)",
01069 $db->quote($this->getId() . ""),
01070 $db->quote($this->author . ""),
01071 $db->quote($this->test_type . ""),
01072 $db->quote($this->introduction . ""),
01073 $db->quote($this->sequence_settings . ""),
01074 $db->quote($this->score_reporting . ""),
01075 $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01076 $db->quote($this->processing_time . ""),
01077 $db->quote("$this->enable_processing_time"),
01078 $db->quote($this->reporting_date . ""),
01079 $db->quote($this->starting_time . ""),
01080 $db->quote($this->ending_time . ""),
01081 $db->quote("$complete"),
01082 $db->quote($this->ects_output . ""),
01083 $db->quote($this->ects_grades["A"] . ""),
01084 $db->quote($this->ects_grades["B"] . ""),
01085 $db->quote($this->ects_grades["C"] . ""),
01086 $db->quote($this->ects_grades["D"] . ""),
01087 $db->quote($this->ects_grades["E"] . ""),
01088 $ects_fx,
01089 $db->quote(sprintf("%d", $this->random_test) . ""),
01090 $random_question_count,
01091 $db->quote($this->count_system . ""),
01092 $db->quote($this->mc_scoring . ""),
01093 $db->quote($created)
01094 );
01095
01096 include_once ("./classes/class.ilObjAssessmentFolder.php");
01097 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01098 {
01099 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
01100 }
01101 $result = $db->query($query);
01102 if ($result == DB_OK) {
01103 $this->test_id = $this->ilias->db->getLastInsertId();
01104 }
01105 } else {
01106
01107 $oldrow = array();
01108 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01109 {
01110 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01111 $db->quote($this->test_id)
01112 );
01113 $result = $db->query($query);
01114 if ($result->numRows() == 1)
01115 {
01116 $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01117 }
01118 }
01119 $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, count_system = %s, mc_scoring = %s WHERE test_id = %s",
01120 $db->quote($this->author . ""),
01121 $db->quote($this->test_type . ""),
01122 $db->quote($this->introduction . ""),
01123 $db->quote($this->sequence_settings . ""),
01124 $db->quote($this->score_reporting . ""),
01125 $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01126 $db->quote($this->processing_time . ""),
01127 $db->quote("$this->enable_processing_time"),
01128 $db->quote($this->reporting_date . ""),
01129 $db->quote($this->starting_time . ""),
01130 $db->quote($this->ending_time . ""),
01131 $db->quote($this->ects_output . ""),
01132 $db->quote($this->ects_grades["A"] . ""),
01133 $db->quote($this->ects_grades["B"] . ""),
01134 $db->quote($this->ects_grades["C"] . ""),
01135 $db->quote($this->ects_grades["D"] . ""),
01136 $db->quote($this->ects_grades["E"] . ""),
01137 $ects_fx,
01138 $db->quote(sprintf("%d", $this->random_test) . ""),
01139 $db->quote("$complete"),
01140 $db->quote($this->count_system . ""),
01141 $db->quote($this->mc_scoring . ""),
01142 $db->quote($this->test_id)
01143 );
01144 $result = $db->query($query);
01145 include_once ("./classes/class.ilObjAssessmentFolder.php");
01146 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01147 {
01148 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01149 $db->quote($this->test_id)
01150 );
01151 $logresult = $db->query($query);
01152 $newrow = array();
01153 if ($logresult->numRows() == 1)
01154 {
01155 $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01156 }
01157 $changed_fields = array();
01158 foreach ($oldrow as $key => $value)
01159 {
01160 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01161 {
01162 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01163 }
01164 }
01165 $changes = join($changed_fields, ", ");
01166 if (count($changed_fields) == 0)
01167 {
01168 $changes = $this->lng->txtlng("assessment", "log_no_test_fields_changed", ilObjAssessmentFolder::_getLogLanguage());
01169 }
01170 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
01171 }
01172 }
01173 if (!$properties_only)
01174 {
01175 if ($result == DB_OK) {
01176 if (!$this->isRandomTest())
01177 {
01178 $this->saveQuestionsToDb();
01179 }
01180 $this->mark_schema->saveToDb($this->test_id);
01181 }
01182 }
01183 }
01184
01193 function saveQuestionsToDb()
01194 {
01195 $oldquestions = array();
01196 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01197 {
01198 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01199 $this->ilias->db->quote($this->getTestId())
01200 );
01201 $result = $this->ilias->db->query($query);
01202 if ($result->numRows() > 0)
01203 {
01204 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01205 {
01206 array_push($oldquestions, $row["question_fi"]);
01207 }
01208 }
01209 }
01210
01211
01212 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01213 $this->ilias->db->quote($this->getTestId())
01214 );
01215 $result = $this->ilias->db->query($query);
01216
01217 foreach ($this->questions as $key => $value) {
01218 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01219 $this->ilias->db->quote($this->getTestId() . ""),
01220 $this->ilias->db->quote($value . ""),
01221 $this->ilias->db->quote($key . "")
01222 );
01223 $result = $this->ilias->db->query($query);
01224 }
01225 include_once ("./classes/class.ilObjAssessmentFolder.php");
01226 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01227 {
01228 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01229 $this->ilias->db->quote($this->getTestId())
01230 );
01231 $result = $this->ilias->db->query($query);
01232 $newquestions = array();
01233 if ($result->numRows() > 0)
01234 {
01235 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01236 {
01237 array_push($newquestions, $row["question_fi"]);
01238 }
01239 }
01240 foreach ($oldquestions as $index => $question_id)
01241 {
01242 if (strcmp($newquestions[$index], $question_id) != 0)
01243 {
01244 $pos = array_search($question_id, $newquestions);
01245 if ($pos === FALSE)
01246 {
01247 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
01248 }
01249 else
01250 {
01251 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01252 }
01253 }
01254 }
01255 foreach ($newquestions as $index => $question_id)
01256 {
01257 if (array_search($question_id, $oldquestions) === FALSE)
01258 {
01259 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
01260 }
01261 }
01262 }
01263 }
01264
01273 function saveRandomQuestion($question_id)
01274 {
01275 global $ilUser;
01276
01277 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE test_fi = %s AND user_fi = %s",
01278 $this->ilias->db->quote($this->getTestId() . ""),
01279 $this->ilias->db->quote($ilUser->id . "")
01280 );
01281 $result = $this->ilias->db->query($query);
01282
01283 $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)",
01284 $this->ilias->db->quote($this->getTestId() . ""),
01285 $this->ilias->db->quote($ilUser->id . ""),
01286 $this->ilias->db->quote($question_id . ""),
01287 $this->ilias->db->quote(($result->numRows()+1) . "")
01288 );
01289 $result = $this->ilias->db->query($query);
01290 }
01291
01300 function saveRandomQuestionCount($total_questions = "NULL")
01301 {
01302 if (strcmp($total_questions, "NULL") != 0)
01303 {
01304 $this->setRandomQuestionCount($total_questions);
01305 $total_questions = $this->ilias->db->quote($total_questions);
01306 }
01307 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01308 $total_questions,
01309 $this->ilias->db->quote($this->getTestId() . "")
01310 );
01311 $result = $this->ilias->db->query($query);
01312 }
01313
01323 function saveRandomQuestionpools($qpl_array)
01324 {
01325
01326 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01327 $this->ilias->db->quote($this->getTestId())
01328 );
01329 $result = $this->ilias->db->query($query);
01330
01331 foreach ($qpl_array as $key => $value) {
01332 if ($value["qpl"] > -1)
01333 {
01334 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01335 if ($value["count"] > $count)
01336 {
01337 $value["count"] = $count;
01338 }
01339 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01340 $this->ilias->db->quote($this->getTestId() . ""),
01341 $this->ilias->db->quote($value["qpl"] . ""),
01342 $this->ilias->db->quote(sprintf("%d", $value["count"]) . "")
01343 );
01344 $result = $this->ilias->db->query($query);
01345 }
01346 }
01347 }
01348
01358 function &getRandomQuestionpools()
01359 {
01360 $qpls = array();
01361 $counter = 0;
01362 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
01363 $this->ilias->db->quote($this->getTestId() . "")
01364 );
01365 $result = $this->ilias->db->query($query);
01366 if ($result->numRows())
01367 {
01368 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01369 {
01370 $qpls[$counter] = array(
01371 "index" => $counter,
01372 "count" => $row["num_of_q"],
01373 "qpl" => $row["questionpool_fi"]
01374 );
01375 $counter++;
01376 }
01377 }
01378 return $qpls;
01379 }
01380
01390 function loadFromDb()
01391 {
01392 $db = $this->ilias->db;
01393
01394 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01395 $db->quote($this->getId())
01396 );
01397 $result = $db->query($query);
01398 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01399 {
01400 if ($result->numRows() == 1)
01401 {
01402 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01403 $this->test_id = $data->test_id;
01404 $this->author = $data->author;
01405 $this->test_type = $data->test_type_fi;
01406 $this->introduction = $data->introduction;
01407 $this->sequence_settings = $data->sequence_settings;
01408 $this->score_reporting = $data->score_reporting;
01409 $this->nr_of_tries = $data->nr_of_tries;
01410 $this->processing_time = $data->processing_time;
01411 $this->enable_processing_time = $data->enable_processing_time;
01412 $this->reporting_date = $data->reporting_date;
01413 $this->starting_time = $data->starting_time;
01414 $this->ending_time = $data->ending_time;
01415 $this->ects_output = $data->ects_output;
01416 $this->ects_grades = array(
01417 "A" => $data->ects_a,
01418 "B" => $data->ects_b,
01419 "C" => $data->ects_c,
01420 "D" => $data->ects_d,
01421 "E" => $data->ects_e
01422 );
01423 $this->ects_fx = $data->ects_fx;
01424 $this->random_test = $data->random_test;
01425 $this->random_question_count = $data->random_question_count;
01426 $this->mark_schema->flush();
01427 $this->mark_schema->loadFromDb($this->test_id);
01428 $this->count_system = $data->count_system;
01429 $this->mc_scoring = $data->mc_scoring;
01430 $this->loadQuestions();
01431 }
01432 }
01433 }
01434
01443 function loadQuestions($user_id = "")
01444 {
01445 global $ilUser;
01446
01447 $db = $this->ilias->db;
01448 $this->questions = array();
01449 if (strcmp($user_id, "") == 0)
01450 {
01451 $user_id = $ilUser->id;
01452 }
01453 if ($this->isRandomTest())
01454 {
01455 $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",
01456 $db->quote($this->test_id . ""),
01457 $db->quote($user_id . "")
01458 );
01459 }
01460 else
01461 {
01462 $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",
01463 $db->quote($this->test_id . "")
01464 );
01465 }
01466 $result = $db->query($query);
01467 $index = 1;
01468 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01469 $this->questions[$index++] = $data->question_fi;
01470 }
01471 }
01472
01482 function setAuthor($author = "")
01483 {
01484 $this->author = $author;
01485 }
01486
01496 function setIntroduction($introduction = "")
01497 {
01498 $this->introduction = $introduction;
01499 }
01500
01510 function getAuthor()
01511 {
01512 return $this->author;
01513 }
01514
01524 function isRandomTest()
01525 {
01526 return $this->random_test;
01527 }
01528
01538 function getRandomQuestionCount()
01539 {
01540 return $this->random_question_count;
01541 }
01542
01552 function getIntroduction()
01553 {
01554 return $this->introduction;
01555 }
01556
01566 function getTestId()
01567 {
01568 return $this->test_id;
01569 }
01570
01580 function setSequenceSettings($sequence_settings = 0)
01581 {
01582 $this->sequence_settings = $sequence_settings;
01583 }
01584
01594 function setTestType($type = TYPE_ASSESSMENT)
01595 {
01596 $this->test_type = $type;
01597 }
01598
01608 function setScoreReporting($score_reporting = 0)
01609 {
01610 $this->score_reporting = $score_reporting;
01611 }
01612
01622 function setRandomTest($a_random_test = 0)
01623 {
01624 $this->random_test = $a_random_test;
01625 }
01626
01636 function setRandomQuestionCount($a_random_question_count = "")
01637 {
01638 $this->random_question_count = $a_random_question_count;
01639 }
01640
01650 function setReportingDate($reporting_date)
01651 {
01652 if (!$reporting_date)
01653 {
01654 $this->reporting_date = "";
01655 $this->ects_output = 0;
01656 }
01657 else
01658 {
01659 $this->reporting_date = $reporting_date;
01660 $this->score_reporting = REPORT_AFTER_TEST;
01661 }
01662 }
01663
01673 function getSequenceSettings()
01674 {
01675 return $this->sequence_settings;
01676 }
01677
01687 function getScoreReporting()
01688 {
01689 return $this->score_reporting;
01690 }
01691
01701 function getCountSystem()
01702 {
01703 return $this->count_system;
01704 }
01705
01715 function _getCountSystem($test_id)
01716 {
01717 global $ilDB;
01718 $query = sprintf("SELECT count_system FROM tst_tests WHERE test_id = %s",
01719 $ilDB->quote($test_id)
01720 );
01721 $result = $ilDB->query($query);
01722 if ($result->numRows())
01723 {
01724 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01725 return $row["count_system"];
01726 }
01727 return FALSE;
01728 }
01729
01739 function getMCScoring()
01740 {
01741 return $this->mc_scoring;
01742 }
01743
01753 function _getMCScoring($test_id)
01754 {
01755 global $ilDB;
01756 $query = sprintf("SELECT mc_scoring FROM tst_tests WHERE test_id = %s",
01757 $ilDB->quote($test_Id)
01758 );
01759 $result = $ilDB->query($query);
01760 if ($result->numRows())
01761 {
01762 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01763 return $row["mc_scoring"];
01764 }
01765 return FALSE;
01766 }
01767
01777 function getTestType()
01778 {
01779 return $this->test_type;
01780 }
01781
01791 function getReportingDate()
01792 {
01793 return $this->reporting_date;
01794 }
01795
01805 function getNrOfTries()
01806 {
01807 return $this->nr_of_tries;
01808 }
01809
01819 function getProcessingTime()
01820 {
01821 return $this->processing_time;
01822 }
01823
01833 function getProcessingTimeInSeconds()
01834 {
01835 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
01836 {
01837 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
01838 }
01839 else
01840 {
01841 return 0;
01842 }
01843 }
01844
01854 function getEnableProcessingTime()
01855 {
01856 return $this->enable_processing_time;
01857 }
01858
01868 function getStartingTime()
01869 {
01870 return $this->starting_time;
01871 }
01872
01882 function getEndingTime()
01883 {
01884 return $this->ending_time;
01885 }
01886
01896 function setNrOfTries($nr_of_tries = 0)
01897 {
01898 $this->nr_of_tries = $nr_of_tries;
01899 }
01900
01910 function setProcessingTime($processing_time = "00:00:00")
01911 {
01912 $this->processing_time = $processing_time;
01913 }
01914
01924 function setEnableProcessingTime($enable = 0)
01925 {
01926 if ($enable) {
01927 $this->enable_processing_time = "1";
01928 } else {
01929 $this->enable_processing_time = "0";
01930 }
01931 }
01932
01942 function setStartingTime($starting_time = "")
01943 {
01944 $this->starting_time = $starting_time;
01945 }
01946
01956 function setEndingTime($ending_time = "")
01957 {
01958 $this->ending_time = $ending_time;
01959 }
01960
01970 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
01971 {
01972 $this->count_system = $a_count_system;
01973 }
01974
01984 function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED)
01985 {
01986 $this->mc_scoring = $a_mc_scoring;
01987 }
01988
01998 function removeQuestion($question_id)
01999 {
02000 $question = new ASS_Question();
02001 include_once ("./classes/class.ilObjAssessmentFolder.php");
02002 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02003 {
02004 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
02005 }
02006 $question->delete($question_id);
02007 $this->removeAllTestEditings($question_id);
02008 $this->loadQuestions();
02009 $this->saveQuestionsToDb();
02010 }
02011
02019 function clearEvalSelectedUsers()
02020 {
02021 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s",
02022 $this->ilias->db->quote($this->getTestId())
02023 );
02024 $result = $this->ilias->db->query($query);
02025 }
02026
02034 function clearEvalSelectedGroups()
02035 {
02036 $query = sprintf("DELETE FROM tst_eval_groups WHERE test_fi = %s",
02037 $this->ilias->db->quote($this->getTestId())
02038 );
02039 $result = $this->ilias->db->query($query);
02040 }
02041
02053 function removeAllTestEditings($question_id = "")
02054 {
02055
02056 $this->deleteActiveTests();
02057
02058 $this->clearEvalSelectedUsers();
02059 $this->clearEvalSelectedGroups();
02060
02061
02062 if ($question_id)
02063 {
02064 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND question_fi = %s",
02065 $this->ilias->db->quote($this->getTestId()),
02066 $this->ilias->db->quote($question_id)
02067 );
02068 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s AND question_fi=%s",
02069 $this->ilias->db->quote($this->getTestId()),
02070 $this->ilias->db->quote($question_id)
02071 );
02072 $query3 = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s AND question_fi = %s",
02073 $this->ilias->db->quote($this->getTestId()),
02074 $this->ilias->db->quote($question_id)
02075 );
02076 } else {
02077 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s",
02078 $this->ilias->db->quote($this->getTestId())
02079 );
02080 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s",
02081 $this->ilias->db->quote($this->getTestId())
02082 );
02083 $query3 = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s",
02084 $this->ilias->db->quote($this->getTestId())
02085 );
02086 }
02087 $result = $this->ilias->db->query($query);
02088 $result = $this->ilias->db->query($query2);
02089 $result = $this->ilias->db->query($query3);
02090
02091 if ($this->isRandomTest())
02092 {
02093 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
02094 $this->ilias->db->quote($this->getTestId())
02095 );
02096 $result = $this->ilias->db->query($query);
02097 }
02098 include_once ("./classes/class.ilObjAssessmentFolder.php");
02099 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02100 {
02101 $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
02102 }
02103 }
02104
02113 function deleteActiveTests()
02114 {
02115 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
02116 $this->ilias->db->quote($this->getTestId())
02117 );
02118 $result = $this->ilias->db->query($query);
02119 }
02120
02131 function deleteResults($user_id = "",$a_delete_active = false)
02132 {
02133 if ($user_id) {
02134 $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND user_fi = %s",
02135 $this->ilias->db->quote($this->getTestId()),
02136 $this->ilias->db->quote($user_id)
02137 );
02138 $result = $this->ilias->db->query($query);
02139 $query = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s AND user_fi = %s",
02140 $this->ilias->db->quote($this->getTestId()),
02141 $this->ilias->db->quote($user_id)
02142 );
02143 $result = $this->ilias->db->query($query);
02144 $sequence_arr = array_flip($this->questions);
02145 $sequence = join($sequence_arr, ",");
02146 $query = sprintf("UPDATE tst_active SET sequence = %s, lastindex = %s WHERE test_fi = %s and user_fi = %s",
02147 $this->ilias->db->quote($sequence),
02148 $this->ilias->db->quote("1"),
02149 $this->ilias->db->quote($this->getTestId()),
02150 $this->ilias->db->quote($user_id)
02151 );
02152 $result = $this->ilias->db->query($query);
02153
02154 $query = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s AND user_fi = %s",
02155 $this->ilias->db->quote($this->getTestId()),
02156 $this->ilias->db->quote($user_id)
02157 );
02158 $result = $this->ilias->db->query($query);
02159
02160
02161 if($a_delete_active)
02162 {
02163 $query = "DELETE FROM tst_active ".
02164 "WHERE user_fi = '".$user_id."' ".
02165 "AND test_fi = '".$this->getTestId()."'";
02166
02167 $this->ilias->db->query($query);
02168 }
02169 }
02170 }
02171
02181 function questionMoveUp($question_id)
02182 {
02183
02184 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
02185 $this->ilias->db->quote($this->getTestId()),
02186 $this->ilias->db->quote($question_id)
02187 );
02188 $result = $this->ilias->db->query($query);
02189 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02190 if ($data->sequence > 1) {
02191
02192 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
02193 $this->ilias->db->quote($this->getTestId()),
02194 $this->ilias->db->quote($data->sequence - 1)
02195 );
02196 $result = $this->ilias->db->query($query);
02197 $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
02198
02199 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02200 $this->ilias->db->quote($data->sequence),
02201 $this->ilias->db->quote($data_previous->test_question_id)
02202 );
02203 $result = $this->ilias->db->query($query);
02204
02205 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02206 $this->ilias->db->quote($data->sequence - 1),
02207 $this->ilias->db->quote($data->test_question_id)
02208 );
02209 $result = $this->ilias->db->query($query);
02210 include_once ("./classes/class.ilObjAssessmentFolder.php");
02211 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02212 {
02213 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
02214 }
02215 }
02216 $this->loadQuestions();
02217 }
02218
02228 function questionMoveDown($question_id)
02229 {
02230
02231 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
02232 $this->ilias->db->quote($this->getTestId()),
02233 $this->ilias->db->quote($question_id)
02234 );
02235 $result = $this->ilias->db->query($query);
02236 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02237 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
02238 $this->ilias->db->quote($this->getTestId()),
02239 $this->ilias->db->quote($data->sequence + 1)
02240 );
02241 $result = $this->ilias->db->query($query);
02242 if ($result->numRows() == 1)
02243 {
02244
02245 $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
02246
02247 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02248 $this->ilias->db->quote($data->sequence),
02249 $this->ilias->db->quote($data_next->test_question_id)
02250 );
02251 $result = $this->ilias->db->query($query);
02252
02253 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02254 $this->ilias->db->quote($data->sequence + 1),
02255 $this->ilias->db->quote($data->test_question_id)
02256 );
02257 $result = $this->ilias->db->query($query);
02258 include_once ("./classes/class.ilObjAssessmentFolder.php");
02259 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02260 {
02261 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
02262 }
02263 }
02264 $this->loadQuestions();
02265 }
02266
02276 function duplicateQuestionForTest($question_id)
02277 {
02278 global $ilUser;
02279
02280 $question =& ilObjTest::_instanciateQuestion($question_id);
02281 $duplicate_id = $question->duplicate(true);
02282
02283 return $duplicate_id;
02284 }
02285
02294 function insertQuestion($question_id)
02295 {
02296 $duplicate_id = $this->duplicateQuestionForTest($question_id);
02297
02298
02299 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
02300 $this->ilias->db->quote($this->getTestId())
02301 );
02302 $result = $this->ilias->db->query($query);
02303 $sequence = 1;
02304
02305 if ($result->numRows() == 1)
02306 {
02307 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02308 $sequence = $data->seq + 1;
02309 }
02310
02311 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02312 $this->ilias->db->quote($this->getTestId()),
02313 $this->ilias->db->quote($duplicate_id),
02314 $this->ilias->db->quote($sequence)
02315 );
02316 $result = $this->ilias->db->query($query);
02317 if ($result != DB_OK)
02318 {
02319
02320 }
02321 else
02322 {
02323 include_once ("./classes/class.ilObjAssessmentFolder.php");
02324 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02325 {
02326 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
02327 }
02328 }
02329
02330 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
02331 $this->ilias->db->quote($this->getTestId())
02332 );
02333 $result = $this->ilias->db->query($query);
02334 $this->loadQuestions();
02335 $this->saveCompleteStatus();
02336 }
02337
02347 function &getQuestionTitles()
02348 {
02349 $titles = array();
02350 if (!$this->isRandomTest())
02351 {
02352 global $ilDB;
02353 $query = sprintf("SELECT qpl_questions.title FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY tst_test_question.sequence",
02354 $ilDB->quote($this->getTestId() . "")
02355 );
02356 $result = $ilDB->query($query);
02357 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
02358 {
02359 array_push($titles, $row["title"]);
02360 }
02361 }
02362 return $titles;
02363 }
02364
02374 function getQuestionTitle($sequence)
02375 {
02376 global $ilUser;
02377 if ($ilUser->id > 0)
02378 {
02379 $active = $this->getActiveTestUser($ilUser->id);
02380 $seq = split(",", $active->sequence);
02381 $query = sprintf("SELECT title from qpl_questions WHERE question_id = %s",
02382 $this->ilias->db->quote($this->questions[$seq[$sequence-1]])
02383 );
02384 }
02385 else
02386 {
02387 $query = sprintf("SELECT title from qpl_questions WHERE question_id = %s",
02388 $this->ilias->db->quote($this->questions[$sequence])
02389 );
02390 }
02391 $result = $this->ilias->db->query($query);
02392 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02393 return $row->title;
02394 }
02395
02406 function getQuestionDataset($question_id)
02407 {
02408 $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",
02409 $this->ilias->db->quote("$question_id")
02410 );
02411 $result = $this->ilias->db->query($query);
02412 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02413 return $row;
02414 }
02415
02424 function &get_qpl_titles()
02425 {
02426 global $rbacsystem;
02427
02428 $qpl_titles = array();
02429
02430 $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";
02431 $result = $this->ilias->db->query($query);
02432 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02433 {
02434 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
02435 {
02436 $qpl_titles["$row->obj_id"] = $row->title;
02437 }
02438 }
02439 return $qpl_titles;
02440 }
02441
02450 function &getExistingQuestions()
02451 {
02452 global $ilUser;
02453 $existing_questions = array();
02454 if ($this->isRandomTest())
02455 {
02456 $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",
02457 $this->ilias->db->quote($this->getTestId() . ""),
02458 $this->ilias->db->quote($ilUser->id . "")
02459 );
02460 }
02461 else
02462 {
02463 $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",
02464 $this->ilias->db->quote($this->getTestId())
02465 );
02466 }
02467 $result = $this->ilias->db->query($query);
02468 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
02469 array_push($existing_questions, $data->original_id);
02470 }
02471 return $existing_questions;
02472 }
02473
02483 function getQuestionType($question_id)
02484 {
02485 if ($question_id < 1)
02486 return -1;
02487 $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",
02488 $this->ilias->db->quote($question_id)
02489 );
02490 $result = $this->ilias->db->query($query);
02491 if ($result->numRows() == 1) {
02492 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02493 return $data->type_tag;
02494 } else {
02495 return "";
02496 }
02497 }
02498
02507 function startWorkingTime ($user_id)
02508 {
02509 $result = "";
02510 if (!($result = $this->getActiveTestUser($user_id))) {
02511 $this->setActiveTestUser();
02512 $result = $this->getActiveTestUser($user_id);
02513 }
02514 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02515 $this->ilias->db->quote($result->active_id),
02516 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02517 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S"))
02518 );
02519 $result = $this->ilias->db->query($q);
02520 return $this->ilias->db->getLastInsertId();
02521 }
02522
02531 function updateWorkingTime($times_id)
02532 {
02533 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
02534 $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02535 $this->ilias->db->quote($times_id)
02536 );
02537 $result = $this->ilias->db->query($q);
02538 }
02539
02549 function getQuestionIdFromActiveUserSequence($sequence)
02550 {
02551 global $ilUser;
02552
02553 $active = $this->getActiveTestUser();
02554 $sequence_array = split(",", $active->sequence);
02555
02556 return $this->questions[$sequence_array[$sequence-1]];
02557 }
02558
02567 function &getAllQuestionsForActiveUser()
02568 {
02569 $result_array = array();
02570 $active = $this->getActiveTestUser();
02571 $sequence_array = split(",", $active->sequence);
02572 $all_questions = &$this->getAllQuestions();
02573 $worked_questions = &$this->getWorkedQuestions();
02574 foreach ($sequence_array as $sequence)
02575 {
02576 if (in_array($this->questions[$sequence], $worked_questions))
02577 {
02578 $all_questions[$this->questions[$sequence]]["worked"] = 1;
02579 }
02580 else
02581 {
02582 $all_questions[$this->questions[$sequence]]["worked"] = 0;
02583 }
02584 array_push($result_array, $all_questions[$this->questions[$sequence]]);
02585 }
02586 return $result_array;
02587 }
02588
02589 function getWrongAnsweredQuestions()
02590 {
02591 global $ilUser;
02592
02593 foreach($all_questions =& $this->getAllQuestionsForActiveUser() as $question)
02594 {
02595 foreach($this->getTestResult($ilUser->getId()) as $result)
02596 {
02597 if($result['qid'] == $question['question_id'])
02598 {
02599 if($result['max'] != $result['reached'])
02600 {
02601 $wrong[] = $question;
02602 }
02603 }
02604 }
02605 }
02606 return $wrong ? $wrong : array();
02607 }
02615 function incrementSequenceByResult($a_sequence)
02616 {
02617 global $ilUser;
02618
02619 for($i = $a_sequence+1; $i <= $this->getQuestionCount(); $i++)
02620 {
02621 $qid = $this->getQuestionIdFromActiveUserSequence($i);
02622
02623 foreach($this->getTestResult($ilUser->getId()) as $result)
02624 {
02625 if($qid == $result['qid'])
02626 {
02627 if($result['max'] != $result['reached'])
02628 {
02629 return $i;
02630 }
02631 }
02632 }
02633 }
02634 return ($this->getQuestionCount()+1);
02635 }
02636
02637
02645 function decrementSequenceByResult($a_sequence)
02646 {
02647 for($i = $a_sequence; $i > 0; $i--)
02648 {
02649 $qid = $this->getQuestionIdFromActiveUserSequence($i);
02650
02651 foreach($this->getTestResult($ilUser->getId()) as $result)
02652 {
02653 if($qid == $result['qid'])
02654 {
02655 if($result['max'] != $result['reached'])
02656 {
02657 return $i;
02658 }
02659 }
02660 }
02661 }
02662 return 1;
02663 }
02664
02665 function getFirstSequence()
02666 {
02667 global $ilUser;
02668
02669 $results = $this->getTestResult($ilUser->getId());
02670
02671 for($i = 1; $i <= $this->getQuestionCount(); $i++)
02672 {
02673 $qid = $this->getQuestionIdFromActiveUserSequence($i);
02674
02675 foreach($results as $result)
02676 {
02677 if($qid == $result['qid'])
02678 {
02679 if(!$result['max'] or $result['max'] != $result['reached'])
02680 {
02681 return $i;
02682 }
02683 }
02684 }
02685 }
02686 return 0;
02687 }
02688
02689
02698 function &getWorkedQuestions()
02699 {
02700 global $ilUser;
02701 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s GROUP BY question_fi",
02702 $this->ilias->db->quote($ilUser->id),
02703 $this->ilias->db->quote($this->getTestId())
02704 );
02705 $result = $this->ilias->db->query($query);
02706 $result_array = array();
02707 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02708 {
02709 array_push($result_array, $row->question_fi);
02710 }
02711 return $result_array;
02712 }
02713
02722 function &getAllQuestions()
02723 {
02724 global $ilUser;
02725
02726 if ($this->isRandomTest())
02727 {
02728 $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, ",") . ")",
02729 $this->ilias->db->quote($ilUser->id . "")
02730 );
02731 }
02732 else
02733 {
02734 $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, ",") . ")";
02735 }
02736 $result = $this->ilias->db->query($query);
02737 $result_array = array();
02738 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
02739 {
02740 $result_array[$row["question_id"]] = $row;
02741 }
02742 return $result_array;
02743 }
02744
02754 function getActiveTestUser($user_id = "")
02755 {
02756 global $ilDB;
02757 global $ilUser;
02758
02759 $db =& $ilDB->db;
02760 if (!$user_id)
02761 {
02762 $user_id = $ilUser->id;
02763 }
02764 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
02765 $db->quote($user_id),
02766 $db->quote($this->test_id)
02767 );
02768
02769 $result = $db->query($query);
02770 if ($result->numRows())
02771 {
02772 $this->active = $result->fetchRow(DB_FETCHMODE_OBJECT);
02773 }
02774 else
02775 {
02776 $this->active = null;
02777 }
02778 return $this->active;
02779 }
02780
02791 function _getActiveTestUser($user_id = "", $test_id = "") {
02792 global $ilDB;
02793 global $ilUser;
02794
02795 $db =& $ilDB->db;
02796 if (!$user_id) {
02797 $user_id = $ilUser->id;
02798 }
02799 if (!$test_id)
02800 {
02801 return "";
02802 }
02803 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
02804 $db->quote($user_id),
02805 $db->quote($test_id)
02806 );
02807
02808 $result = $db->query($query);
02809 if ($result->numRows()) {
02810 return $result->fetchRow(DB_FETCHMODE_OBJECT);
02811 } else {
02812 return "";
02813 }
02814 }
02815
02828 function setActiveTestUser($lastindex = 1, $postpone = "", $addTries = false)
02829 {
02830 global $ilDB;
02831 global $ilUser;
02832
02833 $db =& $ilDB->db;
02834 $old_active = $this->getActiveTestUser();
02835 if ($old_active) {
02836 $sequence = $old_active->sequence;
02837 $postponed = $old_active->postponed;
02838 if ($postpone) {
02839 $sequence_array = split(",", $sequence);
02840 $postpone_sequence = $sequence_array[$postpone-1];
02841 $question_id = $this->questions[$postpone_sequence];
02842 unset($sequence_array[$postpone-1]);
02843 array_push($sequence_array, $postpone_sequence);
02844 $sequence = join(",", $sequence_array);
02845 $postponed .= ",$question_id";
02846 $postponed = preg_replace("/^,/", "", $postponed);
02847 }
02848 $tries = $old_active->tries;
02849 if ($addTries) {
02850 $tries++;
02851 }
02852 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
02853 $db->quote($lastindex),
02854 $db->quote($sequence),
02855 $db->quote($postponed),
02856 $db->quote($tries),
02857 $db->quote($ilUser->id),
02858 $db->quote($this->test_id)
02859 );
02860 } else {
02861 $sequence_arr = array_flip($this->questions);
02862 $sequence = join($sequence_arr, ",");
02863 $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)",
02864 $db->quote($ilUser->id),
02865 $db->quote($this->test_id),
02866 $db->quote($sequence),
02867 $db->quote(""),
02868 $db->quote($lastindex),
02869 $db->quote(0)
02870 );
02871 }
02872 $db->query($query);
02873 }
02874
02884 function &getTestResult($user_id)
02885 {
02886
02887 if ($this->isRandomTest())
02888 {
02889 $this->loadQuestions($user_id);
02890 }
02891 $add_parameter = "?ref_id=$this->ref_id&cmd=run";
02892 $total_max_points = 0;
02893 $total_reached_points = 0;
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904 $key = 1;
02905 $result_array = array();
02906 foreach ($this->questions as $value)
02907 {
02908 $max_points = ASS_Question::_getMaximumPoints($value);
02909 $total_max_points += $max_points;
02910 $reached_points = ASS_Question::_getReachedPoints($user_id, $this->getTestId(), $value);
02911 $total_reached_points += $reached_points;
02912 if ($max_points > 0)
02913 {
02914 $percentvalue = $reached_points / $max_points;
02915 }
02916 else
02917 {
02918 $percentvalue = 0;
02919 }
02920 if (ASS_Question::_getSuggestedSolutionCount($value) == 1)
02921 {
02922 $solution_array =& ASS_Question::_getSuggestedSolution($value, 0);
02923 $href = ASS_Question::_getInternalLinkHref($solution_array["internal_link"]);
02924 }
02925 elseif (ASS_Question::_getSuggestedSolutionCount($value) > 1)
02926 {
02927 $href = "see_details_for_further_information";
02928 }
02929 else
02930 {
02931 $href = "";
02932 }
02933 $info =& ASS_Question::_getQuestionInfo($value);
02934 $row = array(
02935 "nr" => "$key",
02936 "title" => "<a href=\"" . $this->getCallingScript() . "$add_parameter&evaluation=" . $value . "\">" . ilUtil::prepareFormOutput($info["title"]) . "</a>",
02937 "max" => sprintf("%d", $max_points),
02938 "reached" => sprintf("%d", $reached_points),
02939 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
02940 "solution" => $href,
02941 "type" => $info["type_tag"],
02942 "qid" => $value
02943 );
02944 array_push($result_array, $row);
02945 $key++;
02946 }
02947 $result_array["test"]["total_max_points"] = $total_max_points;
02948 $result_array["test"]["total_reached_points"] = $total_reached_points;
02949 if ((!$total_reached_points) or (!$total_max_points))
02950 {
02951 $percentage = 0.0;
02952 }
02953 else
02954 {
02955 $percentage = ($total_reached_points / $total_max_points) * 100.0;
02956 }
02957 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
02958 $passed = "";
02959 if ($mark_obj)
02960 {
02961 if ($mark_obj->get_passed())
02962 {
02963 $passed = 1;
02964 }
02965 else
02966 {
02967 $passed = 0;
02968 }
02969 }
02970 $result_array["test"]["passed"] = $passed;
02971 return $result_array;
02972 }
02973
02974
02983 function &getTestSummary($user_id)
02984 {
02985 global $ilDB;
02986
02987 if ($this->isRandomTest())
02988 {
02989 $this->loadQuestions($user_id);
02990 }
02991
02992 $add_parameter = "?ref_id=$this->ref_id&cmd=run&crs_show_result=0&";
02993
02994 $key = 1;
02995 $result_array = array();
02996
02997 $active = $this->getActiveTestUser();
02998
02999 $solved_questions = ilObjTest::_getSolvedQuestions($this->test_id, $user_id);
03000 $user = new IlObjUser($user_id);
03001 foreach ($this->questions as $val) {
03002 $question =& ilObjTest::_instanciateQuestion($val);
03003 if (is_object($question))
03004 {
03005 $answers = $question->getSolutionValues($this->test_id, $user);
03006 $visited = count($answers);
03007 $solved = 0;
03008 if (array_key_exists($question->getId(),$solved_questions)) {
03009 $solved = $solved_questions[$question->getId()]->solved;
03010 }
03011
03012 $row = array(
03013 "nr" => "$key",
03014 "href_goto" => $this->getCallingScript() . "$add_parameter&sequence=$key",
03015 "href_setsolved" => $this->getCallingScript() . "$add_parameter&question_id=".$question->getId()."&set_solved=".(($solved)?"0":"1"),
03016 "title" => $question->getTitle(),
03017 "qid" => $question->getId(),
03018 "visited" => $visited,
03019 "solved" => (($solved)?"1":"0"),
03020 "description" => $question->getComment(),
03021 "points" => $question->getMaximumPoints()
03022 );
03023 array_push($result_array, $row);
03024 $key++;
03025 }
03026 }
03027
03028 return $result_array;
03029 }
03030
03031
03041 function &_getTestResult($user_id, $test_obj_id)
03042 {
03043 $test = new ilObjTest($test_obj_id, false);
03044 $test->loadFromDb();
03045 $result =& $test->getTestResult($user_id);
03046 return $result;
03047 }
03048
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03101
03102
03103
03104
03105
03106
03107
03113
03114
03115
03116
03117
03118
03119
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03149 function evalTotalPersons()
03150 {
03151 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
03152 $this->ilias->db->quote($this->getTestId())
03153 );
03154 $result = $this->ilias->db->query($q);
03155 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03156 return $row->total;
03157 }
03158
03167 function canViewResults()
03168 {
03169 $result = true;
03170 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST)
03171 {
03172 if ($this->getReportingDate())
03173 {
03174 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches);
03175 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03176 $now = mktime();
03177 if ($now < $epoch_time)
03178 {
03179 $result = false;
03180 }
03181 }
03182 }
03183 return $result;
03184 }
03185
03194 function evalLoadStatisticalSettings($user_id)
03195 {
03196 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
03197 $this->ilias->db->quote("$user_id")
03198 );
03199 $result = $this->ilias->db->query($q);
03200 if (!$result->numRows())
03201 {
03202 $row = array(
03203 "qworkedthrough" => "1",
03204 "pworkedthrough" => "1",
03205 "timeofwork" => "1",
03206 "atimeofwork" => "1",
03207 "firstvisit" => "1",
03208 "lastvisit" => "1",
03209 "resultspoints" => "1",
03210 "resultsmarks" => "1",
03211 "distancemedian" => "1"
03212 );
03213 }
03214 else
03215 {
03216 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03217 unset($row["eval_settings_id"]);
03218 }
03219 return $row;
03220 }
03221
03230 function evalSaveStatisticalSettings($settings_array, $user_id)
03231 {
03232 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
03233 $this->ilias->db->quote("$user_id")
03234 );
03235 $result = $this->ilias->db->query($q);
03236 if ($result->numRows() > 0)
03237 {
03238 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03239 }
03240 $update = $row["eval_settings_id"];
03241 if (!$update) {
03242 $q = sprintf("INSERT INTO tst_eval_settings ".
03243 "(eval_settings_id, user_fi, qworkedthrough, pworkedthrough, timeofwork, atimeofwork, firstvisit, " .
03244 "lastvisit, resultspoints, resultsmarks, distancemedian, TIMESTAMP) VALUES " .
03245 "(NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
03246 $this->ilias->db->quote("$user_id"),
03247 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
03248 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
03249 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
03250 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
03251 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
03252 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
03253 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
03254 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
03255 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"]))
03256 );
03257 }
03258 else
03259 {
03260 $q = sprintf("UPDATE tst_eval_settings SET ".
03261 "qworkedthrough = %s, pworkedthrough = %s, timeofwork = %s, atimeofwork = %s, firstvisit = %s, " .
03262 "lastvisit = %s, resultspoints = %s, resultsmarks = %s, distancemedian = %s " .
03263 "WHERE eval_settings_id = %s",
03264 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
03265 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
03266 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
03267 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
03268 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
03269 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
03270 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
03271 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
03272 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"])),
03273 $this->ilias->db->quote("$update")
03274 );
03275 }
03276 $result = $this->ilias->db->query($q);
03277 }
03278
03287 function getCompleteWorkingTime($user_id)
03288 {
03289 $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",
03290 $this->ilias->db->quote($this->getTestId()),
03291 $this->ilias->db->quote($user_id)
03292 );
03293 $result = $this->ilias->db->query($q);
03294 $time = 0;
03295 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03296 {
03297 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03298 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03299 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03300 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03301 $time += ($epoch_2 - $epoch_1);
03302 }
03303 return $time;
03304 }
03305
03314 function &evalStatistical($user_id)
03315 {
03316
03317
03318 $test_result =& $this->getTestResult($user_id);
03319 $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",
03320 $this->ilias->db->quote($this->getTestId()),
03321 $this->ilias->db->quote($user_id)
03322 );
03323 $result = $this->ilias->db->query($q);
03324 $times = array();
03325 $first_visit = "";
03326 $last_visit = "";
03327 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
03328 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03329 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03330 if (!$first_visit) {
03331 $first_visit = $epoch_1;
03332 }
03333 if ($epoch_1 < $first_visit) {
03334 $first_visit = $epoch_1;
03335 }
03336 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03337 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03338 if (!$last_visit) {
03339 $last_visit = $epoch_2;
03340 }
03341 if ($epoch_2 > $last_visit) {
03342 $last_visit = $epoch_2;
03343 }
03344 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03345 }
03346 $max_time = 0;
03347 foreach ($times as $key => $value) {
03348 $max_time += $value;
03349 }
03350 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"])) {
03351 $percentage = 0.0;
03352 } else {
03353 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
03354 }
03355 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03356 $first_date = getdate($first_visit);
03357 $last_date = getdate($last_visit);
03358 $qworkedthrough = 0;
03359 $query_worked_through = sprintf("SELECT test_result_id FROM tst_test_result WHERE user_fi = %s AND test_fi = %s",
03360
03361 $this->ilias->db->quote("$user_id"),
03362 $this->ilias->db->quote($this->getTestId())
03363 );
03364 $worked_through_result = $this->ilias->db->query($query_worked_through);
03365 if (!$worked_through_result->numRows())
03366 {
03367 $atimeofwork = 0;
03368 }
03369 else
03370 {
03371 $atimeofwork = $max_time / $worked_through_result->numRows();
03372 }
03373 $result_mark = "";
03374 $passed = "";
03375 if ($mark_obj)
03376 {
03377 $result_mark = $mark_obj->get_short_name();
03378 if ($mark_obj->get_passed())
03379 {
03380 $passed = 1;
03381 }
03382 else
03383 {
03384 $passed = 0;
03385 }
03386 }
03387 $result_array = array(
03388 "qworkedthrough" => $worked_through_result->numRows(),
03389 "qmax" => count($this->questions),
03390 "pworkedthrough" => ($worked_through_result->numRows()) / count($this->questions),
03391 "timeofwork" => $max_time,
03392 "atimeofwork" => $atimeofwork,
03393 "firstvisit" => $first_date,
03394 "lastvisit" => $last_date,
03395 "resultspoints" => $test_result["test"]["total_reached_points"],
03396 "maxpoints" => $test_result["test"]["total_max_points"],
03397 "resultsmarks" => $result_mark,
03398 "passed" => $passed,
03399 "distancemedian" => "0"
03400 );
03401 foreach ($test_result as $key => $value)
03402 {
03403 if (preg_match("/\d+/", $key))
03404 {
03405 $result_array[$key] = $value;
03406 }
03407 }
03408 return $result_array;
03409 }
03410
03420 function &getTotalPointsArray()
03421 {
03422 $totalpoints_array = array();
03423 $all_users =& $this->evalTotalPersonsArray();
03424 foreach ($all_users as $user_id => $user_name)
03425 {
03426 $test_result =& $this->getTestResult($user_id);
03427 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03428 }
03429 return $totalpoints_array;
03430 }
03431
03441 function &getTotalPointsPassedArray()
03442 {
03443 $totalpoints_array = array();
03444 $all_users =& $this->evalTotalPersonsArray();
03445 foreach ($all_users as $user_id => $user_name)
03446 {
03447 $test_result =& $this->getTestResult($user_id);
03448 $reached = $test_result["test"]["total_reached_points"];
03449 $total = $test_result["test"]["total_max_points"];
03450 $percentage = $reached/$total;
03451 $mark = $this->mark_schema->get_matching_mark($percentage*100.0);
03452 if ($mark)
03453 {
03454 if ($mark->get_passed())
03455 {
03456 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03457 }
03458 }
03459 }
03460 return $totalpoints_array;
03461 }
03462
03471 function &evalTotalPersonsArray()
03472 {
03473 $q = sprintf("SELECT tst_active.user_fi, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname",
03474 $this->ilias->db->quote($this->getTestId())
03475 );
03476 $result = $this->ilias->db->query($q);
03477 $persons_array = array();
03478 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03479 {
03480 if (strlen($row->firstname.$row->lastname.$row->title) == 0)
03481 {
03482 $persons_array[$row->user_fi] = $this->lng->txt("deleted_user");
03483 }
03484 else
03485 {
03486 $persons_array[$row->user_fi] = trim("$row->lastname, $row->firstname $row->title");
03487 }
03488 }
03489 return $persons_array;
03490 }
03491
03500 function evalTotalFinished()
03501 {
03502 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
03503 $this->ilias->db->quote($this->getTestId())
03504 );
03505 $result = $this->ilias->db->query($q);
03506 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03507 return $row->total;
03508 }
03509
03519 function evalTotalFinishedPassed()
03520 {
03521 $q = sprintf("SELECT * FROM tst_active WHERE test_fi = %s AND tries > 0",
03522 $this->ilias->db->quote($this->getTestId())
03523 );
03524 $result = $this->ilias->db->query($q);
03525 $points = array();
03526 $passed_tests = 0;
03527 $failed_tests = 0;
03528 $maximum_points = 0;
03529 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03530 {
03531 $res =& $this->getTestResult($row->user_fi);
03532 if ((!$res["test"]["total_reached_points"]) or (!$res["test"]["total_max_points"]))
03533 {
03534 $percentage = 0.0;
03535 }
03536 else
03537 {
03538 $percentage = ($res["test"]["total_reached_points"] / $res["test"]["total_max_points"]) * 100.0;
03539 }
03540 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03541 $maximum_points = $res["test"]["total_max_points"];
03542 if ($mark_obj)
03543 {
03544 if ($mark_obj->get_passed()) {
03545 $passed_tests++;
03546 array_push($points, $res["test"]["total_reached_points"]);
03547 }
03548 else
03549 {
03550 $failed_tests++;
03551 }
03552 }
03553 }
03554 $reached_points = 0;
03555 $counter = 0;
03556 foreach ($points as $key => $value)
03557 {
03558 $reached_points += $value;
03559 $counter++;
03560 }
03561 if ($counter)
03562 {
03563 $average_points = round($reached_points / $counter);
03564 }
03565 else
03566 {
03567 $average_points = 0;
03568 }
03569 return array(
03570 "total_passed" => $passed_tests,
03571 "total_failed" => $failed_tests,
03572 "average_points" => $average_points,
03573 "maximum_points" => $maximum_points
03574 );
03575 }
03576
03585 function evalTotalFinishedAverageTime()
03586 {
03587 $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",
03588 $this->ilias->db->quote($this->getTestId())
03589 );
03590 $result = $this->ilias->db->query($q);
03591 $times = array();
03592 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03593 {
03594 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03595 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03596 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03597 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03598 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03599 }
03600 $max_time = 0;
03601 $counter = 0;
03602 foreach ($times as $key => $value)
03603 {
03604 $max_time += $value;
03605 $counter++;
03606 }
03607 if ($counter)
03608 {
03609 $average_time = round($max_time / $counter);
03610 }
03611 else
03612 {
03613 $average_time = 0;
03614 }
03615 return $average_time;
03616 }
03617
03626 function &getAvailableQuestionpoolIDs()
03627 {
03628 global $rbacsystem;
03629
03630 $result_array = array();
03631 $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'";
03632 $result = $this->ilias->db->query($query);
03633 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03634 {
03635 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03636 {
03637 array_push($result_array, $row->obj_id);
03638 }
03639 }
03640 return $result_array;
03641 }
03642
03651 function &getAvailableQuestionpools($use_object_id = false)
03652 {
03653 global $rbacsystem;
03654
03655 $result_array = array();
03656 $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";
03657 $result = $this->ilias->db->query($query);
03658 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03659 {
03660 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03661 {
03662 if ($use_object_id)
03663 {
03664 $result_array[$row->obj_id] = $row->title;
03665 }
03666 else
03667 {
03668 $result_array[$row->ref_id] = $row->title;
03669 }
03670 }
03671 }
03672 return $result_array;
03673 }
03674
03683 function getEstimatedWorkingTime()
03684 {
03685 $time_in_seconds = 0;
03686 foreach ($this->questions as $question_id) {
03687 $question =& ilObjTest::_instanciateQuestion($question_id);
03688 $est_time = $question->getEstimatedWorkingTime();
03689 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
03690 }
03691 $hours = (int)($time_in_seconds / 3600) ;
03692 $time_in_seconds = $time_in_seconds - ($hours * 3600);
03693 $minutes = (int)($time_in_seconds / 60);
03694 $time_in_seconds = $time_in_seconds - ($minutes * 60);
03695 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
03696 return $result;
03697 }
03698
03711 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "")
03712 {
03713 global $rbacsystem;
03714
03715 if ($questionpool != 0)
03716 {
03717
03718 if (!$use_obj_id)
03719 {
03720 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
03721 $this->ilias->db->quote("$questionpool")
03722 );
03723 $result = $this->ilias->db->query($query);
03724 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03725 $questionpool = $row[0];
03726 }
03727 }
03728
03729
03730 $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",
03731 $this->ilias->db->quote($this->getTestId() . "")
03732 );
03733 $result = $this->ilias->db->query($query);
03734 $original_ids = array();
03735 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
03736 {
03737 if (strcmp($row[0], "") != 0)
03738 {
03739 array_push($original_ids, $row[0]);
03740 }
03741 }
03742 $original_clause = "";
03743 if (count($original_ids))
03744 {
03745 $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
03746 }
03747
03748
03749 if (($questionpool == 0) && (!is_array($qpls)))
03750 {
03751 $available_pools =& $this->getAvailableQuestionpoolIDs();
03752 $available = "";
03753 $constraint_qpls = "";
03754 if (count($available_pools))
03755 {
03756 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
03757 }
03758 else
03759 {
03760 return array();
03761 }
03762 }
03763
03764 $result_array = array();
03765 if ($questionpool == 0)
03766 {
03767 if (is_array($qpls))
03768 {
03769 if (count($qpls) > 0)
03770 {
03771 $qplidx = array();
03772 foreach ($qpls as $idx => $arr)
03773 {
03774 array_push($qplidx, $arr["qpl"]);
03775 }
03776 $constraint_qpls = " AND qpl_questions.obj_fi IN (" . join($qplidx, ",") . ")";
03777 }
03778 }
03779 $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$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
03780 }
03781 else
03782 {
03783 $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
03784 $this->ilias->db->quote("$questionpool")
03785 );
03786 }
03787 $result = $this->ilias->db->query($query);
03788 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03789 if (($row[0]) <= $nr_of_questions)
03790 {
03791
03792 if ($questionpool == 0)
03793 {
03794 $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$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
03795 }
03796 else
03797 {
03798 $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",
03799 $this->ilias->db->quote("$questionpool")
03800 );
03801 }
03802 $result = $this->ilias->db->query($query);
03803 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
03804 {
03805 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
03806 {
03807 $result_array[$row[0]] = $row[0];
03808 }
03809 }
03810 }
03811 else
03812 {
03813
03814 mt_srand((double)microtime()*1000000);
03815 $random_number = mt_rand(0, $row[0] - 1);
03816 $securitycounter = 500;
03817 while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
03818 {
03819 if ($questionpool == 0)
03820 {
03821 $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$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1";
03822 }
03823 else
03824 {
03825 $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",
03826 $this->ilias->db->quote("$questionpool")
03827 );
03828 }
03829 $result = $this->ilias->db->query($query);
03830 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
03831 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
03832 {
03833 $result_array[$result_row[0]] = $result_row[0];
03834 }
03835 $random_number = mt_rand(0, $row[0] - 1);
03836 $securitycounter--;
03837 }
03838 }
03839 return $result_array;
03840 }
03841
03850 function getImagePath()
03851 {
03852 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
03853 }
03854
03863 function getImagePathWeb()
03864 {
03865 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
03866 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
03867 }
03868
03879 function &createQuestionGUI($question_type, $question_id = -1)
03880 {
03881 if ((!$question_type) and ($question_id > 0))
03882 {
03883 $question_type = $this->getQuestionType($question_id);
03884 }
03885 switch ($question_type)
03886 {
03887 case "qt_multiple_choice_sr":
03888 $question =& new ASS_MultipleChoiceGUI();
03889 $question->object->set_response(RESPONSE_SINGLE);
03890 break;
03891 case "qt_multiple_choice_mr":
03892 $question =& new ASS_MultipleChoiceGUI();
03893 $question->object->set_response(RESPONSE_MULTIPLE);
03894 break;
03895 case "qt_cloze":
03896 $question =& new ASS_ClozeTestGUI();
03897 break;
03898 case "qt_matching":
03899 $question =& new ASS_MatchingQuestionGUI();
03900 break;
03901 case "qt_ordering":
03902 $question =& new ASS_OrderingQuestionGUI();
03903 break;
03904 case "qt_imagemap":
03905 $question =& new ASS_ImagemapQuestionGUI();
03906 break;
03907 case "qt_javaapplet":
03908 $question =& new ASS_JavaAppletGUI();
03909 break;
03910 case "qt_text":
03911 $question =& new ASS_TextQuestionGUI();
03912 break;
03913 }
03914 if ($question_id > 0)
03915 {
03916 $question->object->loadFromDb($question_id);
03917 }
03918 return $question;
03919 }
03920
03930 function &_instanciateQuestion($question_id)
03931 {
03932 if (strcmp($question_id, "") != 0)
03933 {
03934 $question_type = ASS_Question::_getQuestionType($question_id);
03935
03936 switch ($question_type) {
03937 case "qt_cloze":
03938 $question = new ASS_ClozeTest();
03939 break;
03940 case "qt_matching":
03941 $question = new ASS_MatchingQuestion();
03942 break;
03943 case "qt_ordering":
03944 $question = new ASS_OrderingQuestion();
03945 break;
03946 case "qt_imagemap":
03947 $question = new ASS_ImagemapQuestion();
03948 break;
03949 case "qt_multiple_choice_sr":
03950 case "qt_multiple_choice_mr":
03951 $question = new ASS_MultipleChoice();
03952 break;
03953 case "qt_javaapplet":
03954 $question = new ASS_JavaApplet();
03955 break;
03956 case "qt_text":
03957 $question = new ASS_TextQuestion();
03958 break;
03959
03960 default:
03961
03962 return false;
03963 }
03964
03965 $question->loadFromDb($question_id);
03966 return $question;
03967 }
03968 }
03969
03980 function moveQuestions($move_questions, $target_index, $insert_mode)
03981 {
03982 $this->questions = array_values($this->questions);
03983 $array_pos = array_search($target_index, $this->questions);
03984 if ($insert_mode == 0)
03985 {
03986 $part1 = array_slice($this->questions, 0, $array_pos);
03987 $part2 = array_slice($this->questions, $array_pos);
03988 }
03989 else if ($insert_mode == 1)
03990 {
03991 $part1 = array_slice($this->questions, 0, $array_pos + 1);
03992 $part2 = array_slice($this->questions, $array_pos + 1);
03993 }
03994 foreach ($move_questions as $question_id)
03995 {
03996 if (!(array_search($question_id, $part1) === FALSE))
03997 {
03998 unset($part1[array_search($question_id, $part1)]);
03999 }
04000 if (!(array_search($question_id, $part2) === FALSE))
04001 {
04002 unset($part2[array_search($question_id, $part2)]);
04003 }
04004 }
04005 $part1 = array_values($part1);
04006 $part2 = array_values($part2);
04007 $new_array = array_values(array_merge($part1, $move_questions, $part2));
04008 $this->questions = array();
04009 $counter = 1;
04010 foreach ($new_array as $question_id)
04011 {
04012 $this->questions[$counter] = $question_id;
04013 $counter++;
04014 }
04015 $this->saveQuestionsToDb();
04016 }
04017
04018
04028 function startingTimeReached()
04029 {
04030 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST)
04031 {
04032 if ($this->getStartingTime())
04033 {
04034 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches);
04035 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04036 $now = mktime();
04037 if ($now < $epoch_time)
04038 {
04039
04040 return false;
04041 }
04042 }
04043 }
04044 return true;
04045 }
04046
04056 function endingTimeReached()
04057 {
04058 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST)
04059 {
04060 if ($this->getEndingTime())
04061 {
04062 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches);
04063 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04064 $now = mktime();
04065 if ($now > $epoch_time)
04066 {
04067
04068 return true;
04069 }
04070 }
04071 }
04072 return false;
04073 }
04074
04082 function getQuestionsTable($sortoptions, $filter_text, $sel_filter_type, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
04083 {
04084 global $ilUser;
04085 $where = "";
04086 if (strlen($filter_text) > 0) {
04087 switch($sel_filter_type) {
04088 case "title":
04089 $where = " AND qpl_questions.title LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04090 break;
04091 case "comment":
04092 $where = " AND qpl_questions.comment LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04093 break;
04094 case "author":
04095 $where = " AND qpl_questions.author LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04096 break;
04097 }
04098 }
04099
04100 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
04101 {
04102 $where .= " AND qpl_question_type.type_tag = " . $this->ilias->db->quote($filter_question_type);
04103 }
04104
04105 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
04106 {
04107 $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
04108 }
04109
04110
04111 $order = "";
04112 $images = array();
04113 if (count($sortoptions)) {
04114 foreach ($sortoptions as $key => $value) {
04115 switch($key) {
04116 case "title":
04117 $order = " ORDER BY title $value";
04118 $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04119 break;
04120 case "comment":
04121 $order = " ORDER BY comment $value";
04122 $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04123 break;
04124 case "type":
04125 $order = " ORDER BY question_type_id $value";
04126 $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04127 break;
04128 case "author":
04129 $order = " ORDER BY author $value";
04130 $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04131 break;
04132 case "created":
04133 $order = " ORDER BY created $value";
04134 $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04135 break;
04136 case "updated":
04137 $order = " ORDER BY TIMESTAMP14 $value";
04138 $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04139 break;
04140 case "qpl":
04141 $order = " ORDER BY obj_fi $value";
04142 $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . strtolower($value) . "ending order\" />";
04143 break;
04144 }
04145 }
04146 }
04147 $maxentries = $ilUser->prefs["hits_per_page"];
04148 if ($maxentries < 1)
04149 {
04150 $maxentries = 9999;
04151 }
04152 $available_pools =& $this->getAvailableQuestionpoolIDs();
04153 $available = "";
04154 if (count($available_pools))
04155 {
04156 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
04157 }
04158 else
04159 {
04160 return array();
04161 }
04162 if ($completeonly)
04163 {
04164 $available .= " AND qpl_questions.complete = " . $this->ilias->db->quote("1");
04165 }
04166
04167
04168 $query = sprintf("SELECT qpl_questions.original_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
04169 $this->ilias->db->quote($this->getTestId() . "")
04170 );
04171 $result = $this->ilias->db->query($query);
04172 $original_ids = array();
04173 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04174 {
04175 if (strcmp($row[0], "") != 0)
04176 {
04177 array_push($original_ids, $row[0]);
04178 }
04179 }
04180 $original_clause = " ISNULL(qpl_questions.original_id)";
04181 if (count($original_ids))
04182 {
04183 $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
04184 }
04185
04186 $query = "SELECT qpl_questions.question_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, qpl_question_type WHERE $original_clause$available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
04187 $query_result = $this->ilias->db->query($query);
04188 $max = $query_result->numRows();
04189 if ($startrow > $max -1)
04190 {
04191 $startrow = $max - ($max % $maxentries);
04192 }
04193 else if ($startrow < 0)
04194 {
04195 $startrow = 0;
04196 }
04197 $limit = " LIMIT $startrow, $maxentries";
04198 $query = "SELECT qpl_questions.*, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type WHERE $original_clause $available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
04199 $query_result = $this->ilias->db->query($query);
04200 $rows = array();
04201 if ($query_result->numRows())
04202 {
04203 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
04204 {
04205 array_push($rows, $row);
04206 }
04207 }
04208 $nextrow = $startrow + $maxentries;
04209 if ($nextrow > $max - 1)
04210 {
04211 $nextrow = $startrow;
04212 }
04213 $prevrow = $startrow - $maxentries;
04214 if ($prevrow < 0)
04215 {
04216 $prevrow = 0;
04217 }
04218 return array(
04219 "rows" => $rows,
04220 "images" => $images,
04221 "startrow" => $startrow,
04222 "nextrow" => $nextrow,
04223 "prevrow" => $prevrow,
04224 "step" => $maxentries,
04225 "rowcount" => $max
04226 );
04227 }
04228
04238 function _getTestType($test_id)
04239 {
04240 global $ilDB;
04241
04242 $result = "";
04243 $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",
04244 $ilDB->quote($test_id)
04245 );
04246 $query_result = $ilDB->query($query);
04247 if ($query_result->numRows())
04248 {
04249 $row = $query_result->fetchRow(DB_FETCHMODE_ASSOC);
04250 $result = $row["type_tag"];
04251 }
04252 return $result;
04253 }
04254
04263 function &_getQuestiontypes()
04264 {
04265 global $ilDB;
04266
04267 $questiontypes = array();
04268 $query = "SELECT * FROM qpl_question_type ORDER BY type_tag";
04269 $query_result = $ilDB->query($query);
04270 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
04271 {
04272 array_push($questiontypes, $row["type_tag"]);
04273 }
04274 return $questiontypes;
04275 }
04276
04285 function to_xml()
04286 {
04287 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
04288 $domxml = domxml_open_mem($xml_header);
04289 $root = $domxml->document_element();
04290
04291 $qtiAssessment = $domxml->create_element("assessment");
04292 $qtiAssessment->set_attribute("ident", "il_".IL_INST_ID."_tst_".$this->getTestId());
04293 $qtiAssessment->set_attribute("title", $this->getTitle());
04294
04295
04296 $qtiComment = $domxml->create_element("qticomment");
04297 $qtiCommentText = $domxml->create_text_node($this->getDescription());
04298 $qtiComment->append_child($qtiCommentText);
04299 $qtiAssessment->append_child($qtiComment);
04300
04301
04302 if ($this->enable_processing_time)
04303 {
04304 $qtiDuration = $domxml->create_element("duration");
04305 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
04306 $qtiDurationText = $domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
04307 $qtiDuration->append_child($qtiDurationText);
04308 $qtiAssessment->append_child($qtiDuration);
04309 }
04310
04311
04312 $qtiMetadata = $domxml->create_element("qtimetadata");
04313
04314 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04315 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04316 $qtiFieldLabelText = $domxml->create_text_node("ILIAS_VERSION");
04317 $qtiFieldLabel->append_child($qtiFieldLabelText);
04318 $qtiFieldEntry = $domxml->create_element("fieldentry");
04319 $qtiFieldEntryText = $domxml->create_text_node($this->ilias->getSetting("ilias_version"));
04320 $qtiFieldEntry->append_child($qtiFieldEntryText);
04321 $qtiMetadatafield->append_child($qtiFieldLabel);
04322 $qtiMetadatafield->append_child($qtiFieldEntry);
04323 $qtiMetadata->append_child($qtiMetadatafield);
04324
04325 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04326 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04327 $qtiFieldLabelText = $domxml->create_text_node("test_type");
04328 $qtiFieldLabel->append_child($qtiFieldLabelText);
04329 $qtiFieldEntry = $domxml->create_element("fieldentry");
04330 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getTestType()));
04331 $qtiFieldEntry->append_child($qtiFieldEntryText);
04332 $qtiMetadatafield->append_child($qtiFieldLabel);
04333 $qtiMetadatafield->append_child($qtiFieldEntry);
04334 $qtiMetadata->append_child($qtiMetadatafield);
04335
04336 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04337 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04338 $qtiFieldLabelText = $domxml->create_text_node("sequence_settings");
04339 $qtiFieldLabel->append_child($qtiFieldLabelText);
04340 $qtiFieldEntry = $domxml->create_element("fieldentry");
04341 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getSequenceSettings()));
04342 $qtiFieldEntry->append_child($qtiFieldEntryText);
04343 $qtiMetadatafield->append_child($qtiFieldLabel);
04344 $qtiMetadatafield->append_child($qtiFieldEntry);
04345 $qtiMetadata->append_child($qtiMetadatafield);
04346
04347 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04348 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04349 $qtiFieldLabelText = $domxml->create_text_node("author");
04350 $qtiFieldLabel->append_child($qtiFieldLabelText);
04351 $qtiFieldEntry = $domxml->create_element("fieldentry");
04352 $qtiFieldEntryText = $domxml->create_text_node($this->getAuthor());
04353 $qtiFieldEntry->append_child($qtiFieldEntryText);
04354 $qtiMetadatafield->append_child($qtiFieldLabel);
04355 $qtiMetadatafield->append_child($qtiFieldEntry);
04356 $qtiMetadata->append_child($qtiMetadatafield);
04357
04358 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04359 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04360 $qtiFieldLabelText = $domxml->create_text_node("count_system");
04361 $qtiFieldLabel->append_child($qtiFieldLabelText);
04362 $qtiFieldEntry = $domxml->create_element("fieldentry");
04363 $qtiFieldEntryText = $domxml->create_text_node($this->getCountSystem());
04364 $qtiFieldEntry->append_child($qtiFieldEntryText);
04365 $qtiMetadatafield->append_child($qtiFieldLabel);
04366 $qtiMetadatafield->append_child($qtiFieldEntry);
04367 $qtiMetadata->append_child($qtiMetadatafield);
04368
04369 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04370 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04371 $qtiFieldLabelText = $domxml->create_text_node("mc_scoring");
04372 $qtiFieldLabel->append_child($qtiFieldLabelText);
04373 $qtiFieldEntry = $domxml->create_element("fieldentry");
04374 $qtiFieldEntryText = $domxml->create_text_node($this->getMCScoring());
04375 $qtiFieldEntry->append_child($qtiFieldEntryText);
04376 $qtiMetadatafield->append_child($qtiFieldLabel);
04377 $qtiMetadatafield->append_child($qtiFieldEntry);
04378 $qtiMetadata->append_child($qtiMetadatafield);
04379
04380 if ($this->getReportingDate())
04381 {
04382 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04383 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04384 $qtiFieldLabelText = $domxml->create_text_node("reporting_date");
04385 $qtiFieldLabel->append_child($qtiFieldLabelText);
04386 $qtiFieldEntry = $domxml->create_element("fieldentry");
04387 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
04388 $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]));
04389 $qtiFieldEntry->append_child($qtiFieldEntryText);
04390 $qtiMetadatafield->append_child($qtiFieldLabel);
04391 $qtiMetadatafield->append_child($qtiFieldEntry);
04392 $qtiMetadata->append_child($qtiMetadatafield);
04393 }
04394
04395 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04396 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04397 $qtiFieldLabelText = $domxml->create_text_node("nr_of_tries");
04398 $qtiFieldLabel->append_child($qtiFieldLabelText);
04399 $qtiFieldEntry = $domxml->create_element("fieldentry");
04400 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getNrOfTries()));
04401 $qtiFieldEntry->append_child($qtiFieldEntryText);
04402 $qtiMetadatafield->append_child($qtiFieldLabel);
04403 $qtiMetadatafield->append_child($qtiFieldEntry);
04404 $qtiMetadata->append_child($qtiMetadatafield);
04405
04406 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04407 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04408 $qtiFieldLabelText = $domxml->create_text_node("random_test");
04409 $qtiFieldLabel->append_child($qtiFieldLabelText);
04410 $qtiFieldEntry = $domxml->create_element("fieldentry");
04411 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->isRandomTest()));
04412 $qtiFieldEntry->append_child($qtiFieldEntryText);
04413 $qtiMetadatafield->append_child($qtiFieldLabel);
04414 $qtiMetadatafield->append_child($qtiFieldEntry);
04415 $qtiMetadata->append_child($qtiMetadatafield);
04416
04417 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04418 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04419 $qtiFieldLabelText = $domxml->create_text_node("random_question_count");
04420 $qtiFieldLabel->append_child($qtiFieldLabelText);
04421 $qtiFieldEntry = $domxml->create_element("fieldentry");
04422 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getRandomQuestionCount()));
04423 $qtiFieldEntry->append_child($qtiFieldEntryText);
04424 $qtiMetadatafield->append_child($qtiFieldLabel);
04425 $qtiMetadatafield->append_child($qtiFieldEntry);
04426 $qtiMetadata->append_child($qtiMetadatafield);
04427
04428 if ($this->getStartingTime())
04429 {
04430 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04431 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04432 $qtiFieldLabelText = $domxml->create_text_node("starting_time");
04433 $qtiFieldLabel->append_child($qtiFieldLabelText);
04434 $qtiFieldEntry = $domxml->create_element("fieldentry");
04435 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
04436 $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]));
04437 $qtiFieldEntry->append_child($qtiFieldEntryText);
04438 $qtiMetadatafield->append_child($qtiFieldLabel);
04439 $qtiMetadatafield->append_child($qtiFieldEntry);
04440 $qtiMetadata->append_child($qtiMetadatafield);
04441 }
04442
04443 if ($this->getEndingTime())
04444 {
04445 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04446 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04447 $qtiFieldLabelText = $domxml->create_text_node("ending_time");
04448 $qtiFieldLabel->append_child($qtiFieldLabelText);
04449 $qtiFieldEntry = $domxml->create_element("fieldentry");
04450 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
04451 $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]));
04452 $qtiFieldEntry->append_child($qtiFieldEntryText);
04453 $qtiMetadatafield->append_child($qtiFieldLabel);
04454 $qtiMetadatafield->append_child($qtiFieldEntry);
04455 $qtiMetadata->append_child($qtiMetadatafield);
04456 }
04457 foreach ($this->mark_schema->mark_steps as $index => $mark)
04458 {
04459
04460 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04461 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04462 $qtiFieldLabelText = $domxml->create_text_node("mark_step_$index");
04463 $qtiFieldLabel->append_child($qtiFieldLabelText);
04464 $qtiFieldEntry = $domxml->create_element("fieldentry");
04465 $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()));
04466 $qtiFieldEntry->append_child($qtiFieldEntryText);
04467 $qtiMetadatafield->append_child($qtiFieldLabel);
04468 $qtiMetadatafield->append_child($qtiFieldEntry);
04469 $qtiMetadata->append_child($qtiMetadatafield);
04470 }
04471 $qtiAssessment->append_child($qtiMetadata);
04472
04473
04474 $qtiObjectives = $domxml->create_element("objectives");
04475 $qtiMaterial = $domxml->create_element("material");
04476 $qtiMaterial->set_attribute("label", "introduction");
04477 $qtiMatText = $domxml->create_element("mattext");
04478 $qtiMatTextText = $domxml->create_text_node($this->getIntroduction());
04479 $qtiMatText->append_child($qtiMatTextText);
04480 $qtiMaterial->append_child($qtiMatText);
04481 $qtiObjectives->append_child($qtiMaterial);
04482 $qtiAssessment->append_child($qtiObjectives);
04483
04484
04485 $qtiAssessmentcontrol = $domxml->create_element("assessmentcontrol");
04486 $score_reporting = "No";
04487 switch ($this->getScoreReporting())
04488 {
04489 case "1":
04490 $score_reporting = "Yes";
04491 break;
04492 }
04493 $qtiAssessmentcontrol->set_attribute("solutionswitch", $score_reporting);
04494 $qtiAssessment->append_child($qtiAssessmentcontrol);
04495
04496 $qtiSection = $domxml->create_element("section");
04497 $qtiSection->set_attribute("ident", "1");
04498 $qtiAssessment->append_child($qtiSection);
04499
04500 $root->append_child($qtiAssessment);
04501 $xml = $domxml->dump_mem(true);
04502 $domxml->free();
04503 foreach ($this->questions as $question_id) {
04504 $question =& ilObjTest::_instanciateQuestion($question_id);
04505 $qti_question = $question->to_xml(false);
04506 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
04507 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
04508 if (strpos($xml, "</section>") !== false)
04509 {
04510 $xml = str_replace("</section>", "$qti_question</section>", $xml);
04511 }
04512 else
04513 {
04514 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
04515 }
04516 }
04517 return $xml;
04518 }
04519
04526 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
04527 {
04528 global $ilBench;
04529
04530 $this->mob_ids = array();
04531 $this->file_ids = array();
04532
04533 $attrs = array();
04534 $attrs["Type"] = "Test";
04535 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
04536
04537
04538 $this->exportXMLMetaData($a_xml_writer);
04539
04540
04541 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
04542 $ilBench->start("ContentObjectExport", "exportPageObjects");
04543 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
04544 $ilBench->stop("ContentObjectExport", "exportPageObjects");
04545 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
04546
04547
04548 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
04549 $ilBench->start("ContentObjectExport", "exportMediaObjects");
04550 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
04551 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
04552 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
04553
04554
04555 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
04556 $ilBench->start("ContentObjectExport", "exportFileItems");
04557 $this->exportFileItems($a_target_dir, $expLog);
04558 $ilBench->stop("ContentObjectExport", "exportFileItems");
04559 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
04560
04561 $a_xml_writer->xmlEndTag("ContentObject");
04562 }
04563
04570 function exportXMLMetaData(&$a_xml_writer)
04571 {
04572 include_once("Services/MetaData/classes/class.ilMD2XML.php");
04573 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
04574 $md2xml->setExportMode(true);
04575 $md2xml->startExport();
04576 $a_xml_writer->appendXML($md2xml->getXML());
04577 }
04578
04586 function modifyExportIdentifier($a_tag, $a_param, $a_value)
04587 {
04588 if ($a_tag == "Identifier" && $a_param == "Entry")
04589 {
04590 $a_value = ilUtil::insertInstIntoID($a_value);
04591 }
04592
04593 return $a_value;
04594 }
04595
04596
04603 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
04604 {
04605 global $ilBench;
04606
04607 include_once "./content/classes/class.ilLMPageObject.php";
04608
04609 foreach ($this->questions as $question_id)
04610 {
04611 $ilBench->start("ContentObjectExport", "exportPageObject");
04612 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
04613
04614 $attrs = array();
04615 $a_xml_writer->xmlStartTag("PageObject", $attrs);
04616
04617
04618
04619 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
04620 $page_object = new ilPageObject("qpl", $question_id);
04621 $page_object->buildDom();
04622 $page_object->insertInstIntoIDs($a_inst);
04623 $mob_ids = $page_object->collectMediaObjects(false);
04624 $file_ids = $page_object->collectFileItems();
04625 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
04626 $xml = str_replace("&","&", $xml);
04627 $a_xml_writer->appendXML($xml);
04628 $page_object->freeDom();
04629 unset ($page_object);
04630
04631 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
04632
04633
04634 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
04635
04636 foreach($mob_ids as $mob_id)
04637 {
04638 $this->mob_ids[$mob_id] = $mob_id;
04639 }
04640 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
04641
04642
04643 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
04644
04645 foreach($file_ids as $file_id)
04646 {
04647 $this->file_ids[$file_id] = $file_id;
04648 }
04649 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
04650
04651 $a_xml_writer->xmlEndTag("PageObject");
04652
04653
04654 $ilBench->stop("ContentObjectExport", "exportPageObject");
04655
04656
04657 }
04658 }
04659
04666 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
04667 {
04668 include_once("content/classes/Media/class.ilObjMediaObject.php");
04669
04670 foreach ($this->mob_ids as $mob_id)
04671 {
04672 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
04673 $media_obj = new ilObjMediaObject($mob_id);
04674 $media_obj->exportXML($a_xml_writer, $a_inst);
04675 $media_obj->exportFiles($a_target_dir);
04676 unset($media_obj);
04677 }
04678 }
04679
04684 function exportFileItems($a_target_dir, &$expLog)
04685 {
04686 include_once("classes/class.ilObjFile.php");
04687
04688 foreach ($this->file_ids as $file_id)
04689 {
04690 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
04691 $file_obj = new ilObjFile($file_id, false);
04692 $file_obj->export($a_target_dir);
04693 unset($file_obj);
04694 }
04695 }
04696
04705 function from_xml($xml_text)
04706 {
04707 $result = false;
04708 $this->mark_schema->flush();
04709 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
04710 $domxml = domxml_open_mem($xml_text);
04711 if (!empty($domxml))
04712 {
04713 $root = $domxml->document_element();
04714 $this->setTitle($root->get_attribute("title"));
04715 $item = $root;
04716 $itemnodes = $item->child_nodes();
04717 foreach ($itemnodes as $index => $node)
04718 {
04719 switch ($node->node_name())
04720 {
04721 case "qticomment":
04722 $comment = $node->get_content();
04723 if (strpos($comment, "Author=") !== false)
04724 {
04725 $comment = str_replace("Author=", "", $comment);
04726 $this->setAuthor($comment);
04727 }
04728 elseif (strpos($comment, "ILIAS Version=") !== false)
04729 {
04730 }
04731 else
04732 {
04733 $this->setDescription($comment);
04734 }
04735 break;
04736 case "duration":
04737 $iso8601period = $node->get_content();
04738 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04739 {
04740 $this->enable_processing_time = 1;
04741 $this->setProcessingTime(sprintf("%02d:%02d:%02d", $matches[4], $matches[5], $matches[6]));
04742 }
04743 break;
04744 case "assessmentcontrol":
04745 $score_reporting = $node->get_attribute("solutionswitch");
04746 switch (strtolower($score_reporting))
04747 {
04748 case "1":
04749 case "yes":
04750 $score_reporting = 1;
04751 break;
04752 default:
04753 $score_reporting = 0;
04754 break;
04755 }
04756 $this->setScoreReporting($score_reporting);
04757 break;
04758 case "objectives":
04759 $material = $node->first_child();
04760 if (strcmp($material->get_attribute("label"), "introduction") == 0)
04761 {
04762 $mattext = $material->first_child();
04763 $this->setIntroduction($mattext->get_content());
04764 }
04765 break;
04766 case "qtimetadata":
04767 $metadata_fields = $node->child_nodes();
04768 foreach ($metadata_fields as $index => $metadata_field)
04769 {
04770 $fieldlabel = $metadata_field->first_child();
04771 $fieldentry = $fieldlabel->next_sibling();
04772 switch ($fieldlabel->get_content())
04773 {
04774 case "sequence_settings":
04775 $this->setSequenceSettings($fieldentry->get_content());
04776 break;
04777 case "author":
04778 $this->setAuthor($fieldentry->get_content());
04779 break;
04780 case "test_type":
04781 $this->setTestType($fieldentry->get_content());
04782 break;
04783 case "reporting_date":
04784 $iso8601period = $fieldentry->get_content();
04785 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04786 {
04787 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04788 }
04789 break;
04790 case "nr_of_tries":
04791 $this->setNrOfTries($fieldentry->get_content());
04792 break;
04793 case "random_test":
04794 $this->setRandomTest($fieldentry->get_content());
04795 break;
04796 case "random_question_count":
04797 $this->setRandomQuestionCount($fieldentry->get_content());
04798 break;
04799 case "starting_time":
04800 $iso8601period = $fieldentry->get_content();
04801 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04802 {
04803 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04804 }
04805 break;
04806 case "ending_time":
04807 $iso8601period = $fieldentry->get_content();
04808 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
04809 {
04810 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04811 }
04812 break;
04813 }
04814 if (preg_match("/mark_step_\d+/", $fieldlabel->get_content()))
04815 {
04816 $xmlmark = $fieldentry->get_content();
04817 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
04818 $mark_short = $matches[1];
04819 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
04820 $mark_official = $matches[1];
04821 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
04822 $mark_percentage = $matches[1];
04823 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
04824 $mark_passed = $matches[1];
04825 $this->mark_schema->add_mark_step($mark_short, $mark_official, $mark_percentage, $mark_passed);
04826 }
04827 }
04828 break;
04829 }
04830 }
04831 $result = true;
04832 }
04833 return $result;
04834 }
04835
04844 function importObject($source, $questionpool_id)
04845 {
04846 $ilias_version = "";
04847 $error = 0;
04848 if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK)
04849 {
04850 $this->ilias->raiseError("No file selected!",$this->ilias->error_obj->FATAL);
04851 $error = 1;
04852 }
04853
04854
04855 if (!$error)
04856 {
04857
04858 $fh = fopen($source, "r");
04859 if (!$fh)
04860 {
04861 $this->ilias->raiseError("Error opening the file!",$this->ilias->error_obj->FATAL);
04862 $error = 1;
04863 return $error;
04864 }
04865
04866 $xml = fread($fh, filesize($source));
04867 $result = fclose($fh);
04868
04869 if (!$result)
04870 {
04871 $this->ilias->raiseError("Error closing the file!",$this->ilias->error_obj->FATAL);
04872 $error = 1;
04873 return $error;
04874 }
04875
04876 $assessment_part = "";
04877 if (preg_match("/ILIAS Version\=(\d+)\.(\d+)\.?(\d?)/", $xml, $matches))
04878 {
04879 $major_version = $matches[1];
04880 unset($matches[0]);
04881 $ilias_version = join($matches, ".");
04882 if ($major_version == 2)
04883 {
04884 $this->setTestType(TYPE_SELF_ASSESSMENT);
04885 global $lng;
04886 $lng->loadLanguageModule("assessment");
04887 $this->setTitle($lng->txt("imported_test"));
04888 $assessment_part = $this->to_xml();
04889 if (preg_match("/(<assessment[^>]*>.*?<\/assessment>)/si", $assessment_part, $matches))
04890 {
04891 $assessment_part = $matches[1];
04892 }
04893 }
04894 }
04895
04896 $found_assessment = preg_match("/(<assessment[^>]*>.*?<\/assessment>)/si", $xml, $matches);
04897 if ($found_assessment or $assessment_part)
04898 {
04899 if ((!$found_assessment) and ($assessment_part))
04900 {
04901 $matches[1] = $assessment_part;
04902 }
04903
04904 $succeeded = $this->from_xml($matches[1]);
04905
04906 if (!$succeeded)
04907 {
04908
04909 $error = 1;
04910 return $error;
04911 }
04912 }
04913 else
04914 {
04915
04916 $error = 1;
04917 return $error;
04918 }
04919
04920 $question_counter = 1;
04921
04922 $this->import_mapping = array();
04923
04924 if (preg_match_all("/(<item[^>]*>.*?<\/item>)/si", $xml, $matches))
04925 {
04926
04927 foreach ($matches[1] as $index => $item)
04928 {
04929
04930 if (preg_match("/(<item[^>]*>)/is", $item, $start_tag))
04931 {
04932 if (preg_match("/(ident=\"([^\"]*)\")/is", $start_tag[1], $ident))
04933 {
04934 $ident = $ident[2];
04935 }
04936 }
04937
04938 $question = "";
04939 $qt = "";
04940 if (preg_match("/<fieldlabel>QUESTIONTYPE<\/fieldlabel>\s*<fieldentry>(.*?)<\/fieldentry>/is", $item, $questiontype))
04941 {
04942 $qt = $questiontype[1];
04943 }
04944 if (preg_match("/<qticomment>Questiontype\=(.*?)<\/qticomment>/is", $item, $questiontype))
04945 {
04946 $qt = $questiontype[1];
04947 }
04948 if (strlen($qt))
04949 {
04950 switch ($qt)
04951 {
04952 case CLOZE_TEST_IDENTIFIER:
04953 $question = new ASS_ClozeTest();
04954 break;
04955 case IMAGEMAP_QUESTION_IDENTIFIER:
04956 $question = new ASS_ImagemapQuestion();
04957 break;
04958 case MATCHING_QUESTION_IDENTIFIER:
04959 $question = new ASS_MatchingQuestion();
04960 break;
04961 case MULTIPLE_CHOICE_QUESTION_IDENTIFIER:
04962 $question = new ASS_MultipleChoice();
04963 break;
04964 case ORDERING_QUESTION_IDENTIFIER:
04965 $question = new ASS_OrderingQuestion();
04966 break;
04967 case JAVAAPPLET_QUESTION_IDENTIFIER:
04968 $question = new ASS_JavaApplet();
04969 break;
04970 case TEXT_QUESTION_IDENTIFIER:
04971 $question = new ASS_TextQuestion();
04972 break;
04973 }
04974 if ($question)
04975 {
04976 $question->setObjId($questionpool_id);
04977 if ($question->from_xml("<questestinterop>$item</questestinterop>"))
04978 {
04979 $question->saveToDb();
04980 $q_1_id = $question->getId();
04981 $question_id = $question->duplicate(true);
04982 $this->questions[$question_counter++] = $question_id;
04983 $this->import_mapping[$ident] = array(
04984 "pool" => $q_1_id, "test" => $question_id);
04985 }
04986 else
04987 {
04988 $this->ilias->raiseError($this->lng->txt("error_importing_question"), $this->ilias->error_obj->MESSAGE);
04989 }
04990 }
04991 }
04992 }
04993 }
04994 }
04995
04996 $result = array(
04997 "error" => $error,
04998 "version" => $ilias_version
04999 );
05000 return $result;
05001 }
05002
05007 function getImportMapping()
05008 {
05009 if (!is_array($this->import_mapping))
05010 {
05011 return array();
05012 }
05013 else
05014 {
05015 return $this->import_mapping;
05016 }
05017 }
05018
05029 function getECTSGrade($reached_points, $max_points)
05030 {
05031 require_once "./classes/class.ilStatistics.php";
05032
05033 $passed_statistics = new ilStatistics();
05034 $passed_array =& $this->getTotalPointsPassedArray();
05035 $passed_statistics->setData($passed_array);
05036 $ects_percentiles = array
05037 (
05038 "A" => $passed_statistics->quantile($this->ects_grades["A"]),
05039 "B" => $passed_statistics->quantile($this->ects_grades["B"]),
05040 "C" => $passed_statistics->quantile($this->ects_grades["C"]),
05041 "D" => $passed_statistics->quantile($this->ects_grades["D"]),
05042 "E" => $passed_statistics->quantile($this->ects_grades["E"])
05043 );
05044 if (count($passed_array) && ($reached_points >= $ects_percentiles["A"]))
05045 {
05046 return "A";
05047 }
05048 else if (count($passed_array) && ($reached_points >= $ects_percentiles["B"]))
05049 {
05050 return "B";
05051 }
05052 else if (count($passed_array) && ($reached_points >= $ects_percentiles["C"]))
05053 {
05054 return "C";
05055 }
05056 else if (count($passed_array) && ($reached_points >= $ects_percentiles["D"]))
05057 {
05058 return "D";
05059 }
05060 else if (count($passed_array) && ($reached_points >= $ects_percentiles["E"]))
05061 {
05062 return "E";
05063 }
05064 else if (strcmp($this->ects_fx, "") != 0)
05065 {
05066 if ($max_points > 0)
05067 {
05068 $percentage = ($reached_points / $max_points) * 100.0;
05069 }
05070 else
05071 {
05072 $percentage = 0.0;
05073 }
05074 if ($percentage >= $this->ects_fx)
05075 {
05076 return "FX";
05077 }
05078 else
05079 {
05080 return "F";
05081 }
05082 }
05083 else
05084 {
05085 return "F";
05086 }
05087 }
05088
05089 function checkMarks()
05090 {
05091 return $this->mark_schema->checkMarks();
05092 }
05093
05094 function updateMetaData()
05095 {
05096 global $ilUser;
05097 include_once("Services/MetaData/classes/class.ilMD.php");
05098 $md =& new ilMD($this->getId(), 0, $this->getType());
05099 $md_gen =& $md->getGeneral();
05100 if ($md_gen == false)
05101 {
05102 include_once 'Services/MetaData/classes/class.ilMDCreator.php';
05103 $md_creator = new ilMDCreator($this->getId(),0,$this->getType());
05104 $md_creator->setTitle($this->getTitle());
05105 $md_creator->setTitleLanguage($ilUser->getPref('language'));
05106 $md_creator->create();
05107 }
05108 parent::updateMetaData();
05109 }
05110
05119 function &_getAvailableTests($use_object_id = false)
05120 {
05121 global $rbacsystem;
05122 global $ilDB;
05123
05124 $result_array = array();
05125 $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";
05126 $result = $ilDB->query($query);
05127 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05128 {
05129 if ($rbacsystem->checkAccess("write", $row->ref_id) && (ilObject::_hasUntrashedReference($row->obj_id)))
05130 {
05131 if ($use_object_id)
05132 {
05133 $result_array[$row->obj_id] = $row->title;
05134 }
05135 else
05136 {
05137 $result_array[$row->ref_id] = $row->title;
05138 }
05139 }
05140 }
05141 return $result_array;
05142 }
05143
05152 function cloneRandomQuestions($new_id)
05153 {
05154 if ($new_id > 0)
05155 {
05156 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
05157 $this->ilias->db->quote($this->getTestId() . "")
05158 );
05159 $result = $this->ilias->db->query($query);
05160 if ($result->numRows())
05161 {
05162 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
05163 {
05164 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
05165 $this->ilias->db->quote($new_id . ""),
05166 $this->ilias->db->quote($row["questionpool_fi"] . ""),
05167 $this->ilias->db->quote($row["num_of_q"] . "")
05168 );
05169 $insertresult = $this->ilias->db->query($query);
05170 }
05171 }
05172 }
05173 }
05174
05175
05183 function _clone($obj_id)
05184 {
05185 $original = new ilObjTest($obj_id, false);
05186 $original->loadFromDb();
05187
05188 $newObj = new ilObjTest();
05189 $newObj->setType("tst");
05190 $counter = 2;
05191 while ($newObj->testTitleExists($newObj->getTitle() . " ($counter)"))
05192 {
05193 $counter++;
05194 }
05195 $newObj->setTitle($original->getTitle() . " ($counter)");
05196 $newObj->setDescription($original->getDescription());
05197 $newObj->create(true);
05198 $newObj->createReference();
05199 $newObj->putInTree($_GET["ref_id"]);
05200 $newObj->setPermissions($_GET["ref_id"]);
05201
05202
05203 $newObj->author = $original->getAuthor();
05204 $newObj->introduction = $original->getIntroduction();
05205 $newObj->mark_schema = $original->mark_schema;
05206 $newObj->sequence_settings = $original->getSequenceSettings();
05207 $newObj->score_reporting = $original->getScoreReporting();
05208 $newObj->reporting_date = $original->getReportingDate();
05209 $newObj->test_type = $original->getTestType();
05210 $newObj->nr_of_tries = $original->getNrOfTries();
05211 $newObj->processing_time = $original->getProcessingTime();
05212 $newObj->enable_processing_time = $original->getEnableProcessingTime();
05213 $newObj->starting_time = $original->getStartingTime();
05214 $newObj->ending_time = $original->getEndingTime();
05215 $newObj->ects_output = $original->ects_output;
05216 $newObj->ects_fx = $original->ects_fx;
05217 $newObj->ects_grades = $original->ects_grades;
05218 $newObj->random_test = $original->random_test;
05219 $newObj->random_question_count = $original->random_question_count;
05220 $newObj->setCountSystem($original->getCountSystem());
05221 $newObj->setMCScoring($original->getMCScoring());
05222 $newObj->saveToDb();
05223 if ($original->isRandomTest())
05224 {
05225 $newObj->saveRandomQuestionCount($newObj->random_question_count);
05226 $original->cloneRandomQuestions($newObj->getTestId());
05227 }
05228 else
05229 {
05230
05231 foreach ($original->questions as $key => $question_id)
05232 {
05233 $question = ilObjTest::_instanciateQuestion($question_id);
05234 $newObj->questions[$key] = $question->duplicate();
05235
05236 $original_id = ASS_Question::_getOriginalId($question_id);
05237 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
05238 $question->saveToDb($original_id);
05239 }
05240 }
05241
05242 $newObj->saveToDb();
05243
05244
05245 include_once("Services/MetaData/classes/class.ilMD.php");
05246 $md = new ilMD($original->getId(),0,$original->getType());
05247 $new_md =& $md->cloneMD($newObj->getId(),0,$newObj->getType());
05248 }
05249
05250 function _getRefIdFromObjId($obj_id)
05251 {
05252 global $ilDB;
05253
05254 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
05255 $ilDB->quote($obj_id)
05256
05257 );
05258 $result = $ilDB->query($query);
05259 if ($result->numRows())
05260 {
05261 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05262 return $row["ref_id"];
05263 }
05264 return 0;
05265 }
05266
05267 function createRandomSolutionsForAllUsers()
05268 {
05269 global $ilDB;
05270 global $ilUser;
05271
05272 $db =& $ilDB->db;
05273 $sequence_arr = array_flip($this->questions);
05274 $sequence = join($sequence_arr, ",");
05275 require_once("./classes/class.ilObjUser.php");
05276 $logins = ilObjUser::_getAllUserData(array("login"));
05277
05278 foreach ($logins as $login)
05279 {
05280 $user_id = $login["usr_id"];
05281 $old_active = $this->getActiveTestUser($user_id);
05282 if ($old_active) {
05283 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
05284 $db->quote("0"),
05285 $db->quote($sequence),
05286 $db->quote(""),
05287 $db->quote("1"),
05288 $db->quote($user_id),
05289 $db->quote($this->getTestId())
05290 );
05291 } else {
05292 $sequence_arr = array_flip($this->questions);
05293 $sequence = join($sequence_arr, ",");
05294 $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)",
05295 $db->quote($user_id),
05296 $db->quote($this->getTestId()),
05297 $db->quote($sequence),
05298 $db->quote(""),
05299 $db->quote("0"),
05300 $db->quote("1")
05301 );
05302 }
05303 $db->query($query);
05304 }
05305 foreach ($this->questions as $question_id) {
05306 $question =& ilObjTest::_instanciateQuestion($question_id);
05307 foreach ($logins as $login)
05308 {
05309 $question->createRandomSolution($this->getTestId(), $login["usr_id"]);
05310 }
05311 }
05312 }
05313
05321 function &getEvaluationUsers($user_id)
05322 {
05323 $users = array();
05324 $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",
05325 $this->ilias->db->quote($this->getTestId() . ""),
05326 $this->ilias->db->quote($user_id . "")
05327 );
05328 $result = $this->ilias->db->query($query);
05329 if ($result->numRows())
05330 {
05331 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
05332 {
05333 $users[$row["user_fi"]] = trim($row["firstname"] ." " . $row["lastname"]);
05334 }
05335 }
05336 return $users;
05337 }
05338
05346 function &getEvaluationGroups($user_id)
05347 {
05348 $groups = array();
05349 $query = sprintf("SELECT group_fi FROM tst_eval_groups WHERE test_fi = %s AND evaluator_fi = %s",
05350 $this->ilias->db->quote($this->getTestId() . ""),
05351 $this->ilias->db->quote($user_id . "")
05352 );
05353 $result = $this->ilias->db->query($query);
05354 if ($result->numRows())
05355 {
05356 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
05357 {
05358 $groups[$row["group_fi"]] = $row["group_fi"];
05359 }
05360 }
05361 return $groups;
05362 }
05363
05372 function removeSelectedUser($user_id, $evaluator_id)
05373 {
05374 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s AND user_fi = %s AND evaluator_fi = %s",
05375 $this->ilias->db->quote($this->getTestId() . ""),
05376 $this->ilias->db->quote($user_id . ""),
05377 $this->ilias->db->quote($evaluator_id . "")
05378 );
05379 $result = $this->ilias->db->query($query);
05380 }
05381
05390 function addSelectedUser($user_id, $evaluator_id)
05391 {
05392 $query = sprintf("SELECT user_fi FROM tst_eval_users WHERE test_fi = %s AND evaluator_fi = %s AND user_fi = %s",
05393 $this->ilias->db->quote($this->getTestId() . ""),
05394 $this->ilias->db->quote($evaluator_id . ""),
05395 $this->ilias->db->quote($user_id . "")
05396 );
05397 $result = $this->ilias->db->query($query);
05398 if ($result->numRows() < 1)
05399 {
05400 $query = sprintf("INSERT INTO tst_eval_users (eval_users_id, test_fi, evaluator_fi, user_fi, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
05401 $this->ilias->db->quote($this->getTestId() . ""),
05402 $this->ilias->db->quote($evaluator_id . ""),
05403 $this->ilias->db->quote($user_id . "")
05404 );
05405 $result = $this->ilias->db->query($query);
05406 }
05407 }
05408
05417 function removeSelectedGroup($group_id, $evaluator_id)
05418 {
05419 $query = sprintf("DELETE FROM tst_eval_groups WHERE test_fi = %s AND group_fi = %s AND evaluator_fi = %s",
05420 $this->ilias->db->quote($this->getTestId() . ""),
05421 $this->ilias->db->quote($group_id . ""),
05422 $this->ilias->db->quote($evaluator_id . "")
05423 );
05424 $result = $this->ilias->db->query($query);
05425 }
05426
05435 function addSelectedGroup($group_id, $evaluator_id)
05436 {
05437 $query = sprintf("SELECT group_fi FROM tst_eval_groups WHERE test_fi = %s AND evaluator_fi = %s AND group_fi = %s",
05438 $this->ilias->db->quote($this->getTestId() . ""),
05439 $this->ilias->db->quote($evaluator_id . ""),
05440 $this->ilias->db->quote($group_id . "")
05441 );
05442 $result = $this->ilias->db->query($query);
05443 if ($result->numRows() < 1)
05444 {
05445 $query = sprintf("INSERT INTO tst_eval_groups (eval_groups_id, test_fi, evaluator_fi, group_fi, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
05446 $this->ilias->db->quote($this->getTestId() . ""),
05447 $this->ilias->db->quote($evaluator_id . ""),
05448 $this->ilias->db->quote($group_id . "")
05449 );
05450 $result = $this->ilias->db->query($query);
05451 }
05452 }
05453
05462 function getQuestionCount()
05463 {
05464 $num = 0;
05465
05466 if ($this->isRandomTest())
05467 {
05468 if ($this->getRandomQuestionCount())
05469 {
05470 $num = $this->getRandomQuestionCount();
05471 }
05472 else
05473 {
05474 $qpls =& $this->getRandomQuestionpools();
05475 foreach ($qpls as $data)
05476 {
05477 $num += $data["count"];
05478 }
05479 }
05480 }
05481 else
05482 {
05483 $num = count($this->questions);
05484 }
05485 return $num;
05486 }
05487
05496 function _goto($a_target)
05497 {
05498 global $rbacsystem, $ilErr, $lng;
05499
05500 include_once 'classes/class.ilSearch.php';
05501
05502
05503
05504 if ($rbacsystem->checkAccess("read", $a_target) and ilSearch::_checkParentConditions($a_target))
05505 {
05506 ilUtil::redirect("assessment/test.php?cmd=run&ref_id=$a_target");
05507 }
05508 else
05509 {
05510 $ilErr->raiseError($lng->txt("msg_no_perm_read_lm"), $ilErr->FATAL);
05511 }
05512 }
05513
05521 function removeNonRandomTestData()
05522 {
05523
05524 $this->removeAllTestEditings();
05525 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
05526 $this->ilias->db->quote($this->getTestId())
05527 );
05528 $result = $this->ilias->db->query($query);
05529 $this->questions = array();
05530 $this->saveCompleteStatus();
05531 }
05532
05540 function removeRandomTestData()
05541 {
05542
05543 $this->removeAllTestEditings();
05544 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
05545 $this->ilias->db->quote($this->getTestId())
05546 );
05547 $result = $this->ilias->db->query($query);
05548 $this->questions = array();
05549 $this->saveCompleteStatus();
05550 }
05551
05561 function logAction($logtext = "", $question_id = "")
05562 {
05563 global $ilUser;
05564
05565 $original_id = "";
05566 if (strcmp($question_id, "") != 0)
05567 {
05568 $original_id = ASS_Question::_getOriginalId($question_id);
05569 }
05570 include_once "./classes/class.ilObjAssessmentFolder.php";
05571 ilObjAssessmentFolder::_addLog($ilUser->id, $this->getId(), $logtext, $question_id, $original_id);
05572 }
05573
05583 function _getObjectIDFromTestID($test_id)
05584 {
05585 global $ilDB;
05586 $object_id = FALSE;
05587 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
05588 $ilDB->quote($test_id . "")
05589 );
05590 $result = $ilDB->query($query);
05591 if ($result->numRows())
05592 {
05593 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05594 $object_id = $row["obj_fi"];
05595 }
05596 return $object_id;
05597 }
05598
05608 function _getTestIDFromObjectID($object_id)
05609 {
05610 global $ilDB;
05611 $test_id = FALSE;
05612 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
05613 $ilDB->quote($object_id . "")
05614 );
05615 $result = $ilDB->query($query);
05616 if ($result->numRows())
05617 {
05618 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05619 $test_id = $row["test_id"];
05620 }
05621 return $test_id;
05622 }
05623
05634 function getTextAnswer($user_id, $question_id)
05635 {
05636 $res = "";
05637 if (($user_id) && ($question_id))
05638 {
05639 $query = sprintf("SELECT value1 FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
05640 $this->ilias->db->quote($user_id . ""),
05641 $this->ilias->db->quote($this->getTestId() . ""),
05642 $this->ilias->db->quote($question_id . "")
05643 );
05644 $result = $this->ilias->db->query($query);
05645 if ($result->numRows() == 1)
05646 {
05647 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05648 $res = $row["value1"];
05649 }
05650 }
05651 return $res;
05652 }
05653
05663 function getQuestiontext($question_id)
05664 {
05665 $res = "";
05666 if ($question_id)
05667 {
05668 $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
05669 $this->ilias->db->quote($question_id . "")
05670 );
05671 $result = $this->ilias->db->query($query);
05672 if ($result->numRows() == 1)
05673 {
05674 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05675 $res = $row["question_text"];
05676 }
05677 }
05678 return $res;
05679 }
05680
05689 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
05690 {
05691 $result_array = array();
05692
05693 if (is_numeric($user_id))
05694 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .
05695 "FROM tst_invited_user t, usr_data ".
05696 "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
05697 "WHERE t.test_fi = %s and t.user_fi=usr_id AND usr_id=%s ".
05698 "ORDER BY %s",
05699 $this->ilias->db->quote($this->test_id),
05700 $user_id,
05701 $order
05702 );
05703 else
05704 {
05705 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .
05706 "FROM tst_invited_user t, usr_data ".
05707 "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
05708 "WHERE t.test_fi = %s and t.user_fi=usr_id ".
05709 "ORDER BY %s",
05710 $this->ilias->db->quote($this->test_id),
05711 $order
05712 );
05713 }
05714
05715 return $this->getArrayData($query, "usr_id");
05716 }
05717
05727 function &getUserData($ids)
05728 {
05729 if (!is_array($ids) || count($ids) ==0)
05730 return array();
05731
05732 $result_array = array();
05733
05734 $query = sprintf("SELECT usr_id, login, lastname, firstname, client_ip as clientip FROM usr_data WHERE usr_id IN (%s) ORDER BY login",
05735 join ($ids,",")
05736 );
05737
05738 return $this->getArrayData ($query, "usr_id");
05739 }
05740
05751 function &getArrayData($query, $id_field)
05752 {
05753 return ilObjTest::_getArrayData ($query, $id_field);
05754 }
05755
05756 function &_getArrayData($query, $id_field)
05757 {
05758 global $ilDB;
05759 $result = $ilDB->query($query);
05760 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05761 {
05762 $result_array[$row->$id_field]= $row;
05763 }
05764 return ($result_array)?$result_array:array();
05765 }
05766
05767 function &getGroupData($ids)
05768 {
05769 if (!is_array($ids) || count($ids) ==0)
05770 return array();
05771
05772 $result_array = array();
05773
05774 $query = sprintf("SELECT ref_id, title, description FROM `grp_data` g, object_data o, object_reference r WHERE o.obj_id=grp_id AND o.obj_id = r.obj_id AND ref_id IN (%s)",
05775 join ($ids,",")
05776 );
05777
05778 return $this->getArrayData ($query, "ref_id");
05779 }
05780
05781 function &getRoleData($ids)
05782 {
05783 if (!is_array($ids) || count($ids) ==0)
05784 return array();
05785
05786 $result_array = array();
05787
05788 $query = sprintf("SELECT obj_id, description, title FROM role_data, object_data o WHERE o.obj_id=role_id AND role_id IN (%s)",
05789 join ($ids,",")
05790 );
05791
05792 return $this->getArrayData ($query, "obj_id");
05793 }
05794
05795
05804 function inviteGroup($group_id)
05805 {
05806 require_once "./classes/class.ilObjGroup.php";
05807 $group = new ilObjGroup($group_id);
05808 $members = $group->getGroupMemberIds();
05809 foreach ($members as $user_id)
05810 {
05811 $this->inviteUser($user_id);
05812 }
05813 }
05814
05823 function inviteRole($role_id)
05824 {
05825 global $rbacreview;
05826 $members = $rbacreview->assignedUsers($role_id,"usr_id");
05827 foreach ($members as $user_id)
05828 {
05829 $this->inviteUser($user_id);
05830 }
05831 }
05832
05833
05834
05843 function disinviteUser($user_id)
05844 {
05845 $query = sprintf("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
05846 $this->ilias->db->quote($this->test_id),
05847 $this->ilias->db->quote($user_id)
05848 );
05849 $result = $this->ilias->db->query($query);
05850 }
05851
05860 function inviteUser($user_id, $client_ip="")
05861 {
05862 $query = sprintf("INSERT IGNORE INTO tst_invited_user (test_fi, user_fi, clientip) VALUES (%s, %s, %s)",
05863 $this->ilias->db->quote($this->test_id),
05864 $this->ilias->db->quote($user_id),
05865 $this->ilias->db->quote($client_ip)
05866 );
05867
05868 $result = $this->ilias->db->query($query);
05869 }
05870
05871
05872 function setClientIP($user_id, $client_ip) {
05873 $query = sprintf("UPDATE tst_invited_user SET clientip=%s WHERE test_fi=%s and user_fi=%s",
05874 $this->ilias->db->quote($client_ip),
05875 $this->ilias->db->quote($this->test_id),
05876 $this->ilias->db->quote($user_id)
05877 );
05878 $insertresult = $this->ilias->db->query($query);
05879 }
05880
05889 function &getAllSolutionValues()
05890 {
05891 global $ilUser;
05892 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s GROUP BY question_fi",
05893 $this->ilias->db->quote($ilUser->id),
05894 $this->ilias->db->quote($this->getTestId())
05895 );
05896 $result = $this->ilias->db->query($query);
05897
05898 $result_array = array();
05899 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05900 {
05901 array_push($result_array, $row->question_fi);
05902 }
05903 return $result_array;
05904 }
05905
05906
05913 function isOnlineTest() {
05914 return $this->getTestType()==TYPE_ONLINE_TEST;
05915 }
05916
05917
05918
05924 function _getSolvedQuestions ($test_fi, $user_fi, $question_fi = null) {
05925 global $ilDB;
05926 if (is_numeric($question_fi))
05927 $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
05928 "WHERE user_fi = %s AND test_fi = %s AND question_fi=%s",
05929 $ilDB->quote($user_fi),
05930 $ilDB->quote($test_fi),
05931 $question_fi
05932 );
05933 else $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
05934 "WHERE user_fi = %s AND test_fi = %s",
05935 $ilDB->quote($user_fi),
05936 $ilDB->quote($test_fi)
05937 );
05938 return ilObjTest::_getArrayData ($query, "question_fi");
05939 }
05940
05941
05945 function setQuestionSetSolved ($value, $question_id, $user_id) {
05946 $query = sprintf("REPLACE INTO tst_active_qst_sol_settings SET solved=%s, question_fi=%s, test_fi=%s, user_fi=%s",
05947 $this->ilias->db->quote($value),
05948 $this->ilias->db->quote($question_id),
05949 $this->ilias->db->quote($this->test_id),
05950 $this->ilias->db->quote($user_id)
05951 );
05952
05953 $this->ilias->db->query($query);
05954 }
05955
05956
05960 function setActiveTestSubmitted($user_id) {
05961 $query = sprintf("UPDATE tst_active SET submitted=1, tries=1, submittimestamp=NOW() WHERE test_fi=%s AND user_fi=%s",
05962 $this->ilias->db->quote($this->test_id),
05963 $this->ilias->db->quote($user_id)
05964 );
05965 $this->ilias->db->query($query);
05966
05967 }
05968
05972 function isActiveTestSubmitted($user_id = null) {
05973 global $ilUser;
05974 if (!is_numeric($user_id))
05975 $user_id = $ilUser->getId();
05976
05977 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
05978 $this->ilias->db->quote($this->test_id),
05979 $this->ilias->db->quote($user_id)
05980 );
05981 $result = $this->ilias->db->query($query);
05982
05983 return $result->numRows() == 1;
05984
05985 }
05989 function hasNrOfTriesRestriction () {
05990 return $this->getNrOfTries() != 0;
05991 }
05992
05993
05998 function isNrOfTriesReached ($tries) {
05999 return $tries >= (int) $this->getNrOfTries();
06000 }
06001
06002
06006 function getAllTestResults () {
06007 $participants = $this->getInvitedUsers("matriculation");
06008 $results = array();
06009 $row = array("matriculation" => $this->lng->txt("matriculation"),
06010 "lastname" => $this->lng->txt("lastname"),
06011 "firstname" => $this->lng->txt("firstname"),
06012 "reached_points" => $this->lng->txt("tst_reached_points"),
06013 "max_points" => $this->lng->txt("tst_maximum_points"),
06014 "percent_value" => $this->lng->txt("tst_percent_solved"),
06015 "mark" => $this->lng->txt("tst_mark"),
06016 "ects" => $this->lng->txt("ects_grade"));
06017
06018 $results[] = $row;
06019
06020 foreach ($participants as $user_id => $user_rec) {
06021 $row = array();
06022 $reached_points = 0;
06023 $max_points = 0;
06024
06025 foreach ($this->questions as $value)
06026 {
06027
06028
06029 $question =& ilObjTest::_instanciateQuestion($value);
06030
06031 if (is_object($question))
06032 {
06033 $max_points += $question->getMaximumPoints();
06034 $reached_points += $question->getReachedPoints($user_id, $this->getTestId());
06035 }
06036 }
06037
06038 if ($max_points > 0)
06039 {
06040 $percentvalue = $reached_points / $max_points;
06041 }
06042 else
06043 {
06044 $percentvalue = 0;
06045 }
06046 $mark_obj = $this->mark_schema->get_matching_mark($percentvalue * 100);
06047 $passed = "";
06048 if ($mark_obj)
06049 {
06050 $mark = $mark_obj->get_official_name();
06051 $ects_mark = $this->getECTSGrade($reached_points, $max_points);
06052 }
06053
06054 $row = array(
06055 "matriculation" => $user_rec->matriculation,
06056 "lastname" => $user_rec->lastname,
06057 "firstname" => $user_rec->firstname,
06058 "reached_points" => $reached_points,
06059 "max_points" => $max_points,
06060 "percent_value" => $percentvalue,
06061 "mark" => $mark,
06062 "ects" => $ects_mark);
06063 $results[] = $this->processCSVRow ($row, true);
06064 }
06065 return $results;
06066 }
06067
06080 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
06081 {
06082 $resultarray = array();
06083 foreach ($row as $rowindex => $entry)
06084 {
06085 $surround = FALSE;
06086 if ($quoteAll)
06087 {
06088 $surround = TRUE;
06089 }
06090 if (strpos($entry, "\"") !== FALSE)
06091 {
06092 $entry = str_replace("\"", "\"\"", $entry);
06093 $surround = TRUE;
06094 }
06095 if (strpos($entry, $separator) !== FALSE)
06096 {
06097 $surround = TRUE;
06098 }
06099
06100 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
06101 if ($surround)
06102 {
06103 $resultarray[$rowindex] = utf8_decode("\"" . $entry . "\"");
06104 }
06105 else
06106 {
06107 $resultarray[$rowindex] = utf8_decode($entry);
06108 }
06109 }
06110 return $resultarray;
06111 }
06112
06122 function getStartingTimeOfUser($user_id)
06123 {
06124 global $ilDB;
06125
06126 if ($user_id < 1) return FALSE;
06127 $query = sprintf("SELECT tst_times.started FROM tst_times, tst_active WHERE tst_active.user_fi = %s AND tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.started",
06128 $ilDB->quote($user_id . ""),
06129 $ilDB->quote($this->getTestId() . "")
06130 );
06131 $result = $ilDB->query($query);
06132 if ($result->numRows())
06133 {
06134 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06135 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
06136 {
06137 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
06138 }
06139 else
06140 {
06141 return FALSE;
06142 }
06143 }
06144 else
06145 {
06146 return FALSE;
06147 }
06148 }
06149
06160 function isMaxProcessingTimeReached($starting_time)
06161 {
06162 if ($this->getEnableProcessingTime())
06163 {
06164 $processing_time = $this->getProcessingTimeInSeconds();
06165 $now = mktime();
06166 if ($now > ($starting_time + $processing_time))
06167 {
06168 return TRUE;
06169 }
06170 else
06171 {
06172 return FALSE;
06173 }
06174 }
06175 else
06176 {
06177 return FALSE;
06178 }
06179 }
06180
06181
06182 }
06183
06184 ?>