• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

assessment/classes/class.ilObjTest.php

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

Generated on Fri Dec 13 2013 10:18:26 for ILIAS Release_3_5_x_branch .rev 46805 by  doxygen 1.7.1