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

Generated on Fri Dec 13 2013 08:00:13 for ILIAS Release_3_3_x_branch .rev 46803 by  doxygen 1.7.1