00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00034 include_once "./classes/class.ilObject.php";
00035 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
00036
00037 class ilObjTest extends ilObject
00038 {
00046 var $test_id;
00047
00055 var $invitation = INVITATION_OFF;
00056
00057
00066 var $author;
00067
00075 var $metadata;
00076
00084 var $questions;
00085
00094 var $introduction;
00095
00103 var $mark_schema;
00104
00114 var $sequence_settings;
00115
00127 var $score_reporting;
00128
00138 var $instant_verification;
00139
00147 var $answer_feedback_points;
00148
00159 var $reporting_date;
00160
00168 var $evaluation_data;
00169
00178 var $nr_of_tries;
00179
00188 var $use_previous_answers;
00189
00200 var $title_output;
00201
00209 var $processing_time;
00210
00218 var $enable_processing_time;
00219
00227 var $reset_processing_time;
00228
00236 var $starting_time;
00237
00245 var $ending_time;
00246
00254 var $ects_output;
00255
00263 var $ects_fx;
00264
00272 var $ects_grades;
00273
00283 var $random_test;
00284
00292 var $random_question_count;
00293
00300 var $count_system;
00301
00307 var $mc_scoring;
00308
00314 var $pass_scoring;
00315
00322 var $shuffle_questions;
00323
00329 var $results_presentation;
00330
00336 var $show_summary;
00337
00343 var $score_cutting;
00344
00350 var $password;
00351
00357 var $allowedUsers;
00358
00364 var $allowedUsersTimeGap;
00365
00371 var $certificate_visibility;
00372
00378 var $anonymity;
00379
00385 var $show_cancel;
00386
00392 var $show_marker;
00393
00399 var $fixed_participants;
00400
00406 var $answer_feedback;
00407
00413 var $testSession;
00414
00420 var $testSequence;
00421
00428 function ilObjTest($a_id = 0,$a_call_by_reference = true)
00429 {
00430 global $ilUser;
00431 $this->type = "tst";
00432 include_once "./Modules/Test/classes/class.assMarkSchema.php";
00433 $this->mark_schema = new ASS_MarkSchema();
00434 $this->test_id = -1;
00435 $this->author = $ilUser->fullname;
00436 $this->introduction = "";
00437 $this->questions = array();
00438 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00439 $this->score_reporting = REPORT_AFTER_TEST;
00440 $this->instant_verification = 0;
00441 $this->answer_feedback_points = 0;
00442 $this->reporting_date = "";
00443 $this->nr_of_tries = 0;
00444 $this->use_previous_answers = 1;
00445 $this->title_output = 0;
00446 $this->starting_time = "";
00447 $this->ending_time = "";
00448 $this->processing_time = "00:00:00";
00449 $this->enable_processing_time = "0";
00450 $this->reset_processing_time = 0;
00451 $this->ects_output = 0;
00452 $this->ects_fx = "";
00453 $this->random_test = 0;
00454 $this->shuffle_questions = FALSE;
00455 $this->show_summary = 8;
00456 $this->random_question_count = "";
00457 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
00458 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
00459 $this->score_cutting = SCORE_CUT_QUESTION;
00460 $this->pass_scoring = SCORE_LAST_PASS;
00461 $this->answer_feedback = 0;
00462 $this->password = "";
00463 $this->certificate_visibility = 0;
00464 $this->allowedUsers = "";
00465 $this->allowedUsersTimeGap = "";
00466 $this->anonymity = 0;
00467 $this->show_cancel = 1;
00468 $this->show_marker = 0;
00469 $this->fixed_participants = 0;
00470 $this->setShowPassDetails(TRUE);
00471 $this->setShowSolutionDetails(TRUE);
00472 $this->setShowSolutionAnswersOnly(FALSE);
00473 $this->setShowSolutionSignature(TRUE);
00474 $this->testSession = FALSE;
00475 $this->testSequence = FALSE;
00476 global $lng;
00477 $lng->loadLanguageModule("assessment");
00478 $this->mark_schema->createSimpleSchema($lng->txt("failed_short"), $lng->txt("failed_official"), 0, 0, $lng->txt("passed_short"), $lng->txt("passed_official"), 50, 1);
00479 $this->ects_grades = array(
00480 "A" => 90,
00481 "B" => 65,
00482 "C" => 35,
00483 "D" => 10,
00484 "E" => 0
00485 );
00486 $this->ilObject($a_id, $a_call_by_reference);
00487 }
00488
00492 function create($a_upload = false)
00493 {
00494 parent::create();
00495
00496
00497
00498 if (!$a_upload)
00499 {
00500 $this->createMetaData();
00501 }
00502 }
00503
00510 function update()
00511 {
00512 if (!parent::update())
00513 {
00514 return false;
00515 }
00516
00517
00518
00519 return true;
00520 }
00521
00530 function createReference() {
00531 $result = parent::createReference();
00532 $this->saveToDb();
00533 return $result;
00534 }
00535
00541 function read($a_force_db = false)
00542 {
00543 parent::read($a_force_db);
00544 $this->loadFromDb();
00545 }
00546
00547
00554 function delete()
00555 {
00556
00557 if (!parent::delete())
00558 {
00559 return false;
00560 }
00561
00562
00563 $this->deleteMetaData();
00564
00565
00566 $this->deleteTest();
00567
00568 return true;
00569 }
00570
00578 function deleteTest()
00579 {
00580 global $ilDB;
00581
00582 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00583 $ilDB->quote($this->getTestId())
00584 );
00585 $result = $ilDB->query($query);
00586 $active_array = array();
00587 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00588 {
00589 array_push($active_array, $row["active_id"]);
00590 }
00591
00592 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00593 $ilDB->quote($this->getTestId())
00594 );
00595 $result = $ilDB->query($query);
00596
00597 if (count($active_array))
00598 {
00599 foreach ($active_array as $active_id)
00600 {
00601 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00602 $ilDB->quote($active_id)
00603 );
00604 $result = $ilDB->query($query);
00605
00606 $query = sprintf("DELETE FROM tst_sequence WHERE active_fi = %s",
00607 $ilDB->quote($active_id)
00608 );
00609 $result = $ilDB->query($query);
00610 }
00611 }
00612
00613 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00614 $ilDB->quote($this->getTestId())
00615 );
00616 $result = $ilDB->query($query);
00617
00618 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00619 $ilDB->quote($this->getTestId())
00620 );
00621 $result = $ilDB->query($query);
00622 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00623 {
00624 $this->removeQuestion($row->question_fi);
00625 }
00626
00627 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00628 $ilDB->quote($this->getTestId())
00629 );
00630 $result = $ilDB->query($query);
00631
00632 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00633 $ilDB->quote($this->getTestId())
00634 );
00635 $result = $ilDB->query($query);
00636
00637 $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_random_question.active_fi",
00638 $ilDB->quote($this->getTestId())
00639 );
00640 $result = $ilDB->query($query);
00641
00642 $this->removeAllTestEditings();
00643
00644 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00645 $ilDB->quote($this->getTestId())
00646 );
00647 $result = $ilDB->query($query);
00648
00649
00650 include_once "./Services/Utilities/classes/class.ilUtil.php";
00651 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00652 $directory = $tst_data_dir."/tst_".$this->getId();
00653 if (is_dir($directory))
00654 {
00655 include_once "./Services/Utilities/classes/class.ilUtil.php";
00656 ilUtil::delDir($directory);
00657 }
00658 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
00659 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
00660
00661
00662
00663
00664 foreach($mobs as $mob)
00665 {
00666 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
00667 $mob_obj =& new ilObjMediaObject($mob);
00668 $mob_obj->delete();
00669 }
00670 }
00671
00681 function initDefaultRoles()
00682 {
00683 global $rbacadmin;
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 return $roles ? $roles : array();
00696 }
00697
00711 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00712 {
00713 global $tree;
00714
00715 switch ($a_event)
00716 {
00717 case "link":
00718
00719
00720
00721
00722 break;
00723
00724 case "cut":
00725
00726
00727
00728 break;
00729
00730 case "copy":
00731
00732
00733
00734
00735 break;
00736
00737 case "paste":
00738
00739
00740
00741 break;
00742
00743 case "new":
00744
00745
00746
00747 break;
00748 }
00749
00750
00751 if ($a_node_id==$_GET["ref_id"])
00752 {
00753 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00754 $parent_type = $parent_obj->getType();
00755 if($parent_type == $this->getType())
00756 {
00757 $a_node_id = (int) $tree->getParentId($a_node_id);
00758 }
00759 }
00760
00761 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00762 }
00763
00769 function createExportDirectory()
00770 {
00771 include_once "./Services/Utilities/classes/class.ilUtil.php";
00772 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00773 ilUtil::makeDir($tst_data_dir);
00774 if(!is_writable($tst_data_dir))
00775 {
00776 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00777 .") not writeable.",$this->ilias->error_obj->MESSAGE);
00778 }
00779
00780
00781 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00782 ilUtil::makeDir($tst_dir);
00783 if(!@is_dir($tst_dir))
00784 {
00785 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
00786 }
00787
00788 $export_dir = $tst_dir."/export";
00789 ilUtil::makeDir($export_dir);
00790 if(!@is_dir($export_dir))
00791 {
00792 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
00793 }
00794 }
00795
00803 function getExportDirectory()
00804 {
00805 include_once "./Services/Utilities/classes/class.ilUtil.php";
00806 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00807 return $export_dir;
00808 }
00809
00818 function getExportFiles($dir)
00819 {
00820
00821 if (!@is_dir($dir) or
00822 !is_writeable($dir))
00823 {
00824 return array();
00825 }
00826
00827
00828 $dir = dir($dir);
00829
00830
00831 $file = array();
00832
00833
00834 while ($entry = $dir->read())
00835 {
00836 if ($entry != "." and
00837 $entry != ".." and
00838
00839 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test(__results)?__)*[0-9]+\.[a-z]{1,3}\$", $entry))
00840 {
00841 $file[] = $entry;
00842 }
00843 }
00844
00845
00846 $dir->close();
00847
00848
00849 sort ($file);
00850 reset ($file);
00851
00852 return $file;
00853 }
00854
00855
00861 function _createImportDirectory()
00862 {
00863 global $ilias;
00864
00865 include_once "./Services/Utilities/classes/class.ilUtil.php";
00866 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00867 ilUtil::makeDir($tst_data_dir);
00868
00869 if(!is_writable($tst_data_dir))
00870 {
00871 $ilias->raiseError("Test data directory (".$tst_data_dir
00872 .") not writeable.",$ilias->error_obj->FATAL);
00873 }
00874
00875
00876 $tst_dir = $tst_data_dir."/tst_import";
00877 ilUtil::makeDir($tst_dir);
00878 if(!@is_dir($tst_dir))
00879 {
00880 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00881 }
00882 }
00883
00892 function _getImportDirectory()
00893 {
00894 include_once "./Services/Utilities/classes/class.ilUtil.php";
00895 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00896 if(@is_dir($import_dir))
00897 {
00898 return $import_dir;
00899 }
00900 else
00901 {
00902 return false;
00903 }
00904 }
00905
00911 function createImportDirectory()
00912 {
00913 include_once "./Services/Utilities/classes/class.ilUtil.php";
00914 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00915 ilUtil::makeDir($tst_data_dir);
00916
00917 if(!is_writable($tst_data_dir))
00918 {
00919 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00920 .") not writeable.",$this->ilias->error_obj->FATAL);
00921 }
00922
00923
00924 $tst_dir = $tst_data_dir."/tst_import";
00925 ilUtil::makeDir($tst_dir);
00926 if(!@is_dir($tst_dir))
00927 {
00928 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00929 }
00930 }
00931
00940 function getImportDirectory()
00941 {
00942 include_once "./Services/Utilities/classes/class.ilUtil.php";
00943 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00944 if(@is_dir($import_dir))
00945 {
00946 return $import_dir;
00947 }
00948 else
00949 {
00950 return false;
00951 }
00952 }
00953
00954
00964 function testTitleExists($title)
00965 {
00966 global $ilDB;
00967
00968 $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00969 $ilDB->quote($title),
00970 $ilDB->quote("tst")
00971 );
00972 $result = $ilDB->query($query);
00973 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00974 if ($result->numRows() == 1) {
00975 return TRUE;
00976 }
00977 }
00978 return FALSE;
00979 }
00980
00989 function isComplete()
00990 {
00991 if ((count($this->mark_schema->mark_steps)) and (count($this->questions)))
00992 {
00993 return true;
00994 }
00995 else
00996 {
00997 if ($this->isRandomTest())
00998 {
00999 $arr = $this->getRandomQuestionpools();
01000 if (count($arr) && ($this->getRandomQuestionCount() > 0))
01001 {
01002 return true;
01003 }
01004 $count = 0;
01005 foreach ($arr as $array)
01006 {
01007 $count += $array["count"];
01008 }
01009 if ($count)
01010 {
01011 return true;
01012 }
01013 }
01014 return false;
01015 }
01016 }
01017
01026 function _isComplete($obj_id)
01027 {
01028 $test = new ilObjTest($obj_id, false);
01029 $test->loadFromDb();
01030 return $test->isComplete();
01031 }
01032
01040 function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
01041 {
01042 global $ilDB;
01043 if ($this->test_id > 0) {
01044 $fx_support = preg_replace("/,/", ".", $fx_support);
01045 if (preg_match("/\d+/", $fx_support))
01046 {
01047 $fx_support = $fx_support;
01048 }
01049 else
01050 {
01051 $fx_support = "NULL";
01052 }
01053 $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",
01054 $ilDB->quote("$ects_output"),
01055 $ilDB->quote($ects_a . ""),
01056 $ilDB->quote($ects_b . ""),
01057 $ilDB->quote($ects_c . ""),
01058 $ilDB->quote($ects_d . ""),
01059 $ilDB->quote($ects_e . ""),
01060 $fx_support,
01061 $this->getTestId()
01062 );
01063 $result = $ilDB->query($query);
01064 $this->ects_output = $ects_output;
01065 $this->ects_fx = $fx_support;
01066 }
01067 }
01068
01076 function saveCompleteStatus()
01077 {
01078 global $ilDB;
01079
01080 $complete = 0;
01081 if ($this->isComplete())
01082 {
01083 $complete = 1;
01084 }
01085 if ($this->test_id > 0)
01086 {
01087 $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
01088 $ilDB->quote("$complete"),
01089 $ilDB->quote($this->test_id)
01090 );
01091 $result = $ilDB->query($query);
01092 }
01093 }
01094
01102 function getAllRTEContent()
01103 {
01104 $result = array();
01105 array_push($result, $this->getIntroduction());
01106 return $result;
01107 }
01108
01116 function cleanupMediaobjectUsage()
01117 {
01118 include_once("./Services/RTE/classes/class.ilRTE.php");
01119 $completecontent = "";
01120 foreach ($this->getAllRTEContent() as $content)
01121 {
01122 $completecontent .= $content;
01123 }
01124 ilRTE::_cleanupMediaObjectUsage($completecontent, $this->getType() . ":html",
01125 $this->getId());
01126 }
01127
01136 function saveToDb($properties_only = FALSE)
01137 {
01138 global $ilDB, $ilLog;
01139
01140 $complete = 0;
01141 if ($this->isComplete())
01142 {
01143 $complete = 1;
01144 }
01145 $ects_fx = "NULL";
01146 if (preg_match("/\d+/", $this->ects_fx))
01147 {
01148 $ects_fx = $this->ects_fx;
01149 }
01150 $random_question_count = "NULL";
01151 if ($this->random_question_count > 0)
01152 {
01153 $random_question_count = $ilDB->quote($this->random_question_count . "");
01154 }
01155 $shuffle_questions = 0;
01156 if ($this->getShuffleQuestions())
01157 {
01158 $shuffle_questions = 1;
01159 }
01160 $allowedUsers = $this->getAllowedUsers();
01161 if ($allowedUsers == 0)
01162 {
01163 $allowedUsers = "NULL";
01164 }
01165 else
01166 {
01167 $allowedUsers = $ilDB->quote($allowedUsers);
01168 }
01169 $allowedUsersTimeGap = $this->getAllowedUsersTimeGap();
01170 if ($allowedUsersTimeGap == 0)
01171 {
01172 $allowedUsersTimeGap = "NULL";
01173 }
01174 else
01175 {
01176 $allowedUsersTimeGap = $ilDB->quote($allowedUsersTimeGap);
01177 }
01178
01179
01180 $this->cleanupMediaobjectUsage();
01181
01182 include_once ("./classes/class.ilObjAssessmentFolder.php");
01183 if ($this->test_id == -1)
01184 {
01185
01186 $now = getdate();
01187 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
01188 $query = sprintf("INSERT INTO tst_tests (test_id, obj_fi, author, introduction, sequence_settings, " .
01189 "score_reporting, instant_verification, answer_feedback_points, answer_feedback, anonymity, show_cancel, show_marker, " .
01190 "fixed_participants, nr_of_tries, use_previous_answers, title_output, processing_time, enable_processing_time, reset_processing_time, " .
01191 "reporting_date, starting_time, ending_time, complete, ects_output, ects_a, ects_b, ects_c, ects_d, ects_e, " .
01192 "ects_fx, random_test, random_question_count, count_system, mc_scoring, score_cutting, pass_scoring, " .
01193 "shuffle_questions, results_presentation, show_summary, password, allowedUsers, " .
01194 "allowedUsersTimeGap, certificate_visibility, created, TIMESTAMP) " .
01195 "VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, " .
01196 "%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01197 $ilDB->quote($this->getId() . ""),
01198 $ilDB->quote($this->getAuthor() . ""),
01199 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01200 $ilDB->quote($this->sequence_settings . ""),
01201 $ilDB->quote($this->score_reporting . ""),
01202 $ilDB->quote($this->getInstantFeedbackSolution() . ""),
01203 $ilDB->quote($this->getAnswerFeedbackPoints() . ""),
01204 $ilDB->quote($this->getAnswerFeedback() . ""),
01205 $ilDB->quote($this->getAnonymity() . ""),
01206 $ilDB->quote($this->getShowCancel() . ""),
01207 $ilDB->quote($this->getShowMarker() . ""),
01208 $ilDB->quote($this->getFixedParticipants() . ""),
01209 $ilDB->quote(sprintf("%d", $this->getNrOfTries()) . ""),
01210 $ilDB->quote(sprintf("%d", $this->getUsePreviousAnswers() . "")),
01211 $ilDB->quote(sprintf("%d", $this->getTitleOutput() . "")),
01212 $ilDB->quote($this->processing_time . ""),
01213 $ilDB->quote("$this->enable_processing_time"),
01214 $ilDB->quote($this->getResetProcessingTime() . ""),
01215 $ilDB->quote($this->reporting_date . ""),
01216 $ilDB->quote($this->starting_time . ""),
01217 $ilDB->quote($this->ending_time . ""),
01218 $ilDB->quote("$complete"),
01219 $ilDB->quote($this->ects_output . ""),
01220 $ilDB->quote($this->ects_grades["A"] . ""),
01221 $ilDB->quote($this->ects_grades["B"] . ""),
01222 $ilDB->quote($this->ects_grades["C"] . ""),
01223 $ilDB->quote($this->ects_grades["D"] . ""),
01224 $ilDB->quote($this->ects_grades["E"] . ""),
01225 $ects_fx,
01226 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01227 $random_question_count,
01228 $ilDB->quote($this->count_system . ""),
01229 $ilDB->quote($this->mc_scoring . ""),
01230 $ilDB->quote($this->getScoreCutting() . ""),
01231 $ilDB->quote($this->getPassScoring() . ""),
01232 $ilDB->quote($shuffle_questions . ""),
01233 $ilDB->quote($this->getResultsPresentation() . ""),
01234 $ilDB->quote($this->getListOfQuestionsSettings() . ""),
01235 $ilDB->quote($this->getPassword() . ""),
01236 $allowedUsers,
01237 $allowedUsersTimeGap,
01238 $ilDB->quote("0"),
01239 $ilDB->quote($created)
01240 );
01241
01242 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01243 {
01244 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
01245 }
01246 $result = $ilDB->query($query);
01247 if ($result == DB_OK) {
01248 $this->test_id = $ilDB->getLastInsertId();
01249 }
01250 }
01251 else
01252 {
01253
01254 $oldrow = array();
01255 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01256 {
01257 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01258 $ilDB->quote($this->test_id)
01259 );
01260 $result = $ilDB->query($query);
01261 if ($result->numRows() == 1)
01262 {
01263 $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01264 }
01265 }
01266 $query = sprintf("UPDATE tst_tests SET author = %s, introduction = %s, sequence_settings = %s, score_reporting = %s, instant_verification = %s, answer_feedback_points = %s, answer_feedback = %s, anonymity = %s, show_cancel = %s, show_marker = %s, fixed_participants = %s, nr_of_tries = %s, use_previous_answers = %s, title_output = %s, processing_time = %s, enable_processing_time = %s, reset_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, score_cutting = %s, pass_scoring = %s, shuffle_questions = %s, results_presentation = %s, show_summary = %s, password = %s, allowedUsers = %s, allowedUsersTimeGap = %s WHERE test_id = %s",
01267 $ilDB->quote($this->getAuthor() . ""),
01268 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01269 $ilDB->quote($this->sequence_settings . ""),
01270 $ilDB->quote($this->score_reporting . ""),
01271 $ilDB->quote($this->getInstantFeedbackSolution() . ""),
01272 $ilDB->quote($this->getAnswerFeedbackPoints() . ""),
01273 $ilDB->quote($this->getAnswerFeedback() . ""),
01274 $ilDB->quote($this->getAnonymity() . ""),
01275 $ilDB->quote($this->getShowCancel() . ""),
01276 $ilDB->quote($this->getShowMarker() . ""),
01277 $ilDB->quote($this->getFixedParticipants() . ""),
01278 $ilDB->quote(sprintf("%d", $this->getNrOfTries()) . ""),
01279 $ilDB->quote(sprintf("%d", $this->getUsePreviousAnswers() . "")),
01280 $ilDB->quote(sprintf("%d", $this->getTitleOutput() . "")),
01281 $ilDB->quote($this->processing_time . ""),
01282 $ilDB->quote("$this->enable_processing_time"),
01283 $ilDB->quote($this->getResetProcessingTime() . ""),
01284 $ilDB->quote($this->reporting_date . ""),
01285 $ilDB->quote($this->starting_time . ""),
01286 $ilDB->quote($this->ending_time . ""),
01287 $ilDB->quote($this->ects_output . ""),
01288 $ilDB->quote($this->ects_grades["A"] . ""),
01289 $ilDB->quote($this->ects_grades["B"] . ""),
01290 $ilDB->quote($this->ects_grades["C"] . ""),
01291 $ilDB->quote($this->ects_grades["D"] . ""),
01292 $ilDB->quote($this->ects_grades["E"] . ""),
01293 $ects_fx,
01294 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01295 $ilDB->quote("$complete"),
01296 $ilDB->quote($this->count_system . ""),
01297 $ilDB->quote($this->mc_scoring . ""),
01298 $ilDB->quote($this->getScoreCutting() . ""),
01299 $ilDB->quote($this->getPassScoring() . ""),
01300 $ilDB->quote($shuffle_questions . ""),
01301 $ilDB->quote($this->getResultsPresentation() . ""),
01302 $ilDB->quote($this->getListOfQuestionsSettings() . ""),
01303 $ilDB->quote($this->getPassword() . ""),
01304 $allowedUsers,
01305 $allowedUsersTimeGap,
01306 $ilDB->quote($this->test_id)
01307 );
01308 $result = $ilDB->query($query);
01309 include_once ("./classes/class.ilObjAssessmentFolder.php");
01310 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01311 {
01312 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01313 $ilDB->quote($this->test_id)
01314 );
01315 $logresult = $ilDB->query($query);
01316 $newrow = array();
01317 if ($logresult->numRows() == 1)
01318 {
01319 $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01320 }
01321 $changed_fields = array();
01322 foreach ($oldrow as $key => $value)
01323 {
01324 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01325 {
01326 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01327 }
01328 }
01329 $changes = join($changed_fields, ", ");
01330 if (count($changed_fields) > 0)
01331 {
01332 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
01333 }
01334 }
01335 if ($this->evalTotalPersons() > 0)
01336 {
01337
01338
01339 if ($this->getNrOfTries() > 0)
01340 {
01341
01342 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries >= %s AND submitted = 0",
01343 $ilDB->quote($this->getTestId() . ""),
01344 $ilDB->quote($this->getNrOfTries() . "")
01345 );
01346 $aresult = $ilDB->query($query);
01347 while ($row = $aresult->fetchRow(DB_FETCHMODE_ASSOC))
01348 {
01349 $newquery = sprintf("UPDATE tst_active SET submitted = 1, submittimestamp = NOW() WHERE active_id = %s",
01350 $ilDB->quote($row["active_id"] . "")
01351 );
01352 $newresult = $ilDB->query($newquery);
01353 }
01354
01355
01356 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s AND tries < %s AND submitted = 1",
01357 $ilDB->quote($this->getTestId() . ""),
01358 $ilDB->quote($this->getNrOfTries() . "")
01359 );
01360 $aresult = $ilDB->query($query);
01361 while ($row = $aresult->fetchRow(DB_FETCHMODE_ASSOC))
01362 {
01363 $newquery = sprintf("UPDATE tst_active SET submitted = 0, submittimestamp = NULL WHERE active_id = %s",
01364 $ilDB->quote($row["active_id"] . "")
01365 );
01366 $newresult = $ilDB->query($newquery);
01367 }
01368 }
01369 else
01370 {
01371
01372 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s AND submitted = 1",
01373 $ilDB->quote($this->getTestId() . "")
01374 );
01375 $aresult = $ilDB->query($query);
01376 while ($row = $aresult->fetchRow(DB_FETCHMODE_ASSOC))
01377 {
01378 $newquery = sprintf("UPDATE tst_active SET submitted = 0, submittimestamp = NULL WHERE active_id = %s",
01379 $ilDB->quote($row["active_id"] . "")
01380 );
01381 $newresult = $ilDB->query($newquery);
01382 }
01383 }
01384 }
01385 }
01386 if (!$properties_only)
01387 {
01388 if ($result == DB_OK) {
01389 if (!$this->isRandomTest())
01390 {
01391 $this->saveQuestionsToDb();
01392 }
01393 $this->mark_schema->saveToDb($this->test_id);
01394 }
01395 }
01396 }
01397
01406 function saveQuestionsToDb()
01407 {
01408 global $ilDB;
01409
01410 $oldquestions = array();
01411 include_once "./classes/class.ilObjAssessmentFolder.php";
01412 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01413 {
01414 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01415 $ilDB->quote($this->getTestId())
01416 );
01417 $result = $ilDB->query($query);
01418 if ($result->numRows() > 0)
01419 {
01420 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01421 {
01422 array_push($oldquestions, $row["question_fi"]);
01423 }
01424 }
01425 }
01426
01427
01428 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01429 $ilDB->quote($this->getTestId())
01430 );
01431 $result = $ilDB->query($query);
01432
01433 foreach ($this->questions as $key => $value) {
01434 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01435 $ilDB->quote($this->getTestId() . ""),
01436 $ilDB->quote($value . ""),
01437 $ilDB->quote($key . "")
01438 );
01439 $result = $ilDB->query($query);
01440 }
01441 include_once ("./classes/class.ilObjAssessmentFolder.php");
01442 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01443 {
01444 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01445 $ilDB->quote($this->getTestId())
01446 );
01447 $result = $ilDB->query($query);
01448 $newquestions = array();
01449 if ($result->numRows() > 0)
01450 {
01451 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01452 {
01453 array_push($newquestions, $row["question_fi"]);
01454 }
01455 }
01456 foreach ($oldquestions as $index => $question_id)
01457 {
01458 if (strcmp($newquestions[$index], $question_id) != 0)
01459 {
01460 $pos = array_search($question_id, $newquestions);
01461 if ($pos === FALSE)
01462 {
01463 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
01464 }
01465 else
01466 {
01467 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01468 }
01469 }
01470 }
01471 foreach ($newquestions as $index => $question_id)
01472 {
01473 if (array_search($question_id, $oldquestions) === FALSE)
01474 {
01475 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
01476 }
01477 }
01478 }
01479 }
01480
01489 function saveRandomQuestion($active_id, $question_id, $pass = NULL, $maxcount)
01490 {
01491 global $ilUser;
01492 global $ilDB;
01493
01494 if (is_null($pass)) $pass = 0;
01495 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE active_fi = %s AND pass = %s",
01496 $ilDB->quote($active_id . ""),
01497 $ilDB->quote($pass . "")
01498 );
01499 $result = $ilDB->query($query);
01500 if ($result->numRows() < $maxcount)
01501 {
01502 $duplicate_id = $this->getRandomQuestionDuplicate($question_id, $active_id);
01503 if ($duplicate_id === FALSE)
01504 {
01505 $duplicate_id = $this->duplicateQuestionForTest($question_id);
01506 }
01507
01508 $query = sprintf("INSERT INTO tst_test_random_question (test_random_question_id, active_fi, question_fi, sequence, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
01509 $ilDB->quote($active_id . ""),
01510 $ilDB->quote($duplicate_id . ""),
01511 $ilDB->quote(($result->numRows()+1) . ""),
01512 $ilDB->quote($pass . "")
01513 );
01514 $result = $ilDB->query($query);
01515 }
01516 }
01517
01529 function getRandomQuestionDuplicate($question_id, $active_id)
01530 {
01531 global $ilDB;
01532
01533 $query = sprintf("SELECT qpl_questions.question_id FROM qpl_questions, tst_test_random_question WHERE qpl_questions.original_id = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.active_fi = %s",
01534 $ilDB->quote($question_id . ""),
01535 $ilDB->quote($active_id . "")
01536 );
01537 $result = $ilDB->query($query);
01538 $num = $result->numRows();
01539 if ($num > 0)
01540 {
01541 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01542 return $row["question_id"];
01543 }
01544 else
01545 {
01546 return FALSE;
01547 }
01548 }
01549
01557 function getNrOfResultsForPass($active_id, $pass)
01558 {
01559 global $ilDB;
01560
01561 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
01562 $ilDB->quote($active_id . ""),
01563 $ilDB->quote($pass . "")
01564 );
01565 $result = $ilDB->query($query);
01566 return $result->numRows();
01567 }
01568
01579 function hasRandomQuestionsForPass($active_id, $pass)
01580 {
01581 global $ilDB;
01582 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE active_fi = %s AND pass = %s",
01583 $ilDB->quote($active_id . ""),
01584 $ilDB->quote($pass . "")
01585 );
01586 $result = $ilDB->query($query);
01587 if ($result->numRows() > 0)
01588 {
01589 return TRUE;
01590 }
01591 else
01592 {
01593 return FALSE;
01594 }
01595 }
01596
01605 function generateRandomQuestions($active_id, $pass = NULL)
01606 {
01607 global $ilUser;
01608 global $ilDB;
01609
01610 if ($active_id > 0)
01611 {
01612 if ($this->hasRandomQuestionsForPass($active_id, $pass) > 0)
01613 {
01614
01615
01616 return;
01617 }
01618 if ($pass > 0)
01619 {
01620 if ($this->getNrOfResultsForPass($active_id, $pass - 1) == 0)
01621 {
01622
01623
01624
01625 return;
01626 }
01627 }
01628 }
01629 else
01630 {
01631
01632 global $ilias, $ilErr;
01633 $ilias->raiseError(sprintf($this->lng->txt("error_random_question_generation"), $ilUser->getId(), $this->getTestId()), $ilErr->FATAL);
01634 }
01635
01636 $num = $this->getRandomQuestionCount();
01637 if ($num > 0)
01638 {
01639 $qpls =& $this->getRandomQuestionpools();
01640 $rndquestions = $this->randomSelectQuestions($num, 0, 1, $qpls, $pass);
01641 $allquestions = array();
01642 foreach ($rndquestions as $question_id)
01643 {
01644 array_push($allquestions, $question_id);
01645 }
01646 if ($this->getShuffleQuestions())
01647 {
01648 srand ((float)microtime()*1000000);
01649 shuffle($allquestions);
01650 }
01651
01652 $maxcount = 0;
01653 foreach ($qpls as $data)
01654 {
01655 $maxcount += $data["contains"];
01656 }
01657 if ($num > $maxcount) $num = $maxcount;
01658 foreach ($allquestions as $question_id)
01659 {
01660 $this->saveRandomQuestion($active_id, $question_id, $pass, $num);
01661 }
01662 }
01663 else
01664 {
01665 $qpls =& $this->getRandomQuestionpools();
01666 $allquestions = array();
01667 $maxcount = 0;
01668 foreach ($qpls as $key => $value)
01669 {
01670 if ($value["count"] > 0)
01671 {
01672 $rndquestions = $this->randomSelectQuestions($value["count"], $value["qpl"], 1, $pass);
01673 foreach ($rndquestions as $question_id)
01674 {
01675 array_push($allquestions, $question_id);
01676 }
01677 }
01678 $add = ($value["count"] <= $value["contains"]) ? $value["count"] : $value["contains"];
01679 $maxcount += $add;
01680 }
01681 if ($this->getShuffleQuestions())
01682 {
01683 srand ((float)microtime()*1000000);
01684 shuffle($allquestions);
01685 }
01686 foreach ($allquestions as $question_id)
01687 {
01688 $this->saveRandomQuestion($active_id, $question_id, $pass, $maxcount);
01689 }
01690 }
01691 }
01692
01701 function saveRandomQuestionCount($total_questions = "NULL")
01702 {
01703 global $ilDB;
01704
01705 if (strcmp($total_questions, "NULL") != 0)
01706 {
01707 $this->setRandomQuestionCount($total_questions);
01708 $total_questions = $ilDB->quote($total_questions);
01709 }
01710 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01711 $total_questions,
01712 $ilDB->quote($this->getTestId() . "")
01713 );
01714 $result = $ilDB->query($query);
01715 include_once ("./classes/class.ilObjAssessmentFolder.php");
01716 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01717 {
01718 if (strcmp($total_questions, "NULL") == 0) $total_questions = '0';
01719 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_total_amount_of_questions", ilObjAssessmentFolder::_getLogLanguage()), $total_questions));
01720 }
01721 }
01722
01732 function saveRandomQuestionpools($qpl_array)
01733 {
01734 global $ilDB;
01735
01736 include_once ("./classes/class.ilObjAssessmentFolder.php");
01737
01738 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01739 $ilDB->quote($this->getTestId())
01740 );
01741 $result = $ilDB->query($query);
01742 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01743 {
01744 $this->logAction($this->lng->txtlng("assessment", "log_random_question_pool_deleted", ilObjAssessmentFolder::_getLogLanguage()));
01745 }
01746
01747 foreach ($qpl_array as $key => $value) {
01748 if ($value["qpl"] > -1)
01749 {
01750 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
01751 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01752 if ($value["count"] > $count)
01753 {
01754 $value["count"] = $count;
01755 }
01756 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01757 $ilDB->quote($this->getTestId() . ""),
01758 $ilDB->quote($value["qpl"] . ""),
01759 $ilDB->quote(sprintf("%d", $value["count"]) . "")
01760 );
01761 $result = $ilDB->query($query);
01762 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01763 {
01764 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_random_question_pool_added", ilObjAssessmentFolder::_getLogLanguage()), $value["title"] . " (" . $value["qpl"] . ")", $value["count"]));
01765 }
01766 }
01767 }
01768 }
01769
01779 function &getRandomQuestionpools()
01780 {
01781 global $ilDB;
01782
01783 $qpls = array();
01784 $counter = 0;
01785 $query = sprintf("SELECT tst_test_random.*, qpl_questionpool.questioncount FROM tst_test_random, qpl_questionpool WHERE tst_test_random.test_fi = %s AND tst_test_random.questionpool_fi = qpl_questionpool.obj_fi ORDER BY test_random_id",
01786 $ilDB->quote($this->getTestId() . "")
01787 );
01788 $result = $ilDB->query($query);
01789 if ($result->numRows())
01790 {
01791 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01792 {
01793 $qpls[$counter] = array(
01794 "index" => $counter,
01795 "count" => $row["num_of_q"],
01796 "qpl" => $row["questionpool_fi"],
01797 "contains" => $row["questioncount"]
01798 );
01799 $counter++;
01800 }
01801 }
01802 return $qpls;
01803 }
01804
01814 function loadFromDb()
01815 {
01816 global $ilDB;
01817
01818 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01819 $ilDB->quote($this->getId())
01820 );
01821 $result = $ilDB->query($query);
01822 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01823 {
01824 if ($result->numRows() == 1)
01825 {
01826 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01827 $this->test_id = $data->test_id;
01828 if (strlen($this->getAuthor()) == 0)
01829 {
01830 $this->saveAuthorToMetadata($data->author);
01831 }
01832 $this->author = $this->getAuthor();
01833 include_once("./Services/RTE/classes/class.ilRTE.php");
01834 $this->introduction = ilRTE::_replaceMediaObjectImageSrc($data->introduction, 1);
01835 $this->sequence_settings = $data->sequence_settings;
01836 $this->score_reporting = $data->score_reporting;
01837 $this->instant_verification = $data->instant_verification;
01838 $this->answer_feedback_points = $data->answer_feedback_points;
01839 $this->answer_feedback = $data->answer_feedback;
01840 $this->anonymity = $data->anonymity;
01841 $this->show_cancel = $data->show_cancel;
01842 $this->show_marker = $data->show_marker;
01843 $this->fixed_participants = $data->fixed_participants;
01844 $this->nr_of_tries = $data->nr_of_tries;
01845 $this->setUsePreviousAnswers($data->use_previous_answers);
01846 $this->setTitleOutput($data->title_output);
01847 $this->processing_time = $data->processing_time;
01848 $this->enable_processing_time = $data->enable_processing_time;
01849 $this->reset_processing_time = $data->reset_processing_time;
01850 $this->reporting_date = $data->reporting_date;
01851 $this->setShuffleQuestions($data->shuffle_questions);
01852 $this->setResultsPresentation($data->results_presentation);
01853 $this->setListOfQuestionsSettings($data->show_summary);
01854 $this->starting_time = $data->starting_time;
01855 $this->ending_time = $data->ending_time;
01856 $this->ects_output = $data->ects_output;
01857 $this->ects_grades = array(
01858 "A" => $data->ects_a,
01859 "B" => $data->ects_b,
01860 "C" => $data->ects_c,
01861 "D" => $data->ects_d,
01862 "E" => $data->ects_e
01863 );
01864 $this->ects_fx = $data->ects_fx;
01865 $this->random_test = $data->random_test;
01866 $this->random_question_count = $data->random_question_count;
01867 $this->mark_schema->flush();
01868 $this->mark_schema->loadFromDb($this->test_id);
01869 $this->count_system = $data->count_system;
01870 $this->mc_scoring = $data->mc_scoring;
01871 $this->setScoreCutting($data->score_cutting);
01872 $this->setPassword($data->password);
01873 $this->setAllowedUsers($data->allowedUsers);
01874 $this->setAllowedUsersTimeGap($data->allowedUsersTimeGap);
01875 $this->setPassScoring($data->pass_scoring);
01876 $this->setCertificateVisibility($data->certificate_visibility);
01877 $this->loadQuestions();
01878 }
01879 }
01880 }
01881
01890 function loadQuestions($active_id = "", $pass = NULL)
01891 {
01892 global $ilUser;
01893 global $ilDB;
01894
01895 $this->questions = array();
01896 if (strcmp($active_id, "") == 0)
01897 {
01898 $active_id = $this->getActiveIdOfUser($ilUser->getId());
01899 }
01900 if ($this->isRandomTest())
01901 {
01902 if (is_null($pass))
01903 {
01904 $pass = $this->_getPass($active_id);
01905 }
01906 $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = %s ORDER BY sequence",
01907 $ilDB->quote($active_id . ""),
01908 $ilDB->quote($pass . "")
01909 );
01910 $result = $ilDB->query($query);
01911
01912
01913
01914
01915 if ($result->numRows() == 0)
01916 {
01917 $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = 0 ORDER BY sequence",
01918 $ilDB->quote($active_id . "")
01919 );
01920 $result = $ilDB->query($query);
01921 }
01922 }
01923 else
01924 {
01925 $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",
01926 $ilDB->quote($this->test_id . "")
01927 );
01928 $result = $ilDB->query($query);
01929 }
01930 $index = 1;
01931 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01932 {
01933 $this->questions[$index++] = $data->question_fi;
01934 }
01935 }
01936
01946 function setIntroduction($introduction = "")
01947 {
01948 $this->introduction = $introduction;
01949 }
01950
01960 function isRandomTest()
01961 {
01962 return $this->random_test;
01963 }
01964
01974 function getRandomTest()
01975 {
01976 return $this->isRandomTest();
01977 }
01978
01988 function getRandomQuestionCount()
01989 {
01990 return $this->random_question_count;
01991 }
01992
02002 function getIntroduction()
02003 {
02004 return $this->introduction;
02005 }
02006
02016 function getTestId()
02017 {
02018 return $this->test_id;
02019 }
02020
02030 function getECTSOutput()
02031 {
02032 return $this->ects_output;
02033 }
02034
02044 function setECTSOutput($a_ects_output)
02045 {
02046 $this->ects_output = $a_ects_output ? 1 : 0;
02047 }
02048
02058 function getECTSFX()
02059 {
02060 return $this->ects_fx;
02061 }
02062
02072 function setECTSFX($a_ects_fx)
02073 {
02074 $this->ects_fx = $a_ects_fx;
02075 }
02076
02086 function &getECTSGrades()
02087 {
02088 return $this->ects_grades;
02089 }
02090
02100 function setECTSGrades($a_ects_grades)
02101 {
02102 if (is_array($a_ects_grades))
02103 {
02104 $this->ects_grades = $a_ects_grades;
02105 }
02106 }
02107
02117 function setSequenceSettings($sequence_settings = 0)
02118 {
02119 $this->sequence_settings = $sequence_settings;
02120 }
02121
02131 function setScoreReporting($score_reporting = 0)
02132 {
02133 $this->score_reporting = $score_reporting;
02134 }
02135
02145 function setInstantFeedbackSolution($instant_feedback = 0)
02146 {
02147 switch ($instant_feedback)
02148 {
02149 case 1:
02150 $this->instant_verification = 1;
02151 break;
02152 default:
02153 $this->instant_verification = 0;
02154 break;
02155 }
02156 }
02157
02167 function setAnswerFeedback($answer_feedback = 0)
02168 {
02169 switch ($answer_feedback)
02170 {
02171 case 1:
02172 $this->answer_feedback = 1;
02173 break;
02174 default:
02175 $this->answer_feedback = 0;
02176 break;
02177 }
02178 }
02179
02189 function setAnswerFeedbackPoints($answer_feedback_points = 0)
02190 {
02191 switch ($answer_feedback_points)
02192 {
02193 case 1:
02194 $this->answer_feedback_points = 1;
02195 break;
02196 default:
02197 $this->answer_feedback_points = 0;
02198 break;
02199 }
02200 }
02201
02211 function setRandomTest($a_random_test = 0)
02212 {
02213 $this->random_test = $a_random_test;
02214 }
02215
02225 function setRandomQuestionCount($a_random_question_count = "")
02226 {
02227 $this->random_question_count = $a_random_question_count;
02228 }
02229
02239 function setReportingDate($reporting_date)
02240 {
02241 if (!$reporting_date)
02242 {
02243 $this->reporting_date = "";
02244 $this->ects_output = 0;
02245 }
02246 else
02247 {
02248 $this->reporting_date = $reporting_date;
02249 }
02250 }
02251
02261 function getSequenceSettings()
02262 {
02263 return $this->sequence_settings;
02264 }
02265
02275 function getScoreReporting()
02276 {
02277 return $this->score_reporting;
02278 }
02279
02289 function getInstantFeedbackSolution()
02290 {
02291 return $this->instant_verification;
02292 }
02293
02303 function getAnswerFeedback()
02304 {
02305 return $this->answer_feedback;
02306 }
02307
02317 function getAnswerFeedbackPoints()
02318 {
02319 return $this->answer_feedback_points;
02320 }
02321
02331 function getCountSystem()
02332 {
02333 return $this->count_system;
02334 }
02335
02345 function _getCountSystem($active_id)
02346 {
02347 global $ilDB;
02348 $query = sprintf("SELECT tst_tests.count_system FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02349 $ilDB->quote($active_id)
02350 );
02351 $result = $ilDB->query($query);
02352 if ($result->numRows())
02353 {
02354 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02355 return $row["count_system"];
02356 }
02357 return FALSE;
02358 }
02359
02369 function getMCScoring()
02370 {
02371 return $this->mc_scoring;
02372 }
02373
02383 function getScoreCutting()
02384 {
02385 return $this->score_cutting;
02386 }
02387
02397 function getPassword()
02398 {
02399 return $this->password;
02400 }
02401
02411 function getPassScoring()
02412 {
02413 return $this->pass_scoring;
02414 }
02415
02425 function _getPassScoring($active_id)
02426 {
02427 global $ilDB;
02428 $query = sprintf("SELECT tst_tests.pass_scoring FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02429 $ilDB->quote($active_id . "")
02430 );
02431 $result = $ilDB->query($query);
02432 if ($result->numRows())
02433 {
02434 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02435 return $row["pass_scoring"];
02436 }
02437 return 0;
02438 }
02439
02449 function _getMCScoring($active_id)
02450 {
02451 global $ilDB;
02452 $query = sprintf("SELECT tst_tests.mc_scoring FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02453 $ilDB->quote($active_id)
02454 );
02455 $result = $ilDB->query($query);
02456 if ($result->numRows())
02457 {
02458 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02459 return $row["mc_scoring"];
02460 }
02461 return FALSE;
02462 }
02463
02473 function _getScoreCutting($active_id)
02474 {
02475 global $ilDB;
02476 $query = sprintf("SELECT tst_tests.score_cutting FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
02477 $ilDB->quote($active_id)
02478 );
02479 $result = $ilDB->query($query);
02480 if ($result->numRows())
02481 {
02482 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02483 return $row["score_cutting"];
02484 }
02485 return FALSE;
02486 }
02487
02497 function getReportingDate()
02498 {
02499 return $this->reporting_date;
02500 }
02501
02511 function getNrOfTries()
02512 {
02513 return $this->nr_of_tries;
02514 }
02515
02525 function getUsePreviousAnswers()
02526 {
02527 return $this->use_previous_answers;
02528 }
02529
02539 function getTitleOutput()
02540 {
02541 return $this->title_output;
02542 }
02543
02554 function _getTitleOutput($active_id)
02555 {
02556 global $ilDB;
02557
02558 $query = sprintf("SELECT tst_tests.title_output FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02559 $ilDB->quote($active_id . "")
02560 );
02561 $result = $ilDB->query($query);
02562 if ($result->numRows())
02563 {
02564 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02565 return $row["title_output"];
02566 }
02567 return 0;
02568 }
02569
02581 function _getUsePreviousAnswers($active_id, $user_active_user_setting = false)
02582 {
02583 global $ilDB;
02584 global $ilUser;
02585
02586 $use_previous_answers = 1;
02587
02588 $query = sprintf("SELECT tst_tests.use_previous_answers FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02589 $ilDB->quote($active_id . "")
02590 );
02591 $result = $ilDB->query($query);
02592 if ($result->numRows())
02593 {
02594 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02595 $use_previous_answers = $row["use_previous_answers"];
02596 }
02597
02598 if ($use_previous_answers == 1)
02599 {
02600 if ($user_active_user_setting)
02601 {
02602 $res = $ilUser->getPref("tst_use_previous_answers");
02603 if ($res !== FALSE)
02604 {
02605 $use_previous_answers = $res;
02606 }
02607 }
02608 }
02609 return $use_previous_answers;
02610 }
02611
02621 function getProcessingTime()
02622 {
02623 return $this->processing_time;
02624 }
02625
02635 function getProcessingTimeInSeconds()
02636 {
02637 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
02638 {
02639 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
02640 }
02641 else
02642 {
02643 return 0;
02644 }
02645 }
02646
02656 function getSecondsUntilEndingTime()
02657 {
02658 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
02659 {
02660 $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02661 $now = time();
02662 return $ending - $now;
02663 }
02664 else
02665 {
02666 return 0;
02667 }
02668 }
02669
02679 function getEnableProcessingTime()
02680 {
02681 return $this->enable_processing_time;
02682 }
02683
02693 function getResetProcessingTime()
02694 {
02695 return $this->reset_processing_time;
02696 }
02697
02707 function getStartingTime()
02708 {
02709 return $this->starting_time;
02710 }
02711
02721 function getEndingTime()
02722 {
02723 return $this->ending_time;
02724 }
02725
02735 function setNrOfTries($nr_of_tries = 0)
02736 {
02737 $this->nr_of_tries = $nr_of_tries;
02738 }
02739
02749 function setUsePreviousAnswers($use_previous_answers = 1)
02750 {
02751 if ($use_previous_answers)
02752 {
02753 $this->use_previous_answers = 1;
02754 }
02755 else
02756 {
02757 $this->use_previous_answers = 0;
02758 }
02759 }
02760
02770 function setTitleOutput($title_output = 0)
02771 {
02772 switch ($title_output)
02773 {
02774 case 1:
02775 $this->title_output = 1;
02776 break;
02777 case 2:
02778 $this->title_output = 2;
02779 break;
02780 default:
02781 $this->title_output = 0;
02782 break;
02783 }
02784 }
02785
02795 function setProcessingTime($processing_time = "00:00:00")
02796 {
02797 $this->processing_time = $processing_time;
02798 }
02799
02809 function setEnableProcessingTime($enable = 0)
02810 {
02811 if ($enable) {
02812 $this->enable_processing_time = "1";
02813 } else {
02814 $this->enable_processing_time = "0";
02815 }
02816 }
02817
02827 function setResetProcessingTime($reset = 0)
02828 {
02829 if ($reset)
02830 {
02831 $this->reset_processing_time = 1;
02832 }
02833 else
02834 {
02835 $this->reset_processing_time = 0;
02836 }
02837 }
02838
02848 function setStartingTime($starting_time = "")
02849 {
02850 $this->starting_time = $starting_time;
02851 }
02852
02862 function setEndingTime($ending_time = "")
02863 {
02864 $this->ending_time = $ending_time;
02865 }
02866
02876 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
02877 {
02878 $this->count_system = $a_count_system;
02879 }
02880
02890 function setPassword($a_password = "")
02891 {
02892 $this->password = $a_password;
02893 }
02894
02904 function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
02905 {
02906 $this->score_cutting = $a_score_cutting;
02907 }
02908
02918 function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED)
02919 {
02920 $this->mc_scoring = $a_mc_scoring;
02921 }
02922
02932 function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
02933 {
02934 switch ($a_pass_scoring)
02935 {
02936 case SCORE_BEST_PASS:
02937 $this->pass_scoring = SCORE_BEST_PASS;
02938 break;
02939 default:
02940 $this->pass_scoring = SCORE_LAST_PASS;
02941 break;
02942 }
02943 }
02944
02954 function removeQuestion($question_id)
02955 {
02956 $question =& ilObjTest::_instanciateQuestion($question_id);
02957 include_once ("./classes/class.ilObjAssessmentFolder.php");
02958 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02959 {
02960 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
02961 }
02962 $question->delete($question_id);
02963 $this->removeAllTestEditings($question_id);
02964 $this->loadQuestions();
02965 $this->saveQuestionsToDb();
02966 }
02967
02979 function removeAllTestEditings($question_id = "")
02980 {
02981 global $ilDB;
02982
02983 if ($question_id)
02984 {
02985 $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_solutions.question_fi = %s",
02986 $ilDB->quote($this->getTestId()),
02987 $ilDB->quote($question_id)
02988 );
02989 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active_qst_sol_settings.question_fi = %s",
02990 $ilDB->quote($this->getTestId()),
02991 $ilDB->quote($question_id)
02992 );
02993 $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_test_result.question_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
02994 $ilDB->quote($this->getTestId()),
02995 $ilDB->quote($question_id)
02996 );
02997 $query4 = sprintf("DELETE FROM tst_test_pass_result USING tst_test_pass_result, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_pass_result.active_fi",
02998 $ilDB->quote($this->getTestId())
02999 );
03000 }
03001 else
03002 {
03003 $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
03004 $ilDB->quote($this->getTestId())
03005 );
03006 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
03007 $ilDB->quote($this->getTestId())
03008 );
03009 $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
03010 $ilDB->quote($this->getTestId())
03011 );
03012 $query4 = sprintf("DELETE FROM tst_test_pass_result USING tst_test_pass_result, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_pass_result.active_fi",
03013 $ilDB->quote($this->getTestId())
03014 );
03015 include_once ("./classes/class.ilObjAssessmentFolder.php");
03016 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03017 {
03018 $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
03019 }
03020 }
03021 $query5 = sprintf("DELETE FROM tst_sequence USING tst_sequence, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_sequence.active_fi",
03022 $ilDB->quote($this->getTestId())
03023 );
03024 $result = $ilDB->query($query);
03025 $result = $ilDB->query($query2);
03026 $result = $ilDB->query($query3);
03027 $result = $ilDB->query($query4);
03028 $result = $ilDB->query($query5);
03029
03030 if ($this->isRandomTest())
03031 {
03032 $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_test_random_question.active_fi = tst_active.active_id",
03033 $ilDB->quote($this->getTestId())
03034 );
03035 $result = $ilDB->query($query);
03036 }
03037
03038
03039 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03040 $ilDB->quote($this->getTestId())
03041 );
03042 $result = $ilDB->query($query);
03043
03044
03045 $query = sprintf("DELETE FROM usr_pref WHERE keyword = %s",
03046 $ilDB->quote("tst_password_".$this->getTestId())
03047 );
03048 $result = $ilDB->query($query);
03049 }
03050
03051 function removeSelectedTestResults($active_ids)
03052 {
03053 global $ilDB;
03054
03055
03056 foreach ($active_ids as $active_id)
03057 {
03058 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
03059 $ilDB->quote($active_id . "")
03060 );
03061 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
03062 $ilDB->quote($active_id . "")
03063 );
03064 $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
03065 $ilDB->quote($active_id . "")
03066 );
03067 $query4 = sprintf("DELETE FROM tst_test_pass_result WHERE active_fi = %s",
03068 $ilDB->quote($active_id . "")
03069 );
03070 $result = $ilDB->query($query);
03071 $result = $ilDB->query($query2);
03072 $result = $ilDB->query($query3);
03073 $result = $ilDB->query($query4);
03074
03075 if ($this->isRandomTest())
03076 {
03077 $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
03078 $ilDB->quote($active_id . "")
03079 );
03080 $result = $ilDB->query($query);
03081 }
03082
03083 include_once ("./classes/class.ilObjAssessmentFolder.php");
03084 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03085 {
03086 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
03087 }
03088 }
03089
03090
03091 foreach ($active_ids as $active_id)
03092 {
03093 $usr_id = $this->_getUserIdFromActiveId($active_id);
03094
03095 $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
03096 $ilDB->quote($active_id . "")
03097 );
03098 $result = $ilDB->query($query);
03099
03100 $query = sprintf("DELETE FROM tst_sequence WHERE active_fi = %s",
03101 $ilDB->quote($active_id)
03102 );
03103 $result = $ilDB->query($query);
03104
03105
03106 if ($usr_id > 0)
03107 {
03108 $query = sprintf("DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s",
03109 $ilDB->quote($usr_id),
03110 $ilDB->quote("tst_password_".$this->getTestId())
03111 );
03112 $result = $ilDB->query($query);
03113 }
03114 }
03115 }
03116
03117 function removeTestResultsForUser($user_id)
03118 {
03119 global $ilDB;
03120
03121 $active_id = $this->getActiveIdOfUser($user_id);
03122
03123
03124 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
03125 $ilDB->quote($active_id . "")
03126 );
03127 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
03128 $ilDB->quote($active_id . "")
03129 );
03130 $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
03131 $ilDB->quote($active_id . "")
03132 );
03133 $query4 = sprintf("DELETE FROM tst_test_pass_result WHERE active_fi = %s",
03134 $ilDB->quote($active_id . "")
03135 );
03136 $result = $ilDB->query($query);
03137 $result = $ilDB->query($query2);
03138 $result = $ilDB->query($query3);
03139 $result = $ilDB->query($query4);
03140
03141 if ($this->isRandomTest())
03142 {
03143 $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
03144 $ilDB->quote($active_id . "")
03145 );
03146 $result = $ilDB->query($query);
03147 }
03148
03149 include_once ("./classes/class.ilObjAssessmentFolder.php");
03150 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03151 {
03152 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), $this->userLookupFullName($this->_getUserIdFromActiveId($active_id))));
03153 }
03154
03155 $query = sprintf("DELETE FROM tst_sequence WHERE active_fi = %s",
03156 $ilDB->quote($active_id)
03157 );
03158 $result = $ilDB->query($query);
03159
03160
03161 $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
03162 $ilDB->quote($active_id . "")
03163 );
03164 $result = $ilDB->query($query);
03165
03166
03167 if ($user_id > 0)
03168 {
03169 $query = sprintf("DELETE FROM usr_pref WHERE usr_id = %s AND keyword = %s",
03170 $ilDB->quote($user_id),
03171 $ilDB->quote("tst_password_".$this->getTestId())
03172 );
03173 $result = $ilDB->query($query);
03174 }
03175 }
03176
03186 function questionMoveUp($question_id)
03187 {
03188 global $ilDB;
03189
03190
03191 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03192 $ilDB->quote($this->getTestId()),
03193 $ilDB->quote($question_id)
03194 );
03195 $result = $ilDB->query($query);
03196 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03197 if ($data->sequence > 1) {
03198
03199 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03200 $ilDB->quote($this->getTestId()),
03201 $ilDB->quote($data->sequence - 1)
03202 );
03203 $result = $ilDB->query($query);
03204 $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
03205
03206 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03207 $ilDB->quote($data->sequence),
03208 $ilDB->quote($data_previous->test_question_id)
03209 );
03210 $result = $ilDB->query($query);
03211
03212 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03213 $ilDB->quote($data->sequence - 1),
03214 $ilDB->quote($data->test_question_id)
03215 );
03216 $result = $ilDB->query($query);
03217 include_once ("./classes/class.ilObjAssessmentFolder.php");
03218 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03219 {
03220 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
03221 }
03222 }
03223 $this->loadQuestions();
03224 }
03225
03235 function questionMoveDown($question_id)
03236 {
03237 global $ilDB;
03238
03239
03240 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03241 $ilDB->quote($this->getTestId()),
03242 $ilDB->quote($question_id)
03243 );
03244 $result = $ilDB->query($query);
03245 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03246 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03247 $ilDB->quote($this->getTestId()),
03248 $ilDB->quote($data->sequence + 1)
03249 );
03250 $result = $ilDB->query($query);
03251 if ($result->numRows() == 1)
03252 {
03253
03254 $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
03255
03256 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03257 $ilDB->quote($data->sequence),
03258 $ilDB->quote($data_next->test_question_id)
03259 );
03260 $result = $ilDB->query($query);
03261
03262 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03263 $ilDB->quote($data->sequence + 1),
03264 $ilDB->quote($data->test_question_id)
03265 );
03266 $result = $ilDB->query($query);
03267 include_once ("./classes/class.ilObjAssessmentFolder.php");
03268 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03269 {
03270 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
03271 }
03272 }
03273 $this->loadQuestions();
03274 }
03275
03285 function duplicateQuestionForTest($question_id)
03286 {
03287 global $ilUser;
03288 $question =& ilObjTest::_instanciateQuestion($question_id);
03289 $duplicate_id = $question->duplicate(true);
03290
03291 return $duplicate_id;
03292 }
03293
03302 function insertQuestion($question_id)
03303 {
03304 global $ilDB;
03305
03306 $duplicate_id = $this->duplicateQuestionForTest($question_id);
03307
03308
03309 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
03310 $ilDB->quote($this->getTestId())
03311 );
03312 $result = $ilDB->query($query);
03313 $sequence = 1;
03314
03315 if ($result->numRows() == 1)
03316 {
03317 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03318 $sequence = $data->seq + 1;
03319 }
03320
03321 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
03322 $ilDB->quote($this->getTestId()),
03323 $ilDB->quote($duplicate_id),
03324 $ilDB->quote($sequence)
03325 );
03326 $result = $ilDB->query($query);
03327 if ($result != DB_OK)
03328 {
03329
03330 }
03331 else
03332 {
03333 include_once ("./classes/class.ilObjAssessmentFolder.php");
03334 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03335 {
03336 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
03337 }
03338 }
03339
03340 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03341 $ilDB->quote($this->getTestId())
03342 );
03343 $result = $ilDB->query($query);
03344 $this->loadQuestions();
03345 $this->saveCompleteStatus();
03346 }
03347
03357 function &getQuestionTitles()
03358 {
03359 $titles = array();
03360 if (!$this->isRandomTest())
03361 {
03362 global $ilDB;
03363 $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",
03364 $ilDB->quote($this->getTestId() . "")
03365 );
03366 $result = $ilDB->query($query);
03367 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03368 {
03369 array_push($titles, $row["title"]);
03370 }
03371 }
03372 return $titles;
03373 }
03374
03385 function getQuestionTitle($title)
03386 {
03387 if ($this->getTitleOutput() == 2)
03388 {
03389 return $this->lng->txt("ass_question");
03390 }
03391 else
03392 {
03393 return $title;
03394 }
03395 }
03396
03407 function getQuestionDataset($question_id)
03408 {
03409 global $ilDB;
03410
03411 $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",
03412 $ilDB->quote("$question_id")
03413 );
03414 $result = $ilDB->query($query);
03415 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03416 return $row;
03417 }
03418
03427 function &getExistingQuestions($pass = NULL)
03428 {
03429 global $ilUser;
03430 global $ilDB;
03431
03432 $existing_questions = array();
03433 $active_id = $this->getActiveIdOfUser($ilUser->getId());
03434 if ($this->isRandomTest())
03435 {
03436 if (is_null($pass)) $pass = 0;
03437 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.active_fi = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.pass = %s",
03438 $ilDB->quote($active_id . ""),
03439 $ilDB->quote($pass . "")
03440 );
03441 }
03442 else
03443 {
03444 $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",
03445 $ilDB->quote($this->getTestId())
03446 );
03447 }
03448 $result = $ilDB->query($query);
03449 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
03450 array_push($existing_questions, $data->original_id);
03451 }
03452 return $existing_questions;
03453 }
03454
03464 function getQuestionType($question_id)
03465 {
03466 global $ilDB;
03467
03468 if ($question_id < 1)
03469 return -1;
03470 $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",
03471 $ilDB->quote($question_id)
03472 );
03473 $result = $ilDB->query($query);
03474 if ($result->numRows() == 1) {
03475 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03476 return $data->type_tag;
03477 } else {
03478 return "";
03479 }
03480 }
03481
03490 function startWorkingTime($active_id, $pass)
03491 {
03492 global $ilDB;
03493
03494 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
03495 $ilDB->quote($active_id),
03496 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03497 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03498 $ilDB->quote($pass)
03499 );
03500 $result = $ilDB->query($q);
03501 return $ilDB->getLastInsertId();
03502 }
03503
03512 function updateWorkingTime($times_id)
03513 {
03514 global $ilDB;
03515
03516 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
03517 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03518 $ilDB->quote($times_id)
03519 );
03520 $result = $ilDB->query($q);
03521 }
03522
03531 function &getWorkedQuestions($active_id, $pass = NULL)
03532 {
03533 global $ilUser;
03534 global $ilDB;
03535
03536 if (is_null($pass))
03537 {
03538 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = 0 GROUP BY question_fi",
03539 $ilDB->quote($active_id . "")
03540 );
03541 }
03542 else
03543 {
03544 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
03545 $ilDB->quote($active_id . ""),
03546 $ilDB->quote($pass . "")
03547 );
03548 }
03549 $result = $ilDB->query($query);
03550 $result_array = array();
03551 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03552 {
03553 array_push($result_array, $row->question_fi);
03554 }
03555 return $result_array;
03556 }
03557
03568 function isTestFinishedToViewResults($active_id, $currentpass)
03569 {
03570 $num = $this->getPassFinishDate($active_id, $currentpass);
03571 if (($currentpass > 0) && ($num == 0))
03572 {
03573 return TRUE;
03574 }
03575 else
03576 {
03577 return FALSE;
03578 }
03579 }
03580
03589 function &getAllQuestions($pass = NULL)
03590 {
03591 global $ilUser;
03592 global $ilDB;
03593
03594 $result_array = array();
03595 if ($this->isRandomTest())
03596 {
03597 $active_id = $this->getActiveIdOfUser($ilUser->getId());
03598 $this->loadQuestions($active_id, $pass);
03599 if (count($this->questions) == 0) return $result_array;
03600 if (is_null($pass))
03601 {
03602 $pass = $this->_getPass($active_id);
03603 }
03604 $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.active_fi = %s AND tst_test_random_question.pass = %s AND qpl_questions.question_id IN ('" . join($this->questions, "','") . "')",
03605 $ilDB->quote($active_id . ""),
03606 $ilDB->quote($pass . "")
03607 );
03608 }
03609 else
03610 {
03611 if (count($this->questions) == 0) return $result_array;
03612 $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, "','") . "')";
03613 }
03614 $result = $ilDB->query($query);
03615 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03616 {
03617 $result_array[$row["question_id"]] = $row;
03618 }
03619 return $result_array;
03620 }
03621
03632 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
03633 {
03634 global $ilDB;
03635 global $ilUser;
03636
03637 if (!$user_id) $user_id = $ilUser->getId();
03638 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
03639 {
03640 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03641 $ilDB->quote($user_id),
03642 $ilDB->quote($this->test_id),
03643 $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()])
03644 );
03645 }
03646 else if (strlen($anonymous_id))
03647 {
03648 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03649 $ilDB->quote($user_id),
03650 $ilDB->quote($this->test_id),
03651 $ilDB->quote($anonymous_id)
03652 );
03653 }
03654 else
03655 {
03656 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
03657 {
03658 return NULL;
03659 }
03660 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03661 $ilDB->quote($user_id),
03662 $ilDB->quote($this->test_id)
03663 );
03664 }
03665 $result = $ilDB->query($query);
03666 if ($result->numRows())
03667 {
03668 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03669 return $row["active_id"];
03670 }
03671 else
03672 {
03673 return 0;
03674 }
03675 }
03676
03687 function _getActiveIdOfUser($user_id = "", $test_id = "")
03688 {
03689 global $ilDB;
03690 global $ilUser;
03691
03692 if (!$user_id) {
03693 $user_id = $ilUser->id;
03694 }
03695 if (!$test_id)
03696 {
03697 return "";
03698 }
03699 $query = sprintf("SELECT tst_active.active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03700 $ilDB->quote($user_id . ""),
03701 $ilDB->quote($test_id . "")
03702 );
03703
03704 $result = $ilDB->query($query);
03705 if ($result->numRows())
03706 {
03707 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03708 return $row["active_id"];
03709 }
03710 else
03711 {
03712 return "";
03713 }
03714 }
03715
03724 function pcArrayShuffle($array)
03725 {
03726 mt_srand((double)microtime()*1000000);
03727 $i = count($array);
03728 if ($i > 0)
03729 {
03730 while(--$i)
03731 {
03732 $j = mt_rand(0, $i);
03733 if ($i != $j)
03734 {
03735
03736 $tmp = $array[$j];
03737 $array[$j] = $array[$i];
03738 $array[$i] = $tmp;
03739 }
03740 }
03741 }
03742 return $array;
03743 }
03744
03754 function &getTestResult($active_id, $pass = NULL, $ordered_sequence = FALSE)
03755 {
03756
03757 $total_max_points = 0;
03758 $total_reached_points = 0;
03759
03760 $key = 1;
03761 $result_array = array();
03762 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
03763 $workedthrough = 0;
03764
03765 if (is_null($pass))
03766 {
03767 $pass = $this->_getPass($active_id);
03768 }
03769 include_once "./Modules/Test/classes/class.ilTestSequence.php";
03770 $testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
03771 $sequence = array();
03772 if ($ordered_sequence)
03773 {
03774 $sequence = $testSequence->getOrderedSequence();
03775 }
03776 else
03777 {
03778 $sequence = $testSequence->getUserSequence();
03779 }
03780 foreach ($sequence as $sequenceindex)
03781 {
03782 $value = $testSequence->getQuestionForSequence($sequenceindex);
03783 $max_points = assQuestion::_getMaximumPoints($value);
03784 $total_max_points += $max_points;
03785 $reached_points = assQuestion::_getReachedPoints($active_id, $value, $pass);
03786 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
03787 {
03788 $workedthrough = 1;
03789 }
03790 else
03791 {
03792 $workedthrough = 0;
03793 }
03794 $total_reached_points += $reached_points;
03795 if ($max_points > 0)
03796 {
03797 $percentvalue = $reached_points / $max_points;
03798 }
03799 else
03800 {
03801 $percentvalue = 0;
03802 }
03803 if ($percentvalue < 0) $percentvalue = 0.0;
03804 if (assQuestion::_getSuggestedSolutionCount($value) == 1)
03805 {
03806 $solution_array =& assQuestion::_getSuggestedSolution($value, 0);
03807 $href = assQuestion::_getInternalLinkHref($solution_array["internal_link"]);
03808 }
03809 elseif (assQuestion::_getSuggestedSolutionCount($value) > 1)
03810 {
03811 $href = "see_details_for_further_information";
03812 }
03813 else
03814 {
03815 $href = "";
03816 }
03817 $info =& assQuestion::_getQuestionInfo($value);
03818 include_once "./Services/Utilities/classes/class.ilUtil.php";
03819 $row = array(
03820 "nr" => "$key",
03821 "title" => ilUtil::prepareFormOutput($this->getQuestionTitle($info["title"])),
03822 "max" => $max_points,
03823 "reached" => $reached_points,
03824 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
03825 "solution" => $href,
03826 "type" => $info["type_tag"],
03827 "qid" => $value,
03828 "original_id" => $info["original_id"],
03829 "workedthrough" => $workedthrough
03830 );
03831 array_push($result_array, $row);
03832 $key++;
03833 }
03834
03835 if ($this->getScoreCutting() == 1)
03836 {
03837 if ($total_reached_points < 0)
03838 {
03839 $total_reached_points = 0;
03840 }
03841 }
03842 $result_array["test"]["total_max_points"] = $total_max_points;
03843 $result_array["test"]["total_reached_points"] = $total_reached_points;
03844 if ((!$total_reached_points) or (!$total_max_points))
03845 {
03846 $percentage = 0.0;
03847 }
03848 else
03849 {
03850 $percentage = ($total_reached_points / $total_max_points) * 100.0;
03851 if ($percentage < 0) $percentage = 0.0;
03852 }
03853 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
03854 $passed = "";
03855 if ($mark_obj)
03856 {
03857 if ($mark_obj->getPassed())
03858 {
03859 $passed = 1;
03860 }
03861 else
03862 {
03863 $passed = 0;
03864 }
03865 }
03866 $result_array["test"]["passed"] = $passed;
03867 return $result_array;
03868 }
03869
03878 function evalTotalPersons()
03879 {
03880 global $ilDB;
03881
03882 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
03883 $ilDB->quote($this->getTestId())
03884 );
03885 $result = $ilDB->query($q);
03886 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03887 return $row->total;
03888 }
03889
03898 function getCompleteWorkingTime($user_id)
03899 {
03900 global $ilDB;
03901
03902 $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",
03903 $ilDB->quote($this->getTestId()),
03904 $ilDB->quote($user_id)
03905 );
03906 $result = $ilDB->query($q);
03907 $time = 0;
03908 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03909 {
03910 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03911 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03912 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03913 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03914 $time += ($epoch_2 - $epoch_1);
03915 }
03916 return $time;
03917 }
03918
03927 function &getCompleteWorkingTimeOfParticipants()
03928 {
03929 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
03930 }
03931
03941 function &_getCompleteWorkingTimeOfParticipants($test_id)
03942 {
03943 global $ilDB;
03944
03945 $query = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.active_fi, tst_times.started",
03946 $ilDB->quote($test_id . "")
03947 );
03948 $result = $ilDB->query($query);
03949 $time = 0;
03950 $times = array();
03951 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03952 {
03953 if (!array_key_exists($row["active_fi"], $times))
03954 {
03955 $times[$row["active_fi"]] = 0;
03956 }
03957 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
03958 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03959 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
03960 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03961 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
03962 }
03963 return $times;
03964 }
03965
03974 function getCompleteWorkingTimeOfParticipant($active_id)
03975 {
03976 global $ilDB;
03977
03978 $query = 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.active_id = %s ORDER BY tst_times.active_fi, tst_times.started",
03979 $ilDB->quote($this->getTestId() . ""),
03980 $ilDB->quote($active_id . "")
03981 );
03982 $result = $ilDB->query($query);
03983 $time = 0;
03984 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03985 {
03986 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
03987 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03988 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
03989 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03990 $time += ($epoch_2 - $epoch_1);
03991 }
03992 return $time;
03993 }
03994
04004 function getVisitTimeOfParticipant($active_id)
04005 {
04006 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
04007 }
04008
04019 function _getVisitTimeOfParticipant($test_id, $active_id)
04020 {
04021 global $ilDB;
04022
04023 $query = 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.active_id = %s ORDER BY tst_times.started",
04024 $ilDB->quote($test_id . ""),
04025 $ilDB->quote($active_id . "")
04026 );
04027 $result = $ilDB->query($query);
04028 $firstvisit = 0;
04029 $lastvisit = 0;
04030 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04031 {
04032 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
04033 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04034 if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
04035 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
04036 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04037 if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
04038 }
04039 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
04040 }
04041
04050 function &evalStatistical($active_id)
04051 {
04052 global $ilDB;
04053
04054 $pass = ilObjTest::_getResultPass($active_id);
04055 $test_result =& $this->getTestResult($active_id, $pass);
04056 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
04057 $ilDB->quote($active_id)
04058 );
04059 $result = $ilDB->query($q);
04060 $times = array();
04061 $first_visit = 0;
04062 $last_visit = 0;
04063 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
04064 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04065 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04066 if (!$first_visit) {
04067 $first_visit = $epoch_1;
04068 }
04069 if ($epoch_1 < $first_visit) {
04070 $first_visit = $epoch_1;
04071 }
04072 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04073 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04074 if (!$last_visit) {
04075 $last_visit = $epoch_2;
04076 }
04077 if ($epoch_2 > $last_visit) {
04078 $last_visit = $epoch_2;
04079 }
04080 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
04081 }
04082 $max_time = 0;
04083 foreach ($times as $key => $value) {
04084 $max_time += $value;
04085 }
04086 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
04087 {
04088 $percentage = 0.0;
04089 }
04090 else
04091 {
04092 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
04093 if ($percentage < 0) $percentage = 0.0;
04094 }
04095 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
04096 $first_date = getdate($first_visit);
04097 $last_date = getdate($last_visit);
04098 $qworkedthrough = 0;
04099 foreach ($test_result as $key => $value)
04100 {
04101 if (preg_match("/\d+/", $key))
04102 {
04103 $qworkedthrough += $value["workedthrough"];
04104 }
04105 }
04106 if (!$qworkedthrough)
04107 {
04108 $atimeofwork = 0;
04109 }
04110 else
04111 {
04112 $atimeofwork = $max_time / $qworkedthrough;
04113 }
04114 $result_mark = "";
04115 $passed = "";
04116 if ($mark_obj)
04117 {
04118 $result_mark = $mark_obj->getShortName();
04119 if ($mark_obj->getPassed())
04120 {
04121 $passed = 1;
04122 }
04123 else
04124 {
04125 $passed = 0;
04126 }
04127 }
04128 $percent_worked_through = 0;
04129 if (count($this->questions))
04130 {
04131 $percent_worked_through = $qworkedthrough / count($this->questions);
04132 }
04133 $result_array = array(
04134 "qworkedthrough" => $qworkedthrough,
04135 "qmax" => count($this->questions),
04136 "pworkedthrough" => $percent_worked_through,
04137 "timeofwork" => $max_time,
04138 "atimeofwork" => $atimeofwork,
04139 "firstvisit" => $first_date,
04140 "lastvisit" => $last_date,
04141 "resultspoints" => $test_result["test"]["total_reached_points"],
04142 "maxpoints" => $test_result["test"]["total_max_points"],
04143 "resultsmarks" => $result_mark,
04144 "passed" => $passed,
04145 "distancemedian" => "0"
04146 );
04147 foreach ($test_result as $key => $value)
04148 {
04149 if (preg_match("/\d+/", $key))
04150 {
04151 $result_array[$key] = $value;
04152 }
04153 }
04154 return $result_array;
04155 }
04156
04166 function &getTotalPointsPassedArray()
04167 {
04168 $totalpoints_array = array();
04169 $all_users =& $this->evalTotalParticipantsArray();
04170 foreach ($all_users as $active_id => $user_name)
04171 {
04172 $test_result =& $this->getTestResult($active_id);
04173 $reached = $test_result["test"]["total_reached_points"];
04174 $total = $test_result["test"]["total_max_points"];
04175 $percentage = $total != 0 ? $reached/$total : 0;
04176 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
04177 if ($mark)
04178 {
04179 if ($mark->getPassed())
04180 {
04181 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
04182 }
04183 }
04184 }
04185 return $totalpoints_array;
04186 }
04187
04196 function &getParticipants()
04197 {
04198 global $ilDB;
04199 $q = sprintf("SELECT tst_active.active_id, usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname ASC",
04200 $ilDB->quote($this->getTestId())
04201 );
04202 $result = $ilDB->query($q);
04203 $persons_array = array();
04204 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04205 {
04206 $name = $this->lng->txt("unknown");
04207 $fullname = $this->lng->txt("unknown");
04208 $login = "";
04209 if (!$this->getAnonymity())
04210 {
04211 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04212 {
04213 $name = $this->lng->txt("deleted_user");
04214 $fullname = $this->lng->txt("deleted_user");
04215 $login = $this->lng->txt("unknown");
04216 }
04217 else
04218 {
04219 $login = $row["login"];
04220 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04221 {
04222 $name = $this->lng->txt("unknown");
04223 $fullname = $this->lng->txt("unknown");
04224 }
04225 else
04226 {
04227 $name = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
04228 $fullname = trim($row["title"] . " " . $row["firstname"] . " " . $row["lastname"]);
04229 }
04230 }
04231 }
04232 $persons_array[$row["active_id"]] = array(
04233 "name" => $name,
04234 "fullname" => $fullname,
04235 "login" => $login
04236 );
04237 }
04238 return $persons_array;
04239 }
04240
04249 function &evalTotalPersonsArray($name_sort_order = "asc")
04250 {
04251 global $ilDB;
04252 $q = sprintf("SELECT tst_active.active_id, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04253 $ilDB->quote($this->getTestId())
04254 );
04255 $result = $ilDB->query($q);
04256 $persons_array = array();
04257 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04258 {
04259 if ($this->getAnonymity())
04260 {
04261 $persons_array[$row["active_id"]] = $this->lng->txt("unknown");
04262 }
04263 else
04264 {
04265 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04266 {
04267 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
04268 }
04269 else
04270 {
04271 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04272 {
04273 $persons_array[$row["active_id"]] = $row["lastname"];
04274 }
04275 else
04276 {
04277 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
04278 }
04279 }
04280 }
04281 }
04282 return $persons_array;
04283 }
04284
04293 function &evalTotalParticipantsArray($name_sort_order = "asc")
04294 {
04295 global $ilDB;
04296 $q = sprintf("SELECT tst_active.active_id, usr_data.login, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04297 $ilDB->quote($this->getTestId())
04298 );
04299 $result = $ilDB->query($q);
04300 $persons_array = array();
04301 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04302 {
04303 if ($this->getAnonymity())
04304 {
04305 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("unknown"));
04306 }
04307 else
04308 {
04309 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04310 {
04311 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
04312 }
04313 else
04314 {
04315 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04316 {
04317 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
04318 }
04319 else
04320 {
04321 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
04322 }
04323 }
04324 }
04325 }
04326 return $persons_array;
04327 }
04328
04337 function evalTotalFinished()
04338 {
04339 global $ilDB;
04340
04341 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
04342 $ilDB->quote($this->getTestId())
04343 );
04344 $result = $ilDB->query($q);
04345 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
04346 return $row->total;
04347 }
04348
04357 function &getQuestionsOfTest($active_id)
04358 {
04359 global $ilDB;
04360 if ($this->isRandomTest())
04361 {
04362 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, " .
04363 "tst_test_random_question.pass, qpl_questions.points " .
04364 "FROM tst_test_random_question, qpl_questions " .
04365 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
04366 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
04367 $ilDB->quote($active_id . ""),
04368 $this->getQuestionCount()
04369 );
04370 }
04371 else
04372 {
04373 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
04374 "qpl_questions.points " .
04375 "FROM tst_test_question, tst_active, qpl_questions " .
04376 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
04377 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
04378 $ilDB->quote($active_id . "")
04379 );
04380 }
04381 $result = $ilDB->query($query);
04382 $qtest = array();
04383 if ($result->numRows())
04384 {
04385 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04386 {
04387 array_push($qtest, $row);
04388 }
04389 }
04390 return $qtest;
04391 }
04392
04401 function &getQuestionsOfPass($active_id, $pass)
04402 {
04403 global $ilDB;
04404 if ($this->isRandomTest())
04405 {
04406 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, " .
04407 "qpl_questions.points " .
04408 "FROM tst_test_random_question, qpl_questions " .
04409 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
04410 "AND tst_test_random_question.active_fi = %s AND tst_test_random_question.pass = %s " .
04411 "ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
04412 $ilDB->quote($active_id . ""),
04413 $ilDB->quote($pass . ""),
04414 $this->getQuestionCount()
04415 );
04416 }
04417 else
04418 {
04419 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
04420 "qpl_questions.points " .
04421 "FROM tst_test_question, tst_active, qpl_questions " .
04422 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
04423 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi",
04424 $ilDB->quote($active_id . "")
04425 );
04426 }
04427 $result = $ilDB->query($query);
04428 $qpass = array();
04429 if ($result->numRows())
04430 {
04431 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04432 {
04433 array_push($qpass, $row);
04434 }
04435 }
04436 return $qpass;
04437 }
04438
04439 private function getMembershipByType($a_usr_id,$a_type)
04440 {
04441 global $ilDB;
04442
04443 $query = "SELECT DISTINCT obd.obj_id,obr.ref_id FROM rbac_ua AS ua ".
04444 "JOIN rbac_fa AS fa ON ua.rol_id = fa.rol_id ".
04445 "JOIN tree AS t1 ON t1.child = fa.parent ".
04446 "JOIN object_reference AS obr ON t1.parent = obr.ref_id ".
04447 "JOIN object_data AS obd ON obr.obj_id = obd.obj_id ".
04448 "WHERE obd.type = ".$ilDB->quote($a_type)." ".
04449 "AND fa.assign = 'y' ".
04450 "AND ua.usr_id = ".$ilDB->quote($a_usr_id)." ";
04451 $res = $ilDB->query($query);
04452
04453 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
04454 {
04455 $ref_ids[] = $row->obj_id;
04456 }
04457
04458 return $ref_ids ? $ref_ids : array();
04459 }
04460
04461 function getUnfilteredEvaluationData()
04462 {
04463 global $ilDB;
04464 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
04465 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
04466 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
04467 $data = new ilTestEvaluationData();
04468 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
04469 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
04470 "qpl_questions.points AS maxpoints " .
04471 "FROM tst_test_result, qpl_questions, tst_active " .
04472 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
04473 "WHERE tst_active.active_id = tst_test_result.active_fi " .
04474 "AND qpl_questions.question_id = tst_test_result.question_fi " .
04475 "AND tst_active.test_fi = %s " .
04476 "ORDER BY usr_data.lastname, usr_data.firstname, active_id, pass, TIMESTAMP",
04477 $ilDB->quote($this->getTestId() . "")
04478 );
04479 $result = $ilDB->query($query);
04480 $pass = NULL;
04481 $checked = array();
04482 $datasets = 0;
04483 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04484 {
04485 $datasets++;
04486 $remove = FALSE;
04487 if (!$remove)
04488 {
04489 if (!$data->participantExists($row["active_fi"]))
04490 {
04491 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
04492 $data->getParticipant($row["active_fi"])->setName($this->buildName($row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
04493 $data->getParticipant($row["active_fi"])->setLogin($row["login"]);
04494 $data->getParticipant($row["active_fi"])->setUserID($row["usr_id"]);
04495 }
04496 if (!is_object($data->getParticipant($row["active_fi"])->getPass($row["pass"])))
04497 {
04498 $pass = new ilTestEvaluationPassData();
04499 $pass->setPass($row["pass"]);
04500 $data->getParticipant($row["active_fi"])->addPass($row["pass"], $pass);
04501 }
04502 $data->getParticipant($row["active_fi"])->getPass($row["pass"])->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
04503 }
04504 }
04505 $data->setDatasets($datasets);
04506
04507 foreach (array_keys($data->getParticipants()) as $active_id)
04508 {
04509 if ($this->isRandomTest())
04510 {
04511 for ($testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++)
04512 {
04513 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
04514 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title " .
04515 "FROM tst_test_random_question, qpl_questions " .
04516 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
04517 "AND tst_test_random_question.pass = %s " .
04518 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
04519 $ilDB->quote($testpass . ""),
04520 $ilDB->quote($active_id . ""),
04521 $this->getQuestionCount()
04522 );
04523 $result = $ilDB->query($query);
04524 if ($result->numRows())
04525 {
04526 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04527 {
04528 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
04529 $data->getParticipant($active_id)->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $tpass);
04530 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
04531 }
04532 }
04533 }
04534 }
04535 else
04536 {
04537 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
04538 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
04539 "FROM tst_test_question, tst_active, qpl_questions " .
04540 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
04541 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
04542 $ilDB->quote($active_id . "")
04543 );
04544 $result = $ilDB->query($query);
04545 if ($result->numRows())
04546 {
04547 $questionsbysequence = array();
04548 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04549 {
04550 $questionsbysequence[$row["sequence"]] = $row;
04551 }
04552 $sequery = sprintf("SELECT * FROM tst_sequence WHERE active_fi = %s",
04553 $ilDB->quote($active_id)
04554 );
04555 $seqresult = $ilDB->query($sequery);
04556 while ($seqrow = $seqresult->fetchRow(DB_FETCHMODE_ASSOC))
04557 {
04558 $questionsequence = unserialize($seqrow["sequence"]);
04559 foreach ($questionsequence as $sidx => $seq)
04560 {
04561 $qsid = $questionsbysequence[$seq]["original_id"] ? $questionsbysequence[$seq]["original_id"] : $questionsbysequence[$seq]["question_fi"];
04562 $data->getParticipant($active_id)->addQuestion($qsid, $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
04563 $data->addQuestionTitle($qsid, $questionsbysequence[$seq]["title"]);
04564 }
04565 }
04566 }
04567 }
04568 }
04569
04570 $workingTimes =& $this->getCompleteWorkingTimeOfParticipants();
04571
04572 foreach (array_keys($data->getParticipants()) as $active_id)
04573 {
04574 $tpass = 0;
04575 if ($this->getPassScoring() == SCORE_BEST_PASS)
04576 {
04577 $tpass = $data->getParticipant($active_id)->getBestPass();
04578 }
04579 else
04580 {
04581 $tpass = $data->getParticipant($active_id)->getLastPass();
04582 }
04583 $data->getParticipant($active_id)->setReached($data->getParticipant($active_id)->getReachedPoints($tpass));
04584 $data->getParticipant($active_id)->setMaxPoints($data->getParticipant($active_id)->getAvailablePoints($tpass));
04585 $percentage = $data->getParticipant($active_id)->getMaxPoints() ? $data->getParticipant($active_id)->getReached() / $data->getParticipant($active_id)->getMaxPoints() * 100.0 : 0;
04586 $mark = $this->mark_schema->getMatchingMark($percentage);
04587 if (is_object($mark))
04588 {
04589 $data->getParticipant($active_id)->setMark($mark->getShortName());
04590 $data->getParticipant($active_id)->setMarkOfficial($mark->getOfficialName());
04591 $data->getParticipant($active_id)->setPassed($mark->getPassed());
04592 }
04593 if ($this->ects_output)
04594 {
04595
04596 $ects_mark = $this->getECTSGrade($data->getParticipant($active_id)->getReached(), $data->getParticipant($active_id)->getMaxPoints());
04597 $data->getParticipant($active_id)->setECTSMark($ects_mark);
04598 }
04599 if (is_object($data->getParticipant($active_id)->getPass($tpass)))
04600 {
04601 $data->getParticipant($active_id)->setQuestionsWorkedThrough($data->getParticipant($active_id)->getPass($tpass)->getAnsweredQuestionCount());
04602 }
04603 $questionpass = $tpass;
04604 if (!is_array($data->getParticipant($active_id)->getQuestions($tpass)))
04605 {
04606 $questionpass = 0;
04607 }
04608 $data->getParticipant($active_id)->setNumberOfQuestions(count($data->getParticipant($active_id)->getQuestions($questionpass)));
04609 $data->getParticipant($active_id)->setTimeOfWork($workingTimes[$active_id]);
04610 $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
04611 $data->getParticipant($active_id)->setFirstVisit($visitingTime["firstvisit"]);
04612 $data->getParticipant($active_id)->setLastVisit($visitingTime["lastvisit"]);
04613 }
04614 return $data;
04615 }
04616
04617 function &getCompleteEvaluationData($withStatistics = TRUE, $filterby = "", $filtertext = "")
04618 {
04619 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
04620 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
04621 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
04622 $data = $this->getUnfilteredEvaluationData();
04623 if ($withStatistics)
04624 {
04625 $data->calculateStatistics();
04626 }
04627 $data->setFilter($filterby, $filtertext);
04628 return $data;
04629 }
04630
04631 function &_getCompleteEvaluationData($test_id, $withStatistics = TRUE, $active_id = "")
04632 {
04633 global $ilDB;
04634
04635 $testquery = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
04636 $ilDB->quote($test_id . "")
04637 );
04638 $testres = $ilDB->query($testquery);
04639 $testdata = array();
04640 if ($testres->numRows())
04641 {
04642 $testdata = $testres->fetchRow(DB_FETCHMODE_ASSOC);
04643 }
04644
04645 include_once "./Modules/Test/classes/class.assMarkSchema.php";
04646 $mark_schema = new ASS_MarkSchema();
04647 $mark_schema->loadFromDb($test_id);
04648
04649 include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
04650 include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
04651 include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
04652 if ($active_id > 0) $withStatistics = FALSE;
04653 $data = new ilTestEvaluationData();
04654
04655 if ($active_id > 0)
04656 {
04657 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
04658 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
04659 "qpl_questions.points AS maxpoints " .
04660 "FROM tst_test_result, qpl_questions, tst_active " .
04661 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
04662 "WHERE tst_active.active_id = tst_test_result.active_fi " .
04663 "AND qpl_questions.question_id = tst_test_result.question_fi " .
04664 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
04665 "ORDER BY active_id, pass, TIMESTAMP",
04666 $ilDB->quote($test_id . ""),
04667 $ilDB->quote($active_id . "")
04668 );
04669 }
04670 else
04671 {
04672 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
04673 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
04674 "qpl_questions.points AS maxpoints " .
04675 "FROM tst_test_result, qpl_questions, tst_active " .
04676 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
04677 "WHERE tst_active.active_id = tst_test_result.active_fi " .
04678 "AND qpl_questions.question_id = tst_test_result.question_fi " .
04679 "AND tst_active.test_fi = %s " .
04680 "ORDER BY active_id, pass, TIMESTAMP",
04681 $ilDB->quote($test_id . "")
04682 );
04683 }
04684 $result = $ilDB->query($query);
04685 $pass = NULL;
04686 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04687 {
04688 if (!$data->participantExists($row["active_fi"]))
04689 {
04690 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
04691 $data->getParticipant($row["active_fi"])->setName(ilObjTest::_buildName($testdata["anonymity"], $row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
04692 $data->getParticipant($row["active_fi"])->setLogin($row["login"]);
04693 $data->getParticipant($row["active_fi"])->setUserID($row["usr_id"]);
04694 }
04695 if (!is_object($data->getParticipant($row["active_fi"])->getPass($row["pass"])))
04696 {
04697 $pass = new ilTestEvaluationPassData();
04698 $pass->setPass($row["pass"]);
04699 $data->getParticipant($row["active_fi"])->addPass($row["pass"], $pass);
04700 }
04701 $data->getParticipant($row["active_fi"])->getPass($row["pass"])->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
04702 }
04703
04704 foreach (array_keys($data->getParticipants()) as $active_id)
04705 {
04706 if ($testdata["random_test"])
04707 {
04708 for ($testpass = 0; $testpass <= $data->getParticipant($active_id)->getLastPass(); $testpass++)
04709 {
04710 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
04711 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title " .
04712 "FROM tst_test_random_question, qpl_questions " .
04713 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
04714 "AND tst_test_random_question.pass = %s " .
04715 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
04716 $ilDB->quote($testpass . ""),
04717 $ilDB->quote($active_id . ""),
04718 ilObjTest::_getQuestionCount($test_id)
04719 );
04720 $result = $ilDB->query($query);
04721 if ($result->numRows())
04722 {
04723 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04724 {
04725 $tpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
04726 $data->getParticipant($active_id)->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $tpass);
04727 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
04728 }
04729 }
04730 }
04731 }
04732 else
04733 {
04734 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
04735 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id " .
04736 "FROM tst_test_question, tst_active, qpl_questions " .
04737 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
04738 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
04739 $ilDB->quote($active_id . "")
04740 );
04741 $result = $ilDB->query($query);
04742 if ($result->numRows())
04743 {
04744 $questionsbysequence = array();
04745 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04746 {
04747 $questionsbysequence[$row["sequence"]] = $row;
04748 }
04749 $sequery = sprintf("SELECT * FROM tst_sequence WHERE active_fi = %s",
04750 $ilDB->quote($active_id)
04751 );
04752 $seqresult = $ilDB->query($sequery);
04753 while ($seqrow = $seqresult->fetchRow(DB_FETCHMODE_ASSOC))
04754 {
04755 $questionsequence = unserialize($seqrow["sequence"]);
04756 foreach ($questionsequence as $sidx => $seq)
04757 {
04758 $qsid = $questionsbysequence[$seq]["original_id"] ? $questionsbysequence[$seq]["original_id"] : $questionsbysequence[$seq]["question_fi"];
04759 $data->getParticipant($active_id)->addQuestion($qsid, $questionsbysequence[$seq]["points"], $sidx + 1, $seqrow["pass"]);
04760 $data->addQuestionTitle($qsid, $questionsbysequence[$seq]["title"]);
04761 }
04762 }
04763
04764
04765
04766
04767
04768
04769
04770
04771 }
04772 }
04773 }
04774
04775 $workingTimes =& ilObjTest::_getCompleteWorkingTimeOfParticipants($test_id);
04776
04777 foreach (array_keys($data->getParticipants()) as $active_id)
04778 {
04779 $tpass = 0;
04780 if ($testdata["pass_scoring"] == SCORE_BEST_PASS)
04781 {
04782 $tpass = $data->getParticipant($active_id)->getBestPass();
04783 }
04784 else
04785 {
04786 $tpass = $data->getParticipant($active_id)->getLastPass();
04787 }
04788 $data->getParticipant($active_id)->setReached($data->getParticipant($active_id)->getReachedPoints($tpass));
04789 $data->getParticipant($active_id)->setMaxPoints($data->getParticipant($active_id)->getAvailablePoints($tpass));
04790 $percentage = $data->getParticipant($active_id)->getMaxPoints() ? $data->getParticipant($active_id)->getReached() / $data->getParticipant($active_id)->getMaxPoints() * 100.0 : 0;
04791 $mark = $mark_schema->getMatchingMark($percentage);
04792 if (is_object($mark))
04793 {
04794 $data->getParticipant($active_id)->setMark($mark->getShortName());
04795 $data->getParticipant($active_id)->setMarkOfficial($mark->getOfficialName());
04796 $data->getParticipant($active_id)->setPassed($mark->getPassed());
04797 }
04798 if (is_object($data->getParticipant($active_id)->getPass($tpass)))
04799 {
04800 $data->getParticipant($active_id)->setQuestionsWorkedThrough($data->getParticipant($active_id)->getPass($tpass)->getAnsweredQuestionCount());
04801 }
04802 $questionpass = $tpass;
04803 if (!is_array($data->getParticipant($active_id)->getQuestions($tpass)))
04804 {
04805 $questionpass = 0;
04806 }
04807 $data->getParticipant($active_id)->setNumberOfQuestions(count($data->getParticipant($active_id)->getQuestions($questionpass)));
04808 $data->getParticipant($active_id)->setTimeOfWork($workingTimes[$active_id]);
04809 $visitingTime =& ilObjTest::_getVisitTimeOfParticipant($test_id, $active_id);
04810 $data->getParticipant($active_id)->setFirstVisit($visitingTime["firstvisit"]);
04811 $data->getParticipant($active_id)->setLastVisit($visitingTime["lastvisit"]);
04812 }
04813 $passed_points = array();
04814 foreach (array_keys($data->getParticipants()) as $active_id)
04815 {
04816 $participant =& $data->getParticipant($active_id);
04817 if ($participant->getPassed())
04818 {
04819 array_push($passed_points, $participant->getReached());
04820 }
04821 }
04822 foreach (array_keys($data->getParticipants()) as $active_id)
04823 {
04824 $participant =& $data->getParticipant($active_id);
04825 if ($testdata["ects_output"])
04826 {
04827 $ects_mark = ilObjTest::_getECTSGrade($passed_points, $participant->getReached(), $participant->getMaxPoints(), $testdata["ects_a"], $testdata["ects_b"], $testdata["ects_c"], $testdata["ects_d"], $testdata["ects_e"], $testdata["ects_fx"]);
04828 $participant->setECTSMark($ects_mark);
04829 }
04830 }
04831 if ($withStatistics)
04832 {
04833 $data->calculateStatistics();
04834 }
04835 return $data;
04836 }
04837
04846 function &evalResultsOverview()
04847 {
04848 return $this->_evalResultsOverview($this->getTestId());
04849 }
04850
04859 function &_evalResultsOverview($test_id)
04860 {
04861 global $ilDB;
04862
04863 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
04864 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
04865 "qpl_questions.points AS maxpoints " .
04866 "FROM tst_test_result, qpl_questions, tst_active " .
04867 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
04868 "WHERE tst_active.active_id = tst_test_result.active_fi " .
04869 "AND qpl_questions.question_id = tst_test_result.question_fi " .
04870 "AND tst_active.test_fi = %s " .
04871 "ORDER BY active_id, pass, TIMESTAMP",
04872 $ilDB->quote($test_id . "")
04873 );
04874 $result = $ilDB->query($query);
04875 $overview = array();
04876 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04877 {
04878 if (!array_key_exists($row["active_fi"], $overview))
04879 {
04880 $overview[$row["active_fi"]] = array();
04881 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
04882 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
04883 $overview[$row["active_fi"]]["title"] = $row["title"];
04884 $overview[$row["active_fi"]]["login"] = $row["login"];
04885 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
04886 $overview[$row["active_fi"]]["started"] = $row["started"];
04887 $overview[$row["active_fi"]]["finished"] = $row["finished"];
04888 }
04889 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
04890 {
04891 $overview[$row["active_fi"]][$row["pass"]] = array();
04892 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
04893 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
04894 }
04895 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
04896 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
04897 }
04898 return $overview;
04899 }
04900
04910 function &evalResultsOverviewOfParticipant($active_id)
04911 {
04912 global $ilDB;
04913
04914 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
04915 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
04916 "qpl_questions.points AS maxpoints " .
04917 "FROM tst_test_result, qpl_questions, tst_active " .
04918 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
04919 "WHERE tst_active.active_id = tst_test_result.active_fi " .
04920 "AND qpl_questions.question_id = tst_test_result.question_fi " .
04921 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
04922 "ORDER BY active_id, pass, TIMESTAMP",
04923 $ilDB->quote($this->getTestId() . ""),
04924 $ilDB->quote($active_id . "")
04925 );
04926 $result = $ilDB->query($query);
04927 $overview = array();
04928 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04929 {
04930 if (!array_key_exists($row["active_fi"], $overview))
04931 {
04932 $overview[$row["active_fi"]] = array();
04933 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
04934 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
04935 $overview[$row["active_fi"]]["title"] = $row["title"];
04936 $overview[$row["active_fi"]]["login"] = $row["login"];
04937 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
04938 $overview[$row["active_fi"]]["started"] = $row["started"];
04939 $overview[$row["active_fi"]]["finished"] = $row["finished"];
04940 }
04941 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
04942 {
04943 $overview[$row["active_fi"]][$row["pass"]] = array();
04944 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
04945 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
04946 }
04947 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
04948 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
04949 }
04950 return $overview;
04951 }
04952
04966 function buildName($user_id, $firstname, $lastname, $title)
04967 {
04968 $name = "";
04969 if (strlen($firstname.$lastname.$title) == 0)
04970 {
04971 $name = $this->lng->txt("deleted_user");
04972 }
04973 else
04974 {
04975 if ($user_id == ANONYMOUS_USER_ID)
04976 {
04977 $name = $lastname;
04978 }
04979 else
04980 {
04981 $name = trim($lastname . ", " . $firstname . " " . $title);
04982 }
04983 if ($this->getAnonymity())
04984 {
04985 $name = $this->lng->txt("anonymous");
04986 }
04987 }
04988 return $name;
04989 }
04990
05005 function _buildName($is_anonymous, $user_id, $firstname, $lastname, $title)
05006 {
05007 global $lng;
05008 $name = "";
05009 if (strlen($firstname.$lastname.$title) == 0)
05010 {
05011 $name = $lng->txt("deleted_user");
05012 }
05013 else
05014 {
05015 if ($user_id == ANONYMOUS_USER_ID)
05016 {
05017 $name = $lastname;
05018 }
05019 else
05020 {
05021 $name = trim($lastname . ", " . $firstname . " " . $title);
05022 }
05023 if ($is_anonymous)
05024 {
05025 $name = $lng->txt("anonymous");
05026 }
05027 }
05028 return $name;
05029 }
05030
05039 function evalTotalStartedAverageTime()
05040 {
05041 global $ilDB;
05042
05043 $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",
05044 $ilDB->quote($this->getTestId())
05045 );
05046 $result = $ilDB->query($q);
05047 $times = array();
05048 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05049 {
05050 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
05051 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05052 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
05053 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05054 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
05055 }
05056 $max_time = 0;
05057 $counter = 0;
05058 foreach ($times as $key => $value)
05059 {
05060 $max_time += $value;
05061 $counter++;
05062 }
05063 if ($counter)
05064 {
05065 $average_time = round($max_time / $counter);
05066 }
05067 else
05068 {
05069 $average_time = 0;
05070 }
05071 return $average_time;
05072 }
05073
05082 function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $show_path = FALSE, $with_questioncount = FALSE, $permission = "read")
05083 {
05084 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
05085 return ilObjQuestionPool::_getAvailableQuestionpools($use_object_id, $equal_points, $could_be_offline, $show_path, $with_questioncount, $permission);
05086 }
05087
05096 function getEstimatedWorkingTime()
05097 {
05098 $time_in_seconds = 0;
05099 foreach ($this->questions as $question_id)
05100 {
05101 $question =& ilObjTest::_instanciateQuestion($question_id);
05102 $est_time = $question->getEstimatedWorkingTime();
05103 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
05104 }
05105 $hours = (int)($time_in_seconds / 3600) ;
05106 $time_in_seconds = $time_in_seconds - ($hours * 3600);
05107 $minutes = (int)($time_in_seconds / 60);
05108 $time_in_seconds = $time_in_seconds - ($minutes * 60);
05109 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
05110 return $result;
05111 }
05112
05125 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
05126 {
05127 global $rbacsystem;
05128 global $ilDB;
05129
05130 if ($questionpool != 0)
05131 {
05132
05133 if (!$use_obj_id)
05134 {
05135 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
05136 $ilDB->quote("$questionpool")
05137 );
05138 $result = $ilDB->query($query);
05139 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
05140 $questionpool = $row[0];
05141 }
05142 }
05143
05144
05145 $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",
05146 $ilDB->quote($this->getTestId() . "")
05147 );
05148 $result = $ilDB->query($query);
05149 $original_ids = array();
05150 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
05151 {
05152 if (strcmp($row[0], "") != 0)
05153 {
05154 array_push($original_ids, $row[0]);
05155 }
05156 }
05157 $original_clause = "";
05158 if (count($original_ids))
05159 {
05160 $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN ('" . join($original_ids, "','") . "')";
05161 }
05162
05163
05164 if (($questionpool == 0) && (!is_array($qpls)))
05165 {
05166 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
05167 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
05168 $available = "";
05169 $constraint_qpls = "";
05170 if (count($available_pools))
05171 {
05172 $available = " AND qpl_questions.obj_fi IN ('" . join($available_pools, "','") . "')";
05173 }
05174 else
05175 {
05176 return array();
05177 }
05178 }
05179
05180 $result_array = array();
05181 if ($questionpool == 0)
05182 {
05183 if (is_array($qpls))
05184 {
05185 if (count($qpls) > 0)
05186 {
05187 $qplidx = array();
05188 foreach ($qpls as $idx => $arr)
05189 {
05190 array_push($qplidx, $arr["qpl"]);
05191 }
05192 $constraint_qpls = " AND qpl_questions.obj_fi IN ('" . join($qplidx, "','") . "')";
05193 }
05194 }
05195 $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";
05196 }
05197 else
05198 {
05199 $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
05200 $ilDB->quote("$questionpool")
05201 );
05202 }
05203 $result = $ilDB->query($query);
05204 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
05205 if (($row[0]) <= $nr_of_questions)
05206 {
05207
05208 if ($questionpool == 0)
05209 {
05210 $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";
05211 }
05212 else
05213 {
05214 $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",
05215 $ilDB->quote("$questionpool")
05216 );
05217 }
05218 $result = $ilDB->query($query);
05219 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
05220 {
05221 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
05222 {
05223 $result_array[$row[0]] = $row[0];
05224 }
05225 }
05226 }
05227 else
05228 {
05229
05230 mt_srand((double)microtime()*1000000);
05231 $random_number = mt_rand(0, $row[0] - 1);
05232 $securitycounter = 500;
05233 while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
05234 {
05235 if ($questionpool == 0)
05236 {
05237 $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";
05238 }
05239 else
05240 {
05241 $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",
05242 $ilDB->quote("$questionpool")
05243 );
05244 }
05245 $result = $ilDB->query($query);
05246 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
05247 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
05248 {
05249 $result_array[$result_row[0]] = $result_row[0];
05250 }
05251 $random_number = mt_rand(0, $row[0] - 1);
05252 $securitycounter--;
05253 }
05254 }
05255 return $result_array;
05256 }
05257
05266 function getImagePath()
05267 {
05268 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
05269 }
05270
05279 function getImagePathWeb()
05280 {
05281 include_once "./Services/Utilities/classes/class.ilUtil.php";
05282 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
05283 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
05284 }
05285
05296 function &createQuestionGUI($question_type, $question_id = -1)
05297 {
05298 if ((!$question_type) and ($question_id > 0))
05299 {
05300 $question_type = $this->getQuestionType($question_id);
05301 }
05302 include_once "./Modules/TestQuestionPool/classes/class.".$question_type."GUI.php";
05303 $question_type_gui = $question_type . "GUI";
05304 $question =& new $question_type_gui();
05305 if ($question_id > 0)
05306 {
05307 $question->object->loadFromDb($question_id);
05308 }
05309 return $question;
05310 }
05311
05321 function &_instanciateQuestion($question_id)
05322 {
05323 if (strcmp($question_id, "") != 0)
05324 {
05325 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
05326 $question_type = assQuestion::_getQuestionType($question_id);
05327
05328 if(!strlen($question_type))
05329 {
05330 return false;
05331 }
05332
05333 include_once "./Modules/TestQuestionPool/classes/class.".$question_type.".php";
05334 $question = new $question_type();
05335
05336 $question->loadFromDb($question_id);
05337 return $question;
05338 }
05339 }
05340
05351 function moveQuestions($move_questions, $target_index, $insert_mode)
05352 {
05353 $this->questions = array_values($this->questions);
05354 $array_pos = array_search($target_index, $this->questions);
05355 if ($insert_mode == 0)
05356 {
05357 $part1 = array_slice($this->questions, 0, $array_pos);
05358 $part2 = array_slice($this->questions, $array_pos);
05359 }
05360 else if ($insert_mode == 1)
05361 {
05362 $part1 = array_slice($this->questions, 0, $array_pos + 1);
05363 $part2 = array_slice($this->questions, $array_pos + 1);
05364 }
05365 foreach ($move_questions as $question_id)
05366 {
05367 if (!(array_search($question_id, $part1) === FALSE))
05368 {
05369 unset($part1[array_search($question_id, $part1)]);
05370 }
05371 if (!(array_search($question_id, $part2) === FALSE))
05372 {
05373 unset($part2[array_search($question_id, $part2)]);
05374 }
05375 }
05376 $part1 = array_values($part1);
05377 $part2 = array_values($part2);
05378 $new_array = array_values(array_merge($part1, $move_questions, $part2));
05379 $this->questions = array();
05380 $counter = 1;
05381 foreach ($new_array as $question_id)
05382 {
05383 $this->questions[$counter] = $question_id;
05384 $counter++;
05385 }
05386 $this->saveQuestionsToDb();
05387 }
05388
05389
05399 function startingTimeReached()
05400 {
05401 if ($this->getStartingTime())
05402 {
05403 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
05404 {
05405 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05406 $now = mktime();
05407 if ($now < $epoch_time)
05408 {
05409
05410 return false;
05411 }
05412 }
05413 }
05414 return true;
05415 }
05416
05426 function endingTimeReached()
05427 {
05428 if ($this->getEndingTime())
05429 {
05430 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
05431 {
05432 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05433 $now = mktime();
05434 if ($now > $epoch_time)
05435 {
05436
05437 return true;
05438 }
05439 }
05440 }
05441 return false;
05442 }
05443
05451 function getQuestionsTable($sort, $sortorder, $textfilter, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
05452 {
05453 global $ilUser;
05454 global $ilDB;
05455
05456 $where = "";
05457 foreach ($textfilter as $sel_filter_type => $filter_text)
05458 {
05459 if (strlen($filter_text) > 0)
05460 {
05461 switch($sel_filter_type)
05462 {
05463 case "title":
05464 $where .= " AND qpl_questions.title LIKE " . $ilDB->quote("%" . $filter_text . "%");
05465 break;
05466 case "comment":
05467 $where .= " AND qpl_questions.comment LIKE " . $ilDB->quote("%" . $filter_text . "%");
05468 break;
05469 case "author":
05470 $where .= " AND qpl_questions.author LIKE " . $ilDB->quote("%" . $filter_text . "%");
05471 break;
05472 case "qpl":
05473 $where .= " AND object_data.title LIKE " . $ilDB->quote("%" . $filter_text . "%");
05474 break;
05475 }
05476 }
05477 }
05478
05479 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
05480 {
05481 $where .= " AND qpl_question_type.type_tag = " . $ilDB->quote($filter_question_type);
05482 }
05483
05484 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
05485 {
05486 $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
05487 }
05488
05489
05490 $order = "";
05491 $images = array();
05492 include_once "./Services/Utilities/classes/class.ilUtil.php";
05493 switch($sort)
05494 {
05495 case "title":
05496 $order = " ORDER BY qpl_questions.title $sortorder";
05497 $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05498 break;
05499 case "comment":
05500 $order = " ORDER BY comment $sortorder";
05501 $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05502 break;
05503 case "type":
05504 $order = " ORDER BY question_type_id $sortorder";
05505 $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05506 break;
05507 case "author":
05508 $order = " ORDER BY author $sortorder";
05509 $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05510 break;
05511 case "created":
05512 $order = " ORDER BY created $sortorder";
05513 $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05514 break;
05515 case "updated":
05516 $order = " ORDER BY TIMESTAMP14 $sortorder";
05517 $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05518 break;
05519 case "qpl":
05520 $order = " ORDER BY UPPER(object_data.title) $sortorder";
05521 $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05522 break;
05523 }
05524 $maxentries = $ilUser->prefs["hits_per_page"];
05525 if ($maxentries < 1)
05526 {
05527 $maxentries = 9999;
05528 }
05529 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
05530 $available_pools = array_keys(ilObjQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $equal_points = FALSE, $could_be_offline = FALSE, $showPath = FALSE, $with_questioncount = FALSE));
05531 $available = "";
05532 if (count($available_pools))
05533 {
05534 $available = " AND qpl_questions.obj_fi IN ('" . join($available_pools, "','") . "')";
05535 }
05536 else
05537 {
05538 return array();
05539 }
05540 if ($completeonly)
05541 {
05542 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1");
05543 }
05544
05545
05546 $query = sprintf("SELECT qpl_questions.original_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, tst_test_question, object_data WHERE qpl_questions.question_id = tst_test_question.question_fi AND object_data.obj_id = qpl_questions.obj_fi AND tst_test_question.test_fi = %s",
05547 $ilDB->quote($this->getTestId() . "")
05548 );
05549 $result = $ilDB->query($query);
05550 $original_ids = array();
05551 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
05552 {
05553 if (strcmp($row[0], "") != 0)
05554 {
05555 array_push($original_ids, $row[0]);
05556 }
05557 }
05558 $original_clause = " ISNULL(qpl_questions.original_id)";
05559 if (count($original_ids))
05560 {
05561 $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN ('" . join($original_ids, "','") . "')";
05562 }
05563
05564 $query = "SELECT qpl_questions.question_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, qpl_question_type, object_data WHERE $original_clause$available AND object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05565 $query_result = $ilDB->query($query);
05566 $max = $query_result->numRows();
05567 if ($startrow > $max -1)
05568 {
05569 $startrow = $max - ($max % $maxentries);
05570 }
05571 else if ($startrow < 0)
05572 {
05573 $startrow = 0;
05574 }
05575 $limit = " LIMIT $startrow, $maxentries";
05576 $query = "SELECT qpl_questions.*, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type, object_data WHERE $original_clause $available AND object_data.obj_id = qpl_questions.obj_fi AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05577 $query_result = $ilDB->query($query);
05578 $rows = array();
05579 if ($query_result->numRows())
05580 {
05581 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
05582 {
05583 array_push($rows, $row);
05584 }
05585 }
05586 $nextrow = $startrow + $maxentries;
05587 if ($nextrow > $max - 1)
05588 {
05589 $nextrow = $startrow;
05590 }
05591 $prevrow = $startrow - $maxentries;
05592 if ($prevrow < 0)
05593 {
05594 $prevrow = 0;
05595 }
05596 return array(
05597 "rows" => $rows,
05598 "images" => $images,
05599 "startrow" => $startrow,
05600 "nextrow" => $nextrow,
05601 "prevrow" => $prevrow,
05602 "step" => $maxentries,
05603 "rowcount" => $max
05604 );
05605 }
05606
05615 function fromXML(&$assessment)
05616 {
05617 unset($_SESSION["import_mob_xhtml"]);
05618
05619 $this->setDescription($assessment->getComment());
05620 $this->setTitle($assessment->getTitle());
05621
05622 foreach ($assessment->objectives as $objectives)
05623 {
05624 foreach ($objectives->materials as $material)
05625 {
05626 $this->setIntroduction($this->QTIMaterialToString($material));
05627 }
05628 }
05629 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
05630 {
05631 switch ($assessmentcontrol->getSolutionswitch())
05632 {
05633 case "Yes":
05634 $this->setInstantFeedbackSolution(1);
05635 break;
05636 default:
05637 $this->setInstantFeedbackSolution(0);
05638 break;
05639 }
05640 }
05641
05642 foreach ($assessment->qtimetadata as $metadata)
05643 {
05644 switch ($metadata["label"])
05645 {
05646 case "test_type":
05647
05648 $type = $metadata["entry"];
05649 switch ($type)
05650 {
05651 case 1:
05652
05653 $this->setAnonymity(1);
05654 break;
05655 case 2:
05656
05657 break;
05658 case 4:
05659
05660 $this->setFixedParticipants(1);
05661 $this->setListOfQuestionsSettings(7);
05662 $this->setShowSolutionPrintview(1);
05663 break;
05664 case 5:
05665
05666 break;
05667 }
05668 break;
05669 case "sequence_settings":
05670 $this->setSequenceSettings($metadata["entry"]);
05671 break;
05672 case "author":
05673 $this->setAuthor($metadata["entry"]);
05674 break;
05675 case "nr_of_tries":
05676 $this->setNrOfTries($metadata["entry"]);
05677 break;
05678 case "hide_previous_results":
05679 if ($metadata["entry"] == 0)
05680 {
05681 $this->setUsePreviousAnswers(1);
05682 }
05683 else
05684 {
05685 $this->setUsePreviousAnswers(0);
05686 }
05687 break;
05688 case "use_previous_answers":
05689 $this->setUsePreviousAnswers($metadata["entry"]);
05690 break;
05691 case "answer_feedback":
05692 $this->setAnswerFeedback($metadata["entry"]);
05693 break;
05694 case "hide_title_points":
05695 $this->setTitleOutput($metadata["entry"]);
05696 break;
05697 case "title_output":
05698 $this->setTitleOutput($metadata["entry"]);
05699 break;
05700 case "random_test":
05701 $this->setRandomTest($metadata["entry"]);
05702 break;
05703 case "random_question_count":
05704 $this->setRandomQuestionCount($metadata["entry"]);
05705 break;
05706 case "results_presentation":
05707 $this->setResultsPresentation($metadata["entry"]);
05708 break;
05709 case "reset_processing_time":
05710 $this->setResetProcessingTime($metadata["entry"]);
05711 break;
05712 case "show_solution_details":
05713 $this->setShowSolutionDetails($metadata["entry"]);
05714 break;
05715 case "show_solution_printview":
05716 $this->setShowSolutionPrintview($metadata["entry"]);
05717 break;
05718 case "show_solution_feedback":
05719 $this->setShowSolutionFeedback($metadata["entry"]);
05720 break;
05721 case "instant_verification":
05722 $this->setInstantFeedbackSolution($metadata["entry"]);
05723 break;
05724 case "answer_feedback_points":
05725 $this->setAnswerFeedbackPoints($metadata["entry"]);
05726 break;
05727 case "anonymity":
05728 $this->setAnonymity($metadata["entry"]);
05729 break;
05730 case "show_cancel":
05731 $this->setShowCancel($metadata["entry"]);
05732 break;
05733 case "show_marker":
05734 $this->setShowMarker($metadata["entry"]);
05735 break;
05736 case "fixed_participants":
05737 $this->setFixedParticipants($metadata["entry"]);
05738 break;
05739 case "score_reporting":
05740 $this->setScoreReporting($metadata["entry"]);
05741 break;
05742 case "shuffle_questions":
05743 $this->setShuffleQuestions($metadata["entry"]);
05744 break;
05745 case "count_system":
05746 $this->setCountSystem($metadata["entry"]);
05747 break;
05748 case "mc_scoring":
05749 $this->setMCScoring($metadata["entry"]);
05750 break;
05751 case "score_cutting":
05752 $this->setScoreCutting($metadata["entry"]);
05753 break;
05754 case "password":
05755 $this->setPassword($metadata["entry"]);
05756 break;
05757 case "allowedUsers":
05758 $this->setAllowedUsers($metadata["entry"]);
05759 break;
05760 case "allowedUsersTimeGap":
05761 $this->setAllowedUsersTimeGap($metadata["entry"]);
05762 break;
05763 case "pass_scoring":
05764 $this->setPassScoring($metadata["entry"]);
05765 break;
05766 case "show_summary":
05767 $this->setListOfQuestionsSettings($metadata["entry"]);
05768 break;
05769 case "reporting_date":
05770 $iso8601period = $metadata["entry"];
05771 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05772 {
05773 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05774 }
05775 break;
05776 case "starting_time":
05777 $iso8601period = $metadata["entry"];
05778 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05779 {
05780 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05781 }
05782 break;
05783 case "ending_time":
05784 $iso8601period = $metadata["entry"];
05785 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05786 {
05787 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05788 }
05789 break;
05790 }
05791 if (preg_match("/mark_step_\d+/", $metadata["label"]))
05792 {
05793 $xmlmark = $metadata["entry"];
05794 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
05795 $mark_short = $matches[1];
05796 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
05797 $mark_official = $matches[1];
05798 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
05799 $mark_percentage = $matches[1];
05800 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
05801 $mark_passed = $matches[1];
05802 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
05803 }
05804 }
05805
05806 if (is_array($_SESSION["import_mob_xhtml"]))
05807 {
05808 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
05809 include_once "./Services/RTE/classes/class.ilRTE.php";
05810 include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
05811 foreach ($_SESSION["import_mob_xhtml"] as $mob)
05812 {
05813 $importfile = $this->getImportDirectory() . "/" . $_SESSION["tst_import_subdir"] . "/" . $mob["uri"];
05814 if (file_exists($importfile))
05815 {
05816 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
05817 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
05818 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
05819 }
05820 else
05821 {
05822 global $ilLog;
05823 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
05824 }
05825 }
05826 $this->saveToDb();
05827 }
05828 }
05829
05838 function toXML()
05839 {
05840 include_once("./classes/class.ilXmlWriter.php");
05841 $a_xml_writer = new ilXmlWriter;
05842
05843 $a_xml_writer->xmlHeader();
05844 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
05845 $a_xml_writer->xmlStartTag("questestinterop");
05846
05847 $attrs = array(
05848 "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
05849 "title" => $this->getTitle()
05850 );
05851 $a_xml_writer->xmlStartTag("assessment", $attrs);
05852
05853 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
05854
05855
05856 if ($this->enable_processing_time)
05857 {
05858 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
05859 $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
05860 }
05861
05862 -
05863 $a_xml_writer->xmlStartTag("qtimetadata");
05864 $a_xml_writer->xmlStartTag("qtimetadatafield");
05865 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
05866 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
05867 $a_xml_writer->xmlEndTag("qtimetadatafield");
05868
05869
05870 $a_xml_writer->xmlStartTag("qtimetadatafield");
05871 $a_xml_writer->xmlElement("fieldlabel", NULL, "anonymity");
05872 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnonymity()));
05873 $a_xml_writer->xmlEndTag("qtimetadatafield");
05874
05875
05876 $a_xml_writer->xmlStartTag("qtimetadatafield");
05877 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_test");
05878 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isRandomTest()));
05879 $a_xml_writer->xmlEndTag("qtimetadatafield");
05880
05881
05882 $a_xml_writer->xmlStartTag("qtimetadatafield");
05883 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
05884 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
05885 $a_xml_writer->xmlEndTag("qtimetadatafield");
05886
05887
05888 $a_xml_writer->xmlStartTag("qtimetadatafield");
05889 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
05890 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
05891 $a_xml_writer->xmlEndTag("qtimetadatafield");
05892
05893
05894 $a_xml_writer->xmlStartTag("qtimetadatafield");
05895 $a_xml_writer->xmlElement("fieldlabel", NULL, "reset_processing_time");
05896 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getResetProcessingTime());
05897 $a_xml_writer->xmlEndTag("qtimetadatafield");
05898
05899
05900 $a_xml_writer->xmlStartTag("qtimetadatafield");
05901 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
05902 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
05903 $a_xml_writer->xmlEndTag("qtimetadatafield");
05904
05905
05906 $a_xml_writer->xmlStartTag("qtimetadatafield");
05907 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
05908 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
05909 $a_xml_writer->xmlEndTag("qtimetadatafield");
05910
05911
05912 $a_xml_writer->xmlStartTag("qtimetadatafield");
05913 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
05914 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
05915 $a_xml_writer->xmlEndTag("qtimetadatafield");
05916
05917
05918 $a_xml_writer->xmlStartTag("qtimetadatafield");
05919 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
05920 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
05921 $a_xml_writer->xmlEndTag("qtimetadatafield");
05922
05923
05924 $a_xml_writer->xmlStartTag("qtimetadatafield");
05925 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
05926 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
05927 $a_xml_writer->xmlEndTag("qtimetadatafield");
05928
05929
05930 $a_xml_writer->xmlStartTag("qtimetadatafield");
05931 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
05932 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
05933 $a_xml_writer->xmlEndTag("qtimetadatafield");
05934
05935
05936 $a_xml_writer->xmlStartTag("qtimetadatafield");
05937 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
05938 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
05939 $a_xml_writer->xmlEndTag("qtimetadatafield");
05940
05941
05942 if ($this->getReportingDate())
05943 {
05944 $a_xml_writer->xmlStartTag("qtimetadatafield");
05945 $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
05946 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
05947 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05948 $a_xml_writer->xmlEndTag("qtimetadatafield");
05949 }
05950
05951 $a_xml_writer->xmlStartTag("qtimetadatafield");
05952 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
05953 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
05954 $a_xml_writer->xmlEndTag("qtimetadatafield");
05955
05956
05957 $a_xml_writer->xmlStartTag("qtimetadatafield");
05958 $a_xml_writer->xmlElement("fieldlabel", NULL, "use_previous_answers");
05959 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getUsePreviousAnswers());
05960 $a_xml_writer->xmlEndTag("qtimetadatafield");
05961
05962
05963 $a_xml_writer->xmlStartTag("qtimetadatafield");
05964 $a_xml_writer->xmlElement("fieldlabel", NULL, "title_output");
05965 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getTitleOutput()));
05966 $a_xml_writer->xmlEndTag("qtimetadatafield");
05967
05968
05969 $a_xml_writer->xmlStartTag("qtimetadatafield");
05970 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_question_count");
05971 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getRandomQuestionCount()));
05972 $a_xml_writer->xmlEndTag("qtimetadatafield");
05973
05974
05975 $a_xml_writer->xmlStartTag("qtimetadatafield");
05976 $a_xml_writer->xmlElement("fieldlabel", NULL, "results_presentation");
05977 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getResultsPresentation()));
05978 $a_xml_writer->xmlEndTag("qtimetadatafield");
05979
05980
05981 $a_xml_writer->xmlStartTag("qtimetadatafield");
05982 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
05983 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getListOfQuestionsSettings()));
05984 $a_xml_writer->xmlEndTag("qtimetadatafield");
05985
05986
05987 $a_xml_writer->xmlStartTag("qtimetadatafield");
05988 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
05989 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
05990 $a_xml_writer->xmlEndTag("qtimetadatafield");
05991
05992
05993 $a_xml_writer->xmlStartTag("qtimetadatafield");
05994 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
05995 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantFeedbackSolution()));
05996 $a_xml_writer->xmlEndTag("qtimetadatafield");
05997
05998
05999 $a_xml_writer->xmlStartTag("qtimetadatafield");
06000 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback");
06001 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedback()));
06002 $a_xml_writer->xmlEndTag("qtimetadatafield");
06003
06004
06005 $a_xml_writer->xmlStartTag("qtimetadatafield");
06006 $a_xml_writer->xmlElement("fieldlabel", NULL, "answer_feedback_points");
06007 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
06008 $a_xml_writer->xmlEndTag("qtimetadatafield");
06009
06010
06011 $a_xml_writer->xmlStartTag("qtimetadatafield");
06012 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_cancel");
06013 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowCancel()));
06014 $a_xml_writer->xmlEndTag("qtimetadatafield");
06015
06016
06017 $a_xml_writer->xmlStartTag("qtimetadatafield");
06018 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_marker");
06019 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowMarker()));
06020 $a_xml_writer->xmlEndTag("qtimetadatafield");
06021
06022
06023 $a_xml_writer->xmlStartTag("qtimetadatafield");
06024 $a_xml_writer->xmlElement("fieldlabel", NULL, "fixed_participants");
06025 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getFixedParticipants()));
06026 $a_xml_writer->xmlEndTag("qtimetadatafield");
06027
06028
06029 $a_xml_writer->xmlStartTag("qtimetadatafield");
06030 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
06031 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
06032 $a_xml_writer->xmlEndTag("qtimetadatafield");
06033
06034
06035 if ($this->getStartingTime())
06036 {
06037 $a_xml_writer->xmlStartTag("qtimetadatafield");
06038 $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
06039 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
06040 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
06041 $a_xml_writer->xmlEndTag("qtimetadatafield");
06042 }
06043
06044 if ($this->getEndingTime())
06045 {
06046 $a_xml_writer->xmlStartTag("qtimetadatafield");
06047 $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
06048 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
06049 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
06050 $a_xml_writer->xmlEndTag("qtimetadatafield");
06051 }
06052 foreach ($this->mark_schema->mark_steps as $index => $mark)
06053 {
06054
06055 $a_xml_writer->xmlStartTag("qtimetadatafield");
06056 $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
06057 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>", $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()));
06058 $a_xml_writer->xmlEndTag("qtimetadatafield");
06059 }
06060 $a_xml_writer->xmlEndTag("qtimetadata");
06061
06062
06063 $a_xml_writer->xmlStartTag("objectives");
06064 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
06065 $a_xml_writer->xmlEndTag("objectives");
06066
06067
06068 if ($this->getInstantFeedbackSolution() == 1)
06069 {
06070 $attrs = array(
06071 "solutionswitch" => "Yes"
06072 );
06073 }
06074 else
06075 {
06076 $attrs = NULL;
06077 }
06078 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
06079
06080 $attrs = array(
06081 "ident" => "1"
06082 );
06083 $a_xml_writer->xmlElement("section", $attrs, NULL);
06084 $a_xml_writer->xmlEndTag("assessment");
06085 $a_xml_writer->xmlEndTag("questestinterop");
06086
06087 $xml = $a_xml_writer->xmlDumpMem(FALSE);
06088
06089 foreach ($this->questions as $question_id)
06090 {
06091 $question =& ilObjTest::_instanciateQuestion($question_id);
06092 $qti_question = $question->toXML(false);
06093 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
06094 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
06095 if (strpos($xml, "</section>") !== false)
06096 {
06097 $xml = str_replace("</section>", "$qti_question</section>", $xml);
06098 }
06099 else
06100 {
06101 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
06102 }
06103 }
06104 return $xml;
06105 }
06106
06113 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
06114 {
06115 global $ilBench;
06116
06117 $this->mob_ids = array();
06118 $this->file_ids = array();
06119
06120 $attrs = array();
06121 $attrs["Type"] = "Test";
06122 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
06123
06124
06125 $this->exportXMLMetaData($a_xml_writer);
06126
06127
06128 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
06129 $ilBench->start("ContentObjectExport", "exportPageObjects");
06130 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
06131 $ilBench->stop("ContentObjectExport", "exportPageObjects");
06132 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
06133
06134
06135 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
06136 $ilBench->start("ContentObjectExport", "exportMediaObjects");
06137 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
06138 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
06139 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
06140
06141
06142 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
06143 $ilBench->start("ContentObjectExport", "exportFileItems");
06144 $this->exportFileItems($a_target_dir, $expLog);
06145 $ilBench->stop("ContentObjectExport", "exportFileItems");
06146 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
06147
06148 $a_xml_writer->xmlEndTag("ContentObject");
06149 }
06150
06157 function exportXMLMetaData(&$a_xml_writer)
06158 {
06159 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
06160 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
06161 $md2xml->setExportMode(true);
06162 $md2xml->startExport();
06163 $a_xml_writer->appendXML($md2xml->getXML());
06164 }
06165
06173 function modifyExportIdentifier($a_tag, $a_param, $a_value)
06174 {
06175 if ($a_tag == "Identifier" && $a_param == "Entry")
06176 {
06177 include_once "./Services/Utilities/classes/class.ilUtil.php";
06178 $a_value = ilUtil::insertInstIntoID($a_value);
06179 }
06180
06181 return $a_value;
06182 }
06183
06184
06191 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
06192 {
06193 global $ilBench;
06194
06195 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
06196
06197 foreach ($this->questions as $question_id)
06198 {
06199 $ilBench->start("ContentObjectExport", "exportPageObject");
06200 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
06201
06202 $attrs = array();
06203 $a_xml_writer->xmlStartTag("PageObject", $attrs);
06204
06205
06206
06207 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
06208 $page_object = new ilPageObject("qpl", $question_id);
06209 $page_object->buildDom();
06210 $page_object->insertInstIntoIDs($a_inst);
06211 $mob_ids = $page_object->collectMediaObjects(false);
06212 $file_ids = $page_object->collectFileItems();
06213 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
06214 $xml = str_replace("&","&", $xml);
06215 $a_xml_writer->appendXML($xml);
06216 $page_object->freeDom();
06217 unset ($page_object);
06218
06219 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
06220
06221
06222 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
06223
06224 foreach($mob_ids as $mob_id)
06225 {
06226 $this->mob_ids[$mob_id] = $mob_id;
06227 }
06228 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
06229
06230
06231 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
06232
06233 foreach($file_ids as $file_id)
06234 {
06235 $this->file_ids[$file_id] = $file_id;
06236 }
06237 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
06238
06239 $a_xml_writer->xmlEndTag("PageObject");
06240
06241
06242 $ilBench->stop("ContentObjectExport", "exportPageObject");
06243
06244
06245 }
06246 }
06247
06254 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
06255 {
06256 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
06257
06258 foreach ($this->mob_ids as $mob_id)
06259 {
06260 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
06261 $media_obj = new ilObjMediaObject($mob_id);
06262 $media_obj->exportXML($a_xml_writer, $a_inst);
06263 $media_obj->exportFiles($a_target_dir);
06264 unset($media_obj);
06265 }
06266 }
06267
06272 function exportFileItems($a_target_dir, &$expLog)
06273 {
06274 include_once "./Modules/File/classes/class.ilObjFile.php";
06275
06276 foreach ($this->file_ids as $file_id)
06277 {
06278 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
06279 $file_obj = new ilObjFile($file_id, false);
06280 $file_obj->export($a_target_dir);
06281 unset($file_obj);
06282 }
06283 }
06284
06289 function getImportMapping()
06290 {
06291 if (!is_array($this->import_mapping))
06292 {
06293 return array();
06294 }
06295 else
06296 {
06297 return $this->import_mapping;
06298 }
06299 }
06300
06311 function getECTSGrade($reached_points, $max_points)
06312 {
06313 $passed_array =& $this->getTotalPointsPassedArray();
06314 return ilObjTest::_getECTSGrade($passed_array, $reached_points, $max_points, $this->ects_grades["A"], $this->ects_grades["B"], $this->ects_grades["C"], $this->ects_grades["D"], $this->ects_grades["E"], $this->ects_fx);
06315 }
06316
06327 function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
06328 {
06329 include_once "./classes/class.ilStatistics.php";
06330
06331 $passed_statistics = new ilStatistics();
06332 $passed_statistics->setData($points_passed);
06333 $ects_percentiles = array
06334 (
06335 "A" => $passed_statistics->quantile($a),
06336 "B" => $passed_statistics->quantile($b),
06337 "C" => $passed_statistics->quantile($c),
06338 "D" => $passed_statistics->quantile($d),
06339 "E" => $passed_statistics->quantile($e)
06340 );
06341 if (count($points_passed) && ($reached_points >= $ects_percentiles["A"]))
06342 {
06343 return "A";
06344 }
06345 else if (count($points_passed) && ($reached_points >= $ects_percentiles["B"]))
06346 {
06347 return "B";
06348 }
06349 else if (count($points_passed) && ($reached_points >= $ects_percentiles["C"]))
06350 {
06351 return "C";
06352 }
06353 else if (count($points_passed) && ($reached_points >= $ects_percentiles["D"]))
06354 {
06355 return "D";
06356 }
06357 else if (count($points_passed) && ($reached_points >= $ects_percentiles["E"]))
06358 {
06359 return "E";
06360 }
06361 else if (strcmp($fx, "") != 0)
06362 {
06363 if ($max_points > 0)
06364 {
06365 $percentage = ($reached_points / $max_points) * 100.0;
06366 if ($percentage < 0) $percentage = 0.0;
06367 }
06368 else
06369 {
06370 $percentage = 0.0;
06371 }
06372 if ($percentage >= $fx)
06373 {
06374 return "FX";
06375 }
06376 else
06377 {
06378 return "F";
06379 }
06380 }
06381 else
06382 {
06383 return "F";
06384 }
06385 }
06386
06387 function checkMarks()
06388 {
06389 return $this->mark_schema->checkMarks();
06390 }
06391
06401 function setAuthor($author = "")
06402 {
06403 $this->author = $author;
06404 }
06405
06417 function saveAuthorToMetadata($a_author = "")
06418 {
06419 $md =& new ilMD($this->getId(), 0, $this->getType());
06420 $md_life =& $md->getLifecycle();
06421 if (!$md_life)
06422 {
06423 if (strlen($a_author) == 0)
06424 {
06425 global $ilUser;
06426 $a_author = $ilUser->getFullname();
06427 }
06428
06429 $md_life =& $md->addLifecycle();
06430 $md_life->save();
06431 $con =& $md_life->addContribute();
06432 $con->setRole("Author");
06433 $con->save();
06434 $ent =& $con->addEntity();
06435 $ent->setEntity($a_author);
06436 $ent->save();
06437 }
06438 }
06439
06447 function createMetaData()
06448 {
06449 parent::createMetaData();
06450 $this->saveAuthorToMetadata();
06451 }
06452
06462 function getAuthor()
06463 {
06464 $author = array();
06465 include_once "./Services/MetaData/classes/class.ilMD.php";
06466 $md =& new ilMD($this->getId(), 0, $this->getType());
06467 $md_life =& $md->getLifecycle();
06468 if ($md_life)
06469 {
06470 $ids =& $md_life->getContributeIds();
06471 foreach ($ids as $id)
06472 {
06473 $md_cont =& $md_life->getContribute($id);
06474 if (strcmp($md_cont->getRole(), "Author") == 0)
06475 {
06476 $entids =& $md_cont->getEntityIds();
06477 foreach ($entids as $entid)
06478 {
06479 $md_ent =& $md_cont->getEntity($entid);
06480 array_push($author, $md_ent->getEntity());
06481 }
06482 }
06483 }
06484 }
06485 return join($author, ",");
06486 }
06487
06497 function _lookupAuthor($obj_id)
06498 {
06499 $author = array();
06500 include_once "./Services/MetaData/classes/class.ilMD.php";
06501 $md =& new ilMD($obj_id, 0, "tst");
06502 $md_life =& $md->getLifecycle();
06503 if ($md_life)
06504 {
06505 $ids =& $md_life->getContributeIds();
06506 foreach ($ids as $id)
06507 {
06508 $md_cont =& $md_life->getContribute($id);
06509 if (strcmp($md_cont->getRole(), "Author") == 0)
06510 {
06511 $entids =& $md_cont->getEntityIds();
06512 foreach ($entids as $entid)
06513 {
06514 $md_ent =& $md_cont->getEntity($entid);
06515 array_push($author, $md_ent->getEntity());
06516 }
06517 }
06518 }
06519 }
06520 return join($author, ",");
06521 }
06522
06531 function &_getAvailableTests($use_object_id = FALSE)
06532 {
06533 global $ilUser;
06534 global $ilDB;
06535
06536 $result_array = array();
06537 $tests = ilUtil::_getObjectsByOperations("tst","write", $ilUser->getId(), -1);
06538 if (count($tests))
06539 {
06540 $titles = ilObject::_prepareCloneSelection($tests, "tst");
06541 $query = sprintf("SELECT object_data.*, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_reference.ref_id IN ('%s') ORDER BY object_data.title",
06542 implode("','", $tests)
06543 );
06544 $result = $ilDB->query($query);
06545 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06546 {
06547 if ($use_object_id)
06548 {
06549 $result_array[$row["obj_id"]] = $titles[$row["ref_id"]];
06550 }
06551 else
06552 {
06553 $result_array[$row["ref_id"]] = $titles[$row["ref_id"]];
06554 }
06555 }
06556 }
06557 return $result_array;
06558 }
06559
06568 function cloneRandomQuestions($new_id)
06569 {
06570 global $ilDB;
06571
06572 if ($new_id > 0)
06573 {
06574 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
06575 $ilDB->quote($this->getTestId() . "")
06576 );
06577 $result = $ilDB->query($query);
06578 if ($result->numRows())
06579 {
06580 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06581 {
06582 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
06583 $ilDB->quote($new_id . ""),
06584 $ilDB->quote($row["questionpool_fi"] . ""),
06585 $ilDB->quote($row["num_of_q"] . "")
06586 );
06587 $insertresult = $ilDB->query($query);
06588 }
06589 }
06590 }
06591 }
06592
06601 public function cloneObject($a_target_id,$a_copy_id = 0)
06602 {
06603 global $ilDB,$ilLog;
06604
06605 $this->loadFromDb();
06606
06607
06608 $newObj = parent::cloneObject($a_target_id,$a_copy_id);
06609 $this->cloneMetaData($newObj);
06610 $newObj->setAnonymity($this->getAnonymity());
06611 $newObj->setAnswerFeedback($this->getAnswerFeedback());
06612 $newObj->setAnswerFeedbackPoints($this->getAnswerFeedbackPoints());
06613 $newObj->setAuthor($this->getAuthor());
06614 $newObj->setCountSystem($this->getCountSystem());
06615 $newObj->setECTSFX($this->getECTSFX());
06616 $newObj->setECTSGrades($this->getECTSGrades());
06617 $newObj->setECTSOutput($this->getECTSOutput());
06618 $newObj->setEnableProcessingTime($this->getEnableProcessingTime());
06619 $newObj->setEndingTime($this->getEndingTime());
06620 $newObj->setFixedParticipants($this->getFixedParticipants());
06621 $newObj->setInstantFeedbackSolution($this->getInstantFeedbackSolution());
06622 $newObj->setIntroduction($this->getIntroduction());
06623 $newObj->setListOfQuestionsSettings($this->getListOfQuestionsSettings());
06624 $newObj->setMCScoring($this->getMCScoring());
06625 $newObj->setNrOfTries($this->getNrOfTries());
06626 $newObj->setPassScoring($this->getPassScoring());
06627 $newObj->setPassword($this->getPassword());
06628 $newObj->setProcessingTime($this->getProcessingTime());
06629 $newObj->setRandomQuestionCount($this->getRandomQuestionCount());
06630 $newObj->setRandomTest($this->getRandomTest());
06631 $newObj->setReportingDate($this->getReportingDate());
06632 $newObj->setResetProcessingTime($this->getResetProcessingTime());
06633 $newObj->setResultsPresentation($this->getResultsPresentation());
06634 $newObj->setScoreCutting($this->getScoreCutting());
06635 $newObj->setScoreReporting($this->getScoreReporting());
06636 $newObj->setSequenceSettings($this->getSequenceSettings());
06637 $newObj->setShowCancel($this->getShowCancel());
06638 $newObj->setShowMarker($this->getShowMarker());
06639 $newObj->setShuffleQuestions($this->getShuffleQuestions());
06640 $newObj->setStartingTime($this->getStartingTime());
06641 $newObj->setTitleOutput($this->getTitleOutput());
06642 $newObj->setUsePreviousAnswers($this->getUsePreviousAnswers());
06643 $newObj->mark_schema = clone $this->mark_schema;
06644 $newObj->saveToDb();
06645
06646 if ($this->isRandomTest())
06647 {
06648 $newObj->saveRandomQuestionCount($newObj->getRandomQuestionCount());
06649 $this->cloneRandomQuestions($newObj->getTestId());
06650 }
06651 else
06652 {
06653 include_once("./Services/CopyWizard/classes/class.ilCopyWizardOptions.php");
06654 $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
06655
06656
06657 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
06658 foreach ($this->questions as $key => $question_id)
06659 {
06660 $question = ilObjTest::_instanciateQuestion($question_id);
06661 $newObj->questions[$key] = $question->duplicate();
06662 $original_id = assQuestion::_getOriginalId($question_id);
06663 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
06664 $question->saveToDb($original_id);
06665
06666
06667
06668 $cwo->appendMapping($this->getRefId().'_'.$question_id,$newObj->getRefId().'_'.$newObj->questions[$key]);
06669 $ilLog->write(__METHOD__.': Added mapping '.$this->getRefId().'_'.$question_id.' <-> ' .
06670 $newObj->getRefId().'_'.$newObj->questions[$key]);
06671 }
06672 }
06673 $newObj->saveToDb();
06674 return $newObj;
06675 }
06676
06677 function _getRefIdFromObjId($obj_id)
06678 {
06679 global $ilDB;
06680
06681 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
06682 $ilDB->quote($obj_id)
06683
06684 );
06685 $result = $ilDB->query($query);
06686 if ($result->numRows())
06687 {
06688 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06689 return $row["ref_id"];
06690 }
06691 return 0;
06692 }
06693
06702 function getQuestionCount()
06703 {
06704 $num = 0;
06705
06706 if ($this->isRandomTest())
06707 {
06708 if ($this->getRandomQuestionCount())
06709 {
06710 $num = $this->getRandomQuestionCount();
06711 $qpls =& $this->getRandomQuestionpools();
06712 $maxcount = 0;
06713 foreach ($qpls as $data)
06714 {
06715 $maxcount += $data["contains"];
06716 }
06717 if ($num > $maxcount) $num = $maxcount;
06718 }
06719 else
06720 {
06721 $qpls =& $this->getRandomQuestionpools();
06722 foreach ($qpls as $data)
06723 {
06724 $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06725 $num += $add;
06726 }
06727 }
06728 }
06729 else
06730 {
06731 $num = count($this->questions);
06732 }
06733 return $num;
06734 }
06735
06744 function _getQuestionCount($test_id)
06745 {
06746 global $ilDB;
06747
06748 $num = 0;
06749
06750 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
06751 $ilDB->quote($test_id . "")
06752 );
06753 $result = $ilDB->query($query);
06754 if (!$result->numRows())
06755 {
06756 return 0;
06757 }
06758 $test = $result->fetchRow(DB_FETCHMODE_ASSOC);
06759
06760 if ($test["random_test"] == 1)
06761 {
06762 $qpls = array();
06763 $counter = 0;
06764 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
06765 $ilDB->quote($test_id . "")
06766 );
06767 $result = $ilDB->query($query);
06768 if ($result->numRows())
06769 {
06770 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06771 {
06772 $countquery = sprintf("SELECT question_id FROM qpl_questions WHERE obj_fi = %s AND original_id IS NULL",
06773 $ilDB->quote($row["questionpool_fi"] . "")
06774 );
06775 $countresult = $ilDB->query($countquery);
06776 $contains = $countresult->numRows();
06777 $qpls[$counter] = array(
06778 "index" => $counter,
06779 "count" => $row["num_of_q"],
06780 "qpl" => $row["questionpool_fi"],
06781 "contains" => $contains
06782 );
06783 $counter++;
06784 }
06785 }
06786 if ($test["random_question_count"] > 0)
06787 {
06788 $num = $test["random_question_count"];
06789 $maxcount = 0;
06790 foreach ($qpls as $data)
06791 {
06792 $maxcount += $data["contains"];
06793 }
06794 if ($num > $maxcount) $num = $maxcount;
06795 }
06796 else
06797 {
06798 $num = 0;
06799 foreach ($qpls as $data)
06800 {
06801 $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06802 $num += $add;
06803 }
06804 }
06805 }
06806 else
06807 {
06808 $query = sprintf("SELECT test_question_id FROM tst_test_question WHERE test_fi = %s",
06809 $ilDB->quote($test_id . "")
06810 );
06811 $result = $ilDB->query($query);
06812 $num = $result->numRows();
06813 }
06814 return $num;
06815 }
06816
06824 function removeNonRandomTestData()
06825 {
06826 global $ilDB;
06827
06828
06829 $this->removeAllTestEditings();
06830 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
06831 $ilDB->quote($this->getTestId())
06832 );
06833 $result = $ilDB->query($query);
06834 $this->questions = array();
06835 $this->saveCompleteStatus();
06836 }
06837
06845 function removeRandomTestData()
06846 {
06847 global $ilDB;
06848
06849 $this->removeAllTestEditings();
06850 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
06851 $ilDB->quote($this->getTestId())
06852 );
06853 $result = $ilDB->query($query);
06854 $this->questions = array();
06855 $this->saveCompleteStatus();
06856 }
06857
06867 function logAction($logtext = "", $question_id = "")
06868 {
06869 global $ilUser;
06870
06871 $original_id = "";
06872 if (strcmp($question_id, "") != 0)
06873 {
06874 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
06875 $original_id = assQuestion::_getOriginalId($question_id);
06876 }
06877 include_once "./classes/class.ilObjAssessmentFolder.php";
06878 ilObjAssessmentFolder::_addLog($ilUser->getId(), $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
06879 }
06880
06890 function _getObjectIDFromTestID($test_id)
06891 {
06892 global $ilDB;
06893 $object_id = FALSE;
06894 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
06895 $ilDB->quote($test_id . "")
06896 );
06897 $result = $ilDB->query($query);
06898 if ($result->numRows())
06899 {
06900 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06901 $object_id = $row["obj_fi"];
06902 }
06903 return $object_id;
06904 }
06905
06915 function _getObjectIDFromActiveID($active_id)
06916 {
06917 global $ilDB;
06918 $object_id = FALSE;
06919 $query = sprintf("SELECT tst_tests.obj_fi FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
06920 $ilDB->quote($active_id . "")
06921 );
06922 $result = $ilDB->query($query);
06923 if ($result->numRows())
06924 {
06925 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06926 $object_id = $row["obj_fi"];
06927 }
06928 return $object_id;
06929 }
06930
06940 function _getTestIDFromObjectID($object_id)
06941 {
06942 global $ilDB;
06943 $test_id = FALSE;
06944 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
06945 $ilDB->quote($object_id . "")
06946 );
06947 $result = $ilDB->query($query);
06948 if ($result->numRows())
06949 {
06950 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06951 $test_id = $row["test_id"];
06952 }
06953 return $test_id;
06954 }
06955
06966 function getTextAnswer($active_id, $question_id, $pass = NULL)
06967 {
06968 global $ilDB;
06969
06970 $res = "";
06971 if (($active_id) && ($question_id))
06972 {
06973 if (is_null($pass))
06974 {
06975 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
06976 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
06977 }
06978 $query = sprintf("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
06979 $ilDB->quote($active_id . ""),
06980 $ilDB->quote($question_id . ""),
06981 $ilDB->quote($pass . "")
06982 );
06983 $result = $ilDB->query($query);
06984 if ($result->numRows() == 1)
06985 {
06986 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06987 $res = $row["value1"];
06988 }
06989 }
06990 return $res;
06991 }
06992
07002 function getQuestiontext($question_id)
07003 {
07004 global $ilDB;
07005
07006 $res = "";
07007 if ($question_id)
07008 {
07009 $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
07010 $ilDB->quote($question_id . "")
07011 );
07012 $result = $ilDB->query($query);
07013 if ($result->numRows() == 1)
07014 {
07015 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07016 $res = $row["question_text"];
07017 }
07018 }
07019 return $res;
07020 }
07021
07030 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
07031 {
07032 global $ilDB;
07033
07034 $result_array = array();
07035
07036 if ($this->getAnonymity())
07037 {
07038 if (is_numeric($user_id))
07039 {
07040 $query = sprintf("SELECT tst_active.active_id, tst_active.tries, usr_id, '' AS login, %s AS lastname, '' AS firstname, tst_invited_user.clientip, " .
07041 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
07042 "FROM usr_data, tst_invited_user " .
07043 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
07044 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
07045 "ORDER BY %s",
07046 $ilDB->quote($this->lng->txt("unknown")),
07047 $ilDB->quote($this->test_id),
07048 $user_id,
07049 $order
07050 );
07051 }
07052 else
07053 {
07054 $query = sprintf("SELECT tst_active.active_id, usr_id, '' AS login, %s AS lastname, '' AS firstname, tst_invited_user.clientip, " .
07055 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
07056 "FROM usr_data, tst_invited_user " .
07057 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
07058 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
07059 "ORDER BY %s",
07060 $ilDB->quote($this->lng->txt("unknown")),
07061 $ilDB->quote($this->test_id),
07062 $order
07063 );
07064 }
07065 }
07066 else
07067 {
07068 if (is_numeric($user_id))
07069 {
07070 $query = sprintf("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
07071 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
07072 "FROM usr_data, tst_invited_user " .
07073 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
07074 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
07075 "ORDER BY %s",
07076 $ilDB->quote($this->test_id),
07077 $user_id,
07078 $order
07079 );
07080 }
07081 else
07082 {
07083 $query = sprintf("SELECT tst_active.active_id, tst_active.tries, usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
07084 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
07085 "FROM usr_data, tst_invited_user " .
07086 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
07087 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
07088 "ORDER BY %s",
07089 $ilDB->quote($this->test_id),
07090 $order
07091 );
07092 }
07093 }
07094 return $this->getArrayData($query, "usr_id");
07095 }
07096
07105 function &getTestParticipants()
07106 {
07107 global $ilDB;
07108
07109 if ($this->getAnonymity())
07110 {
07111 $q = sprintf("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi AS usr_id, '' AS login, %s AS lastname, '' AS firstname, tst_active.submitted as test_finished, usr_data.matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started ".
07112 "FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
07113 $ilDB->quote($this->lng->txt("unknown")),
07114 $ilDB->quote($this->getTestId())
07115 );
07116 }
07117 else
07118 {
07119 $q = sprintf("SELECT tst_active.active_id, tst_active.tries, tst_active.user_fi AS usr_id, usr_data.login, usr_data.lastname, usr_data.firstname, tst_active.submitted as test_finished, usr_data.matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started ".
07120 "FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
07121 $ilDB->quote($this->getTestId())
07122 );
07123 }
07124 $data = $this->getArrayData($q, "active_id");
07125 foreach ($data as $index => $participant)
07126 {
07127 if (strlen(trim($participant->firstname.$participant->lastname)) == 0)
07128 {
07129 $data[$index]->lastname = $this->lng->txt("deleted_user");
07130 }
07131 }
07132 return $data;
07133 }
07134
07144 function &getUserData($ids)
07145 {
07146 if (!is_array($ids) || count($ids) ==0)
07147 return array();
07148
07149 $result_array = array();
07150
07151 if ($this->getAnonymity())
07152 {
07153 $query = sprintf("SELECT usr_id, '' AS login, %s AS lastname, '' AS firstname, client_ip as clientip FROM usr_data WHERE usr_id IN ('%s') ORDER BY login",
07154 $ilDB->quote($this->lng->txt("unknown")),
07155 join ($ids,"','")
07156 );
07157 }
07158 else
07159 {
07160 $query = sprintf("SELECT usr_id, login, lastname, firstname, client_ip as clientip FROM usr_data WHERE usr_id IN ('%s') ORDER BY login",
07161 join ($ids,"','")
07162 );
07163 }
07164
07165 return $this->getArrayData ($query, "usr_id");
07166 }
07167
07178 function &getArrayData($query, $id_field)
07179 {
07180 return ilObjTest::_getArrayData ($query, $id_field);
07181 }
07182
07183 function &_getArrayData($query, $id_field)
07184 {
07185 global $ilDB;
07186 $result = $ilDB->query($query);
07187 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
07188 {
07189 $result_array[$row->$id_field]= $row;
07190 }
07191 return ($result_array)?$result_array:array();
07192 }
07193
07194 function &getGroupData($ids)
07195 {
07196 if (!is_array($ids) || count($ids) ==0)
07197 return array();
07198
07199 $result_array = array();
07200
07201 $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')",
07202 join ($ids,"','")
07203 );
07204
07205 return $this->getArrayData ($query, "ref_id");
07206 }
07207
07208 function &getRoleData($ids)
07209 {
07210 if (!is_array($ids) || count($ids) ==0)
07211 return array();
07212
07213 $result_array = array();
07214
07215 $query = sprintf("SELECT obj_id, description, title FROM role_data, object_data o WHERE o.obj_id=role_id AND role_id IN ('%s')",
07216 join ($ids,"','")
07217 );
07218
07219 return $this->getArrayData ($query, "obj_id");
07220 }
07221
07222
07231 function inviteGroup($group_id)
07232 {
07233 include_once "./classes/class.ilObjGroup.php";
07234 $group = new ilObjGroup($group_id);
07235 $members = $group->getGroupMemberIds();
07236 include_once './Services/User/classes/class.ilObjUser.php';
07237 foreach ($members as $user_id)
07238 {
07239 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
07240 }
07241 }
07242
07251 function inviteRole($role_id)
07252 {
07253 global $rbacreview;
07254 $members = $rbacreview->assignedUsers($role_id,"usr_id");
07255 include_once './Services/User/classes/class.ilObjUser.php';
07256 foreach ($members as $user_id)
07257 {
07258 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
07259 }
07260 }
07261
07262
07263
07272 function disinviteUser($user_id)
07273 {
07274 global $ilDB;
07275
07276 $query = sprintf("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
07277 $ilDB->quote($this->test_id),
07278 $ilDB->quote($user_id)
07279 );
07280 $result = $ilDB->query($query);
07281 }
07282
07291 function inviteUser($user_id, $client_ip="")
07292 {
07293 global $ilDB;
07294
07295 $query = sprintf("INSERT IGNORE INTO tst_invited_user (test_fi, user_fi, clientip) VALUES (%s, %s, %s)",
07296 $ilDB->quote($this->test_id),
07297 $ilDB->quote($user_id),
07298 $ilDB->quote($client_ip)
07299 );
07300 $result = $ilDB->query($query);
07301 }
07302
07303
07304 function setClientIP($user_id, $client_ip)
07305 {
07306 global $ilDB;
07307
07308 $query = sprintf("UPDATE tst_invited_user SET clientip=%s WHERE test_fi=%s and user_fi=%s",
07309 $ilDB->quote($client_ip),
07310 $ilDB->quote($this->test_id),
07311 $ilDB->quote($user_id)
07312 );
07313 $insertresult = $ilDB->query($query);
07314 }
07315
07321 function _getSolvedQuestions($active_id, $question_fi = null)
07322 {
07323 global $ilDB;
07324 if (is_numeric($question_fi))
07325 $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
07326 "WHERE active_fi = %s AND question_fi=%s",
07327 $ilDB->quote($active_id),
07328 $question_fi
07329 );
07330 else $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
07331 "WHERE active_fi = %s",
07332 $ilDB->quote($active_id)
07333 );
07334 return ilObjTest::_getArrayData ($query, "question_fi");
07335 }
07336
07337
07341 function setQuestionSetSolved($value, $question_id, $user_id)
07342 {
07343 global $ilDB;
07344
07345 $active_id = $this->getActiveIdOfUser($user_id);
07346 $query = sprintf("REPLACE INTO tst_active_qst_sol_settings SET solved=%s, question_fi=%s, active_fi = %s",
07347 $ilDB->quote($value),
07348 $ilDB->quote($question_id),
07349 $ilDB->quote($active_id)
07350 );
07351
07352 $ilDB->query($query);
07353 }
07354
07355
07359 function setActiveTestSubmitted($user_id)
07360 {
07361 global $ilDB, $ilLog;
07362
07363 $query = sprintf("UPDATE tst_active SET submitted = 1, submittimestamp = NOW() WHERE test_fi = %s AND user_fi = %s",
07364 $ilDB->quote($this->getTestId() . ""),
07365 $ilDB->quote($user_id . "")
07366 );
07367 $result = $ilDB->query($query);
07368 $this->testSession = NULL;
07369 }
07370
07374 function isActiveTestSubmitted($user_id = null)
07375 {
07376 global $ilUser;
07377 global $ilDB;
07378
07379 if (!is_numeric($user_id))
07380 $user_id = $ilUser->getId();
07381
07382 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
07383 $ilDB->quote($this->test_id),
07384 $ilDB->quote($user_id)
07385 );
07386 $result = $ilDB->query($query);
07387
07388 return $result->numRows() == 1;
07389
07390 }
07394 function hasNrOfTriesRestriction()
07395 {
07396 return $this->getNrOfTries() != 0;
07397 }
07398
07399
07404 function isNrOfTriesReached($tries)
07405 {
07406 return $tries >= (int) $this->getNrOfTries();
07407 }
07408
07421 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
07422 {
07423 $resultarray = array();
07424 foreach ($row as $rowindex => $entry)
07425 {
07426 $surround = FALSE;
07427 if ($quoteAll)
07428 {
07429 $surround = TRUE;
07430 }
07431 if (strpos($entry, "\"") !== FALSE)
07432 {
07433 $entry = str_replace("\"", "\"\"", $entry);
07434 $surround = TRUE;
07435 }
07436 if (strpos($entry, $separator) !== FALSE)
07437 {
07438 $surround = TRUE;
07439 }
07440
07441 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
07442 if ($surround)
07443 {
07444 $resultarray[$rowindex] = utf8_decode("\"" . $entry . "\"");
07445 }
07446 else
07447 {
07448 $resultarray[$rowindex] = utf8_decode($entry);
07449 }
07450 }
07451 return $resultarray;
07452 }
07453
07464 function _getPass($active_id)
07465 {
07466 global $ilDB;
07467 $query = sprintf("SELECT tries FROM tst_active WHERE active_id = %s",
07468 $ilDB->quote($active_id . "")
07469 );
07470 $result = $ilDB->query($query);
07471 if ($result->numRows())
07472 {
07473 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07474 return $row["tries"];
07475 }
07476 else
07477 {
07478 return 0;
07479 }
07480 }
07481
07493 function _getMaxPass($active_id)
07494 {
07495 global $ilDB;
07496 $query = sprintf("SELECT MAX(pass) as maxpass FROM tst_test_result WHERE active_fi = %s",
07497 $ilDB->quote($active_id . "")
07498 );
07499 $result = $ilDB->query($query);
07500 if ($result->numRows())
07501 {
07502 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07503 $max = $row["maxpass"];
07504 }
07505 else
07506 {
07507 $max = NULL;
07508 }
07509 return $max;
07510 }
07511
07522 function _getBestPass($active_id)
07523 {
07524 global $ilDB;
07525 $query = sprintf("SELECT test_fi FROM tst_active WHERE active_id = %s",
07526 $ilDB->quote($active_id . "")
07527 );
07528 $result = $ilDB->query($query);
07529 if ($result->numRows())
07530 {
07531 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07532 $test_id = $row["test_fi"];
07533 $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE, $active_id);
07534 $participant =& $results->getParticipant($active_id);
07535 if ($participant != null)
07536 {
07537 return $participant->getBestPass();
07538 }
07539 else
07540 {
07541 return 0;
07542 }
07543 }
07544 else
07545 {
07546 return 0;
07547 }
07548 }
07549
07560 function _getResultPass($active_id)
07561 {
07562 $counted_pass = NULL;
07563 if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS)
07564 {
07565 $counted_pass = ilObjTest::_getBestPass($active_id);
07566 }
07567 else
07568 {
07569 $counted_pass = ilObjTest::_getMaxPass($active_id);
07570 }
07571 return $counted_pass;
07572 }
07573
07585 function getAnsweredQuestionCount($active_id, $pass = NULL)
07586 {
07587 if ($this->isRandomTest())
07588 {
07589 $this->loadQuestions($active_id, $pass);
07590 }
07591 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
07592 $workedthrough = 0;
07593 foreach ($this->questions as $value)
07594 {
07595 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
07596 {
07597 $workedthrough += 1;
07598 }
07599 }
07600 return $workedthrough;
07601 }
07602
07614 function getPassFinishDate($active_id, $pass)
07615 {
07616 global $ilDB;
07617 if (is_null($pass)) $pass = 0;
07618 $query = sprintf("SELECT tst_test_result.TIMESTAMP + 0 AS TIMESTAMP14 FROM tst_test_result WHERE active_fi = %s AND pass = %s ORDER BY tst_test_result.TIMESTAMP DESC",
07619 $ilDB->quote($active_id . ""),
07620 $ilDB->quote($pass . "")
07621 );
07622 $result = $ilDB->query($query);
07623 if ($result->numRows())
07624 {
07625 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07626 return $row["TIMESTAMP14"];
07627 }
07628 else
07629 {
07630 return 0;
07631 }
07632 }
07633
07643 function isExecutable($user_id, $allowPassIncrease = FALSE)
07644 {
07645 $result = array(
07646 "executable" => true,
07647 "errormessage" => ""
07648 );
07649 if (!$this->startingTimeReached())
07650 {
07651 $result["executable"] = false;
07652 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilFormat::ftimestamp2datetimeDB($this->getStartingTime()));
07653 return $result;
07654 }
07655 if ($this->endingTimeReached())
07656 {
07657 $result["executable"] = false;
07658 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilFormat::ftimestamp2datetimeDB($this->getEndingTime()));
07659 return $result;
07660 }
07661
07662 $active_id = $this->getActiveIdOfUser($user_id);
07663
07664 if ($this->getEnableProcessingTime())
07665 {
07666 if ($active_id > 0)
07667 {
07668 $starting_time = $this->getStartingTimeOfUser($active_id);
07669 if ($starting_time !== FALSE)
07670 {
07671 if ($this->isMaxProcessingTimeReached($starting_time))
07672 {
07673 if ($allowPassIncrease && $this->getResetProcessingTime() && (($this->getNrOfTries() == 0) || ($this->getNrOfTries() > ($this->_getPass($active_id)+1))))
07674 {
07675
07676
07677
07678
07679
07680 $this->getTestSession()->increasePass();
07681 $this->getTestSession()->setLastSequence(0);
07682 $this->getTestSession()->saveToDb();
07683 }
07684 else
07685 {
07686 $result["executable"] = false;
07687 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
07688 }
07689 return $result;
07690 }
07691 }
07692 }
07693 }
07694
07695 if ($this->hasNrOfTriesRestriction() && ($active_id > 0) && $this->isNrOfTriesReached($this->getTestSession($active_id)->getPass()))
07696 {
07697 $result["executable"] = false;
07698 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
07699 return $result;
07700 }
07701
07702 if ($this->getTestSession($active_id)->isSubmitted())
07703 {
07704 $result["executable"] = FALSE;
07705 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
07706 return $result;
07707 }
07708
07709
07710
07711 return $result;
07712 }
07713
07722 function canViewResults()
07723 {
07724 $result = true;
07725 if ($this->getReportingDate())
07726 {
07727 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
07728 {
07729 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07730 $now = mktime();
07731 if ($now < $epoch_time)
07732 {
07733 $result = false;
07734 }
07735 }
07736 }
07737 return $result;
07738 }
07739
07740 function canShowTestResults($user_id)
07741 {
07742 $active_id = $this->getActiveIdOfUser($user_id);
07743 if ($active_id > 0)
07744 {
07745 $starting_time = $this->getStartingTimeOfUser($active_id);
07746 }
07747 $notimeleft = FALSE;
07748 if ($starting_time !== FALSE)
07749 {
07750 if ($this->isMaxProcessingTimeReached($starting_time))
07751 {
07752 $notimeleft = TRUE;
07753 }
07754 }
07755 $result = TRUE;
07756 if (!$this->isTestFinishedToViewResults($active_id, $this->getTestSession($active_id)->getPass()) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
07757 {
07758 $result = FALSE;
07759 }
07760 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
07761 $result = $result & $this->canViewResults();
07762 return $result;
07763 }
07764
07765 function canEditMarks()
07766 {
07767 $total = $this->evalTotalPersons();
07768 if ($total > 0)
07769 {
07770 if ($this->getReportingDate())
07771 {
07772 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
07773 {
07774 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07775 $now = mktime();
07776 if ($now < $epoch_time)
07777 {
07778 return true;
07779 }
07780 }
07781 }
07782 return false;
07783 }
07784 else
07785 {
07786 return true;
07787 }
07788 }
07789
07799 function getStartingTimeOfUser($active_id)
07800 {
07801 global $ilDB;
07802
07803 if ($active_id < 1) return FALSE;
07804 $pass = ($this->getResetProcessingTime()) ? $this->_getPass($active_id) : 0;
07805 $query = sprintf("SELECT tst_times.started FROM tst_times WHERE tst_times.active_fi = %s AND tst_times.pass = %s ORDER BY tst_times.started",
07806 $ilDB->quote($active_id . ""),
07807 $ilDB->quote($pass . "")
07808 );
07809 $result = $ilDB->query($query);
07810 if ($result->numRows())
07811 {
07812 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07813 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
07814 {
07815 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07816 }
07817 else
07818 {
07819 return mktime();
07820 }
07821 }
07822 else
07823 {
07824 return mktime();
07825 }
07826 }
07827
07838 function isMaxProcessingTimeReached($starting_time)
07839 {
07840 if ($this->getEnableProcessingTime())
07841 {
07842 $processing_time = $this->getProcessingTimeInSeconds();
07843 $now = mktime();
07844 if ($now > ($starting_time + $processing_time))
07845 {
07846 return TRUE;
07847 }
07848 else
07849 {
07850 return FALSE;
07851 }
07852 }
07853 else
07854 {
07855 return FALSE;
07856 }
07857 }
07858
07859 function &getTestQuestions()
07860 {
07861 global $ilDB;
07862 $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type, tst_test_question WHERE qpl_questions.question_type_fi = qpl_question_type.question_type_id AND tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY sequence",
07863 $ilDB->quote($this->getTestId() . "")
07864 );
07865 $query_result = $ilDB->query($query);
07866 $removableQuestions = array();
07867 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
07868 {
07869 array_push($removableQuestions, $row);
07870 }
07871 return $removableQuestions;
07872 }
07873
07882 function getShuffleQuestions()
07883 {
07884 return $this->shuffle_questions;
07885 }
07886
07895 function setShuffleQuestions($a_shuffle)
07896 {
07897 if ($a_shuffle)
07898 {
07899 $this->shuffle_questions = TRUE;
07900 }
07901 else
07902 {
07903 $this->shuffle_questions = FALSE;
07904 }
07905 }
07906
07921 function getListOfQuestionsSettings()
07922 {
07923 return $this->show_summary;
07924 }
07925
07940 function setListOfQuestionsSettings($a_value = 0)
07941 {
07942 $this->show_summary = $a_value;
07943 }
07944
07953 function getListOfQuestions()
07954 {
07955 if (($this->show_summary & 1) > 0)
07956 {
07957 return TRUE;
07958 }
07959 else
07960 {
07961 return FALSE;
07962 }
07963 }
07964
07973 function setListOfQuestions($a_value = TRUE)
07974 {
07975 if ($a_value)
07976 {
07977 $this->show_summary = 1;
07978 }
07979 else
07980 {
07981 $this->show_summary = 0;
07982 }
07983 }
07984
07993 function getListOfQuestionsStart()
07994 {
07995 if (($this->show_summary & 2) > 0)
07996 {
07997 return TRUE;
07998 }
07999 else
08000 {
08001 return FALSE;
08002 }
08003 }
08004
08013 function setListOfQuestionsStart($a_value = TRUE)
08014 {
08015 if ($a_value && $this->getListOfQuestions())
08016 {
08017 $this->show_summary = $this->show_summary | 2;
08018 }
08019 if (!$a_value && $this->getListOfQuestions())
08020 {
08021 if ($this->getListOfQuestionsStart())
08022 {
08023 $this->show_summary = $this->show_summary ^ 2;
08024 }
08025 }
08026 }
08027
08036 function getListOfQuestionsEnd()
08037 {
08038 if (($this->show_summary & 4) > 0)
08039 {
08040 return TRUE;
08041 }
08042 else
08043 {
08044 return FALSE;
08045 }
08046 }
08047
08056 function setListOfQuestionsEnd($a_value = TRUE)
08057 {
08058 if ($a_value && $this->getListOfQuestions())
08059 {
08060 $this->show_summary = $this->show_summary | 4;
08061 }
08062 if (!$a_value && $this->getListOfQuestions())
08063 {
08064 if ($this->getListOfQuestionsEnd())
08065 {
08066 $this->show_summary = $this->show_summary ^ 4;
08067 }
08068 }
08069 }
08070
08079 function getListOfQuestionsDescription()
08080 {
08081 if (($this->show_summary & 8) > 0)
08082 {
08083 return TRUE;
08084 }
08085 else
08086 {
08087 return FALSE;
08088 }
08089 }
08090
08099 function setListOfQuestionsDescription($a_value = TRUE)
08100 {
08101 if ($a_value && $this->getListOfQuestions())
08102 {
08103 $this->show_summary = $this->show_summary | 8;
08104 }
08105 if (!$a_value && $this->getListOfQuestions())
08106 {
08107 if ($this->getListOfQuestionsDescription())
08108 {
08109 $this->show_summary = $this->show_summary ^ 8;
08110 }
08111 }
08112 }
08113
08122 function getResultsPresentation()
08123 {
08124 return $this->results_presentation;
08125 }
08126
08135 function getShowPassDetails()
08136 {
08137 if (($this->results_presentation & 1) > 0)
08138 {
08139 return TRUE;
08140 }
08141 else
08142 {
08143 return FALSE;
08144 }
08145 }
08146
08155 function getShowSolutionDetails()
08156 {
08157 if (($this->results_presentation & 2) > 0)
08158 {
08159 return TRUE;
08160 }
08161 else
08162 {
08163 return FALSE;
08164 }
08165 }
08166
08175 function getShowSolutionPrintview()
08176 {
08177 if (($this->results_presentation & 4) > 0)
08178 {
08179 return TRUE;
08180 }
08181 else
08182 {
08183 return FALSE;
08184 }
08185 }
08186
08195 function getShowSolutionFeedback()
08196 {
08197 if (($this->results_presentation & 8) > 0)
08198 {
08199 return TRUE;
08200 }
08201 else
08202 {
08203 return FALSE;
08204 }
08205 }
08206
08215 function getShowSolutionAnswersOnly()
08216 {
08217 if (($this->results_presentation & 16) > 0)
08218 {
08219 return TRUE;
08220 }
08221 else
08222 {
08223 return FALSE;
08224 }
08225 }
08226
08235 function getShowSolutionSignature()
08236 {
08237 if (($this->results_presentation & 32) > 0)
08238 {
08239 return TRUE;
08240 }
08241 else
08242 {
08243 return FALSE;
08244 }
08245 }
08246
08255 function setResultsPresentation($a_results_presentation = 3)
08256 {
08257 $this->results_presentation = $a_results_presentation;
08258 }
08259
08268 function setShowPassDetails($a_details = 1)
08269 {
08270 if ($a_details)
08271 {
08272 $this->results_presentation = $this->results_presentation | 1;
08273 }
08274 else
08275 {
08276 if ($this->getShowPassDetails())
08277 {
08278 $this->results_presentation = $this->results_presentation ^ 1;
08279 }
08280 }
08281 }
08282
08291 function setShowSolutionDetails($a_details = 1)
08292 {
08293 if ($a_details)
08294 {
08295 $this->results_presentation = $this->results_presentation | 2;
08296 }
08297 else
08298 {
08299 if ($this->getShowSolutionDetails())
08300 {
08301 $this->results_presentation = $this->results_presentation ^ 2;
08302 }
08303 }
08304 }
08305
08314 function canShowSolutionPrintview($user_id = NULL)
08315 {
08316 return $this->getShowSolutionPrintview();
08317 }
08318
08327 function setShowSolutionPrintview($a_printview = 1)
08328 {
08329 if ($a_printview)
08330 {
08331 $this->results_presentation = $this->results_presentation | 4;
08332 }
08333 else
08334 {
08335 if ($this->getShowSolutionPrintview())
08336 {
08337 $this->results_presentation = $this->results_presentation ^ 4;
08338 }
08339 }
08340 }
08341
08350 function setShowSolutionFeedback($a_feedback = TRUE)
08351 {
08352 if ($a_feedback)
08353 {
08354 $this->results_presentation = $this->results_presentation | 8;
08355 }
08356 else
08357 {
08358 if ($this->getShowSolutionFeedback())
08359 {
08360 $this->results_presentation = $this->results_presentation ^ 8;
08361 }
08362 }
08363 }
08364
08373 function setShowSolutionAnswersOnly($a_full = TRUE)
08374 {
08375 if ($a_full)
08376 {
08377 $this->results_presentation = $this->results_presentation | 16;
08378 }
08379 else
08380 {
08381 if ($this->getShowSolutionAnswersOnly())
08382 {
08383 $this->results_presentation = $this->results_presentation ^ 16;
08384 }
08385 }
08386 }
08387
08396 function setShowSolutionSignature($a_signature = TRUE)
08397 {
08398 if ($a_signature)
08399 {
08400 $this->results_presentation = $this->results_presentation | 32;
08401 }
08402 else
08403 {
08404 if ($this->getShowSolutionSignature())
08405 {
08406 $this->results_presentation = $this->results_presentation ^ 32;
08407 }
08408 }
08409 }
08410
08422 function &_getPassedUsers($a_obj_id)
08423 {
08424 $passed_users = array();
08425 $test_id = ilObjTest::_getTestIDFromObjectID($a_obj_id);
08426 $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE);
08427 if (is_object($results))
08428 {
08429 $participants =& $results->getParticipants();
08430 foreach ($participants as $active_id => $participant)
08431 {
08432 if (is_object($participant) && $participant->getPassed())
08433 {
08434 array_push($passed_users, $active_id);
08435 }
08436 }
08437 }
08438 return $passed_users;
08439 }
08440
08446 function createNewAccessCode()
08447 {
08448
08449 $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
08450 mt_srand();
08451 $code = "";
08452 for ($i = 1; $i <=5; $i++)
08453 {
08454 $index = mt_rand(0, strlen($codestring)-1);
08455 $code .= substr($codestring, $index, 1);
08456 }
08457
08458 while ($this->isAccessCodeUsed($code))
08459 {
08460 $code = $this->createNewAccessCode();
08461 }
08462 return $code;
08463 }
08464
08465 function isAccessCodeUsed($code)
08466 {
08467 global $ilDB;
08468
08469 $query = sprintf("SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s",
08470 $ilDB->quote($this->getTestId() . ""),
08471 $ilDB->quote($code . "")
08472 );
08473 $result = $ilDB->query($query);
08474 if ($result->numRows() > 0)
08475 {
08476 return TRUE;
08477 }
08478 else
08479 {
08480 return FALSE;
08481 }
08482 }
08483
08484 function _getUserIdFromActiveId($active_id)
08485 {
08486 global $ilDB;
08487 $query = sprintf("SELECT user_fi FROM tst_active WHERE active_id = %s",
08488 $ilDB->quote($active_id . "")
08489 );
08490 $result = $ilDB->query($query);
08491 if ($result->numRows())
08492 {
08493 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
08494 return $row["user_fi"];
08495 }
08496 else
08497 {
08498 return -1;
08499 }
08500 }
08501
08502 function getAccessCodeSession()
08503 {
08504 $id = $this->getTestId();
08505 if (!is_array($_SESSION["tst_access_code"]))
08506 {
08507 return "";
08508 }
08509 else
08510 {
08511 return $_SESSION["tst_access_code"]["$id"];
08512 }
08513 }
08514
08515 function setAccessCodeSession($access_code)
08516 {
08517 $id = $this->getTestId();
08518 if (!is_array($_SESSION["tst_access_code"]))
08519 {
08520 $_SESSION["tst_access_code"] = array();
08521 }
08522 $_SESSION["tst_access_code"]["$id"] = $access_code;
08523 }
08524
08525 function unsetAccessCodeSession()
08526 {
08527 $id = $this->getTestId();
08528 unset($_SESSION["tst_access_code"]["$id"]);
08529 }
08530
08531 function getAllowedUsers()
08532 {
08533 return $this->allowedUsers;
08534 }
08535
08536 function setAllowedUsers($a_allowed_users)
08537 {
08538 $this->allowedUsers = $a_allowed_users;
08539 }
08540
08541 function getAllowedUsersTimeGap()
08542 {
08543 return $this->allowedUsersTimeGap;
08544 }
08545
08546 function setAllowedUsersTimeGap($a_allowed_users_time_gap)
08547 {
08548 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
08549 }
08550
08551 function checkMaximumAllowedUsers()
08552 {
08553 global $ilDB;
08554
08555 $nr_of_users = $this->getAllowedUsers();
08556 $time_gap = ($this->getAllowedUsersTimeGap()) ? $this->getAllowedUsersTimeGap() : 60;
08557 if (($nr_of_users > 0) && ($time_gap > 0))
08558 {
08559 $now = mktime();
08560 $time_border = $now - $time_gap;
08561 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
08562 $query = sprintf("SELECT DISTINCT tst_times.active_fi FROM tst_times, tst_active WHERE tst_times.TIMESTAMP > %s AND tst_times.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
08563 $ilDB->quote($str_time_border),
08564 $ilDB->quote($this->getTestId() . "")
08565 );
08566 $result = $ilDB->query($query);
08567 if ($result->numRows() >= $nr_of_users)
08568 {
08569 include_once "./classes/class.ilObjAssessmentFolder.php";
08570 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
08571 {
08572 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
08573 }
08574 return FALSE;
08575 }
08576 else
08577 {
08578 return TRUE;
08579 }
08580 }
08581 return TRUE;
08582 }
08583
08584 function _getLastAccess($active_id)
08585 {
08586 global $ilDB;
08587
08588 $query = sprintf("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
08589 $ilDB->quote($active_id . "")
08590 );
08591 $result = $ilDB->query($query);
08592 if ($result->numRows())
08593 {
08594 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
08595 return $row["finished"];
08596 }
08597 return "";
08598 }
08599
08607 function isHTML($a_text)
08608 {
08609 if (preg_match("/<[^>]*?>/", $a_text))
08610 {
08611 return TRUE;
08612 }
08613 else
08614 {
08615 return FALSE;
08616 }
08617 }
08618
08626 function QTIMaterialToString($a_material)
08627 {
08628 $result = "";
08629 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
08630 {
08631 $material = $a_material->getMaterial($i);
08632 if (strcmp($material["type"], "mattext") == 0)
08633 {
08634 $result .= $material["material"]->getContent();
08635 }
08636 if (strcmp($material["type"], "matimage") == 0)
08637 {
08638 $matimage = $material["material"];
08639 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
08640 {
08641
08642 if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
08643 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
08644 }
08645 }
08646 }
08647 global $ilLog;
08648 $ilLog->write(print_r($_SESSION["import_mob_xhtml"], true));
08649 return $result;
08650 }
08651
08660 function addQTIMaterial(&$a_xml_writer, $a_material)
08661 {
08662 include_once "./Services/RTE/classes/class.ilRTE.php";
08663 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
08664
08665 $a_xml_writer->xmlStartTag("material");
08666 $attrs = array(
08667 "texttype" => "text/plain"
08668 );
08669 if ($this->isHTML($a_material))
08670 {
08671 $attrs["texttype"] = "text/xhtml";
08672 }
08673 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
08674
08675 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
08676 foreach ($mobs as $mob)
08677 {
08678 $mob_obj =& new ilObjMediaObject($mob);
08679 $imgattrs = array(
08680 "label" => "il_" . IL_INST_ID . "_mob_" . $mob,
08681 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
08682 );
08683 $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
08684 }
08685 $a_xml_writer->xmlEndTag("material");
08686 }
08687
08694 function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE)
08695 {
08696 include_once "./Services/Utilities/classes/class.ilUtil.php";
08697 return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
08698 }
08699
08708 function saveCertificateVisibility($a_value)
08709 {
08710 global $ilDB;
08711
08712 $query = sprintf("UPDATE tst_tests SET certificate_visibility = %s WHERE test_id = %s",
08713 $ilDB->quote($a_value),
08714 $ilDB->quote($this->getTestId())
08715 );
08716 $result = $ilDB->query($query);
08717 }
08718
08727 function getCertificateVisibility()
08728 {
08729 return $this->certificate_visibility;
08730 }
08731
08740 function setCertificateVisibility($a_value)
08741 {
08742 $this->certificate_visibility = $a_value;
08743 }
08744
08753 function getAnonymity()
08754 {
08755 return $this->anonymity;
08756 }
08757
08766 function setAnonymity($a_value = 0)
08767 {
08768 switch ($a_value)
08769 {
08770 case 1:
08771 $this->anonymity = 1;
08772 break;
08773 default:
08774 $this->anonymity = 0;
08775 break;
08776 }
08777 }
08778
08787 function getShowCancel()
08788 {
08789 return $this->show_cancel;
08790 }
08791
08800 function setShowCancel($a_value = 1)
08801 {
08802 switch ($a_value)
08803 {
08804 case 1:
08805 $this->show_cancel = 1;
08806 break;
08807 default:
08808 $this->show_cancel = 0;
08809 break;
08810 }
08811 }
08812
08821 function getShowMarker()
08822 {
08823 return $this->show_marker;
08824 }
08825
08834 function setShowMarker($a_value = 1)
08835 {
08836 switch ($a_value)
08837 {
08838 case 1:
08839 $this->show_marker = 1;
08840 break;
08841 default:
08842 $this->show_marker = 0;
08843 break;
08844 }
08845 }
08846
08855 function getFixedParticipants()
08856 {
08857 return $this->fixed_participants;
08858 }
08859
08868 function setFixedParticipants($a_value = 1)
08869 {
08870 switch ($a_value)
08871 {
08872 case 1:
08873 $this->fixed_participants = 1;
08874 break;
08875 default:
08876 $this->fixed_participants = 0;
08877 break;
08878 }
08879 }
08880
08890 function _lookupAnonymity($a_obj_id)
08891 {
08892 global $ilDB;
08893
08894 $query = "SELECT anonymity FROM tst_tests ".
08895 "WHERE obj_fi = '".$a_obj_id."'";
08896 $res = $ilDB->query($query);
08897 while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
08898 {
08899 return $row['anonymity'];
08900 }
08901 return 0;
08902 }
08903
08913 function _lookupRandomTestFromActiveId($active_id)
08914 {
08915 global $ilDB;
08916
08917 $query = sprintf("SELECT tst_tests.random_test FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
08918 $ilDB->quote($active_id . "")
08919 );
08920 $res = $ilDB->query($query);
08921 while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
08922 {
08923 return $row['random_test'];
08924 }
08925 return 0;
08926 }
08927
08938 function userLookupFullName($user_id, $overwrite_anonymity = FALSE, $sorted_order = FALSE, $suffix = "")
08939 {
08940 if ($this->getAnonymity() && !$overwrite_anonymity)
08941 {
08942 return $this->lng->txt("unknown") . $suffix;
08943 }
08944 else
08945 {
08946 include_once './Services/User/classes/class.ilObjUser.php';
08947 $uname = ilObjUser::_lookupName($user_id);
08948 if (strlen($uname["firstname"].$uname["lastname"]) == 0) $uname["firstname"] = $this->lng->txt("deleted_user");
08949 if ($sorted_order)
08950 {
08951 return trim($uname["lastname"] . ", " . $uname["firstname"]) . $suffix;
08952 }
08953 else
08954 {
08955 return trim($uname["firstname"] . " " . $uname["lastname"]) . $suffix;
08956 }
08957 }
08958 }
08959
08969 function getStartTestLabel($active_id)
08970 {
08971 if ($this->getNrOfTries() == 1)
08972 {
08973 return $this->lng->txt("tst_start_test");
08974 }
08975 $active_pass = $this->_getPass($active_id);
08976 $res = $this->getNrOfResultsForPass($active_id, $active_pass);
08977 if ($res == 0)
08978 {
08979 if ($active_pass == 0)
08980 {
08981 return $this->lng->txt("tst_start_test");
08982 }
08983 else
08984 {
08985 return $this->lng->txt("tst_start_new_test_pass");
08986 }
08987 }
08988 else
08989 {
08990 return $this->lng->txt("tst_resume_test");
08991 }
08992 }
08993
09004 function &getAvailableDefaults($sortby = "name", $sortorder = "asc")
09005 {
09006 global $ilDB;
09007 global $ilUser;
09008
09009 $query = sprintf("SELECT * FROM tst_test_defaults WHERE user_fi = %s ORDER BY $sortby $sortorder",
09010 $ilDB->quote($ilUser->getId() . "")
09011 );
09012 $result = $ilDB->query($query);
09013 $defaults = array();
09014 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
09015 {
09016 $defaults[$row["test_defaults_id"]] = $row;
09017 }
09018 return $defaults;
09019 }
09020
09030 function &getTestDefaults($test_defaults_id)
09031 {
09032 global $ilDB;
09033
09034 $query = sprintf("SELECT * FROM tst_test_defaults WHERE test_defaults_id = %s",
09035 $ilDB->quote($test_defaults_id . "")
09036 );
09037 $result = $ilDB->query($query);
09038 if ($result->numRows() == 1)
09039 {
09040 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
09041 return $row;
09042 }
09043 else
09044 {
09045 return NULL;
09046 }
09047 }
09048
09057 function deleteDefaults($test_default_id)
09058 {
09059 global $ilDB;
09060 $query = sprintf("DELETE FROM tst_test_defaults WHERE test_defaults_id = %s",
09061 $ilDB->quote($test_default_id . "")
09062 );
09063 $result = $ilDB->query($query);
09064 }
09065
09074 function addDefaults($a_name)
09075 {
09076 global $ilDB;
09077 global $ilUser;
09078 $testsettings = array(
09079 "TitleOutput" => $this->getTitleOutput(),
09080 "PassScoring" => $this->getPassScoring(),
09081 "Introduction" => $this->getIntroduction(),
09082 "SequenceSettings" => $this->getSequenceSettings(),
09083 "ScoreReporting" => $this->getScoreReporting(),
09084 "InstantFeedbackSolution" => $this->getInstantFeedbackSolution(),
09085 "AnswerFeedback" => $this->getAnswerFeedback(),
09086 "AnswerFeedbackPoints" => $this->getAnswerFeedbackPoints(),
09087 "ResultsPresentation" => $this->getResultsPresentation(),
09088 "Anonymity" => $this->getAnonymity(),
09089 "ShowCancel" => $this->getShowCancel(),
09090 "ShowMarker" => $this->getShowMarker(),
09091 "ReportingDate" => $this->getReportingDate(),
09092 "NrOfTries" => $this->getNrOfTries(),
09093 "UsePreviousAnswers" => $this->getUsePreviousAnswers(),
09094 "ProcessingTime" => $this->getProcessingTime(),
09095 "EnableProcessingTime" => $this->getEnableProcessingTime(),
09096 "ResetProcessingTime" => $this->getResetProcessingTime(),
09097 "StartingTime" => $this->getStartingTime(),
09098 "EndingTime" => $this->getEndingTime(),
09099 "ECTSOutput" => $this->getECTSOutput(),
09100 "ECTSFX" => $this->getECTSFX(),
09101 "ECTSGrades" => $this->getECTSGrades(),
09102 "isRandomTest" => $this->isRandomTest(),
09103 "RandomQuestionCount" => $this->getRandomQuestionCount(),
09104 "CountSystem" => $this->getCountSystem(),
09105 "MCScoring" => $this->getMCScoring(),
09106 "ListOfQuestionsSettings" => $this->getListOfQuestionsSettings()
09107 );
09108 $query = sprintf("INSERT INTO tst_test_defaults (test_defaults_id, name, user_fi, defaults, marks) VALUES (NULL, %s, %s, %s, %s)",
09109 $ilDB->quote($a_name . ""),
09110 $ilDB->quote($ilUser->getId(). ""),
09111 $ilDB->quote(serialize($testsettings)),
09112 $ilDB->quote(serialize($this->mark_schema))
09113 );
09114 $result = $ilDB->query($query);
09115 }
09116
09126 function applyDefaults($test_defaults_id)
09127 {
09128 $total = $this->evalTotalPersons();
09129 $result = FALSE;
09130 if (($this->getQuestionCount() == 0) && ($total == 0))
09131 {
09132
09133 $defaults =& $this->getTestDefaults($test_defaults_id);
09134 $testsettings = unserialize($defaults["defaults"]);
09135 include_once "./Modules/Test/classes/class.assMarkSchema.php";
09136 $this->mark_schema = unserialize($defaults["marks"]);
09137 $this->setTitleOutput($testsettings["TitleOutput"]);
09138 $this->setPassScoring($testsettings["PassScoring"]);
09139 $this->setIntroduction($testsettings["Introduction"]);
09140 $this->setSequenceSettings($testsettings["SequenceSettings"]);
09141 $this->setScoreReporting($testsettings["ScoreReporting"]);
09142 $this->setInstantFeedbackSolution($testsettings["InstantFeedbackSolution"]);
09143 $this->setAnswerFeedback($testsettings["AnswerFeedback"]);
09144 $this->setAnswerFeedbackPoints($testsettings["AnswerFeedbackPoints"]);
09145 $this->setResultsPresentation($testsettings["ResultsPresentation"]);
09146 $this->setAnonymity($testsettings["Anonymity"]);
09147 $this->setShowCancel($testsettings["ShowCancel"]);
09148 $this->setShowMarker($testsettings["ShowMarker"]);
09149 $this->setReportingDate($testsettings["ReportingDate"]);
09150 $this->setNrOfTries($testsettings["NrOfTries"]);
09151 $this->setUsePreviousAnswers($testsettings["UsePreviousAnswers"]);
09152 $this->setProcessingTime($testsettings["ProcessingTime"]);
09153 $this->setResetProcessingTime($testsettings["ResetProcessingTime"]);
09154 $this->setEnableProcessingTime($testsettings["EnableProcessingTime"]);
09155 $this->setStartingTime($testsettings["StartingTime"]);
09156 $this->setEndingTime($testsettings["EndingTime"]);
09157 $this->setECTSOutput($testsettings["ECTSOutput"]);
09158 $this->setECTSFX($testsettings["ECTSFX"]);
09159 $this->setECTSGrades($testsettings["ECTSGrades"]);
09160 $this->setRandomTest($testsettings["isRandomTest"]);
09161 $this->setRandomQuestionCount($testsettings["RandomQuestionCount"]);
09162 $this->setCountSystem($testsettings["CountSystem"]);
09163 $this->setMCScoring($testsettings["MCScoring"]);
09164 $this->setListOfQuestionsSettings($testsettings["ListOfQuestionsSettings"]);
09165 $this->saveToDb();
09166 $result = TRUE;
09167 }
09168 return $result;
09169 }
09170
09180 function processPrintoutput2FO($print_output)
09181 {
09182 $print_output = str_replace(" ", " ", $print_output);
09183 $print_output = str_replace("⊗", "X", $print_output);
09184
09185 $xsl = file_get_contents("./Modules/Test/xml/question2fo.xsl");
09186 $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
09187 $xh = xslt_create();
09188 $params = array();
09189 $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", NULL, $args, $params);
09190 xslt_error($xh);
09191 xslt_free($xh);
09192 return $output;
09193 }
09194
09203 function deliverPDFfromFO($fo)
09204 {
09205 include_once "./Services/Utilities/classes/class.ilUtil.php";
09206 $fo_file = ilUtil::ilTempnam() . ".fo";
09207 $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
09208 include_once "./Services/Transformation/classes/class.ilFO2PDF.php";
09209 $fo2pdf = new ilFO2PDF();
09210 $fo2pdf->setFOString($fo);
09211 $result = $fo2pdf->send();
09212 ilUtil::deliverData($result, ilUtil::getASCIIFilename($this->getTitle()) . ".pdf", "application/pdf");
09213 }
09214
09226 static function getManualFeedback($active_id, $question_id, $pass)
09227 {
09228 global $ilDB;
09229 $feedback = "";
09230 $query = sprintf("SELECT feedback FROM tst_manual_feedback WHERE active_fi = %s AND question_fi = %s AND pass = %s",
09231 $ilDB->quote($active_id . ""),
09232 $ilDB->quote($question_id . ""),
09233 $ilDB->quote($pass . "")
09234 );
09235 $result = $ilDB->query($query);
09236 if ($result->numRows())
09237 {
09238 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
09239 include_once("./Services/RTE/classes/class.ilRTE.php");
09240 $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
09241 }
09242 return $feedback;
09243 }
09244
09257 function saveManualFeedback($active_id, $question_id, $pass, $feedback)
09258 {
09259 global $ilDB;
09260
09261 $query = sprintf("DELETE FROM tst_manual_feedback WHERE active_fi = %s AND question_fi = %s AND pass = %s",
09262 $ilDB->quote($active_id . ""),
09263 $ilDB->quote($question_id . ""),
09264 $ilDB->quote($pass . "")
09265 );
09266 $result = $ilDB->query($query);
09267
09268 if (strlen($feedback))
09269 {
09270 $query = sprintf("INSERT INTO tst_manual_feedback (active_fi, question_fi, pass, feedback) VALUES (%s, %s, %s, %s)",
09271 $ilDB->quote($active_id . ""),
09272 $ilDB->quote($question_id . ""),
09273 $ilDB->quote($pass . ""),
09274 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($feedback, 0) . "")
09275 );
09276 $result = $ilDB->query($query);
09277 }
09278 if ($result == DB_OK)
09279 {
09280 return TRUE;
09281 }
09282 else
09283 {
09284 return FALSE;
09285 }
09286 }
09287
09295 function getJavaScriptOutput()
09296 {
09297 global $ilUser;
09298 $assessmentSetting = new ilSetting("assessment");
09299 return ($ilUser->getPref("tst_javascript") === FALSE) ? $assessmentSetting->get("use_javascript") : $ilUser->getPref("tst_javascript");
09300 }
09301
09308 function &createTestSession()
09309 {
09310 global $ilUser;
09311
09312 include_once "./Modules/Test/classes/class.ilTestSession.php";
09313 $testSession = FALSE;
09314 $testSession = new ilTestSession();
09315 $testSession->setTestId($this->getTestId());
09316 $testSession->setUserId($ilUser->getId());
09317 $testSession->setAnonymousId($_SESSION["tst_access_code"][$this->getTestId()]);
09318 $testSession->saveToDb();
09319 $this->testSession =& $testSession;
09320 return $this->testSession;
09321 }
09322
09330 function &setTestSession($active_id = "")
09331 {
09332 if (is_object($this->testSession) && ($this->testSession->getActiveId() > 0)) return $this->testSession;
09333
09334 global $ilUser;
09335
09336 include_once "./Modules/Test/classes/class.ilTestSession.php";
09337 $testSession = FALSE;
09338 if ($active_id > 0)
09339 {
09340 $testSession = new ilTestSession($active_id);
09341 }
09342 else
09343 {
09344 $testSession = new ilTestSession();
09345 $testSession->loadTestSession($this->getTestId(), $ilUser->getId(), $_SESSION["tst_access_code"][$this->getTestId()]);
09346 }
09347 $this->testSession =& $testSession;
09348 return $this->testSession;
09349 }
09350
09357 function &getTestSession($active_id = "")
09358 {
09359 if (is_object($this->testSession) && ($this->testSession->getActiveId() > 0)) return $this->testSession;
09360 return $this->setTestSession($active_id);
09361 }
09362
09363 function &createTestSequence($active_id, $pass, $shuffle)
09364 {
09365 include_once "./Modules/Test/classes/class.ilTestSequence.php";
09366 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
09367 if (!$this->testSequence->hasSequence())
09368 {
09369 $this->testSequence->createNewSequence($this->getQuestionCount(), $shuffle);
09370 $this->testSequence->saveToDb();
09371 }
09372 }
09373
09374 function &getTestSequence($active_id = "", $pass = "")
09375 {
09376 if (is_object($this->testSequence) && ($this->testSequence->getActiveId() > 0)) return $this->testSequence;
09377
09378 include_once "./Modules/Test/classes/class.ilTestSequence.php";
09379 if (($active_id > 0) && (strlen($pass)))
09380 {
09381 $this->testSequence = new ilTestSequence($active_id, $pass, $this->isRandomTest());
09382 }
09383 else
09384 {
09385 $this->testSequence = new ilTestSequence($this->getTestSession()->getActiveId(), $this->getTestSession()->getPass(), $this->isRandomTest());
09386 }
09387 return $this->testSequence;
09388 }
09389
09390 function hideCorrectAnsweredQuestions()
09391 {
09392 if ($this->getTestSession()->getActiveId() > 0)
09393 {
09394 $result = $this->getTestResult($this->getTestSession()->getActiveId(), $this->getTestSession()->getPass(), TRUE);
09395 foreach ($result as $sequence => $question)
09396 {
09397 if (is_numeric($sequence))
09398 {
09399 if ($question["reached"] == $question["max"])
09400 {
09401 $this->getTestSequence()->hideQuestion($question["qid"]);
09402 }
09403 }
09404 }
09405 $this->getTestSequence()->saveToDb();
09406 }
09407 }
09408
09412 function _lookupTestObjIdForQuestionId($a_q_id)
09413 {
09414 global $ilDB;
09415
09416 $set = $ilDB->query("SELECT t.obj_fi AS obj_id FROM tst_test_question AS q, tst_tests AS t WHERE".
09417 " q.test_fi = t.test_id AND q.question_fi = ".$ilDB->quote($a_q_id));
09418 $rec = $set->fetchRow(DB_FETCHMODE_ASSOC);
09419 return $rec["obj_id"];
09420 }
09421
09429 function canShowCertificate($user_id, $active_id)
09430 {
09431 if ($this->canShowTestResults($user_id))
09432 {
09433 $counted_pass = ilObjTest::_getResultPass($active_id);
09434 $result_array =& $this->getTestResult($active_id, $counted_pass);
09435
09436 include_once "./Modules/Test/classes/class.ilTestCertificate.php";
09437 $cert = new ilTestCertificate($this);
09438 if ($cert->isComplete())
09439 {
09440 $vis = $this->getCertificateVisibility();
09441 $showcert = FALSE;
09442 switch ($vis)
09443 {
09444 case 0:
09445 $showcert = TRUE;
09446 break;
09447 case 1:
09448 if ($result_array["test"]["passed"] == 1)
09449 {
09450 $showcert = TRUE;
09451 }
09452 break;
09453 case 2:
09454 $showcert = FALSE;
09455 break;
09456 }
09457 if ($showcert)
09458 {
09459 return TRUE;
09460 }
09461 else
09462 {
09463 return FALSE;
09464 }
09465 }
09466 else
09467 {
09468 return FALSE;
09469 }
09470 }
09471 else
09472 {
09473 return FALSE;
09474 }
09475 }
09476 }
09477
09478 ?>