• Main Page
  • Related Pages
  • Modules
  • 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 include_once "./classes/class.ilObject.php";
00036 include_once "./assessment/classes/inc.AssessmentConstants.php";
00037 
00038 class ilObjTest extends ilObject
00039 {
00047   var $test_id;
00048 
00056         var $invitation = INVITATION_OFF;
00057 
00058 
00067   var $author;
00068 
00076   var $metadata;
00077 
00085   var $questions;
00086 
00095   var $introduction;
00096 
00104   var $mark_schema;
00105 
00115   var $sequence_settings;
00116 
00128   var $score_reporting;
00129 
00139         var $instant_verification;
00140 
00151   var $reporting_date;
00152 
00160   var $evaluation_data;
00161 
00169   var $test_type;
00170 
00179   var $nr_of_tries;
00180 
00189         var $hide_previous_results;
00190 
00198   var $hide_title_points;
00199 
00207   var $processing_time;
00208 
00216         var $enable_processing_time;
00217 
00225   var $starting_time;
00226 
00234   var $ending_time;
00235 
00243   var $ects_output;
00244 
00252   var $ects_fx;
00253 
00264         var $test_types;
00265 
00273   var $ects_grades;
00274 
00284         var $random_test;
00285 
00293         var $random_question_count;
00294 
00301         var $count_system;
00302 
00308         var $mc_scoring;
00309 
00315         var $pass_scoring;
00316 
00323         var $shuffle_questions;
00324 
00331         var $show_solution_details;
00332 
00338         var $show_summary;
00339 
00346         var $show_solution_printview;
00347 
00353         var $score_cutting;
00354 
00360         var $password;
00361 
00367         var $allowedUsers;
00368 
00374         var $allowedUsersTimeGap;
00375 
00382         function ilObjTest($a_id = 0,$a_call_by_reference = true)
00383         {
00384                 global $ilUser;
00385                 $this->type = "tst";
00386                 include_once "./assessment/classes/class.assMarkSchema.php";
00387                 $this->mark_schema = new ASS_MarkSchema();
00388                 //$this->ilObject($a_id, $a_call_by_reference);
00389                 $this->retrieveTestTypes();
00390                 $this->test_id = -1;
00391                 $this->author = $ilUser->fullname;
00392                 $this->introduction = "";
00393                 $this->questions = array();
00394                 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00395                 $this->score_reporting = REPORT_AFTER_TEST;
00396                 $this->instant_verification = 0;
00397                 $this->reporting_date = "";
00398                 $this->nr_of_tries = 0;
00399                 $this->hide_previous_results = 0;
00400                 $this->hide_title_points = 0;
00401                 $this->starting_time = "";
00402                 $this->ending_time = "";
00403                 $this->processing_time = "00:00:00";
00404                 $this->enable_processing_time = "0";
00405                 $this->test_type = TYPE_ASSESSMENT;
00406                 $this->ects_output = 0;
00407                 $this->ects_fx = "";
00408                 $this->random_test = 0;
00409                 $this->shuffle_questions = FALSE;
00410                 $this->show_solution_details = TRUE;
00411                 $this->show_summary = FALSE;
00412                 $this->show_solution_printview = FALSE;
00413                 $this->random_question_count = "";
00414                 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
00415                 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
00416                 $this->score_cutting = SCORE_CUT_QUESTION;
00417                 $this->pass_scoring = SCORE_LAST_PASS;
00418                 $this->password = "";
00419                 $this->allowedUsers = "";
00420                 $this->allowedUsersTimeGap = "";
00421                 global $lng;
00422                 $lng->loadLanguageModule("assessment");
00423                 $this->mark_schema->createSimpleSchema($lng->txt("failed_short"), $lng->txt("failed_official"), 0, 0, $lng->txt("passed_short"), $lng->txt("passed_official"), 50, 1);
00424                 $this->ects_grades = array(
00425                         "A" => 90,
00426                         "B" => 65,
00427                         "C" => 35,
00428                         "D" => 10,
00429                         "E" => 0
00430                 );
00431                 $this->ilObject($a_id, $a_call_by_reference);
00432         }
00433 
00437         function create($a_upload = false)
00438         {
00439                 parent::create();
00440 
00441                 // meta data will be created by
00442                 // import parser
00443                 if (!$a_upload)
00444                 {
00445                         $this->createMetaData();
00446                 }
00447         }
00448 
00455         function update()
00456         {
00457                 $this->updateMetaData();
00458                 if (!parent::update())
00459                 {
00460                         return false;
00461                 }
00462 
00463                 // put here object specific stuff
00464 
00465                 return true;
00466         }
00467 
00476         function createReference() {
00477                 $result = parent::createReference();
00478                 $this->saveToDb();
00479                 return $result;
00480         }
00481 
00487         function read($a_force_db = false)
00488         {
00489                 parent::read($a_force_db);
00490                 $this->loadFromDb();
00491         }
00492 
00500         function ilClone($a_parent_ref)
00501         {
00502                 global $rbacadmin;
00503 
00504                 // always call parent ilClone function first!!
00505                 $new_ref_id = parent::ilClone($a_parent_ref);
00506 
00507                 // get object instance of ilCloned object
00508                 //$newObj =& $this->ilias->obj_factory->getInstanceByRefId($new_ref_id);
00509 
00510                 // create a local role folder & default roles
00511                 //$roles = $newObj->initDefaultRoles();
00512 
00513                 // ...finally assign role to creator of object
00514                 //$rbacadmin->assignUser($roles[0], $newObj->getOwner(), "n");
00515 
00516                 // always destroy objects in ilClone method because ilClone() is recursive and creates instances for each object in subtree!
00517                 //unset($newObj);
00518 
00519                 // ... and finally always return new reference ID!!
00520                 return $new_ref_id;
00521         }
00522 
00529         function delete()
00530         {
00531                 // always call parent delete function first!!
00532                 if (!parent::delete())
00533                 {
00534                         return false;
00535                 }
00536 
00537                 // delet meta data
00538                 $this->deleteMetaData();
00539 
00540                 //put here your module specific stuff
00541                 $this->deleteTest();
00542 
00543                 return true;
00544         }
00545 
00553         function deleteTest()
00554         {
00555                 global $ilDB;
00556 
00557                 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00558                         $ilDB->quote($this->getTestId())
00559                 );
00560                 $result = $ilDB->query($query);
00561                 $active_array = array();
00562                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00563                 {
00564                         array_push($active_array, $row["active_id"]);
00565                 }
00566 
00567                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00568                         $ilDB->quote($this->getTestId())
00569                 );
00570                 $result = $ilDB->query($query);
00571 
00572                 if (count($active_array))
00573                 {
00574                         foreach ($active_array as $active_id)
00575                         {
00576                                 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00577                                         $ilDB->quote($active_id)
00578                                 );
00579                                 $result = $ilDB->query($query);
00580                         }
00581                 }
00582 
00583                 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00584                         $ilDB->quote($this->getTestId())
00585                 );
00586                 $result = $ilDB->query($query);
00587 
00588                 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00589                         $ilDB->quote($this->getTestId())
00590                 );
00591                 $result = $ilDB->query($query);
00592                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00593                 {
00594                         $this->removeQuestion($row->question_fi);
00595                 }
00596 
00597                 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00598                         $ilDB->quote($this->getTestId())
00599                 );
00600                 $result = $ilDB->query($query);
00601 
00602                 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00603                         $ilDB->quote($this->getTestId())
00604                 );
00605                 $result = $ilDB->query($query);
00606 
00607                 $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_random_question.active_fi",
00608                         $ilDB->quote($this->getTestId())
00609                 );
00610                 $result = $ilDB->query($query);
00611 
00612                 $this->removeAllTestEditings();
00613 
00614                 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00615                         $ilDB->quote($this->getTestId())
00616                 );
00617                 $result = $ilDB->query($query);
00618 
00619                 // delete export files
00620                 include_once "./classes/class.ilUtil.php";
00621                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00622                 $directory = $tst_data_dir."/tst_".$this->getId();
00623                 if (is_dir($directory))
00624                 {
00625                         include_once "./classes/class.ilUtil.php";
00626                         ilUtil::delDir($directory);
00627                 }
00628                 include_once("./content/classes/Media/class.ilObjMediaObject.php");
00629                 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
00630                 // remaining usages are not in text anymore -> delete them
00631                 // and media objects (note: delete method of ilObjMediaObject
00632                 // checks whether object is used in another context; if yes,
00633                 // the object is not deleted!)
00634                 foreach($mobs as $mob)
00635                 {
00636                         ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
00637                         $mob_obj =& new ilObjMediaObject($mob);
00638                         $mob_obj->delete();
00639                 }
00640         }
00641 
00651         function initDefaultRoles()
00652         {
00653                 global $rbacadmin;
00654 
00655                 // create a local role folder
00656                 //$rfoldObj = $this->createRoleFolder("Local roles","Role Folder of forum obj_no.".$this->getId());
00657 
00658                 // create moderator role and assign role to rolefolder...
00659                 //$roleObj = $rfoldObj->createRole("Moderator","Moderator of forum obj_no.".$this->getId());
00660                 //$roles[] = $roleObj->getId();
00661 
00662                 //unset($rfoldObj);
00663                 //unset($roleObj);
00664 
00665                 return $roles ? $roles : array();
00666         }
00667 
00681         function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00682         {
00683                 global $tree;
00684 
00685                 switch ($a_event)
00686                 {
00687                         case "link":
00688 
00689                                 //var_dump("<pre>",$a_params,"</pre>");
00690                                 //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
00691                                 //exit;
00692                                 break;
00693 
00694                         case "cut":
00695 
00696                                 //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
00697                                 //exit;
00698                                 break;
00699 
00700                         case "copy":
00701 
00702                                 //var_dump("<pre>",$a_params,"</pre>");
00703                                 //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
00704                                 //exit;
00705                                 break;
00706 
00707                         case "paste":
00708 
00709                                 //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
00710                                 //exit;
00711                                 break;
00712 
00713                         case "new":
00714 
00715                                 //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
00716                                 //exit;
00717                                 break;
00718                 }
00719 
00720                 // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
00721                 if ($a_node_id==$_GET["ref_id"])
00722                 {
00723                         $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00724                         $parent_type = $parent_obj->getType();
00725                         if($parent_type == $this->getType())
00726                         {
00727                                 $a_node_id = (int) $tree->getParentId($a_node_id);
00728                         }
00729                 }
00730 
00731                 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00732         }
00733 
00739         function createExportDirectory()
00740         {
00741                 include_once "./classes/class.ilUtil.php";
00742                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00743                 ilUtil::makeDir($tst_data_dir);
00744                 if(!is_writable($tst_data_dir))
00745                 {
00746                         $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00747                                 .") not writeable.",$this->ilias->error_obj->MESSAGE);
00748                 }
00749 
00750                 // create learning module directory (data_dir/lm_data/lm_<id>)
00751                 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00752                 ilUtil::makeDir($tst_dir);
00753                 if(!@is_dir($tst_dir))
00754                 {
00755                         $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
00756                 }
00757                 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
00758                 $export_dir = $tst_dir."/export";
00759                 ilUtil::makeDir($export_dir);
00760                 if(!@is_dir($export_dir))
00761                 {
00762                         $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
00763                 }
00764         }
00765 
00773         function getExportDirectory()
00774         {
00775                 include_once "./classes/class.ilUtil.php";
00776                 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00777                 return $export_dir;
00778         }
00779 
00788         function getExportFiles($dir)
00789         {
00790                 // quit if import dir not available
00791                 if (!@is_dir($dir) or
00792                         !is_writeable($dir))
00793                 {
00794                         return array();
00795                 }
00796 
00797                 // open directory
00798                 $dir = dir($dir);
00799 
00800                 // initialize array
00801                 $file = array();
00802 
00803                 // get files and save the in the array
00804                 while ($entry = $dir->read())
00805                 {
00806                         if ($entry != "." and
00807                                 $entry != ".." and
00808                                 //substr($entry, -4) == ".zip" and
00809                                 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test(__results)?__)*[0-9]+\.[a-z]{1,3}\$", $entry))
00810                         {
00811                                 $file[] = $entry;
00812                         }
00813                 }
00814 
00815                 // close import directory
00816                 $dir->close();
00817 
00818                 // sort files
00819                 sort ($file);
00820                 reset ($file);
00821 
00822                 return $file;
00823         }
00824 
00825 
00831         function _createImportDirectory()
00832         {
00833                 global $ilias;
00834 
00835                 include_once "./classes/class.ilUtil.php";
00836                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00837                 ilUtil::makeDir($tst_data_dir);
00838 
00839                 if(!is_writable($tst_data_dir))
00840                 {
00841                         $ilias->raiseError("Test data directory (".$tst_data_dir
00842                                 .") not writeable.",$ilias->error_obj->FATAL);
00843                 }
00844 
00845                 // create test directory (data_dir/tst_data/tst_import)
00846                 $tst_dir = $tst_data_dir."/tst_import";
00847                 ilUtil::makeDir($tst_dir);
00848                 if(!@is_dir($tst_dir))
00849                 {
00850                         $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00851                 }
00852         }
00853 
00862         function _getImportDirectory()
00863         {
00864                 include_once "./classes/class.ilUtil.php";
00865                 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00866                 if(@is_dir($import_dir))
00867                 {
00868                         return $import_dir;
00869                 }
00870                 else
00871                 {
00872                         return false;
00873                 }
00874         }
00875 
00881         function createImportDirectory()
00882         {
00883                 include_once "./classes/class.ilUtil.php";
00884                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00885                 ilUtil::makeDir($tst_data_dir);
00886 
00887                 if(!is_writable($tst_data_dir))
00888                 {
00889                         $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00890                                 .") not writeable.",$this->ilias->error_obj->FATAL);
00891                 }
00892 
00893                 // create test directory (data_dir/tst_data/tst_import)
00894                 $tst_dir = $tst_data_dir."/tst_import";
00895                 ilUtil::makeDir($tst_dir);
00896                 if(!@is_dir($tst_dir))
00897                 {
00898                         $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00899                 }
00900         }
00901 
00910         function getImportDirectory()
00911         {
00912                 include_once "./classes/class.ilUtil.php";
00913                 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00914                 if(@is_dir($import_dir))
00915                 {
00916                         return $import_dir;
00917                 }
00918                 else
00919                 {
00920                         return false;
00921                 }
00922         }
00923 
00924 
00934         function retrieveTestTypes()
00935         {
00936                 global $ilDB;
00937 
00938                 $this->test_types = array();
00939                 $query = "SELECT * FROM tst_test_type ORDER BY test_type_id";
00940                 $result = $ilDB->query($query);
00941                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00942                 {
00943                         $this->test_types[$row->test_type_id] = $row->type_tag;
00944                 }
00945         }
00946 
00956   function testTitleExists($title)
00957         {
00958                 global $ilDB;
00959 
00960     $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00961       $ilDB->quote($title),
00962                         $ilDB->quote("tst")
00963     );
00964     $result = $ilDB->query($query);
00965     if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00966       if ($result->numRows() == 1) {
00967         return TRUE;
00968       }
00969     }
00970     return FALSE;
00971   }
00972 
00980   function duplicate()
00981         {
00982                 global $ilDB;
00983 
00984     $clone = $this;
00985     $clone->setId(-1);
00986     $counter = 2;
00987     while ($this->testTitleExists($this->get_title() . " ($counter)")) {
00988       $counter++;
00989     }
00990     $clone->setTitle($this->get_title() . " ($counter)");
00991     $clone->setOwner($this->ilias->account->id);
00992     $clone->setAuthor($this->ilias->account->fullname);
00993     $clone->saveToDb($ilDB);
00994     // Duplicate questions
00995     $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi = %s",
00996       $ilDB->quote($this->getId())
00997     );
00998     $result = $ilDB->query($query);
00999     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01000       $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01001         $ilDB->quote($clone->getId()),
01002         $ilDB->quote($data->question_fi),
01003         $ilDB->quote($data->sequence)
01004       );
01005       $insert_result = $ilDB->query($query);
01006     }
01007   }
01008 
01017         function isComplete()
01018         {
01019                 if (($this->getTitle()) and ($this->author) and (count($this->mark_schema->mark_steps)) and (count($this->questions)))
01020                 {
01021                         return true;
01022                 }
01023                         else
01024                 {
01025                         if ($this->isRandomTest())
01026                         {
01027                                 $arr = $this->getRandomQuestionpools();
01028                                 if (count($arr) && ($this->getRandomQuestionCount() > 0))
01029                                 {
01030                                         return true;
01031                                 }
01032                                 $count = 0;
01033                                 foreach ($arr as $array)
01034                                 {
01035                                         $count += $array["count"];
01036                                 }
01037                                 if ($count)
01038                                 {
01039                                         return true;
01040                                 }
01041                         }
01042                         return false;
01043                 }
01044         }
01045 
01054         function _isComplete($obj_id)
01055         {
01056                 $test = new ilObjTest($obj_id, false);
01057                 $test->loadFromDb();
01058                 return $test->isComplete();
01059         }
01060 
01068         function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
01069         {
01070     global $ilDB;
01071     if ($this->test_id > 0) {
01072                         $fx_support = preg_replace("/,/", ".", $fx_support);
01073                         if (preg_match("/\d+/", $fx_support))
01074                         {
01075                                 $fx_support = $fx_support;
01076                         }
01077                         else
01078                         {
01079                                 $fx_support = "NULL";
01080                         }
01081       $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",
01082                                 $ilDB->quote("$ects_output"),
01083                                 $ilDB->quote($ects_a . ""),
01084                                 $ilDB->quote($ects_b . ""),
01085                                 $ilDB->quote($ects_c . ""),
01086                                 $ilDB->quote($ects_d . ""),
01087                                 $ilDB->quote($ects_e . ""),
01088         $fx_support,
01089                                 $this->getTestId()
01090       );
01091       $result = $ilDB->query($query);
01092                         $this->ects_output = $ects_output;
01093                         $this->ects_fx = $fx_support;
01094                 }
01095         }
01096 
01104         function saveCompleteStatus()
01105         {
01106     global $ilDB;
01107 
01108                 $complete = 0;
01109                 if ($this->isComplete()) {
01110                         $complete = 1;
01111                 }
01112     if ($this->test_id > 0) {
01113       $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
01114                                 $ilDB->quote("$complete"),
01115         $ilDB->quote($this->test_id)
01116       );
01117       $result = $ilDB->query($query);
01118                 }
01119         }
01120 
01129   function saveToDb($properties_only = FALSE)
01130   {
01131     global $ilDB;
01132 
01133                 $complete = 0;
01134                 if ($this->isComplete()) {
01135                         $complete = 1;
01136                 }
01137                 $ects_fx = "NULL";
01138                 if (preg_match("/\d+/", $this->ects_fx))
01139                 {
01140                         $ects_fx = $this->ects_fx;
01141                 }
01142                 $random_question_count = "NULL";
01143                 if ($this->random_question_count > 0)
01144                 {
01145                         $random_question_count = $ilDB->quote($this->random_question_count . "");
01146                 }
01147                 $shuffle_questions = 0;
01148                 if ($this->getShuffleQuestions())
01149                 {
01150                         $shuffle_questions = 1;
01151                 }
01152                 $show_solution_details = 0;
01153                 if ($this->getShowSolutionDetails())
01154                 {
01155                         $show_solution_details = 1;
01156                 }
01157                 $show_summary = 0;
01158                 if ($this->getShowSummary())
01159                 {
01160                         $show_summary = 1;
01161                 }
01162                 $show_solution_printview = 0;
01163                 if ($this->getShowSolutionPrintview())
01164                 {
01165                         $show_solution_printview = 1;
01166                 }
01167                 $allowedUsers = $this->getAllowedUsers();
01168                 if ($allowedUsers == 0)
01169                 {
01170                         $allowedUsers = "NULL";
01171                 }
01172                 else
01173                 {
01174                         $allowedUsers = $ilDB->quote($allowedUsers);
01175                 }
01176                 $allowedUsersTimeGap = $this->getAllowedUsersTimeGap();
01177                 if ($allowedUsersTimeGap == 0)
01178                 {
01179                         $allowedUsersTimeGap = "NULL";
01180                 }
01181                 else
01182                 {
01183                         $allowedUsersTimeGap = $ilDB->quote($allowedUsersTimeGap);
01184                 }
01185 
01186                 // cleanup RTE images which are not inserted into the question text
01187                 include_once("./Services/RTE/classes/class.ilRTE.php");
01188                 ilRTE::_cleanupMediaObjectUsage($this->introduction, $this->getType() . ":html",
01189                         $this->getId());
01190 
01191                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01192     if ($this->test_id == -1)
01193                 {
01194       // Create new dataset
01195       $now = getdate();
01196       $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
01197       $query = sprintf("INSERT INTO tst_tests (test_id, obj_fi, author, test_type_fi, introduction, sequence_settings, score_reporting, instant_verification, nr_of_tries, hide_previous_results, hide_title_points, processing_time, enable_processing_time, reporting_date, starting_time, ending_time, complete, ects_output, ects_a, ects_b, ects_c, ects_d, ects_e, ects_fx, random_test, random_question_count, count_system, mc_scoring, score_cutting, pass_scoring, shuffle_questions, show_solution_details, show_summary, show_solution_printview, password, allowedUsers, allowedUsersTimeGap, created, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01198                                 $ilDB->quote($this->getId() . ""),
01199                                 $ilDB->quote($this->author . ""),
01200                                 $ilDB->quote($this->test_type . ""),
01201                                 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01202                                 $ilDB->quote($this->sequence_settings . ""),
01203                                 $ilDB->quote($this->score_reporting . ""),
01204                                 $ilDB->quote($this->instant_verification . ""),
01205                                 $ilDB->quote(sprintf("%d", $this->nr_of_tries) . ""),
01206                                 $ilDB->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01207                                 $ilDB->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01208                                 $ilDB->quote($this->processing_time . ""),
01209                                 $ilDB->quote("$this->enable_processing_time"),
01210                                 $ilDB->quote($this->reporting_date . ""),
01211                                 $ilDB->quote($this->starting_time . ""),
01212                                 $ilDB->quote($this->ending_time . ""),
01213                                 $ilDB->quote("$complete"),
01214                                 $ilDB->quote($this->ects_output . ""),
01215                                 $ilDB->quote($this->ects_grades["A"] . ""),
01216                                 $ilDB->quote($this->ects_grades["B"] . ""),
01217                                 $ilDB->quote($this->ects_grades["C"] . ""),
01218                                 $ilDB->quote($this->ects_grades["D"] . ""),
01219                                 $ilDB->quote($this->ects_grades["E"] . ""),
01220                                 $ects_fx,
01221                                 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01222                                 $random_question_count,
01223                                 $ilDB->quote($this->count_system . ""),
01224                                 $ilDB->quote($this->mc_scoring . ""),
01225                                 $ilDB->quote($this->getScoreCutting() . ""),
01226                                 $ilDB->quote($this->getPassScoring() . ""),
01227                                 $ilDB->quote($shuffle_questions . ""),
01228                                 $ilDB->quote($show_solution_details . ""),
01229                                 $ilDB->quote($show_summary . ""),
01230                                 $ilDB->quote($show_solution_printview . ""),
01231                                 $ilDB->quote($this->getPassword() . ""),
01232                                 $allowedUsers,
01233                                 $allowedUsersTimeGap,
01234                                 $ilDB->quote($created)
01235       );
01236 
01237                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01238                         {
01239                                 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
01240                         }
01241       $result = $ilDB->query($query);
01242       if ($result == DB_OK) {
01243         $this->test_id = $ilDB->getLastInsertId();
01244       }
01245     }
01246                 else
01247                 {
01248       // Modify existing dataset
01249                         $oldrow = array();
01250                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01251                         {
01252                                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01253                 $ilDB->quote($this->test_id)
01254                                 );
01255                                 $result = $ilDB->query($query);
01256                                 if ($result->numRows() == 1)
01257                                 {
01258                                         $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01259                                 }
01260                         }
01261       $query = sprintf("UPDATE tst_tests SET author = %s, test_type_fi = %s, introduction = %s, sequence_settings = %s, score_reporting = %s, instant_verification = %s, nr_of_tries = %s, hide_previous_results = %s, hide_title_points = %s, processing_time = %s, enable_processing_time = %s, reporting_date = %s, starting_time = %s, ending_time = %s, ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s, random_test = %s, complete = %s, count_system = %s, mc_scoring = %s, score_cutting = %s, pass_scoring = %s, shuffle_questions = %s, show_solution_details = %s, show_summary = %s, show_solution_printview = %s, password = %s, allowedUsers = %s, allowedUsersTimeGap = %s WHERE test_id = %s",
01262         $ilDB->quote($this->author . ""),
01263         $ilDB->quote($this->test_type . ""),
01264                                 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01265         $ilDB->quote($this->sequence_settings . ""),
01266         $ilDB->quote($this->score_reporting . ""),
01267         $ilDB->quote($this->instant_verification . ""),
01268         $ilDB->quote(sprintf("%d", $this->nr_of_tries) . ""),
01269                                 $ilDB->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01270                                 $ilDB->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01271         $ilDB->quote($this->processing_time . ""),
01272                                 $ilDB->quote("$this->enable_processing_time"),
01273         $ilDB->quote($this->reporting_date . ""),
01274         $ilDB->quote($this->starting_time . ""),
01275         $ilDB->quote($this->ending_time . ""),
01276                                 $ilDB->quote($this->ects_output . ""),
01277                                 $ilDB->quote($this->ects_grades["A"] . ""),
01278                                 $ilDB->quote($this->ects_grades["B"] . ""),
01279                                 $ilDB->quote($this->ects_grades["C"] . ""),
01280                                 $ilDB->quote($this->ects_grades["D"] . ""),
01281                                 $ilDB->quote($this->ects_grades["E"] . ""),
01282                                 $ects_fx,
01283                                 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01284                                 $ilDB->quote("$complete"),
01285                                 $ilDB->quote($this->count_system . ""),
01286                                 $ilDB->quote($this->mc_scoring . ""),
01287                                 $ilDB->quote($this->getScoreCutting() . ""),
01288                                 $ilDB->quote($this->getPassScoring() . ""),
01289                                 $ilDB->quote($shuffle_questions . ""),
01290                                 $ilDB->quote($show_solution_details . ""),
01291                                 $ilDB->quote($show_summary . ""),
01292                                 $ilDB->quote($show_solution_printview . ""),
01293                                 $ilDB->quote($this->getPassword() . ""),
01294                                 $allowedUsers,
01295                                 $allowedUsersTimeGap,
01296         $ilDB->quote($this->test_id)
01297       );
01298             $result = $ilDB->query($query);
01299                         include_once ("./classes/class.ilObjAssessmentFolder.php");
01300                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01301                         {
01302                                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01303                 $ilDB->quote($this->test_id)
01304                                 );
01305                                 $logresult = $ilDB->query($query);
01306                                 $newrow = array();
01307                                 if ($logresult->numRows() == 1)
01308                                 {
01309                                         $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01310                                 }
01311                                 $changed_fields = array();
01312                                 foreach ($oldrow as $key => $value)
01313                                 {
01314                                         if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01315                                         {
01316                                                 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01317                                         }
01318                                 }
01319                                 $changes = join($changed_fields, ", ");
01320                                 if (count($changed_fields) == 0)
01321                                 {
01322                                         $changes = $this->lng->txtlng("assessment", "log_no_test_fields_changed", ilObjAssessmentFolder::_getLogLanguage());
01323                                 }
01324                                 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
01325                         }
01326     }
01327                 if (!$properties_only)
01328                 {
01329                         if ($result == DB_OK) {
01330                                 if (!$this->isRandomTest())
01331                                 {
01332                                         $this->saveQuestionsToDb();
01333                                 }
01334                                 $this->mark_schema->saveToDb($this->test_id);
01335                         }
01336                 }
01337   }
01338 
01347         function saveQuestionsToDb()
01348         {
01349                 global $ilDB;
01350 
01351                 $oldquestions = array();
01352                 include_once "./classes/class.ilObjAssessmentFolder.php";
01353                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01354                 {
01355                         $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01356                                 $ilDB->quote($this->getTestId())
01357                         );
01358                         $result = $ilDB->query($query);
01359                         if ($result->numRows() > 0)
01360                         {
01361                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01362                                 {
01363                                         array_push($oldquestions, $row["question_fi"]);
01364                                 }
01365                         }
01366                 }
01367 
01368                 // delete existing category relations
01369     $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01370                         $ilDB->quote($this->getTestId())
01371                 );
01372                 $result = $ilDB->query($query);
01373                 // create new category relations
01374                 foreach ($this->questions as $key => $value) {
01375                         $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01376                                 $ilDB->quote($this->getTestId() . ""),
01377                                 $ilDB->quote($value . ""),
01378                                 $ilDB->quote($key . "")
01379                         );
01380                         $result = $ilDB->query($query);
01381                 }
01382                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01383                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01384                 {
01385                         $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01386                                 $ilDB->quote($this->getTestId())
01387                         );
01388                         $result = $ilDB->query($query);
01389                         $newquestions = array();
01390                         if ($result->numRows() > 0)
01391                         {
01392                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01393                                 {
01394                                         array_push($newquestions, $row["question_fi"]);
01395                                 }
01396                         }
01397                         foreach ($oldquestions as $index => $question_id)
01398                         {
01399                                 if (strcmp($newquestions[$index], $question_id) != 0)
01400                                 {
01401                                         $pos = array_search($question_id, $newquestions);
01402                                         if ($pos === FALSE)
01403                                         {
01404                                                 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
01405                                         }
01406                                         else
01407                                         {
01408                                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01409                                         }
01410                                 }
01411                         }
01412                         foreach ($newquestions as $index => $question_id)
01413                         {
01414                                 if (array_search($question_id, $oldquestions) === FALSE)
01415                                 {
01416                                         $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
01417                                 }
01418                         }
01419                 }
01420         }
01421 
01430         function saveRandomQuestion($active_id, $question_id, $pass = NULL, $maxcount)
01431         {
01432                 global $ilUser;
01433                 global $ilDB;
01434 
01435                 if (is_null($pass)) $pass = 0;
01436                 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE active_fi = %s AND pass = %s",
01437                         $ilDB->quote($active_id . ""),
01438                         $ilDB->quote($pass . "")
01439                 );
01440                 $result = $ilDB->query($query);
01441                 if ($result->numRows() < $maxcount)
01442                 {
01443                         $duplicate_id = $this->getRandomQuestionDuplicate($question_id, $active->active_id);
01444                         if ($duplicate_id === FALSE)
01445                         {
01446                                 $duplicate_id = $this->duplicateQuestionForTest($question_id);
01447                         }
01448 
01449                         $query = sprintf("INSERT INTO tst_test_random_question (test_random_question_id, active_fi, question_fi, sequence, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
01450                                 $ilDB->quote($active_id . ""),
01451                                 $ilDB->quote($duplicate_id . ""),
01452                                 $ilDB->quote(($result->numRows()+1) . ""),
01453                                 $ilDB->quote($pass . "")
01454                         );
01455                         $result = $ilDB->query($query);
01456                 }
01457         }
01458 
01470         function getRandomQuestionDuplicate($question_id, $active_id)
01471         {
01472                 global $ilDB;
01473 
01474                 $query = sprintf("SELECT qpl_questions.question_id FROM qpl_questions, tst_test_random_question WHERE qpl_questions.original_id = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.active_fi = %s",
01475                         $ilDB->quote($question_id . ""),
01476                         $ilDB->quote($active_id . "")
01477                 );
01478                 $result = $ilDB->query($query);
01479                 $num = $result->numRows();
01480                 if ($num > 0)
01481                 {
01482                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01483                         return $row["question_id"];
01484                 }
01485                 else
01486                 {
01487                         return FALSE;
01488                 }
01489         }
01490 
01498         function getNrOfResultsForPass($active_id, $pass)
01499         {
01500                 global $ilDB;
01501 
01502                 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
01503                         $ilDB->quote($active_id . ""),
01504                         $ilDB->quote($pass . "")
01505                 );
01506                 $result = $ilDB->query($query);
01507                 return $result->numRows();
01508         }
01509 
01518         function generateRandomQuestions($pass = NULL)
01519         {
01520                 global $ilUser;
01521                 $active = $this->getActiveTestUser($ilUser->getId());
01522                 $active_id = 0;
01523                 if (is_object($active))
01524                 {
01525                         $active_id = $active->active_id;
01526                         $this->loadQuestions($active_id, $pass);
01527                         if (count($this->questions) > 0)
01528                         {
01529                                 // Something went wrong. Maybe the user pressed the start button twice
01530                                 // Questions already exist so there is no need to create new questions
01531                                 return;
01532                         }
01533                         if ($pass > 0)
01534                         {
01535                                 if ($this->getNrOfResultsForPass($active_id, $pass - 1) == 0)
01536                                 {
01537                                         // This means that someone maybe reloaded the test submission page
01538                                         // If there are no existing results for the previous test, it makes
01539                                         // no sense to create a new set of random questions
01540                                         return;
01541                                 }
01542                         }
01543                 }
01544                 else
01545                 {
01546                         $active_id = $this->setActiveTestUser();
01547                 }
01548                 if ($active_id == 0)
01549                 {
01550                         // This may not happen! If it happens, raise a fatal error...
01551                         global $ilias, $ilErr;
01552                         $ilias->raiseError(sprintf($this->lng->txt("error_random_question_generation"), $ilUser->getId(), $this->getTestId()), $ilErr->FATAL);
01553                 }
01554                 $num = $this->getRandomQuestionCount();
01555                 if ($num > 0)
01556                 {
01557                         $qpls =& $this->getRandomQuestionpools();
01558                         $rndquestions = $this->randomSelectQuestions($num, 0, 1, $qpls, $pass);
01559                         $allquestions = array();
01560                         foreach ($rndquestions as $question_id)
01561                         {
01562                                 array_push($allquestions, $question_id);
01563                         }
01564                         srand ((float)microtime()*1000000);
01565                         shuffle($allquestions);
01566 
01567                         $maxcount = 0;
01568                         foreach ($qpls as $data)
01569                         {
01570                                 $maxcount += $data["contains"];
01571                         }
01572                         if ($num > $maxcount) $num = $maxcount;
01573                         foreach ($allquestions as $question_id)
01574                         {
01575                                 $this->saveRandomQuestion($active_id, $question_id, $pass, $num);
01576                         }
01577                 }
01578                 else
01579                 {
01580                         $qpls =& $this->getRandomQuestionpools();
01581                         $allquestions = array();
01582                         $maxcount = 0;
01583                         foreach ($qpls as $key => $value)
01584                         {
01585                                 if ($value["count"] > 0)
01586                                 {
01587                                         $rndquestions = $this->randomSelectQuestions($value["count"], $value["qpl"], 1, $pass);
01588                                         foreach ($rndquestions as $question_id)
01589                                         {
01590                                                 array_push($allquestions, $question_id);
01591                                         }
01592                                 }
01593                                 $add = ($value["count"] <= $value["contains"]) ? $value["count"] : $value["contains"];
01594                                 $maxcount += $add;
01595                         }
01596                         srand ((float)microtime()*1000000);
01597                         shuffle($allquestions);
01598                         foreach ($allquestions as $question_id)
01599                         {
01600                                 $this->saveRandomQuestion($active_id, $question_id, $pass, $maxcount);
01601                         }
01602                 }
01603                 if (!is_object($active))
01604                 {
01605                         $active = $this->getActiveTestUser($ilUser->getId());
01606                 }
01607                 if (strlen($active->sequence) == 0)
01608                 {
01609                         $this->addQuestionSequence($active->active_id);
01610                 }
01611                 return;
01612         }
01613 
01622         function saveRandomQuestionCount($total_questions = "NULL")
01623         {
01624                 global $ilDB;
01625 
01626                 if (strcmp($total_questions, "NULL") != 0)
01627                 {
01628                         $this->setRandomQuestionCount($total_questions);
01629                         $total_questions = $ilDB->quote($total_questions);
01630                 }
01631                 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01632                         $total_questions,
01633                         $ilDB->quote($this->getTestId() . "")
01634                 );
01635                 $result = $ilDB->query($query);
01636                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01637                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01638                 {
01639                         if (strcmp($total_questions, "NULL") == 0) $total_questions = '0';
01640                         $this->logAction(sprintf($this->lng->txtlng("assessment", "log_total_amount_of_questions", ilObjAssessmentFolder::_getLogLanguage()), $total_questions));
01641                 }
01642         }
01643 
01653         function saveRandomQuestionpools($qpl_array)
01654         {
01655                 global $ilDB;
01656 
01657                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01658                 // delete existing random questionpools
01659     $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01660                         $ilDB->quote($this->getTestId())
01661                 );
01662                 $result = $ilDB->query($query);
01663                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01664                 {
01665                         $this->logAction($this->lng->txtlng("assessment", "log_random_question_pool_deleted", ilObjAssessmentFolder::_getLogLanguage()));
01666                 }
01667                 // create new random questionpools
01668                 foreach ($qpl_array as $key => $value) {
01669                         if ($value["qpl"] > -1)
01670                         {
01671                                 include_once "./assessment/classes/class.ilObjQuestionPool.php";
01672                                 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01673                                 if ($value["count"] > $count)
01674                                 {
01675                                         $value["count"] = $count;
01676                                 }
01677                                 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01678                                         $ilDB->quote($this->getTestId() . ""),
01679                                         $ilDB->quote($value["qpl"] . ""),
01680                                         $ilDB->quote(sprintf("%d", $value["count"]) . "")
01681                                 );
01682                                 $result = $ilDB->query($query);
01683                                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01684                                 {
01685                                         $this->logAction(sprintf($this->lng->txtlng("assessment", "log_random_question_pool_added", ilObjAssessmentFolder::_getLogLanguage()), $value["title"] . " (" . $value["qpl"] . ")", $value["count"]));
01686                                 }
01687                         }
01688                 }
01689         }
01690 
01700         function &getRandomQuestionpools()
01701         {
01702                 global $ilDB;
01703 
01704                 $qpls = array();
01705                 $counter = 0;
01706                 if ($ilDB->tableColumnExists("qpl_questionpool", "questioncount"))
01707                 {
01708                         $query = sprintf("SELECT tst_test_random.*, qpl_questionpool.questioncount FROM tst_test_random, qpl_questionpool WHERE tst_test_random.test_fi = %s AND tst_test_random.questionpool_fi = qpl_questionpool.obj_fi ORDER BY test_random_id",
01709                                 $ilDB->quote($this->getTestId() . "")
01710                         );
01711                         $result = $ilDB->query($query);
01712                         if ($result->numRows())
01713                         {
01714                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01715                                 {
01716                                         $qpls[$counter] = array(
01717                                                 "index" => $counter,
01718                                                 "count" => $row["num_of_q"],
01719                                                 "qpl"   => $row["questionpool_fi"],
01720                                                 "contains" => $row["questioncount"]
01721                                         );
01722                                         $counter++;
01723                                 }
01724                         }
01725                 }
01726                 else
01727                 {
01728                         $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
01729                                 $ilDB->quote($this->getTestId() . "")
01730                         );
01731                         $result = $ilDB->query($query);
01732                         if ($result->numRows())
01733                         {
01734                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01735                                 {
01736                                         $countquery = sprintf("SELECT question_id FROM qpl_questions WHERE obj_fi =  %s AND original_id IS NULL",
01737                                                 $ilDB->quote($row["questionpool_fi"] . "")
01738                                         );
01739                                         $countresult = $ilDB->query($countquery);
01740                                         $contains = $countresult->numRows();
01741                                         $qpls[$counter] = array(
01742                                                 "index" => $counter,
01743                                                 "count" => $row["num_of_q"],
01744                                                 "qpl"   => $row["questionpool_fi"],
01745                                                 "contains" => $contains
01746                                         );
01747                                         $counter++;
01748                                 }
01749                         }
01750                 }
01751                 return $qpls;
01752         }
01753 
01763         function loadFromDb()
01764         {
01765                 global $ilDB;
01766 
01767                 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01768                 $ilDB->quote($this->getId())
01769                         );
01770                 $result = $ilDB->query($query);
01771                 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01772                 {
01773                         if ($result->numRows() == 1)
01774                         {
01775                                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01776                                 $this->test_id = $data->test_id;
01777                                 $this->author = $data->author;
01778                                 $this->test_type = $data->test_type_fi;
01779                                 include_once("./Services/RTE/classes/class.ilRTE.php");
01780                                 $this->introduction = ilRTE::_replaceMediaObjectImageSrc($data->introduction, 1);
01781                                 $this->sequence_settings = $data->sequence_settings;
01782                                 $this->score_reporting = $data->score_reporting;
01783                                 $this->instant_verification = $data->instant_verification;
01784                                 $this->nr_of_tries = $data->nr_of_tries;
01785                                 $this->setHidePreviousResults($data->hide_previous_results);
01786                                 $this->setHideTitlePoints($data->hide_title_points);
01787                                 $this->processing_time = $data->processing_time;
01788                                 $this->enable_processing_time = $data->enable_processing_time;
01789                                 $this->reporting_date = $data->reporting_date;
01790                                 $this->setShuffleQuestions($data->shuffle_questions);
01791                                 $this->setShowSolutionDetails($data->show_solution_details);
01792                                 $this->setShowSummary($data->show_summary);
01793                                 $this->setShowSolutionPrintview($data->show_solution_printview);
01794                                 $this->starting_time = $data->starting_time;
01795                                 $this->ending_time = $data->ending_time;
01796                                 $this->ects_output = $data->ects_output;
01797                                 $this->ects_grades = array(
01798                                         "A" => $data->ects_a,
01799                                         "B" => $data->ects_b,
01800                                         "C" => $data->ects_c,
01801                                         "D" => $data->ects_d,
01802                                         "E" => $data->ects_e
01803                                 );
01804                                 $this->ects_fx = $data->ects_fx;
01805                                 $this->random_test = $data->random_test;
01806                                 $this->random_question_count = $data->random_question_count;
01807                                 $this->mark_schema->flush();
01808                                 $this->mark_schema->loadFromDb($this->test_id);
01809                                 $this->count_system = $data->count_system;
01810                                 $this->mc_scoring = $data->mc_scoring;
01811                                 $this->setScoreCutting($data->score_cutting);
01812                                 $this->setPassword($data->password);
01813                                 $this->setAllowedUsers($data->allowedUsers);
01814                                 $this->setAllowedUsersTimeGap($data->allowedUsersTimeGap);
01815                                 $this->setPassScoring($data->pass_scoring);
01816                                 $this->loadQuestions();
01817                         }
01818                 }
01819         }
01820 
01829         function loadQuestions($active_id = "", $pass = NULL)
01830         {
01831                 global $ilUser;
01832                 global $ilDB;
01833 
01834                 $this->questions = array();
01835                 if (strcmp($active_id, "") == 0)
01836                 {
01837                         $active = $this->getActiveTestUser($ilUser->getId());
01838                         $active_id = $active->active_id;
01839                 }
01840                 if ($this->isRandomTest())
01841                 {
01842                         if (is_null($pass))
01843                         {
01844                                 if ($this->getTestType() == TYPE_VARYING_RANDOMTEST)
01845                                 {
01846                                         $pass = $this->_getPass($active_id);
01847                                 }
01848                                 else
01849                                 {
01850                                         // normal random questions are created only once, for pass 0
01851                                         $pass = 0;
01852                                 }
01853                         }
01854                         $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = %s ORDER BY sequence",
01855                                 $ilDB->quote($active_id . ""),
01856                                 $ilDB->quote($pass . "")
01857                         );
01858                 }
01859                 else
01860                 {
01861                         $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",
01862                                 $ilDB->quote($this->test_id . "")
01863                         );
01864                 }
01865                 $result = $ilDB->query($query);
01866                 $index = 1;
01867                 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01868                 {
01869                         $this->questions[$index++] = $data->question_fi;
01870                 }
01871         }
01872 
01886         function &getQuestions($active_id = "", $pass = NULL, $userorder = FALSE)
01887         {
01888                 if ($active_id > 0)
01889                 {
01890                         if ($this->isRandomTest())
01891                         {
01892                                 $this->loadQuestions($active_id, $pass);
01893                         }
01894                         if ($userorder)
01895                         {
01896                                 $result_array = array();
01897                                 $active =& $this->getActiveTestUserFromActiveId($active_id);
01898                                 $sequence_array = split(",", $active->sequence);
01899                                 $index = 1;
01900                                 foreach ($sequence_array as $sequence)
01901                                 {
01902                                         $result_array[$index] = $this->questions[$sequence];
01903                                         $index++;
01904                                 }
01905                                 return $result_array;
01906                         }
01907                 }
01908                 return $this->questions;
01909         }
01910 
01920   function setAuthor($author = "")
01921         {
01922     $this->author = $author;
01923   }
01924 
01934   function setIntroduction($introduction = "")
01935         {
01936     $this->introduction = $introduction;
01937   }
01938 
01948   function getAuthor()
01949         {
01950     return $this->author;
01951   }
01952 
01962   function isRandomTest()
01963         {
01964     return $this->random_test;
01965   }
01966 
01976   function getRandomQuestionCount()
01977         {
01978     return $this->random_question_count;
01979   }
01980 
01990   function getIntroduction()
01991         {
01992     return $this->introduction;
01993   }
01994 
02004   function getTestId()
02005         {
02006     return $this->test_id;
02007   }
02008 
02018   function setSequenceSettings($sequence_settings = 0)
02019         {
02020     $this->sequence_settings = $sequence_settings;
02021   }
02022 
02032   function setTestType($type = TYPE_ASSESSMENT)
02033   {
02034     $this->test_type = $type;
02035   }
02036 
02046   function setScoreReporting($score_reporting = 0)
02047         {
02048     $this->score_reporting = $score_reporting;
02049   }
02050 
02060   function setInstantVerification($instant_verification = 0)
02061         {
02062                 switch ($instant_verification)
02063                 {
02064                         case 1:
02065                                 $this->instant_verification = 1;
02066                                 break;
02067                         default:
02068                                 $this->instant_verification = 0;
02069                                 break;
02070                 }
02071   }
02072 
02082   function setRandomTest($a_random_test = 0)
02083         {
02084     $this->random_test = $a_random_test;
02085   }
02086 
02096   function setRandomQuestionCount($a_random_question_count = "")
02097         {
02098     $this->random_question_count = $a_random_question_count;
02099   }
02100 
02110   function setReportingDate($reporting_date)
02111   {
02112                 if (!$reporting_date)
02113                 {
02114                         $this->reporting_date = "";
02115                         $this->ects_output = 0;
02116                 }
02117                 else
02118                 {
02119                         $this->reporting_date = $reporting_date;
02120                 }
02121   }
02122 
02132   function getSequenceSettings()
02133         {
02134     return $this->sequence_settings;
02135   }
02136 
02146   function getScoreReporting()
02147         {
02148     return $this->score_reporting;
02149   }
02150 
02160   function getInstantVerification()
02161         {
02162     return $this->instant_verification;
02163   }
02164 
02174   function getCountSystem()
02175         {
02176     return $this->count_system;
02177   }
02178 
02188   function _getCountSystem($active_id)
02189         {
02190                 global $ilDB;
02191                 $query = sprintf("SELECT tst_tests.count_system FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02192                         $ilDB->quote($active_id)
02193                 );
02194                 $result = $ilDB->query($query);
02195                 if ($result->numRows())
02196                 {
02197                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02198                         return $row["count_system"];
02199                 }
02200     return FALSE;
02201   }
02202 
02212   function getMCScoring()
02213         {
02214     return $this->mc_scoring;
02215   }
02216 
02226   function getScoreCutting()
02227         {
02228     return $this->score_cutting;
02229   }
02230 
02240   function getPassword()
02241         {
02242     return $this->password;
02243   }
02244 
02254   function getPassScoring()
02255         {
02256     return $this->pass_scoring;
02257   }
02258 
02268   function _getPassScoring($active_id)
02269         {
02270                 global $ilDB;
02271                 $query = sprintf("SELECT tst_tests.pass_scoring FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02272                         $ilDB->quote($active_id . "")
02273                 );
02274                 $result = $ilDB->query($query);
02275                 if ($result->numRows())
02276                 {
02277                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02278                         return $row["pass_scoring"];
02279                 }
02280     return 0;
02281   }
02282 
02292   function _getMCScoring($active_id)
02293         {
02294                 global $ilDB;
02295                 $query = sprintf("SELECT tst_tests.mc_scoring FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02296                         $ilDB->quote($active_id)
02297                 );
02298                 $result = $ilDB->query($query);
02299                 if ($result->numRows())
02300                 {
02301                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02302                         return $row["mc_scoring"];
02303                 }
02304     return FALSE;
02305   }
02306 
02316   function _getScoreCutting($active_id)
02317         {
02318                 global $ilDB;
02319                 $query = sprintf("SELECT tst_tests.score_cutting FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
02320                         $ilDB->quote($active_id)
02321                 );
02322                 $result = $ilDB->query($query);
02323                 if ($result->numRows())
02324                 {
02325                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02326                         return $row["score_cutting"];
02327                 }
02328     return FALSE;
02329   }
02330 
02340   function getTestType()
02341         {
02342     return $this->test_type;
02343   }
02344 
02353   function _lookupTestType($a_obj_id)
02354   {
02355           global $ilDB;
02356 
02357           $query = "SELECT test_type_fi FROM tst_tests ".
02358                   "WHERE obj_fi = '".$a_obj_id."'";
02359           $res = $ilDB->query($query);
02360           while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
02361           {
02362                   return $row['test_type_fi'];
02363           }
02364           return 0;
02365   }
02366 
02375   function _lookupTestIdForQuestion($a_question_id)
02376   {
02377           global $ilDB;
02378 
02379           $query = sprintf("SELECT tst_tests.obj_fi FROM tst_tests, tst_test_question WHERE tst_test_question.test_fi = tst_tests.test_id AND tst_test_question.question_fi = %s",
02380                                 $ilDB->quote($a_question_id)
02381                         );
02382       $res = $ilDB->query($query);
02383 
02384           while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
02385           {
02386                   return $row['obj_fi'];
02387           }
02388           return 0;
02389   }
02390 
02400   function _lookupAuthor($obj_id)
02401         {
02402                 global $ilDB;
02403                 $query = sprintf("SELECT author FROM tst_tests WHERE obj_fi = %s",
02404                         $ilDB->quote($obj_id . "")
02405                 );
02406                 $result = $ilDB->query($query);
02407                 if ($result->numRows())
02408                 {
02409                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02410                         return $row["author"];
02411                 }
02412                 return "";
02413   }
02414 
02415 
02425   function getReportingDate()
02426         {
02427     return $this->reporting_date;
02428   }
02429 
02439   function getNrOfTries()
02440         {
02441     return $this->nr_of_tries;
02442   }
02443 
02453   function getHidePreviousResults()
02454         {
02455     return $this->hide_previous_results;
02456   }
02457 
02467   function getHideTitlePoints()
02468         {
02469     return $this->hide_title_points;
02470   }
02471 
02482   function _getHideTitlePoints($active_id)
02483         {
02484                 global $ilDB;
02485 
02486                 $query = sprintf("SELECT tst_tests.hide_title_points FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02487                         $ilDB->quote($active_id . "")
02488                 );
02489                 $result = $ilDB->query($query);
02490                 if ($result->numRows())
02491                 {
02492                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02493                         return $row["hide_title_points"];
02494                 }
02495                 return 0;
02496   }
02497 
02509   function _getHidePreviousResults($active_id, $user_active_user_setting = false)
02510         {
02511                 global $ilDB;
02512                 global $ilUser;
02513 
02514                 $user_hide_previous_results = 0;
02515                 if ($user_active_user_setting)
02516                 {
02517                         if (array_key_exists("tst_hide_previous_results", $ilUser->prefs))
02518                         {
02519                                 $user_hide_previous_results = $ilUser->prefs["tst_hide_previous_results"];
02520                         }
02521                 }
02522                 $query = sprintf("SELECT tst_tests.hide_previous_results FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02523                         $ilDB->quote($active_id . "")
02524                 );
02525                 $result = $ilDB->query($query);
02526                 if ($result->numRows())
02527                 {
02528                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02529                         if ($row["hide_previous_results"] != 1)
02530                         {
02531                                 return $row["hide_previous_results"] | $user_hide_previous_results;
02532                         }
02533                         else
02534                         {
02535                                 return $row["hide_previous_results"];
02536                         }
02537                 }
02538                 return 0;
02539   }
02540 
02550   function getProcessingTime()
02551         {
02552     return $this->processing_time;
02553   }
02554 
02564         function getProcessingTimeInSeconds()
02565         {
02566                 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
02567                 {
02568                         return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
02569                 }
02570                         else
02571                 {
02572                         return 0;
02573                 }
02574         }
02575 
02585                 function getSecondsUntilEndingTime()
02586                 {
02587                         if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
02588                         {
02589                                 $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02590                                 $now = time();
02591                                 return $ending - $now;
02592                         }
02593                         else
02594                         {
02595                                 return 0;
02596                         }
02597                 }
02598 
02608   function getEnableProcessingTime()
02609         {
02610     return $this->enable_processing_time;
02611   }
02612 
02622   function getStartingTime()
02623         {
02624     return $this->starting_time;
02625   }
02626 
02636   function getEndingTime()
02637         {
02638     return $this->ending_time;
02639   }
02640 
02650   function setNrOfTries($nr_of_tries = 0)
02651         {
02652     $this->nr_of_tries = $nr_of_tries;
02653   }
02654 
02664   function setHidePreviousResults($hide_previous_results = 0)
02665         {
02666                 if ($hide_previous_results)
02667                 {
02668                         $this->hide_previous_results = 1;
02669                 }
02670                 else
02671                 {
02672                         $this->hide_previous_results = 0;
02673                 }
02674   }
02675 
02685   function setHideTitlePoints($hide_title_points = 0)
02686         {
02687                 if ($hide_title_points)
02688                 {
02689                         $this->hide_title_points = 1;
02690                 }
02691                 else
02692                 {
02693                         $this->hide_title_points = 0;
02694                 }
02695   }
02696 
02706   function setProcessingTime($processing_time = "00:00:00")
02707         {
02708     $this->processing_time = $processing_time;
02709   }
02710 
02720         function setEnableProcessingTime($enable = 0)
02721         {
02722                 if ($enable) {
02723                         $this->enable_processing_time = "1";
02724                 } else {
02725                         $this->enable_processing_time = "0";
02726                 }
02727         }
02728 
02738   function setStartingTime($starting_time = "")
02739         {
02740     $this->starting_time = $starting_time;
02741   }
02742 
02752   function setEndingTime($ending_time = "")
02753         {
02754     $this->ending_time = $ending_time;
02755   }
02756 
02766   function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
02767         {
02768     $this->count_system = $a_count_system;
02769   }
02770 
02780   function setPassword($a_password = "")
02781         {
02782     $this->password = $a_password;
02783   }
02784 
02794   function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
02795         {
02796     $this->score_cutting = $a_score_cutting;
02797   }
02798 
02808   function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED)
02809         {
02810     $this->mc_scoring = $a_mc_scoring;
02811   }
02812 
02822   function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
02823         {
02824                 switch ($a_pass_scoring)
02825                 {
02826                         case SCORE_BEST_PASS:
02827                                 $this->pass_scoring = SCORE_BEST_PASS;
02828                                 break;
02829                         default:
02830                                 $this->pass_scoring = SCORE_LAST_PASS;
02831                                 break;
02832                 }
02833   }
02834 
02844         function removeQuestion($question_id)
02845         {
02846                 $question =& ilObjTest::_instanciateQuestion($question_id);
02847                 include_once ("./classes/class.ilObjAssessmentFolder.php");
02848                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02849                 {
02850                         $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
02851                 }
02852                 $question->delete($question_id);
02853                 $this->removeAllTestEditings($question_id);
02854                 $this->loadQuestions();
02855                 $this->saveQuestionsToDb();
02856         }
02857 
02865         function clearEvalSelectedUsers()
02866         {
02867                 global $ilDB;
02868 
02869                 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s",
02870                         $ilDB->quote($this->getTestId())
02871                 );
02872                 $result = $ilDB->query($query);
02873         }
02874 
02886         function removeAllTestEditings($question_id = "")
02887         {
02888                 global $ilDB;
02889                 // remove test_active entries, because test has changed
02890                 $this->deleteActiveTests();
02891                 // remove selected users/groups
02892                 $this->clearEvalSelectedUsers();
02893 
02894                 // remove the question from tst_solutions
02895                 if ($question_id)
02896                 {
02897                         $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_solutions.question_fi = %s",
02898                                 $ilDB->quote($this->getTestId()),
02899                                 $ilDB->quote($question_id)
02900                         );
02901                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active_qst_sol_settings.question_fi = %s",
02902                                 $ilDB->quote($this->getTestId()),
02903                                 $ilDB->quote($question_id)
02904                         );
02905                         $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_test_result.question_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
02906                                 $ilDB->quote($this->getTestId()),
02907                                 $ilDB->quote($question_id)
02908                         );
02909                 } else {
02910                         $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
02911                                 $ilDB->quote($this->getTestId())
02912                         );
02913                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
02914                                 $ilDB->quote($this->getTestId())
02915                         );
02916                         $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
02917                                 $ilDB->quote($this->getTestId())
02918                         );
02919                 }
02920                 $result = $ilDB->query($query);
02921                 $result = $ilDB->query($query2);
02922                 $result = $ilDB->query($query3);
02923 
02924                 if ($this->isRandomTest())
02925                 {
02926                         $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_test_random_question.active_fi = tst_active.active_id",
02927                                 $ilDB->quote($this->getTestId())
02928                         );
02929                         $result = $ilDB->query($query);
02930                 }
02931                 include_once ("./classes/class.ilObjAssessmentFolder.php");
02932                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02933                 {
02934                         $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
02935                 }
02936         }
02937 
02949         function removeSelectedTestResults($active_ids)
02950         {
02951                 global $ilDB;
02952 
02953                 // remove selected users/groups
02954                 $this->clearEvalSelectedUsers();
02955 
02956                 // remove the question from tst_solutions
02957                 foreach ($active_ids as $active_id)
02958                 {
02959                         $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
02960                                 $ilDB->quote($active_id . "")
02961                         );
02962                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
02963                                 $ilDB->quote($active_id . "")
02964                         );
02965                         $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
02966                                 $ilDB->quote($active_id . "")
02967                         );
02968                         $result = $ilDB->query($query);
02969                         $result = $ilDB->query($query2);
02970                         $result = $ilDB->query($query3);
02971 
02972                         if ($this->isRandomTest())
02973                         {
02974                                 $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
02975                                         $ilDB->quote($active_id . "")
02976                                 );
02977                                 $result = $ilDB->query($query);
02978                         }
02979 
02980                         include_once ("./classes/class.ilObjAssessmentFolder.php");
02981                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02982                         {
02983                                 include_once ("./classes/class.ilObjUser.php");
02984                                 $uname = ilObjUser::_lookupName($this->_getUserIdFromActiveId($active_id));
02985                                 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), trim($uname["title"] . " " . $uname["firstname"] . " " . $uname["lastname"] . " (" . $uname["user_id"] . ")")));
02986                         }
02987                 }
02988 
02989                 // remove test_active entries of selected users
02990                 foreach ($active_ids as $active_id)
02991                 {
02992                         $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
02993                                 $ilDB->quote($active_id . "")
02994                         );
02995                         $result = $ilDB->query($query);
02996                 }
02997         }
02998 
03010         function removeTestResultsForUser($user_id)
03011         {
03012                 global $ilDB;
03013 
03014                 $active = $this->getActiveTestUser($user_id);
03015                 $active_id = $active->active_id;
03016 
03017                 // remove the question from tst_solutions
03018                 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
03019                         $ilDB->quote($active_id . "")
03020                 );
03021                 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
03022                         $ilDB->quote($active_id . "")
03023                 );
03024                 $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
03025                         $ilDB->quote($active_id . "")
03026                 );
03027                 $result = $ilDB->query($query);
03028                 $result = $ilDB->query($query2);
03029                 $result = $ilDB->query($query3);
03030 
03031                 if ($this->isRandomTest())
03032                 {
03033                         $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
03034                                 $ilDB->quote($active_id . "")
03035                         );
03036                         $result = $ilDB->query($query);
03037                 }
03038 
03039                 include_once ("./classes/class.ilObjAssessmentFolder.php");
03040                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03041                 {
03042                         include_once ("./classes/class.ilObjUser.php");
03043                         $uname = ilObjUser::_lookupName($this->_getUserIdFromActiveId($active_id));
03044                         $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), trim($uname["title"] . " " . $uname["firstname"] . " " . $uname["lastname"] . " (" . $uname["user_id"] . ")")));
03045                 }
03046 
03047                 // remove test_active entry
03048                 $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
03049                         $ilDB->quote($active_id . "")
03050                 );
03051                 $result = $ilDB->query($query);
03052         }
03053 
03062         function deleteActiveTests()
03063         {
03064                 global $ilDB;
03065 
03066                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03067                         $ilDB->quote($this->getTestId())
03068                 );
03069                 $result = $ilDB->query($query);
03070         }
03071 
03082         function deleteResults($user_id = "")
03083         {
03084                 global $ilDB;
03085 
03086                 if ($user_id)
03087                 {
03088                         $active = $this->getActiveTestUser($user_id);
03089                         $pass = $this->_getPass($active->active_id);
03090                         $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active.user_fi = %s AND tst_solutions.pass = %s",
03091                                 $ilDB->quote($this->getTestId() . ""),
03092                                 $ilDB->quote($user_id . ""),
03093                                 $ilDB->quote($pass . "")
03094                         );
03095                         $result = $ilDB->query($query);
03096                         $query = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s AND pass = %s",
03097                                 $ilDB->quote($active->active_id . ""),
03098                                 $ilDB->quote($pass . "")
03099                         );
03100                         $result = $ilDB->query($query);
03101                         $sequence_arr = array_flip($this->questions);
03102                         $sequence = join($sequence_arr, ",");
03103                         $query = sprintf("UPDATE tst_active SET sequence = %s, lastindex = %s WHERE test_fi = %s and user_fi = %s",
03104                                 $ilDB->quote($sequence),
03105                                 $ilDB->quote("1"),
03106                                 $ilDB->quote($this->getTestId()),
03107                                 $ilDB->quote($user_id)
03108                         );
03109                         $result = $ilDB->query($query);
03110 
03111                         $query = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active.user_fi = %s",
03112                                 $ilDB->quote($this->getTestId()),
03113                                 $ilDB->quote($user_id)
03114                         );
03115                         $result = $ilDB->query($query);
03116                 }
03117         }
03118 
03128         function questionMoveUp($question_id)
03129         {
03130                 global $ilDB;
03131 
03132                 // Move a question up in sequence
03133                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03134                         $ilDB->quote($this->getTestId()),
03135                         $ilDB->quote($question_id)
03136                 );
03137                 $result = $ilDB->query($query);
03138                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03139                 if ($data->sequence > 1) {
03140                         // OK, it's not the top question, so move it up
03141                         $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03142                                 $ilDB->quote($this->getTestId()),
03143                                 $ilDB->quote($data->sequence - 1)
03144                         );
03145                         $result = $ilDB->query($query);
03146                         $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
03147                         // change previous dataset
03148                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03149                                 $ilDB->quote($data->sequence),
03150                                 $ilDB->quote($data_previous->test_question_id)
03151                         );
03152                         $result = $ilDB->query($query);
03153                         // move actual dataset up
03154                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03155                                 $ilDB->quote($data->sequence - 1),
03156                                 $ilDB->quote($data->test_question_id)
03157                         );
03158                         $result = $ilDB->query($query);
03159                         include_once ("./classes/class.ilObjAssessmentFolder.php");
03160                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03161                         {
03162                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
03163                         }
03164                 }
03165                 $this->loadQuestions();
03166         }
03167 
03177         function questionMoveDown($question_id)
03178         {
03179                 global $ilDB;
03180 
03181                 // Move a question down in sequence
03182                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03183                         $ilDB->quote($this->getTestId()),
03184                         $ilDB->quote($question_id)
03185                 );
03186                 $result = $ilDB->query($query);
03187                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03188                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03189                         $ilDB->quote($this->getTestId()),
03190                         $ilDB->quote($data->sequence + 1)
03191                 );
03192                 $result = $ilDB->query($query);
03193                 if ($result->numRows() == 1)
03194                 {
03195                         // OK, it's not the last question, so move it down
03196                         $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
03197                         // change next dataset
03198                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03199                                 $ilDB->quote($data->sequence),
03200                                 $ilDB->quote($data_next->test_question_id)
03201                         );
03202                         $result = $ilDB->query($query);
03203                         // move actual dataset down
03204                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03205                                 $ilDB->quote($data->sequence + 1),
03206                                 $ilDB->quote($data->test_question_id)
03207                         );
03208                         $result = $ilDB->query($query);
03209                         include_once ("./classes/class.ilObjAssessmentFolder.php");
03210                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03211                         {
03212                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
03213                         }
03214                 }
03215                 $this->loadQuestions();
03216         }
03217 
03227         function duplicateQuestionForTest($question_id)
03228         {
03229                 global $ilUser;
03230                 $question =& ilObjTest::_instanciateQuestion($question_id);
03231                 $duplicate_id = $question->duplicate(true);
03232 
03233                 return $duplicate_id;
03234         }
03235 
03244         function insertQuestion($question_id)
03245         {
03246                 global $ilDB;
03247 
03248                 $duplicate_id = $this->duplicateQuestionForTest($question_id);
03249 
03250                 // get maximum sequence index in test
03251                 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
03252                         $ilDB->quote($this->getTestId())
03253                         );
03254                 $result = $ilDB->query($query);
03255                 $sequence = 1;
03256 
03257                 if ($result->numRows() == 1)
03258                 {
03259                         $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03260                         $sequence = $data->seq + 1;
03261                 }
03262 
03263                 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
03264                         $ilDB->quote($this->getTestId()),
03265                         $ilDB->quote($duplicate_id),
03266                         $ilDB->quote($sequence)
03267                         );
03268                 $result = $ilDB->query($query);
03269                 if ($result != DB_OK)
03270                 {
03271                         // Error
03272                 }
03273                 else
03274                 {
03275                         include_once ("./classes/class.ilObjAssessmentFolder.php");
03276                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03277                         {
03278                                 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
03279                         }
03280                 }
03281                 // remove test_active entries, because test has changed
03282                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03283                         $ilDB->quote($this->getTestId())
03284                         );
03285                 $result = $ilDB->query($query);
03286                 $this->loadQuestions();
03287                 $this->saveCompleteStatus();
03288         }
03289 
03299         function &getQuestionTitles()
03300         {
03301                 $titles = array();
03302                 if (!$this->isRandomTest())
03303                 {
03304                         global $ilDB;
03305                         $query = sprintf("SELECT qpl_questions.title FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY tst_test_question.sequence",
03306                                 $ilDB->quote($this->getTestId() . "")
03307                         );
03308                         $result = $ilDB->query($query);
03309                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03310                         {
03311                                 array_push($titles, $row["title"]);
03312                         }
03313                 }
03314                 return $titles;
03315         }
03316 
03327         function getQuestionDataset($question_id)
03328         {
03329                 global $ilDB;
03330 
03331                 $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",
03332                         $ilDB->quote("$question_id")
03333                 );
03334     $result = $ilDB->query($query);
03335                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03336                 return $row;
03337         }
03338 
03347         function &get_qpl_titles()
03348         {
03349                 global $rbacsystem;
03350                 global $ilDB;
03351 
03352                 $qpl_titles = array();
03353                 // get all available questionpools and remove the trashed questionspools
03354                 $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";
03355                 $result = $ilDB->query($query);
03356                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03357                 {
03358                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03359                         {
03360                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
03361                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
03362                                 {
03363                                         $qpl_titles["$row->obj_id"] = $row->title;
03364                                 }
03365                         }
03366                 }
03367                 return $qpl_titles;
03368         }
03369 
03378         function &getExistingQuestions($pass = NULL)
03379         {
03380                 global $ilUser;
03381                 global $ilDB;
03382 
03383                 $existing_questions = array();
03384                 $active = $this->getActiveTestUser($ilUser->getId());
03385                 if ($this->isRandomTest())
03386                 {
03387                         if (is_null($pass)) $pass = 0;
03388                         $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.active_fi = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.pass = %s",
03389                                 $ilDB->quote($active->active_id . ""),
03390                                 $ilDB->quote($pass . "")
03391                         );
03392                 }
03393                 else
03394                 {
03395                         $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",
03396                                 $ilDB->quote($this->getTestId())
03397                         );
03398                 }
03399                 $result = $ilDB->query($query);
03400                 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
03401                         array_push($existing_questions, $data->original_id);
03402                 }
03403                 return $existing_questions;
03404         }
03405 
03415   function getQuestionType($question_id)
03416         {
03417                 global $ilDB;
03418 
03419     if ($question_id < 1)
03420       return -1;
03421     $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",
03422       $ilDB->quote($question_id)
03423     );
03424     $result = $ilDB->query($query);
03425     if ($result->numRows() == 1) {
03426       $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03427       return $data->type_tag;
03428     } else {
03429       return "";
03430     }
03431   }
03432 
03441         function startWorkingTime($user_id)
03442         {
03443                 global $ilDB;
03444 
03445                 $result = "";
03446                 if (!($result = $this->getActiveTestUser($user_id))) {
03447                         $this->setActiveTestUser();
03448                         $result = $this->getActiveTestUser($user_id);
03449                 }
03450                 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
03451                         $ilDB->quote($result->active_id),
03452                         $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03453                         $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S"))
03454                 );
03455                 $result = $ilDB->query($q);
03456                 return $ilDB->getLastInsertId();
03457         }
03458 
03467         function updateWorkingTime($times_id)
03468         {
03469                 global $ilDB;
03470 
03471                 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
03472                         $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03473                         $ilDB->quote($times_id)
03474                 );
03475                 $result = $ilDB->query($q);
03476         }
03477 
03487         function getQuestionIdFromActiveUserSequence($sequence)
03488         {
03489                 global $ilUser;
03490 
03491                 $active = $this->getActiveTestUser();
03492                 $sequence_array = split(",", $active->sequence);
03493                 return $this->questions[$sequence_array[$sequence-1]];
03494         }
03495 
03504         function &getAllQuestionsForActiveUser()
03505         {
03506                 $result_array = array();
03507                 $active = $this->getActiveTestUser();
03508                 $sequence_array = split(",", $active->sequence);
03509                 $all_questions = &$this->getAllQuestions();
03510                 $worked_questions = &$this->getWorkedQuestions($active->active_id);
03511                 foreach ($sequence_array as $sequence)
03512                 {
03513                         if (in_array($this->questions[$sequence], $worked_questions))
03514                         {
03515                                 $all_questions[$this->questions[$sequence]]["worked"] = 1;
03516                         }
03517                         else
03518                         {
03519                                 $all_questions[$this->questions[$sequence]]["worked"] = 0;
03520                         }
03521                         array_push($result_array, $all_questions[$this->questions[$sequence]]);
03522                 }
03523                 return $result_array;
03524         }
03525 
03526         function getFirstSequence()
03527         {
03528                 global $ilUser;
03529 
03530                 $active = $this->getActiveTestUser($ilUser->getId());
03531                 $results = $this->getTestResult($active->active_id);
03532 
03533                 for($i = 1; $i <= $this->getQuestionCount(); $i++)
03534                 {
03535                         $qid = $this->getQuestionIdFromActiveUserSequence($i);
03536 
03537                         foreach($results as $result)
03538                         {
03539                                 if($qid == $result['qid'])
03540                                 {
03541                                         if(!$result['max'] or $result['max'] != $result['reached'])
03542                                         {
03543                                                 return $i;
03544                                         }
03545                                 }
03546                         }
03547                 }
03548                 return 0;
03549         }
03550 
03551 
03560         function &getWorkedQuestions($active_id, $pass = NULL)
03561         {
03562                 global $ilUser;
03563                 global $ilDB;
03564 
03565                 if (is_null($pass))
03566                 {
03567                         $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = 0 GROUP BY question_fi",
03568                                 $ilDB->quote($active_id . "")
03569                         );
03570                 }
03571                 else
03572                 {
03573                         $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
03574                                 $ilDB->quote($active_id . ""),
03575                                 $ilDB->quote($pass . "")
03576                         );
03577                 }
03578                 $result = $ilDB->query($query);
03579                 $result_array = array();
03580                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03581                 {
03582                         array_push($result_array, $row->question_fi);
03583                 }
03584                 return $result_array;
03585         }
03586 
03597         function isTestFinishedToViewResults($active_id, $currentpass)
03598         {
03599                 $num = $this->getPassFinishDate($active_id, $currentpass);
03600                 if (($currentpass > 0) && ($num == 0))
03601                 {
03602                         return TRUE;
03603                 }
03604                 else
03605                 {
03606                         if (($currentpass > 0) && ($this->getTestType() != TYPE_VARYING_RANDOMTEST))
03607                         {
03608                                 return TRUE;
03609                         }
03610                         else
03611                         {
03612                                 return FALSE;
03613                         }
03614                 }
03615         }
03616 
03617 
03626         function &getAllQuestions($pass = NULL)
03627         {
03628                 global $ilUser;
03629                 global $ilDB;
03630 
03631                 if ($this->isRandomTest())
03632                 {
03633                         $active = $this->getActiveTestUser($ilUser->getId());
03634                         $this->loadQuestions($active->active_id, $pass);
03635                         $query = sprintf("SELECT qpl_questions.* FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.active_fi = %s AND tst_test_random_question.pass = %s AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")",
03636                                 $ilDB->quote($active->active_id . ""),
03637                                 $ilDB->quote($pass . "")
03638                         );
03639                 }
03640                 else
03641                 {
03642                         $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, ",") . ")";
03643                 }
03644                 $result = $ilDB->query($query);
03645                 $result_array = array();
03646                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03647                 {
03648                         $result_array[$row["question_id"]] = $row;
03649                 }
03650                 return $result_array;
03651         }
03652 
03653         function &getActiveTestUserFromActiveId($active_id)
03654         {
03655                 global $ilDB;
03656                 $query = sprintf("SELECT * FROM tst_active WHERE active_id = %s",
03657                         $ilDB->quote($active_id . "")
03658                 );
03659                 $result = $ilDB->query($query);
03660                 $row = NULL;
03661                 if ($result->numRows())
03662                 {
03663                         $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03664                 }
03665                 return $row;
03666         }
03667 
03677         function getActiveTestUser($user_id = "", $anonymous_id = "")
03678         {
03679                 global $ilDB;
03680                 global $ilUser;
03681 
03682                 if (!$user_id)
03683                 {
03684                         $user_id = $ilUser->id;
03685                 }
03686                 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
03687                 {
03688                         $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03689                                 $ilDB->quote($user_id),
03690                                 $ilDB->quote($this->test_id),
03691                                 $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()])
03692                         );
03693                 }
03694                 else if (strlen($anonymous_id))
03695                 {
03696                         $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03697                                 $ilDB->quote($user_id),
03698                                 $ilDB->quote($this->test_id),
03699                                 $ilDB->quote($anonymous_id)
03700                         );
03701                 }
03702                 else
03703                 {
03704                         if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
03705                         {
03706                                 return NULL;
03707                         }
03708                         $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03709                                 $ilDB->quote($user_id),
03710                                 $ilDB->quote($this->test_id)
03711                         );
03712                 }
03713                 $result = $ilDB->query($query);
03714                 if ($result->numRows())
03715                 {
03716                         $this->active = $result->fetchRow(DB_FETCHMODE_OBJECT);
03717                 }
03718                 else
03719                 {
03720                         $this->active = null;
03721                 }
03722                 return $this->active;
03723         }
03724 
03735                 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
03736                 {
03737                         global $ilDB;
03738                         global $ilUser;
03739 
03740                         if (!$user_id) $user_id = $ilUser->getId();
03741                         if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
03742                         {
03743                                 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03744                                         $ilDB->quote($user_id),
03745                                         $ilDB->quote($this->test_id),
03746                                         $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()])
03747                                 );
03748                         }
03749                         else if (strlen($anonymous_id))
03750                         {
03751                                 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03752                                         $ilDB->quote($user_id),
03753                                         $ilDB->quote($this->test_id),
03754                                         $ilDB->quote($anonymous_id)
03755                                 );
03756                         }
03757                         else
03758                         {
03759                                 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
03760                                 {
03761                                         return NULL;
03762                                 }
03763                                 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03764                                         $ilDB->quote($user_id),
03765                                         $ilDB->quote($this->test_id)
03766                                 );
03767                         }
03768                         $result = $ilDB->query($query);
03769                         if ($result->numRows())
03770                         {
03771                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03772                                 return $row["active_id"];
03773                         }
03774                         else
03775                         {
03776                                 return 0;
03777                         }
03778                 }
03779 
03790         function _getActiveTestUser($user_id = "", $test_id = "") {
03791                 global $ilDB;
03792                 global $ilUser;
03793 
03794                 if (!$user_id) {
03795                         $user_id = $ilUser->id;
03796                 }
03797                 if (!$test_id)
03798                 {
03799                         return "";
03800                 }
03801                 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03802                         $ilDB->quote($user_id),
03803                         $ilDB->quote($test_id)
03804                 );
03805 
03806                 $result = $ilDB->query($query);
03807                 if ($result->numRows()) {
03808                         return $result->fetchRow(DB_FETCHMODE_OBJECT);
03809                 } else {
03810                         return "";
03811                 }
03812         }
03813 
03826         function setActiveTestUser($lastindex = 1, $postpone = "", $addTries = false)
03827         {
03828                 global $ilDB;
03829                 global $ilUser;
03830 
03831                 if ($lastindex < 1) $lastindex = 1;
03832 
03833                 $old_active = $this->getActiveTestUser();
03834                 if ($old_active)
03835                 {
03836                         $sequence = $old_active->sequence;
03837                         $postponed = $old_active->postponed;
03838                         if ($postpone)
03839                         {
03840                                 $sequence_array = split(",", $sequence);
03841                                 $postpone_sequence = $sequence_array[$postpone-1];
03842                                 $question_id = $this->questions[$postpone_sequence];
03843                                 unset($sequence_array[$postpone-1]);
03844                                 array_push($sequence_array, $postpone_sequence);
03845                                 $sequence = join(",", $sequence_array);
03846                                 $postponed .= ",$question_id";
03847                                 $postponed = preg_replace("/^,/", "", $postponed);
03848                         }
03849                         $tries = $old_active->tries;
03850                         if ($addTries && ($this->getNrOfResultsForPass($old_active->active_id, $old_active->tries) > 0))
03851                         {
03852                                 // only add the number of tries if there are ANY results for the current
03853                                 // test pass. Otherwise something must be wrong (doubleclick, reload etc.)
03854                                 $tries++;
03855                         }
03856                         $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
03857                                 $ilDB->quote($lastindex),
03858                                 $ilDB->quote($sequence),
03859                                 $ilDB->quote($postponed),
03860                                 $ilDB->quote($tries),
03861                                 $ilDB->quote($ilUser->id),
03862                                 $ilDB->quote($this->test_id)
03863                         );
03864                 }
03865                 else
03866                 {
03867                         $sequence_arr = array_flip($this->questions);
03868                         if ($this->getShuffleQuestions())
03869                         {
03870                                 $sequence_arr = array_values($sequence_arr);
03871                                 $sequence_arr = $this->pcArrayShuffle($sequence_arr);
03872                         }
03873                         $sequence = join($sequence_arr, ",");
03874                         if ($_SESSION["tst_access_code"][$this->getTestId()])
03875                         {
03876                                 $anonymous_id = $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()]);
03877                         }
03878                         else
03879                         {
03880                                 $anonymous_id = "NULL";
03881                         }
03882                         $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, anonymous_id, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, NULL)",
03883                                 $ilDB->quote($ilUser->getId()),
03884                                 $ilDB->quote($this->getTestId()),
03885                                 $anonymous_id,
03886                                 $ilDB->quote($sequence),
03887                                 $ilDB->quote(""),
03888                                 $ilDB->quote($lastindex),
03889                                 $ilDB->quote(0)
03890                         );
03891                 }
03892                 $ilDB->query($query);
03893                 if ($old_active)
03894                 {
03895                         return $old_active->active_id;
03896                 }
03897                 else
03898                 {
03899                         return $ilDB->getLastInsertId();
03900                 }
03901         }
03902 
03915         function addQuestionSequence($active_id)
03916         {
03917                 if ($this->isRandomTest())
03918                 {
03919                         global $ilUser;
03920                         global $ilDB;
03921 
03922                         $this->loadQuestions($active_id, 0);
03923                         if ((count($this->questions)) > $this->getQuestionCount())
03924                         {
03925                                 // something went terribly wrong, so create a sequence with only the maximum number of allowed questions
03926                                 // This section was introduced due to some random problems with the question sequence (HS, 2007-02-06)
03927                                 global $ilLog;
03928                                 $ilLog->write("fatal error: The number of questions is greater than the allowed question count. user id = " . $ilUser->getId() . ", active id = $active_id, questions = " . print_r($this->questions, true));
03929                                 $sequence_arr = array();
03930                                 for ($i = 1; $i <=  $this->getQuestionCount(); $i++)
03931                                 {
03932                                         $sequence_arr[$i] = $i;
03933                                 }
03934                         }
03935                         else
03936                         {
03937                                 $sequence_arr = array_flip($this->questions);
03938                         }
03939                         if ($this->getShuffleQuestions())
03940                         {
03941                                 $sequence_arr = array_values($sequence_arr);
03942                                 $sequence_arr = $this->pcArrayShuffle($sequence_arr);
03943                         }
03944                         $sequence = join($sequence_arr, ",");
03945                         $query = sprintf("UPDATE tst_active SET sequence = %s WHERE active_id = %s",
03946                                 $ilDB->quote($sequence . ""),
03947                                 $ilDB->quote($active_id . "")
03948                         );
03949                         $ilDB->query($query);
03950                 }
03951         }
03952 
03961         function pcArrayShuffle($array)
03962         {
03963                 mt_srand((double)microtime()*1000000);
03964                 $i = count($array);
03965                 if ($i > 0)
03966                 {
03967                         while(--$i)
03968                         {
03969                                 $j = mt_rand(0, $i);
03970                                 if ($i != $j)
03971                                 {
03972                                         // swap elements
03973                                         $tmp = $array[$j];
03974                                         $array[$j] = $array[$i];
03975                                         $array[$i] = $tmp;
03976                                 }
03977                         }
03978                 }
03979                 return $array;
03980         }
03981 
03991         function &getTestResult($active_id, $pass = NULL)
03992         {
03993                 //              global $ilBench;
03994                 if ($this->isRandomTest())
03995                 {
03996                         $this->loadQuestions($active_id, $pass);
03997                 }
03998                 $total_max_points = 0;
03999                 $total_reached_points = 0;
04000 
04001                 $key = 1;
04002                 $result_array = array();
04003                 include_once "./assessment/classes/class.assQuestion.php";
04004                 $workedthrough = 0;
04005                 $active_object = $this->getActiveTestUserFromActiveId($active_id);
04006                 $user_sequence = split(",", $active_object->sequence);
04007                 foreach ($user_sequence as $questionindex)
04008                 {
04009                         $value = $this->questions[$questionindex];
04010                         $max_points = assQuestion::_getMaximumPoints($value);
04011                         $total_max_points += $max_points;
04012                         $reached_points = assQuestion::_getReachedPoints($active_id, $value, $pass);
04013                         if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
04014                         {
04015                                 $workedthrough = 1;
04016                         }
04017                         else
04018                         {
04019                                 $workedthrough = 0;
04020                         }
04021                         $total_reached_points += $reached_points;
04022                         if ($max_points > 0)
04023                         {
04024                                 $percentvalue = $reached_points / $max_points;
04025                         }
04026                         else
04027                         {
04028                                 $percentvalue = 0;
04029                         }
04030                         if ($percentvalue < 0) $percentvalue = 0.0;
04031                         if (assQuestion::_getSuggestedSolutionCount($value) == 1)
04032                         {
04033                                 $solution_array =& assQuestion::_getSuggestedSolution($value, 0);
04034                                 $href = assQuestion::_getInternalLinkHref($solution_array["internal_link"]);
04035                         }
04036                         elseif (assQuestion::_getSuggestedSolutionCount($value) > 1)
04037                         {
04038                                 $href = "see_details_for_further_information";
04039                         }
04040                         else
04041                         {
04042                                 $href = "";
04043                         }
04044                         $info =& assQuestion::_getQuestionInfo($value);
04045                         include_once "./classes/class.ilUtil.php";
04046                         $row = array(
04047                                 "nr" => "$key",
04048                                 "title" => ilUtil::prepareFormOutput($info["title"]),
04049                                 "max" => $max_points,
04050                                 "reached" => $reached_points,
04051                                 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
04052                                 "solution" => $href,
04053                                 "type" => $info["type_tag"],
04054                                 "qid" => $value,
04055                                 "original_id" => $info["original_id"],
04056                                 "workedthrough" => $workedthrough
04057                         );
04058                         array_push($result_array, $row);
04059                         $key++;
04060                 }
04061                 if ($this->getScoreCutting() == 1)
04062                 {
04063                         if ($total_reached_points < 0)
04064                         {
04065                                 $total_reached_points = 0;
04066                         }
04067                 }
04068                 $result_array["test"]["total_max_points"] = $total_max_points;
04069                 $result_array["test"]["total_reached_points"] = $total_reached_points;
04070                 if ((!$total_reached_points) or (!$total_max_points))
04071                 {
04072                         $percentage = 0.0;
04073                 }
04074                 else
04075                 {
04076                         $percentage = ($total_reached_points / $total_max_points) * 100.0;
04077                         if ($percentage < 0) $percentage = 0.0;
04078                 }
04079                 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
04080                 $passed = "";
04081                 if ($mark_obj)
04082                 {
04083                         if ($mark_obj->getPassed())
04084                         {
04085                                 $passed = 1;
04086                         }
04087                         else
04088                         {
04089                                 $passed = 0;
04090                         }
04091                 }
04092                 $result_array["test"]["passed"] = $passed;
04093                 return $result_array;
04094         }
04095 
04096 
04105         function &getTestSummary($active_id, $pass = NULL)
04106         {
04107                 global $ilDB;
04108                 if ($this->isRandomTest())
04109                 {
04110                         $this->loadQuestions($active_id, $pass);
04111                 }
04112 
04113                 $key = 1;
04114                 $result_array = array();
04115 
04116                 $active = $this->getActiveTestUserFromActiveId($active_id);
04117                 $postponed = explode(",", $active->postponed);
04118                 $solved_questions = ilObjTest::_getSolvedQuestions($active_id);
04119                 include_once "./classes/class.ilObjUser.php";
04120                 $user = new ilObjUser($user_id);
04121                 $sequence_array = split(",", $active->sequence);
04122                 foreach ($sequence_array as $question_index)
04123                 {
04124                         $val = $this->questions[$question_index];
04125                         $question =& ilObjTest::_instanciateQuestion($val);
04126                         if (is_object($question))
04127                         {
04128                                 $worked_through = $question->_isWorkedThrough($active_id, $question->getId(), $pass);
04129                                 $solved  = 0;
04130                                 if (array_key_exists($question->getId(),$solved_questions))
04131                                 {
04132                                         $solved =  $solved_questions[$question->getId()]->solved;
04133                                 }
04134                                 $is_postponed = FALSE;
04135                                 if (in_array($question->getId(), $postponed))
04136                                 {
04137                                         $is_postponed = TRUE;
04138                                 }
04139 
04140                                 $row = array(
04141                                         "nr" => "$key",
04142                                         "title" => $question->getTitle(),
04143                                         "qid" => $question->getId(),
04144                                         "visited" => $worked_through,
04145                                         "solved" => (($solved)?"1":"0"),
04146                                         "description" => $question->getComment(),
04147                                         "points" => $question->getMaximumPoints(),
04148                                         "worked_through" => $worked_through,
04149                                         "postponed" => $is_postponed
04150                                 );
04151                                 array_push($result_array, $row);
04152                                 $key++;
04153                         }
04154                 }
04155 
04156                 return $result_array;
04157         }
04158 
04159 
04168         function evalTotalPersons()
04169         {
04170                 global $ilDB;
04171 
04172                 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
04173                         $ilDB->quote($this->getTestId())
04174                 );
04175                 $result = $ilDB->query($q);
04176                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
04177                 return $row->total;
04178         }
04179 
04188         function canViewResults()
04189         {
04190                 $result = true;
04191                 if ($this->getTestType() != TYPE_SELF_ASSESSMENT)
04192                 {
04193                         if ($this->getReportingDate())
04194                         {
04195                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
04196                                 {
04197                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04198                                         $now = mktime();
04199                                         if ($now < $epoch_time)
04200                                         {
04201                                                 $result = false;
04202                                         }
04203                                 }
04204                         }
04205                 }
04206                 return $result;
04207         }
04208 
04217         function evalLoadStatisticalSettings($user_id)
04218         {
04219                 global $ilDB;
04220 
04221                 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
04222                         $ilDB->quote("$user_id")
04223                 );
04224                 $result = $ilDB->query($q);
04225                 if (!$result->numRows())
04226                 {
04227                         $row = array(
04228                                 "qworkedthrough" => "1",
04229                                 "pworkedthrough" => "1",
04230                                 "timeofwork" => "1",
04231                                 "atimeofwork" => "1",
04232                                 "firstvisit" => "1",
04233                                 "lastvisit" => "1",
04234                                 "resultspoints" => "1",
04235                                 "resultsmarks" => "1",
04236                                 "distancemedian" => "1"
04237                         );
04238                 }
04239                         else
04240                 {
04241                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
04242                         unset($row["eval_settings_id"]);
04243                 }
04244                 return $row;
04245         }
04246 
04255         function evalSaveStatisticalSettings($settings_array, $user_id)
04256         {
04257                 global $ilDB;
04258 
04259                 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
04260                         $ilDB->quote("$user_id")
04261                 );
04262                 $result = $ilDB->query($q);
04263                 if ($result->numRows() > 0)
04264                 {
04265                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
04266                 }
04267                 $update = $row["eval_settings_id"];
04268                 if (!$update) {
04269                         $q = sprintf("INSERT INTO tst_eval_settings ".
04270                                          "(eval_settings_id, user_fi, qworkedthrough, pworkedthrough, timeofwork, atimeofwork, firstvisit, " .
04271                                          "lastvisit, resultspoints, resultsmarks, distancemedian, TIMESTAMP) VALUES " .
04272                                          "(NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
04273                                 $ilDB->quote("$user_id"),
04274                                 $ilDB->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
04275                                 $ilDB->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
04276                                 $ilDB->quote(sprintf("%01d", $settings_array["timeofwork"])),
04277                                 $ilDB->quote(sprintf("%01d", $settings_array["atimeofwork"])),
04278                                 $ilDB->quote(sprintf("%01d", $settings_array["firstvisit"])),
04279                                 $ilDB->quote(sprintf("%01d", $settings_array["lastvisit"])),
04280                                 $ilDB->quote(sprintf("%01d", $settings_array["resultspoints"])),
04281                                 $ilDB->quote(sprintf("%01d", $settings_array["resultsmarks"])),
04282                                 $ilDB->quote(sprintf("%01d", $settings_array["distancemedian"]))
04283                         );
04284                 }
04285                         else
04286                 {
04287                         $q = sprintf("UPDATE tst_eval_settings SET ".
04288                                          "qworkedthrough = %s, pworkedthrough = %s, timeofwork = %s, atimeofwork = %s, firstvisit = %s, " .
04289                                          "lastvisit = %s, resultspoints = %s, resultsmarks = %s, distancemedian = %s " .
04290                                          "WHERE eval_settings_id = %s",
04291                                 $ilDB->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
04292                                 $ilDB->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
04293                                 $ilDB->quote(sprintf("%01d", $settings_array["timeofwork"])),
04294                                 $ilDB->quote(sprintf("%01d", $settings_array["atimeofwork"])),
04295                                 $ilDB->quote(sprintf("%01d", $settings_array["firstvisit"])),
04296                                 $ilDB->quote(sprintf("%01d", $settings_array["lastvisit"])),
04297                                 $ilDB->quote(sprintf("%01d", $settings_array["resultspoints"])),
04298                                 $ilDB->quote(sprintf("%01d", $settings_array["resultsmarks"])),
04299                                 $ilDB->quote(sprintf("%01d", $settings_array["distancemedian"])),
04300                                 $ilDB->quote("$update")
04301                         );
04302                 }
04303                 $result = $ilDB->query($q);
04304         }
04305 
04314         function getCompleteWorkingTime($user_id)
04315         {
04316                 global $ilDB;
04317 
04318                 $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",
04319                         $ilDB->quote($this->getTestId()),
04320                         $ilDB->quote($user_id)
04321                 );
04322                 $result = $ilDB->query($q);
04323                 $time = 0;
04324                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04325                 {
04326                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04327                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04328                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04329                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04330                         $time += ($epoch_2 - $epoch_1);
04331                 }
04332                 return $time;
04333         }
04334 
04343         function &evalStatistical($active_id)
04344         {
04345                 global $ilDB;
04346 //              global $ilBench;
04347                 $pass = ilObjTest::_getResultPass($active_id);
04348                 $test_result =& $this->getTestResult($active_id, $pass);
04349                 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
04350                         $ilDB->quote($active_id)
04351                 );
04352                 $result = $ilDB->query($q);
04353                 $times = array();
04354                 $first_visit = 0;
04355                 $last_visit = 0;
04356                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
04357                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04358                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04359                         if (!$first_visit) {
04360                                 $first_visit = $epoch_1;
04361                         }
04362                         if ($epoch_1 < $first_visit) {
04363                                 $first_visit = $epoch_1;
04364                         }
04365                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04366                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04367                         if (!$last_visit) {
04368                                 $last_visit = $epoch_2;
04369                         }
04370                         if ($epoch_2 > $last_visit) {
04371                                 $last_visit = $epoch_2;
04372                         }
04373                         $times[$row->active_fi] += ($epoch_2 - $epoch_1);
04374                 }
04375                 $max_time = 0;
04376                 foreach ($times as $key => $value) {
04377                         $max_time += $value;
04378                 }
04379                 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
04380                 {
04381                         $percentage = 0.0;
04382                 }
04383                 else
04384                 {
04385                         $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
04386                         if ($percentage < 0) $percentage = 0.0;
04387                 }
04388                 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
04389                 $first_date = getdate($first_visit);
04390                 $last_date = getdate($last_visit);
04391                 $qworkedthrough = 0;
04392                 foreach ($test_result as $key => $value)
04393                 {
04394                         if (preg_match("/\d+/", $key))
04395                         {
04396                                 $qworkedthrough += $value["workedthrough"];
04397                         }
04398                 }
04399                 if (!$qworkedthrough)
04400                 {
04401                         $atimeofwork = 0;
04402                 }
04403                 else
04404                 {
04405                         $atimeofwork = $max_time / $qworkedthrough;
04406                 }
04407                 $result_mark = "";
04408                 $passed = "";
04409                 if ($mark_obj)
04410                 {
04411                         $result_mark = $mark_obj->getShortName();
04412                         if ($mark_obj->getPassed())
04413                         {
04414                                 $passed = 1;
04415                         }
04416                         else
04417                         {
04418                                 $passed = 0;
04419                         }
04420                 }
04421                 $percent_worked_through = 0;
04422                 if (count($this->questions))
04423                 {
04424                         $percent_worked_through = $qworkedthrough / count($this->questions);
04425                 }
04426                 $result_array = array(
04427                         "qworkedthrough" => $qworkedthrough,
04428                         "qmax" => count($this->questions),
04429                         "pworkedthrough" => $percent_worked_through,
04430                         "timeofwork" => $max_time,
04431                         "atimeofwork" => $atimeofwork,
04432                         "firstvisit" => $first_date,
04433                         "lastvisit" => $last_date,
04434                         "resultspoints" => $test_result["test"]["total_reached_points"],
04435                         "maxpoints" => $test_result["test"]["total_max_points"],
04436                         "resultsmarks" => $result_mark,
04437                         "passed" => $passed,
04438                         "distancemedian" => "0"
04439                 );
04440                 foreach ($test_result as $key => $value)
04441                 {
04442                         if (preg_match("/\d+/", $key))
04443                         {
04444                                 $result_array[$key] = $value;
04445                         }
04446                 }
04447                 return $result_array;
04448         }
04449 
04459         function &getTotalPointsArray()
04460         {
04461                 $totalpoints_array = array();
04462                 $all_users =& $this->evalTotalParticipantsArray();
04463                 foreach ($all_users as $active_id => $user_name)
04464                 {
04465                         $test_result =& $this->getTestResult($active_id);
04466                         array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
04467                 }
04468                 return $totalpoints_array;
04469         }
04470 
04480         function &getTotalPointsPassedArray()
04481         {
04482                 $totalpoints_array = array();
04483                 $all_users =& $this->evalTotalParticipantsArray();
04484                 foreach ($all_users as $active_id => $user_name)
04485                 {
04486                         $test_result =& $this->getTestResult($active_id);
04487                         $reached = $test_result["test"]["total_reached_points"];
04488                         $total = $test_result["test"]["total_max_points"];
04489                         $percentage = $total != 0 ? $reached/$total : 0;
04490                         $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
04491                         if ($mark)
04492                         {
04493                                 if ($mark->getPassed())
04494                                 {
04495                                         array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
04496                                 }
04497                         }
04498                 }
04499                 return $totalpoints_array;
04500         }
04501 
04510         function &evalTotalPersonsArray($name_sort_order = "asc")
04511         {
04512                 global $ilDB;
04513                 $q = sprintf("SELECT tst_active.active_id, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04514                         $ilDB->quote($this->getTestId())
04515                 );
04516                 $result = $ilDB->query($q);
04517                 $persons_array = array();
04518                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04519                 {
04520                         if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04521                         {
04522                                 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
04523                         }
04524                         else
04525                         {
04526                                 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04527                                 {
04528                                         $persons_array[$row["active_id"]] = $row["lastname"];
04529                                 }
04530                                 else
04531                                 {
04532                                         $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " .  $row["title"]);
04533                                 }
04534                                 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
04535                                 {
04536                                         $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
04537                                 }
04538                         }
04539                 }
04540                 return $persons_array;
04541         }
04542 
04551         function &evalTotalParticipantsArray($name_sort_order = "asc")
04552         {
04553                 global $ilDB;
04554                 $q = sprintf("SELECT tst_active.active_id, usr_data.login, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04555                         $ilDB->quote($this->getTestId())
04556                 );
04557                 $result = $ilDB->query($q);
04558                 $persons_array = array();
04559                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04560                 {
04561                         if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04562                         {
04563                                 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
04564                         }
04565                         else
04566                         {
04567                                 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04568                                 {
04569                                         $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
04570                                 }
04571                                 else
04572                                 {
04573                                         $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " .  $row["title"]), "login" => $row["login"]);
04574                                 }
04575                                 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
04576                                 {
04577                                         $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
04578                                 }
04579                         }
04580                 }
04581                 return $persons_array;
04582         }
04583 
04592         function evalTotalFinished()
04593         {
04594                 global $ilDB;
04595 
04596                 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
04597                         $ilDB->quote($this->getTestId())
04598                 );
04599                 $result = $ilDB->query($q);
04600                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
04601                 return $row->total;
04602         }
04603 
04612         function evalTotalStartedAverageTime()
04613         {
04614                 global $ilDB;
04615 
04616                 $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",
04617                         $ilDB->quote($this->getTestId())
04618                 );
04619                 $result = $ilDB->query($q);
04620                 $times = array();
04621                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04622                 {
04623                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04624                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04625                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04626                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04627                         $times[$row->active_fi] += ($epoch_2 - $epoch_1);
04628                 }
04629                 $max_time = 0;
04630                 $counter = 0;
04631                 foreach ($times as $key => $value)
04632                 {
04633                         $max_time += $value;
04634                         $counter++;
04635                 }
04636                 if ($counter)
04637                 {
04638                         $average_time = round($max_time / $counter);
04639                 }
04640                         else
04641                 {
04642                         $average_time = 0;
04643                 }
04644                 return $average_time;
04645         }
04646 
04655         function evalTotalPassedAverageTime()
04656         {
04657                 global $ilDB;
04658 
04659                 include_once "./assessment/classes/class.ilObjTestAccess.php";
04660                 $passed_users =& ilObjTest::_getPassedUsers($this->getId());
04661                 $q = sprintf("SELECT tst_times.*, tst_active.active_id FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
04662                         $ilDB->quote($this->getTestId())
04663                 );
04664                 $result = $ilDB->query($q);
04665                 $times = array();
04666                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04667                 {
04668                         if (in_array($row->active_id, $passed_users))
04669                         {
04670                                 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04671                                 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04672                                 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04673                                 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04674                                 $times[$row->active_id] += ($epoch_2 - $epoch_1);
04675                         }
04676                 }
04677                 $max_time = 0;
04678                 $counter = 0;
04679                 foreach ($times as $key => $value)
04680                 {
04681                         $max_time += $value;
04682                         $counter++;
04683                 }
04684                 if ($counter)
04685                 {
04686                         $average_time = round($max_time / $counter);
04687                 }
04688                         else
04689                 {
04690                         $average_time = 0;
04691                 }
04692                 return $average_time;
04693         }
04694 
04703         function &getAvailableQuestionpoolIDs()
04704         {
04705                 global $rbacsystem;
04706                 global $ilDB;
04707 
04708                 $result_array = array();
04709                 $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'";
04710                 $result = $ilDB->query($query);
04711                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04712                 {
04713                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
04714                         {
04715                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
04716                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
04717                                 {
04718                                         array_push($result_array, $row->obj_id);
04719                                 }
04720                         }
04721                 }
04722                 return $result_array;
04723         }
04724 
04733         function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $with_questioncount = FALSE)
04734         {
04735                 global $rbacsystem;
04736                 global $ilDB;
04737 
04738                 $result_array = array();
04739                 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id, qpl_questionpool.* FROM object_data, object_reference, qpl_questionpool WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questionpool.obj_fi ORDER BY object_data.title";
04740                 $result = $ilDB->query($query);
04741                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04742                 {
04743                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
04744                         {
04745                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
04746                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id) || $could_be_offline)
04747                                 {
04748                                         if ((!$equal_points) || (($equal_points) && (ilObjQuestionPool::_hasEqualPoints($row->obj_id))))
04749                                         {
04750                                                 $qpl_title = $row->title;
04751                                                 if ($with_questioncount)
04752                                                 {
04753                                                         if ($row->questioncount == 1)
04754                                                         {
04755                                                                 $qpl_title .= " (" . $row->questioncount . " " . $this->lng->txt("ass_question") . ")";
04756                                                         }
04757                                                         else
04758                                                         {
04759                                                                 $qpl_title .= " (" . $row->questioncount . " " . $this->lng->txt("assQuestions") . ")";
04760                                                         }
04761                                                 }
04762                                                 if ($use_object_id)
04763                                                 {
04764                                                         $result_array[$row->obj_id] = array("title" => $qpl_title, "count" => $row->questioncount);
04765                                                 }
04766                                                 else
04767                                                 {
04768                                                         $result_array[$row->ref_id] = array("title" => $qpl_title, "count" => $row->questioncount);
04769                                                 }
04770                                         }
04771                                 }
04772                         }
04773                 }
04774                 return $result_array;
04775         }
04776 
04785         function getEstimatedWorkingTime()
04786         {
04787                 $time_in_seconds = 0;
04788                 foreach ($this->questions as $question_id)
04789                 {
04790                         $question =& ilObjTest::_instanciateQuestion($question_id);
04791                         $est_time = $question->getEstimatedWorkingTime();
04792                         $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
04793                 }
04794                 $hours = (int)($time_in_seconds / 3600) ;
04795                 $time_in_seconds = $time_in_seconds - ($hours * 3600);
04796                 $minutes = (int)($time_in_seconds / 60);
04797                 $time_in_seconds = $time_in_seconds - ($minutes * 60);
04798                 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
04799                 return $result;
04800         }
04801 
04814         function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
04815         {
04816                 global $rbacsystem;
04817                 global $ilDB;
04818                 // get the questionpool id if a questionpool ref id was entered
04819                 if ($questionpool != 0)
04820                 {
04821                         // retrieve object id
04822                         if (!$use_obj_id)
04823                         {
04824                                 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
04825                                         $ilDB->quote("$questionpool")
04826                                 );
04827                                 $result = $ilDB->query($query);
04828                                 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04829                                 $questionpool = $row[0];
04830                         }
04831                 }
04832 
04833                 // get all existing questions in the test
04834                 $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",
04835                         $ilDB->quote($this->getTestId() . "")
04836                 );
04837                 $result = $ilDB->query($query);
04838                 $original_ids = array();
04839                 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04840                 {
04841                         if (strcmp($row[0], "") != 0)
04842                         {
04843                                 array_push($original_ids, $row[0]);
04844                         }
04845                 }
04846                 $original_clause = "";
04847                 if (count($original_ids))
04848                 {
04849                         $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
04850                 }
04851 
04852                 // get a list of questionpools which are not allowed for the test (only for random selection of questions in test questions editor)
04853                 if (($questionpool == 0) && (!is_array($qpls)))
04854                 {
04855                         $available_pools =& $this->getAvailableQuestionpoolIDs();
04856                         $available = "";
04857                         $constraint_qpls = "";
04858                         if (count($available_pools))
04859                         {
04860                                 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
04861                         }
04862                         else
04863                         {
04864                                 return array();
04865                         }
04866                 }
04867 
04868                 $result_array = array();
04869                 if ($questionpool == 0)
04870                 {
04871                         if (is_array($qpls))
04872                         {
04873                                 if (count($qpls) > 0)
04874                                 {
04875                                         $qplidx = array();
04876                                         foreach ($qpls as $idx => $arr)
04877                                         {
04878                                                 array_push($qplidx, $arr["qpl"]);
04879                                         }
04880                                         $constraint_qpls = " AND qpl_questions.obj_fi IN (" . join($qplidx, ",") . ")";
04881                                 }
04882                         }
04883                         $query = "SELECT COUNT(question_id) FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
04884                 }
04885                         else
04886                 {
04887                         $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
04888                                 $ilDB->quote("$questionpool")
04889                         );
04890                 }
04891                 $result = $ilDB->query($query);
04892                 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04893                 if (($row[0]) <= $nr_of_questions)
04894                 {
04895                         // take all available questions
04896                         if ($questionpool == 0)
04897                         {
04898                                 $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
04899                         }
04900                                 else
04901                         {
04902                                 $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",
04903                                         $ilDB->quote("$questionpool")
04904                                 );
04905                         }
04906                         $result = $ilDB->query($query);
04907                         while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04908                         {
04909                                 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
04910                                 {
04911                                         $result_array[$row[0]] = $row[0];
04912                                 }
04913                         }
04914                 }
04915                         else
04916                 {
04917                         // select a random number out of the maximum number of questions
04918                         mt_srand((double)microtime()*1000000);
04919                         $random_number = mt_rand(0, $row[0] - 1);
04920                         $securitycounter = 500;
04921                         while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
04922                         {
04923                                 if ($questionpool == 0)
04924                                 {
04925                                         $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1";
04926                                 }
04927                                         else
04928                                 {
04929                                         $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",
04930                                                 $ilDB->quote("$questionpool")
04931                                         );
04932                                 }
04933                                 $result = $ilDB->query($query);
04934                                 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04935                                 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
04936                                 {
04937                                         $result_array[$result_row[0]] = $result_row[0];
04938                                 }
04939                                 $random_number = mt_rand(0, $row[0] - 1);
04940                                 $securitycounter--;
04941                         }
04942                 }
04943                 return $result_array;
04944         }
04945 
04954         function getImagePath()
04955         {
04956                 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
04957         }
04958 
04967         function getImagePathWeb()
04968         {
04969                 include_once "./classes/class.ilUtil.php";
04970                 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
04971                 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
04972         }
04973 
04984   function &createQuestionGUI($question_type, $question_id = -1)
04985         {
04986     if ((!$question_type) and ($question_id > 0))
04987                 {
04988                         $question_type = $this->getQuestionType($question_id);
04989     }
04990                 include_once "./assessment/classes/class.".$question_type."GUI.php";
04991                 $question_type_gui = $question_type . "GUI";
04992                 $question =& new $question_type_gui();
04993                 if ($question_id > 0)
04994                 {
04995                         $question->object->loadFromDb($question_id);
04996                 }
04997                 return $question;
04998   }
04999 
05009   function &_instanciateQuestion($question_id)
05010         {
05011                 if (strcmp($question_id, "") != 0)
05012                 {
05013                         include_once "./assessment/classes/class.assQuestion.php";
05014                         $question_type = assQuestion::_getQuestionType($question_id);
05015 
05016                         if(!strlen($question_type))
05017                         {
05018                                 return false;
05019                         }
05020 
05021                         include_once "./assessment/classes/class.".$question_type.".php";
05022                         $question = new $question_type();
05023 
05024                         $question->loadFromDb($question_id);
05025                         return $question;
05026                 }
05027   }
05028 
05039         function moveQuestions($move_questions, $target_index, $insert_mode)
05040         {
05041                 $this->questions = array_values($this->questions);
05042                 $array_pos = array_search($target_index, $this->questions);
05043                 if ($insert_mode == 0)
05044                 {
05045                         $part1 = array_slice($this->questions, 0, $array_pos);
05046                         $part2 = array_slice($this->questions, $array_pos);
05047                 }
05048                 else if ($insert_mode == 1)
05049                 {
05050                         $part1 = array_slice($this->questions, 0, $array_pos + 1);
05051                         $part2 = array_slice($this->questions, $array_pos + 1);
05052                 }
05053                 foreach ($move_questions as $question_id)
05054                 {
05055                         if (!(array_search($question_id, $part1) === FALSE))
05056                         {
05057                                 unset($part1[array_search($question_id, $part1)]);
05058                         }
05059                         if (!(array_search($question_id, $part2) === FALSE))
05060                         {
05061                                 unset($part2[array_search($question_id, $part2)]);
05062                         }
05063                 }
05064                 $part1 = array_values($part1);
05065                 $part2 = array_values($part2);
05066                 $new_array = array_values(array_merge($part1, $move_questions, $part2));
05067                 $this->questions = array();
05068                 $counter = 1;
05069                 foreach ($new_array as $question_id)
05070                 {
05071                         $this->questions[$counter] = $question_id;
05072                         $counter++;
05073                 }
05074                 $this->saveQuestionsToDb();
05075         }
05076 
05077 
05087         function startingTimeReached()
05088         {
05089                 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST)
05090                 {
05091                         if ($this->getStartingTime())
05092                         {
05093                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
05094                                 {
05095                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05096                                         $now = mktime();
05097                                         if ($now < $epoch_time)
05098                                         {
05099                                                 // starting time not reached
05100                                                 return false;
05101                                         }
05102                                 }
05103                         }
05104                 }
05105                 return true;
05106         }
05107 
05117         function endingTimeReached()
05118         {
05119                 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST)
05120                 {
05121                         if ($this->getEndingTime())
05122                         {
05123                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
05124                                 {
05125                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05126                                         $now = mktime();
05127                                         if ($now > $epoch_time)
05128                                         {
05129                                                 // ending time reached
05130                                                 return true;
05131                                         }
05132                                 }
05133                         }
05134                 }
05135                 return false;
05136         }
05137 
05145         function getQuestionsTable($sort, $sortorder, $filter_text, $sel_filter_type, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
05146         {
05147                 global $ilUser;
05148                 global $ilDB;
05149 
05150                 $where = "";
05151                 if (strlen($filter_text) > 0) {
05152                         switch($sel_filter_type) {
05153                                 case "title":
05154                                         $where = " AND qpl_questions.title LIKE " . $ilDB->quote("%" . $filter_text . "%");
05155                                         break;
05156                                 case "comment":
05157                                         $where = " AND qpl_questions.comment LIKE " . $ilDB->quote("%" . $filter_text . "%");
05158                                         break;
05159                                 case "author":
05160                                         $where = " AND qpl_questions.author LIKE " . $ilDB->quote("%" . $filter_text . "%");
05161                                         break;
05162                         }
05163                 }
05164 
05165                 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
05166                 {
05167                         $where .= " AND qpl_question_type.type_tag = " . $ilDB->quote($filter_question_type);
05168                 }
05169 
05170                 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
05171                 {
05172                         $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
05173                 }
05174 
05175     // build sort order for sql query
05176                 $order = "";
05177                 $images = array();
05178                 include_once "./classes/class.ilUtil.php";
05179                 switch($sort) 
05180                 {
05181                         case "title":
05182                                 $order = " ORDER BY title $sortorder";
05183                                 $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05184                                 break;
05185                         case "comment":
05186                                 $order = " ORDER BY comment $sortorder";
05187                                 $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05188                                 break;
05189                         case "type":
05190                                 $order = " ORDER BY question_type_id $sortorder";
05191                                 $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05192                                 break;
05193                         case "author":
05194                                 $order = " ORDER BY author $sortorder";
05195                                 $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05196                                 break;
05197                         case "created":
05198                                 $order = " ORDER BY created $sortorder";
05199                                 $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05200                                 break;
05201                         case "updated":
05202                                 $order = " ORDER BY TIMESTAMP14 $sortorder";
05203                                 $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05204                                 break;
05205                         case "qpl":
05206                                 $order = " ORDER BY obj_fi $sortorder";
05207                                 $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05208                                 break;
05209                 }
05210                 $maxentries = $ilUser->prefs["hits_per_page"];
05211                 if ($maxentries < 1)
05212                 {
05213                         $maxentries = 9999;
05214                 }
05215                 $available_pools =& $this->getAvailableQuestionpoolIDs();
05216                 $available = "";
05217                 if (count($available_pools))
05218                 {
05219                         $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
05220                 }
05221                 else
05222                 {
05223                         return array();
05224                 }
05225                 if ($completeonly)
05226                 {
05227                         $available .= " AND qpl_questions.complete = " . $ilDB->quote("1");
05228                 }
05229 
05230                 // get all questions in the test
05231                 $query = sprintf("SELECT qpl_questions.original_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
05232                         $ilDB->quote($this->getTestId() . "")
05233                 );
05234                 $result = $ilDB->query($query);
05235                 $original_ids = array();
05236                 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
05237                 {
05238                         if (strcmp($row[0], "") != 0)
05239                         {
05240                                 array_push($original_ids, $row[0]);
05241                         }
05242                 }
05243                 $original_clause = " ISNULL(qpl_questions.original_id)";
05244                 if (count($original_ids))
05245                 {
05246                         $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
05247                 }
05248 
05249                 $query = "SELECT qpl_questions.question_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, qpl_question_type WHERE $original_clause$available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05250     $query_result = $ilDB->query($query);
05251                 $max = $query_result->numRows();
05252                 if ($startrow > $max -1)
05253                 {
05254                         $startrow = $max - ($max % $maxentries);
05255                 }
05256                 else if ($startrow < 0)
05257                 {
05258                         $startrow = 0;
05259                 }
05260                 $limit = " LIMIT $startrow, $maxentries";
05261                 $query = "SELECT qpl_questions.*, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type WHERE $original_clause $available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05262     $query_result = $ilDB->query($query);
05263                 $rows = array();
05264                 if ($query_result->numRows())
05265                 {
05266                         while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
05267                         {
05268                                 array_push($rows, $row);
05269                         }
05270                 }
05271                 $nextrow = $startrow + $maxentries;
05272                 if ($nextrow > $max - 1)
05273                 {
05274                         $nextrow = $startrow;
05275                 }
05276                 $prevrow = $startrow - $maxentries;
05277                 if ($prevrow < 0)
05278                 {
05279                         $prevrow = 0;
05280                 }
05281                 return array(
05282                         "rows" => $rows,
05283                         "images" => $images,
05284                         "startrow" => $startrow,
05285                         "nextrow" => $nextrow,
05286                         "prevrow" => $prevrow,
05287                         "step" => $maxentries,
05288                         "rowcount" => $max
05289                 );
05290         }
05291 
05301         function _getTestType($active_id)
05302         {
05303                 global $ilDB;
05304 
05305                 $result = "";
05306                 $query = sprintf("SELECT tst_test_type.type_tag FROM tst_test_type, tst_tests, tst_active WHERE tst_test_type.test_type_id = tst_tests.test_type_fi AND tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
05307                         $ilDB->quote($active_id . "")
05308                 );
05309                 $query_result = $ilDB->query($query);
05310                 if ($query_result->numRows())
05311                 {
05312                         $row = $query_result->fetchRow(DB_FETCHMODE_ASSOC);
05313                         $result = $row["type_tag"];
05314                 }
05315                 return $result;
05316         }
05317 
05326         function &_getQuestiontypes()
05327         {
05328                 global $ilDB;
05329 
05330                 $questiontypes = array();
05331                 $query = "SELECT * FROM qpl_question_type ORDER BY type_tag";
05332                 $query_result = $ilDB->query($query);
05333                 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
05334                 {
05335                         $questiontypes[$this->lng->txt($row["type_tag"])] = $row;
05336                 }
05337                 ksort($questiontypes);
05338                 return $questiontypes;
05339         }
05340 
05349         function fromXML(&$assessment)
05350         {
05351                 unset($_SESSION["import_mob_xhtml"]);
05352 
05353                 $this->setDescription($assessment->getComment());
05354                 $this->setTitle($assessment->getTitle());
05355 
05356                 foreach ($assessment->objectives as $objectives)
05357                 {
05358                         foreach ($objectives->materials as $material)
05359                         {
05360                                 $this->setIntroduction($this->QTIMaterialToString($material));
05361                         }
05362                 }
05363                 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
05364                 {
05365                         switch ($assessmentcontrol->getSolutionswitch())
05366                         {
05367                                 case "Yes":
05368                                         $this->setInstantVerification(1);
05369                                         break;
05370                                 default:
05371                                         $this->setInstantVerification(0);
05372                                         break;
05373                         }
05374                 }
05375 
05376                 foreach ($assessment->qtimetadata as $metadata)
05377                 {
05378                         switch ($metadata["label"])
05379                         {
05380                                 case "test_type":
05381                                         $this->setTestType($metadata["entry"]);
05382                                         break;
05383                                 case "sequence_settings":
05384                                         $this->setSequenceSettings($metadata["entry"]);
05385                                         break;
05386                                 case "author":
05387                                         $this->setAuthor($metadata["entry"]);
05388                                         break;
05389                                 case "nr_of_tries":
05390                                         $this->setNrOfTries($metadata["entry"]);
05391                                         break;
05392                                 case "hide_previous_results":
05393                                         $this->setHidePreviousResults($metadata["entry"]);
05394                                         break;
05395                                 case "hide_title_points":
05396                                         $this->setHideTitlePoints($metadata["entry"]);
05397                                         break;
05398                                 case "random_test":
05399                                         $this->setRandomTest($metadata["entry"]);
05400                                         break;
05401                                 case "random_question_count":
05402                                         $this->setRandomQuestionCount($metadata["entry"]);
05403                                         break;
05404                                 case "show_solution_details":
05405                                         $this->setShowSolutionDetails($metadata["entry"]);
05406                                         break;
05407                                 case "instant_verification":
05408                                         $this->setInstantVerification($metadata["entry"]);
05409                                         break;
05410                                 case "show_solution_printview":
05411                                         $this->setShowSolutionPrintview($metadata["entry"]);
05412                                         break;
05413                                 case "score_reporting":
05414                                         $this->setScoreReporting($metadata["entry"]);
05415                                         break;
05416                                 case "shuffle_questions":
05417                                         $this->setShuffleQuestions($metadata["entry"]);
05418                                         break;
05419                                 case "count_system":
05420                                         $this->setCountSystem($metadata["entry"]);
05421                                         break;
05422                                 case "mc_scoring":
05423                                         $this->setMCScoring($metadata["entry"]);
05424                                         break;
05425                                 case "score_cutting":
05426                                         $this->setScoreCutting($metadata["entry"]);
05427                                         break;
05428                                 case "password":
05429                                         $this->setPassword($metadata["entry"]);
05430                                         break;
05431                                 case "allowedUsers":
05432                                         $this->setAllowedUsers($metadata["entry"]);
05433                                         break;
05434                                 case "allowedUsersTimeGap":
05435                                         $this->setAllowedUsersTimeGap($metadata["entry"]);
05436                                         break;
05437                                 case "pass_scoring":
05438                                         $this->setPassScoring($metadata["entry"]);
05439                                         break;
05440                                 case "show_summary":
05441                                         $this->setShowSummary($metadata["entry"]);
05442                                         break;
05443                                 case "reporting_date":
05444                                         $iso8601period = $metadata["entry"];
05445                                         if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05446                                         {
05447                                                 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05448                                         }
05449                                         break;
05450                                 case "starting_time":
05451                                         $iso8601period = $metadata["entry"];
05452                                         if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05453                                         {
05454                                                 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05455                                         }
05456                                         break;
05457                                 case "ending_time":
05458                                         $iso8601period = $metadata["entry"];
05459                                         if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05460                                         {
05461                                                 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05462                                         }
05463                                         break;
05464                         }
05465                         if (preg_match("/mark_step_\d+/", $metadata["label"]))
05466                         {
05467                                 $xmlmark = $metadata["entry"];
05468                                 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
05469                                 $mark_short = $matches[1];
05470                                 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
05471                                 $mark_official = $matches[1];
05472                                 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
05473                                 $mark_percentage = $matches[1];
05474                                 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
05475                                 $mark_passed = $matches[1];
05476                                 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
05477                         }
05478                 }
05479                 // handle the import of media objects in XHTML code
05480                 if (is_array($_SESSION["import_mob_xhtml"]))
05481                 {
05482                         include_once "./content/classes/Media/class.ilObjMediaObject.php";
05483                         include_once "./Services/RTE/classes/class.ilRTE.php";
05484                         include_once "./assessment/classes/class.ilObjQuestionPool.php";
05485                         foreach ($_SESSION["import_mob_xhtml"] as $mob)
05486                         {
05487                                 $importfile = $this->getImportDirectory() . "/" . $_SESSION["tst_import_subdir"] . "/" . $mob["uri"];
05488                                 if (file_exists($importfile))
05489                                 {
05490                                         $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
05491                                         ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
05492                                         $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
05493                                 }
05494                                 else
05495                                 {
05496                                         global $ilLog;
05497                                         $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
05498                                 }
05499                         }
05500                         $this->saveToDb();
05501                 }
05502         }
05503 
05512         function to_xml()
05513         {
05514                 include_once("./classes/class.ilXmlWriter.php");
05515                 $a_xml_writer = new ilXmlWriter;
05516                 // set xml header
05517                 $a_xml_writer->xmlHeader();
05518                 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
05519                 $a_xml_writer->xmlStartTag("questestinterop");
05520 
05521                 $attrs = array(
05522                         "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
05523                         "title" => $this->getTitle()
05524                 );
05525                 $a_xml_writer->xmlStartTag("assessment", $attrs);
05526                 // add qti comment
05527                 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
05528 
05529                 // add qti duration
05530                 if ($this->enable_processing_time)
05531                 {
05532                         preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
05533                         $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
05534                 }
05535 
05536                 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
05537                 $a_xml_writer->xmlStartTag("qtimetadata");
05538                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05539                 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
05540                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
05541                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05542 
05543                 // test type
05544                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05545                 $a_xml_writer->xmlElement("fieldlabel", NULL, "test_type");
05546                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getTestType());
05547                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05548 
05549                 // sequence settings
05550                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05551                 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
05552                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
05553                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05554 
05555                 // author
05556                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05557                 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
05558                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
05559                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05560 
05561                 // count system
05562                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05563                 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
05564                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
05565                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05566 
05567                 // multiple choice scoring
05568                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05569                 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
05570                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
05571                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05572 
05573                 // multiple choice scoring
05574                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05575                 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
05576                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
05577                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05578 
05579                 // multiple choice scoring
05580                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05581                 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
05582                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
05583                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05584 
05585                 // allowed users
05586                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05587                 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
05588                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
05589                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05590 
05591                 // allowed users time gap
05592                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05593                 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
05594                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
05595                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05596 
05597                 // pass scoring
05598                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05599                 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
05600                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
05601                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05602 
05603                 // score reporting date
05604                 if ($this->getReportingDate())
05605                 {
05606                         $a_xml_writer->xmlStartTag("qtimetadatafield");
05607                         $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
05608                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
05609                         $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05610                         $a_xml_writer->xmlEndTag("qtimetadatafield");
05611                 }
05612                 // number of tries
05613                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05614                 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
05615                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
05616                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05617 
05618                 // hide previous results
05619                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05620                 $a_xml_writer->xmlElement("fieldlabel", NULL, "hide_previous_results");
05621                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getHidePreviousResults());
05622                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05623 
05624                 // hide title points
05625                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05626                 $a_xml_writer->xmlElement("fieldlabel", NULL, "hide_title_points");
05627                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getHideTitlePoints()));
05628                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05629 
05630                 // random test
05631                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05632                 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_test");
05633                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isRandomTest()));
05634                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05635 
05636                 // random question count
05637                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05638                 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_question_count");
05639                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getRandomQuestionCount()));
05640                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05641 
05642                 // solution details
05643                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05644                 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_solution_details");
05645                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSolutionDetails()));
05646                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05647 
05648                 // solution details
05649                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05650                 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
05651                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSummary()));
05652                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05653 
05654                 // solution details
05655                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05656                 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
05657                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
05658                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05659 
05660                 // solution details
05661                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05662                 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
05663                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantVerification()));
05664                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05665 
05666                 // solution printview
05667                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05668                 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_solution_printview");
05669                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSolutionPrintview()));
05670                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05671 
05672                 // shuffle questions
05673                 $a_xml_writer->xmlStartTag("qtimetadatafield");
05674                 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
05675                 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
05676                 $a_xml_writer->xmlEndTag("qtimetadatafield");
05677 
05678                 // starting time
05679                 if ($this->getStartingTime())
05680                 {
05681                         $a_xml_writer->xmlStartTag("qtimetadatafield");
05682                         $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
05683                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
05684                         $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05685                         $a_xml_writer->xmlEndTag("qtimetadatafield");
05686                 }
05687                 // ending time
05688                 if ($this->getEndingTime())
05689                 {
05690                         $a_xml_writer->xmlStartTag("qtimetadatafield");
05691                         $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
05692                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
05693                         $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05694                         $a_xml_writer->xmlEndTag("qtimetadatafield");
05695                 }
05696                 foreach ($this->mark_schema->mark_steps as $index => $mark)
05697                 {
05698                         // mark steps
05699                         $a_xml_writer->xmlStartTag("qtimetadatafield");
05700                         $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
05701                         $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>", $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()));
05702                         $a_xml_writer->xmlEndTag("qtimetadatafield");
05703                 }
05704                 $a_xml_writer->xmlEndTag("qtimetadata");
05705 
05706                 // add qti objectives
05707                 $a_xml_writer->xmlStartTag("objectives");
05708                 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
05709                 $a_xml_writer->xmlEndTag("objectives");
05710 
05711                 // add qti assessmentcontrol
05712                 if ($this->getInstantVerification() == 1)
05713                 {
05714                         $attrs = array(
05715                                 "solutionswitch" => "Yes"
05716                         );
05717                 }
05718                 else
05719                 {
05720                         $attrs = NULL;
05721                 }
05722                 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
05723 
05724                 $attrs = array(
05725                         "ident" => "1"
05726                 );
05727                 $a_xml_writer->xmlElement("section", $attrs, NULL);
05728                 $a_xml_writer->xmlEndTag("assessment");
05729                 $a_xml_writer->xmlEndTag("questestinterop");
05730 
05731                 $xml = $a_xml_writer->xmlDumpMem(FALSE);
05732 
05733                 foreach ($this->questions as $question_id)
05734                 {
05735                         $question =& ilObjTest::_instanciateQuestion($question_id);
05736                         $qti_question = $question->to_xml(false);
05737                         $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
05738                         $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
05739                         if (strpos($xml, "</section>") !== false)
05740                         {
05741                                 $xml = str_replace("</section>", "$qti_question</section>", $xml);
05742                         }
05743                         else
05744                         {
05745                                 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
05746                         }
05747                 }
05748                 return $xml;
05749         }
05750 
05757         function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
05758         {
05759                 global $ilBench;
05760 
05761                 $this->mob_ids = array();
05762                 $this->file_ids = array();
05763 
05764                 $attrs = array();
05765                 $attrs["Type"] = "Test";
05766                 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
05767 
05768                 // MetaData
05769                 $this->exportXMLMetaData($a_xml_writer);
05770 
05771                 // PageObjects
05772                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
05773                 $ilBench->start("ContentObjectExport", "exportPageObjects");
05774                 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
05775                 $ilBench->stop("ContentObjectExport", "exportPageObjects");
05776                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
05777 
05778                 // MediaObjects
05779                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
05780                 $ilBench->start("ContentObjectExport", "exportMediaObjects");
05781                 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
05782                 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
05783                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
05784 
05785                 // FileItems
05786                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
05787                 $ilBench->start("ContentObjectExport", "exportFileItems");
05788                 $this->exportFileItems($a_target_dir, $expLog);
05789                 $ilBench->stop("ContentObjectExport", "exportFileItems");
05790                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
05791 
05792                 $a_xml_writer->xmlEndTag("ContentObject");
05793         }
05794 
05801         function exportXMLMetaData(&$a_xml_writer)
05802         {
05803                 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
05804                 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
05805                 $md2xml->setExportMode(true);
05806                 $md2xml->startExport();
05807                 $a_xml_writer->appendXML($md2xml->getXML());
05808         }
05809 
05817         function modifyExportIdentifier($a_tag, $a_param, $a_value)
05818         {
05819                 if ($a_tag == "Identifier" && $a_param == "Entry")
05820                 {
05821                         include_once "./classes/class.ilUtil.php";
05822                         $a_value = ilUtil::insertInstIntoID($a_value);
05823                 }
05824 
05825                 return $a_value;
05826         }
05827 
05828 
05835         function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
05836         {
05837                 global $ilBench;
05838 
05839                 include_once "./content/classes/class.ilLMPageObject.php";
05840 
05841                 foreach ($this->questions as $question_id)
05842                 {
05843                         $ilBench->start("ContentObjectExport", "exportPageObject");
05844                         $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
05845 
05846                         $attrs = array();
05847                         $a_xml_writer->xmlStartTag("PageObject", $attrs);
05848 
05849 
05850                         // export xml to writer object
05851                         $ilBench->start("ContentObjectExport", "exportPageObject_XML");
05852                         $page_object = new ilPageObject("qpl", $question_id);
05853                         $page_object->buildDom();
05854                         $page_object->insertInstIntoIDs($a_inst);
05855                         $mob_ids = $page_object->collectMediaObjects(false);
05856                         $file_ids = $page_object->collectFileItems();
05857                         $xml = $page_object->getXMLFromDom(false, false, false, "", true);
05858                         $xml = str_replace("&","&amp;", $xml);
05859                         $a_xml_writer->appendXML($xml);
05860                         $page_object->freeDom();
05861                         unset ($page_object);
05862 
05863                         $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
05864 
05865                         // collect media objects
05866                         $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
05867                         //$mob_ids = $page_obj->getMediaObjectIDs();
05868                         foreach($mob_ids as $mob_id)
05869                         {
05870                                 $this->mob_ids[$mob_id] = $mob_id;
05871                         }
05872                         $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
05873 
05874                         // collect all file items
05875                         $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
05876                         //$file_ids = $page_obj->getFileItemIds();
05877                         foreach($file_ids as $file_id)
05878                         {
05879                                 $this->file_ids[$file_id] = $file_id;
05880                         }
05881                         $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
05882 
05883                         $a_xml_writer->xmlEndTag("PageObject");
05884                         //unset($page_obj);
05885 
05886                         $ilBench->stop("ContentObjectExport", "exportPageObject");
05887 
05888 
05889                 }
05890         }
05891 
05898         function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
05899         {
05900                 include_once "./content/classes/Media/class.ilObjMediaObject.php";
05901 
05902                 foreach ($this->mob_ids as $mob_id)
05903                 {
05904                         $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
05905                         $media_obj = new ilObjMediaObject($mob_id);
05906                         $media_obj->exportXML($a_xml_writer, $a_inst);
05907                         $media_obj->exportFiles($a_target_dir);
05908                         unset($media_obj);
05909                 }
05910         }
05911 
05916         function exportFileItems($a_target_dir, &$expLog)
05917         {
05918                 include_once "./classes/class.ilObjFile.php";
05919 
05920                 foreach ($this->file_ids as $file_id)
05921                 {
05922                         $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
05923                         $file_obj = new ilObjFile($file_id, false);
05924                         $file_obj->export($a_target_dir);
05925                         unset($file_obj);
05926                 }
05927         }
05928 
05933         function getImportMapping()
05934         {
05935                 if (!is_array($this->import_mapping))
05936                 {
05937                         return array();
05938                 }
05939                 else
05940                 {
05941                         return $this->import_mapping;
05942                 }
05943         }
05944 
05955         function getECTSGrade($reached_points, $max_points)
05956         {
05957                 $passed_array =& $this->getTotalPointsPassedArray();
05958                 return ilObjTest::_getECTSGrade($passed_array, $reached_points, $max_points, $this->ects_grades["A"], $this->ects_grades["B"], $this->ects_grades["C"], $this->ects_grades["D"], $this->ects_grades["E"], $this->ects_fx);
05959         }
05960 
05971                 function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
05972                 {
05973                         include_once "./classes/class.ilStatistics.php";
05974                         // calculate the median
05975                         $passed_statistics = new ilStatistics();
05976                         $passed_statistics->setData($points_passed);
05977                         $ects_percentiles = array
05978                         (
05979                                 "A" => $passed_statistics->quantile($a),
05980                                 "B" => $passed_statistics->quantile($b),
05981                                 "C" => $passed_statistics->quantile($c),
05982                                 "D" => $passed_statistics->quantile($d),
05983                                 "E" => $passed_statistics->quantile($e)
05984                         );
05985                         if (count($passed_array) && ($reached_points >= $ects_percentiles["A"]))
05986                         {
05987                                 return "A";
05988                         }
05989                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["B"]))
05990                         {
05991                                 return "B";
05992                         }
05993                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["C"]))
05994                         {
05995                                 return "C";
05996                         }
05997                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["D"]))
05998                         {
05999                                 return "D";
06000                         }
06001                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["E"]))
06002                         {
06003                                 return "E";
06004                         }
06005                         else if (strcmp($fx, "") != 0)
06006                         {
06007                                 if ($max_points > 0)
06008                                 {
06009                                         $percentage = ($reached_points / $max_points) * 100.0;
06010                                         if ($percentage < 0) $percentage = 0.0;
06011                                 }
06012                                 else
06013                                 {
06014                                         $percentage = 0.0;
06015                                 }
06016                                 if ($percentage >= $fx)
06017                                 {
06018                                         return "FX";
06019                                 }
06020                                 else
06021                                 {
06022                                         return "F";
06023                                 }
06024                         }
06025                         else
06026                         {
06027                                 return "F";
06028                         }
06029         }
06030 
06031         function checkMarks()
06032         {
06033                 return $this->mark_schema->checkMarks();
06034         }
06035 
06036         function updateMetaData()
06037         {
06038                 global $ilUser;
06039                 include_once "./Services/MetaData/classes/class.ilMD.php";
06040                 $md =& new ilMD($this->getId(), 0, $this->getType());
06041                 $md_gen =& $md->getGeneral();
06042                 if ($md_gen == false)
06043                 {
06044                         include_once "./Services/MetaData/classes/class.ilMDCreator.php";
06045                         $md_creator = new ilMDCreator($this->getId(),0,$this->getType());
06046                         $md_creator->setTitle($this->getTitle());
06047                         $md_creator->setTitleLanguage($ilUser->getPref('language'));
06048                         $md_creator->create();
06049                 }
06050                 parent::updateMetaData();
06051         }
06052 
06061         function &_getAvailableTests($use_object_id = false)
06062         {
06063                 global $rbacsystem;
06064                 global $ilDB;
06065 
06066                 $result_array = array();
06067                 $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";
06068                 $result = $ilDB->query($query);
06069                 include_once "./classes/class.ilObject.php";
06070                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
06071                 {
06072                         if ($rbacsystem->checkAccess("write", $row->ref_id) && (ilObject::_hasUntrashedReference($row->obj_id)))
06073                         {
06074                                 if ($use_object_id)
06075                                 {
06076                                         $result_array[$row->obj_id] = $row->title;
06077                                 }
06078                                 else
06079                                 {
06080                                         $result_array[$row->ref_id] = $row->title;
06081                                 }
06082                         }
06083                 }
06084                 return $result_array;
06085         }
06086 
06095         function cloneRandomQuestions($new_id)
06096         {
06097                 global $ilDB;
06098 
06099                 if ($new_id > 0)
06100                 {
06101                         $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
06102                                 $ilDB->quote($this->getTestId() . "")
06103                         );
06104                         $result = $ilDB->query($query);
06105                         if ($result->numRows())
06106                         {
06107                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06108                                 {
06109                                         $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
06110                                                 $ilDB->quote($new_id . ""),
06111                                                 $ilDB->quote($row["questionpool_fi"] . ""),
06112                                                 $ilDB->quote($row["num_of_q"] . "")
06113                                         );
06114                                         $insertresult = $ilDB->query($query);
06115                                 }
06116                         }
06117                 }
06118         }
06119 
06120 
06128         function _clone($obj_id)
06129         {
06130                 $original = new ilObjTest($obj_id, false);
06131                 $original->loadFromDb();
06132 
06133                 $newObj = new ilObjTest();
06134                 $newObj->setType("tst");
06135     $counter = 2;
06136     while ($newObj->testTitleExists($newObj->getTitle() . " ($counter)"))
06137                 {
06138       $counter++;
06139     }
06140                 $newObj->setAuthor($original->getAuthor());
06141                 $newObj->setHideTitlePoints($original->getHideTitlePoints());
06142                 $newObj->setPassScoring($original->getPassScoring());
06143                 $newObj->setTitle($original->getTitle() . " ($counter)");
06144                 $newObj->setDescription($original->getDescription());
06145                 $newObj->create(true);
06146                 $newObj->createReference();
06147                 $newObj->putInTree($_GET["ref_id"]);
06148                 $newObj->setPermissions($_GET["ref_id"]);
06149                 $newObj->author = $original->getAuthor();
06150                 $newObj->introduction = $original->getIntroduction();
06151                 $newObj->mark_schema = $original->mark_schema;
06152                 $newObj->sequence_settings = $original->getSequenceSettings();
06153                 $newObj->score_reporting = $original->getScoreReporting();
06154                 $newObj->instant_verification = $original->getInstantVerification();
06155                 $newObj->reporting_date = $original->getReportingDate();
06156                 $newObj->test_type = $original->getTestType();
06157                 $newObj->nr_of_tries = $original->getNrOfTries();
06158                 $newObj->setHidePreviousResults($original->getHidePreviousResults());
06159                 $newObj->processing_time = $original->getProcessingTime();
06160                 $newObj->enable_processing_time = $original->getEnableProcessingTime();
06161                 $newObj->starting_time = $original->getStartingTime();
06162                 $newObj->ending_time = $original->getEndingTime();
06163                 $newObj->ects_output = $original->ects_output;
06164                 $newObj->ects_fx = $original->ects_fx;
06165                 $newObj->ects_grades = $original->ects_grades;
06166                 $newObj->random_test = $original->random_test;
06167                 $newObj->random_question_count = $original->random_question_count;
06168                 $newObj->setCountSystem($original->getCountSystem());
06169                 $newObj->setMCScoring($original->getMCScoring());
06170                 $newObj->saveToDb();
06171                 if ($original->isRandomTest())
06172                 {
06173                         $newObj->saveRandomQuestionCount($newObj->random_question_count);
06174                         $original->cloneRandomQuestions($newObj->getTestId());
06175                 }
06176                 else
06177                 {
06178                         // clone the questions
06179                         include_once "./assessment/classes/class.assQuestion.php";
06180                         foreach ($original->questions as $key => $question_id)
06181                         {
06182                                 $question = ilObjTest::_instanciateQuestion($question_id);
06183                                 $newObj->questions[$key] = $question->duplicate();
06184         //                      $question->id = -1;
06185                                 $original_id = assQuestion::_getOriginalId($question_id);
06186                                 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
06187                                 $question->saveToDb($original_id);
06188                         }
06189                 }
06190 
06191                 $newObj->saveToDb();
06192 
06193                 // clone meta data
06194                 include_once "./Services/MetaData/classes/class.ilMD.php";
06195                 $md = new ilMD($original->getId(),0,$original->getType());
06196                 $new_md =& $md->cloneMD($newObj->getId(),0,$newObj->getType());
06197                 return $newObj->getRefId();
06198         }
06199 
06200         function _getRefIdFromObjId($obj_id)
06201         {
06202                 global $ilDB;
06203 
06204                 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
06205                         $ilDB->quote($obj_id)
06206 
06207                 );
06208                 $result = $ilDB->query($query);
06209                 if ($result->numRows())
06210                 {
06211                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06212                         return $row["ref_id"];
06213                 }
06214                 return 0;
06215         }
06216 
06224         function &getEvaluationUsers($user_id, $sort_name_option = "asc")
06225         {
06226                 global $ilDB;
06227 
06228                 $users = array();
06229                 $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 ORDER BY usr_data.lastname " . strtoupper($sort_name_option),
06230                         $ilDB->quote($this->getTestId() . ""),
06231                         $ilDB->quote($user_id . "")
06232                 );
06233                 $result = $ilDB->query($query);
06234                 if ($result->numRows())
06235                 {
06236                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06237                         {
06238                                 $name = trim($row["lastname"] . ", " . $row["firstname"] ." " . $row["title"]);
06239                                 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
06240                                 {
06241                                         $name = $this->lng->txt("anonymous");
06242                                 }
06243                                 $users[$row["user_fi"]] = $name;
06244                         }
06245                 }
06246                 return $users;
06247         }
06248 
06256         function &getEvaluationParticipants($user_id, $sort_name_option = "asc")
06257         {
06258                 global $ilDB;
06259 
06260                 $users = array();
06261                 $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 ORDER BY usr_data.lastname " . strtoupper($sort_name_option),
06262                         $ilDB->quote($this->getTestId() . ""),
06263                         $ilDB->quote($user_id . "")
06264                 );
06265                 $result = $ilDB->query($query);
06266                 if ($result->numRows())
06267                 {
06268                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06269                         {
06270                                 $active = $this->getActiveTestUser($row["user_fi"]);
06271                                 if (is_object($active))
06272                                 {
06273                                         $name = trim($row["lastname"] . ", " . $row["firstname"] ." " . $row["title"]);
06274                                         if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
06275                                         {
06276                                                 $name = $this->lng->txt("anonymous");
06277                                         }
06278                                         $users[$active->active_id] = $name;
06279                                 }
06280                         }
06281                 }
06282                 return $users;
06283         }
06284 
06293         function removeSelectedUser($user_id, $evaluator_id)
06294         {
06295                 global $ilDB;
06296 
06297                 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s AND user_fi = %s AND evaluator_fi = %s",
06298                         $ilDB->quote($this->getTestId() . ""),
06299                         $ilDB->quote($user_id . ""),
06300                         $ilDB->quote($evaluator_id . "")
06301                 );
06302                 $result = $ilDB->query($query);
06303         }
06304 
06313         function addSelectedUser($user_id, $evaluator_id)
06314         {
06315                 global $ilDB;
06316 
06317                 $query = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
06318                         $ilDB->quote($this->getTestId() . ""),
06319                         $ilDB->quote($user_id . "")
06320                 );
06321                 $result = $ilDB->query($query);
06322                 if ($result->numRows() == 1)
06323                 {
06324                         $query = sprintf("REPLACE INTO tst_eval_users (test_fi, evaluator_fi, user_fi) VALUES (%s, %s, %s)",
06325                                 $ilDB->quote($this->getTestId() . ""),
06326                                 $ilDB->quote($evaluator_id . ""),
06327                                 $ilDB->quote($user_id . "")
06328                         );
06329                         $result = $ilDB->query($query);
06330                 }
06331         }
06332 
06341         function addSelectedGroup($group_id, $evaluator_id)
06342         {
06343                 include_once "./classes/class.ilObjGroup.php";
06344                 $group = new ilObjGroup($group_id);
06345                 $members = $group->getGroupMemberIds();
06346                 foreach ($members as $user_id)
06347                 {
06348                         $this->addSelectedUser($user_id, $evaluator_id);
06349                 }
06350         }
06351 
06360         function addSelectedRole($role_id, $evaluator_id)
06361         {
06362                 global $rbacreview;
06363                 $members =  $rbacreview->assignedUsers($role_id,"usr_id");
06364                 foreach ($members as $user_id)
06365                 {
06366                         $this->addSelectedUser($user_id, $evaluator_id);
06367                 }
06368         }
06369 
06378         function getQuestionCount()
06379         {
06380                 $num = 0;
06381 
06382                 if ($this->isRandomTest())
06383                 {
06384                         if ($this->getRandomQuestionCount())
06385                         {
06386                                 $num = $this->getRandomQuestionCount();
06387                                 $qpls =& $this->getRandomQuestionpools();
06388                                 $maxcount = 0;
06389                                 foreach ($qpls as $data)
06390                                 {
06391                                         $maxcount += $data["contains"];
06392                                 }
06393                                 if ($num > $maxcount) $num = $maxcount;
06394                         }
06395                                 else
06396                         {
06397                                 $qpls =& $this->getRandomQuestionpools();
06398                                 foreach ($qpls as $data)
06399                                 {
06400                                         $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06401                                         $num += $add;
06402                                 }
06403                         }
06404                 }
06405                         else
06406                 {
06407                         $num = count($this->questions);
06408                 }
06409                 return $num;
06410         }
06411 
06420         function _getQuestionCount($test_id)
06421         {
06422                 global $ilDB;
06423 
06424                 $num = 0;
06425 
06426                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
06427                         $ilDB->quote($test_id . "")
06428                 );
06429                 $result = $ilDB->query($query);
06430                 if (!$result->numRows())
06431                 {
06432                         return 0;
06433                 }
06434                 $test = $result->fetchRow(DB_FETCHMODE_ASSOC);
06435 
06436                 if ($test["random_test"] == 1)
06437                 {
06438                         $qpls = array();
06439                         $counter = 0;
06440                         $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
06441                                 $ilDB->quote($test_id . "")
06442                         );
06443                         $result = $ilDB->query($query);
06444                         if ($result->numRows())
06445                         {
06446                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06447                                 {
06448                                         $countquery = sprintf("SELECT question_id FROM qpl_questions WHERE obj_fi =  %s AND original_id IS NULL",
06449                                                 $ilDB->quote($row["questionpool_fi"] . "")
06450                                         );
06451                                         $countresult = $ilDB->query($countquery);
06452                                         $contains = $countresult->numRows();
06453                                         $qpls[$counter] = array(
06454                                                 "index" => $counter,
06455                                                 "count" => $row["num_of_q"],
06456                                                 "qpl"   => $row["questionpool_fi"],
06457                                                 "contains" => $contains
06458                                         );
06459                                         $counter++;
06460                                 }
06461                         }
06462                         if ($test["random_question_count"] > 0)
06463                         {
06464                                 $num = $test["random_question_count"];
06465                                 $maxcount = 0;
06466                                 foreach ($qpls as $data)
06467                                 {
06468                                         $maxcount += $data["contains"];
06469                                 }
06470                                 if ($num > $maxcount) $num = $maxcount;
06471                         }
06472                                 else
06473                         {
06474                                 $num = 0;
06475                                 foreach ($qpls as $data)
06476                                 {
06477                                         $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06478                                         $num += $add;
06479                                 }
06480                         }
06481                 }
06482                 else
06483                 {
06484                         $query = sprintf("SELECT test_question_id FROM tst_test_question WHERE test_fi = %s",
06485                                 $ilDB->quote($test_id . "")
06486                         );
06487                         $result = $ilDB->query($query);
06488                         $num = $result->numRows();
06489                 }
06490                 return $num;
06491         }
06492 
06493 
06501         function removeNonRandomTestData()
06502         {
06503                 global $ilDB;
06504 
06505                 // delete eventually set questions of a previous non-random test
06506                 $this->removeAllTestEditings();
06507                 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
06508                         $ilDB->quote($this->getTestId())
06509                 );
06510                 $result = $ilDB->query($query);
06511                 $this->questions = array();
06512                 $this->saveCompleteStatus();
06513         }
06514 
06522         function removeRandomTestData()
06523         {
06524                 global $ilDB;
06525                 // delete eventually set random question pools of a previous random test
06526                 $this->removeAllTestEditings();
06527                 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
06528                         $ilDB->quote($this->getTestId())
06529                 );
06530                 $result = $ilDB->query($query);
06531                 $this->questions = array();
06532                 $this->saveCompleteStatus();
06533         }
06534 
06544         function logAction($logtext = "", $question_id = "")
06545         {
06546                 global $ilUser;
06547 
06548                 $original_id = "";
06549                 if (strcmp($question_id, "") != 0)
06550                 {
06551                         include_once "./assessment/classes/class.assQuestion.php";
06552                         $original_id = assQuestion::_getOriginalId($question_id);
06553                 }
06554                 include_once "./classes/class.ilObjAssessmentFolder.php";
06555                 ilObjAssessmentFolder::_addLog($ilUser->id, $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
06556         }
06557 
06567         function _getObjectIDFromTestID($test_id)
06568         {
06569                 global $ilDB;
06570                 $object_id = FALSE;
06571                 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
06572                         $ilDB->quote($test_id . "")
06573                 );
06574                 $result = $ilDB->query($query);
06575                 if ($result->numRows())
06576                 {
06577                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06578                         $object_id = $row["obj_fi"];
06579                 }
06580                 return $object_id;
06581         }
06582 
06592         function _getObjectIDFromActiveID($active_id)
06593         {
06594                 global $ilDB;
06595                 $object_id = FALSE;
06596                 $query = sprintf("SELECT tst_tests.obj_fi FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
06597                         $ilDB->quote($active_id . "")
06598                 );
06599                 $result = $ilDB->query($query);
06600                 if ($result->numRows())
06601                 {
06602                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06603                         $object_id = $row["obj_fi"];
06604                 }
06605                 return $object_id;
06606         }
06607 
06617         function _getTestIDFromObjectID($object_id)
06618         {
06619                 global $ilDB;
06620                 $test_id = FALSE;
06621                 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
06622                         $ilDB->quote($object_id . "")
06623                 );
06624                 $result = $ilDB->query($query);
06625                 if ($result->numRows())
06626                 {
06627                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06628                         $test_id = $row["test_id"];
06629                 }
06630                 return $test_id;
06631         }
06632 
06643         function getTextAnswer($active_id, $question_id, $pass = NULL)
06644         {
06645                 global $ilDB;
06646 
06647                 $res = "";
06648                 if (($active_id) && ($question_id))
06649                 {
06650                         if (is_null($pass))
06651                         {
06652                                 include_once "./assessment/classes/class.assQuestion.php";
06653                                 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
06654                         }
06655                         $query = sprintf("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
06656                                 $ilDB->quote($active_id . ""),
06657                                 $ilDB->quote($question_id . ""),
06658                                 $ilDB->quote($pass . "")
06659                         );
06660                         $result = $ilDB->query($query);
06661                         if ($result->numRows() == 1)
06662                         {
06663                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06664                                 $res = $row["value1"];
06665                         }
06666                 }
06667                 return $res;
06668         }
06669 
06679         function getQuestiontext($question_id)
06680         {
06681                 global $ilDB;
06682 
06683                 $res = "";
06684                 if ($question_id)
06685                 {
06686                         $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
06687                                 $ilDB->quote($question_id . "")
06688                         );
06689                         $result = $ilDB->query($query);
06690                         if ($result->numRows() == 1)
06691                         {
06692                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06693                                 $res = $row["question_text"];
06694                         }
06695                 }
06696                 return $res;
06697         }
06698 
06707         function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
06708         {
06709                 global $ilDB;
06710 
06711                 $result_array = array();
06712 
06713                 if (is_numeric($user_id))
06714                 {
06715                         $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
06716                                 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
06717                                 "FROM usr_data, tst_invited_user " .
06718                                 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
06719                                 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
06720                                 "ORDER BY %s",
06721                                 $ilDB->quote($this->test_id),
06722                                 $user_id,
06723                                 $order
06724                         );
06725 /*              CREATED NEW VERSION FOR MYSQL 5 COMPATIBILITY (Helmut Schottmüller, 2006-09-18)
06726                                 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .
06727                                                          "FROM tst_invited_user t, usr_data ".
06728                                                          "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
06729                                                          "WHERE t.test_fi = %s and t.user_fi=usr_id AND usr_id=%s ".
06730                                                          "ORDER BY %s",
06731                                 $ilDB->quote($this->test_id),
06732                                 $user_id,
06733                                 $order
06734                         );*/
06735                 }
06736                 else
06737                 {
06738                         $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
06739                                 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
06740                                 "FROM usr_data, tst_invited_user " .
06741                                 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
06742                                 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
06743                                 "ORDER BY %s",
06744                                 $ilDB->quote($this->test_id),
06745                                 $order
06746                         );
06747 /*              CREATED NEW VERSION FOR MYSQL 5 COMPATIBILITY (Helmut Schottmüller, 2006-09-18)
06748                                 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .
06749                                                          "FROM tst_invited_user t, usr_data ".
06750                                                          "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
06751                                                          "WHERE t.test_fi = %s and t.user_fi=usr_id ".
06752                                                          "ORDER BY %s",
06753                                 $ilDB->quote($this->test_id),
06754                                 $order
06755                         );*/
06756                 }
06757 
06758                 return $this->getArrayData($query, "usr_id");
06759         }
06760 
06770         function &getUserData($ids)
06771         {
06772                 if (!is_array($ids) || count($ids) ==0)
06773                         return array();
06774 
06775                 $result_array = array();
06776 
06777                 $query = sprintf("SELECT usr_id, login, lastname, firstname, client_ip as clientip FROM usr_data WHERE usr_id IN (%s) ORDER BY login",
06778                         join ($ids,",")
06779                 );
06780 
06781                 return $this->getArrayData ($query, "usr_id");
06782         }
06783 
06794         function &getArrayData($query, $id_field)
06795         {
06796                 return ilObjTest::_getArrayData ($query, $id_field);
06797         }
06798 
06799         function &_getArrayData($query, $id_field)
06800         {
06801                 global $ilDB;
06802                 $result = $ilDB->query($query);
06803                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
06804                 {
06805                         $result_array[$row->$id_field]= $row;
06806                 }
06807                 return ($result_array)?$result_array:array();
06808         }
06809 
06810         function &getGroupData($ids)
06811         {
06812                 if (!is_array($ids) || count($ids) ==0)
06813                         return array();
06814 
06815                 $result_array = array();
06816 
06817                 $query = sprintf("SELECT ref_id, title, description FROM `grp_data` g, object_data o, object_reference r WHERE o.obj_id=grp_id AND o.obj_id = r.obj_id AND ref_id IN (%s)",
06818                         join ($ids,",")
06819                 );
06820 
06821                 return $this->getArrayData ($query, "ref_id");
06822         }
06823 
06824         function &getRoleData($ids)
06825         {
06826                 if (!is_array($ids) || count($ids) ==0)
06827                         return array();
06828 
06829                 $result_array = array();
06830 
06831                 $query = sprintf("SELECT obj_id, description, title FROM role_data, object_data o WHERE o.obj_id=role_id AND role_id IN (%s)",
06832                         join ($ids,",")
06833                 );
06834 
06835                 return $this->getArrayData ($query, "obj_id");
06836         }
06837 
06838 
06847         function inviteGroup($group_id)
06848         {
06849                 include_once "./classes/class.ilObjGroup.php";
06850                 $group = new ilObjGroup($group_id);
06851                 $members = $group->getGroupMemberIds();
06852                 include_once "./classes/class.ilObjUser.php";
06853                 foreach ($members as $user_id)
06854                 {
06855                         $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
06856                 }
06857         }
06858 
06867         function inviteRole($role_id)
06868         {
06869                 global $rbacreview;
06870                 $members =  $rbacreview->assignedUsers($role_id,"usr_id");
06871                 include_once "./classes/class.ilObjUser.php";
06872                 foreach ($members as $user_id)
06873                 {
06874                         $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
06875                 }
06876         }
06877 
06878 
06879 
06888         function disinviteUser($user_id)
06889         {
06890                 global $ilDB;
06891 
06892                 $query = sprintf("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
06893                         $ilDB->quote($this->test_id),
06894                         $ilDB->quote($user_id)
06895                 );
06896                 $result = $ilDB->query($query);
06897         }
06898 
06907         function inviteUser($user_id, $client_ip="")
06908         {
06909                 global $ilDB;
06910 
06911                 $query = sprintf("INSERT IGNORE INTO tst_invited_user (test_fi, user_fi, clientip) VALUES (%s, %s, %s)",
06912                         $ilDB->quote($this->test_id),
06913                         $ilDB->quote($user_id),
06914                         $ilDB->quote($client_ip)
06915                 );
06916 
06917                 $result = $ilDB->query($query);
06918         }
06919 
06920 
06921         function setClientIP($user_id, $client_ip)
06922         {
06923                 global $ilDB;
06924 
06925                 $query = sprintf("UPDATE tst_invited_user SET clientip=%s WHERE test_fi=%s and user_fi=%s",
06926                                 $ilDB->quote($client_ip),
06927                                 $ilDB->quote($this->test_id),
06928                                 $ilDB->quote($user_id)
06929                 );
06930                 $insertresult = $ilDB->query($query);
06931         }
06932 
06939         function isOnlineTest()
06940         {
06941                 return $this->getTestType()==TYPE_ONLINE_TEST;
06942         }
06943 
06949         function _getSolvedQuestions($active_id, $question_fi = null)
06950         {
06951                 global $ilDB;
06952                 if (is_numeric($question_fi))
06953                         $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06954                                                  "WHERE active_fi = %s AND question_fi=%s",
06955                                                         $ilDB->quote($active_id),
06956                                                         $question_fi
06957                         );
06958                 else $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06959                                                  "WHERE active_fi = %s",
06960                         $ilDB->quote($active_id)
06961                 );
06962                 return ilObjTest::_getArrayData ($query, "question_fi");
06963         }
06964 
06965 
06969         function setQuestionSetSolved($value, $question_id, $user_id)
06970         {
06971                 global $ilDB;
06972 
06973                 $active = $this->getActiveTestUser($user_id);
06974                 $query = sprintf("REPLACE INTO tst_active_qst_sol_settings SET solved=%s, question_fi=%s, active_fi = %s",
06975                         $ilDB->quote($value),
06976                         $ilDB->quote($question_id),
06977                         $ilDB->quote($active->active_id)
06978                 );
06979 
06980                 $ilDB->query($query);
06981         }
06982 
06983 
06987         function setActiveTestSubmitted($user_id)
06988         {
06989                 global $ilDB;
06990 
06991                 $query = sprintf("UPDATE tst_active SET submitted=1, tries=1, submittimestamp=NOW() WHERE test_fi=%s AND user_fi=%s",
06992                         $ilDB->quote($this->test_id),
06993                         $ilDB->quote($user_id)
06994                 );
06995                 $ilDB->query($query);
06996 
06997         }
06998 
07002         function isActiveTestSubmitted($user_id = null)
07003         {
07004                 global $ilUser;
07005                 global $ilDB;
07006 
07007                 if (!is_numeric($user_id))
07008                         $user_id = $ilUser->getId();
07009 
07010                 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
07011                         $ilDB->quote($this->test_id),
07012                         $ilDB->quote($user_id)
07013                 );
07014                 $result = $ilDB->query($query);
07015 
07016                 return  $result->numRows() == 1;
07017 
07018         }
07022         function hasNrOfTriesRestriction()
07023         {
07024                 return $this->getNrOfTries() != 0;
07025         }
07026 
07027 
07032         function isNrOfTriesReached($tries)
07033         {
07034                 return $tries >= (int) $this->getNrOfTries();
07035         }
07036 
07037 
07041         function getAllTestResults($participants, $skip_csv = false)
07042         {
07043                 $results = array();
07044                 $row = array("matriculation" =>  $this->lng->txt("matriculation"),
07045                                         "lastname" =>  $this->lng->txt("lastname"),
07046                                         "firstname" => $this->lng->txt("firstname"),
07047                                         "reached_points" => $this->lng->txt("tst_reached_points"),
07048                                         "max_points" => $this->lng->txt("tst_maximum_points"),
07049                                         "percent_value" => $this->lng->txt("tst_percent_solved"),
07050                                         "mark" => $this->lng->txt("tst_mark"),
07051                                         "ects" => $this->lng->txt("ects_grade"));
07052 
07053                 $results[] = $row;
07054                 foreach ($participants as $user_id => $user_rec)
07055                 {
07056                         $row = array();
07057                         $active = $this->getActiveTestUser($user_id);
07058                         $reached_points = 0;
07059                         $max_points = 0;
07060 
07061                         foreach ($this->questions as $value)
07062                         {
07063                         //$value = $this->questions[$seq];
07064 //                              $ilBench->start("getTestResult","instanciate question");
07065                                 $question =& ilObjTest::_instanciateQuestion($value);
07066 //                              $ilBench->stop("getTestResult","instanciate question");
07067                                 if (is_object($question))
07068                                 {
07069                                         $max_points += $question->getMaximumPoints();
07070                                         $reached_points += $question->getReachedPoints($active->active_id);
07071                                 }
07072                         }
07073 
07074                         if ($max_points > 0)
07075                         {
07076                                 $percentvalue = $reached_points / $max_points;
07077                                 if ($percentvalue < 0) $percentvalue = 0.0;
07078                         }
07079                         else
07080                         {
07081                                 $percentvalue = 0;
07082                         }
07083                         $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
07084                         $passed = "";
07085                         if ($mark_obj)
07086                         {
07087                                 $mark = $mark_obj->getOfficialName();
07088                                 $ects_mark = $this->getECTSGrade($reached_points, $max_points);
07089                         }
07090 
07091                         $row = array(
07092                                         "matriculation" =>  $user_rec->matriculation,
07093                                         "lastname" =>  $user_rec->lastname,
07094                                         "firstname" => $user_rec->firstname,
07095                                         "reached_points" => $reached_points,
07096                                         "max_points" => $max_points,
07097                                         "percent_value" => $percentvalue,
07098                                         "mark" => $mark,
07099                                         "ects" => $ects_mark);
07100                         $results[] = $skip_csv == true? $row : $this->processCSVRow ($row, true);
07101                 }
07102                 return $results;
07103         }
07104 
07117         function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
07118         {
07119                 $resultarray = array();
07120                 foreach ($row as $rowindex => $entry)
07121                 {
07122                         $surround = FALSE;
07123                         if ($quoteAll)
07124                         {
07125                                 $surround = TRUE;
07126                         }
07127                         if (strpos($entry, "\"") !== FALSE)
07128                         {
07129                                 $entry = str_replace("\"", "\"\"", $entry);
07130                                 $surround = TRUE;
07131                         }
07132                         if (strpos($entry, $separator) !== FALSE)
07133                         {
07134                                 $surround = TRUE;
07135                         }
07136                         // replace all CR LF with LF (for Excel for Windows compatibility
07137                         $entry = str_replace(chr(13).chr(10), chr(10), $entry);
07138                         if ($surround)
07139                         {
07140                                 $resultarray[$rowindex] = utf8_decode("\"" . $entry . "\"");
07141                         }
07142                         else
07143                         {
07144                                 $resultarray[$rowindex] = utf8_decode($entry);
07145                         }
07146                 }
07147                 return $resultarray;
07148         }
07149 
07160         function _getPass($active_id)
07161         {
07162                 global $ilDB;
07163                 $query = sprintf("SELECT tries FROM tst_active WHERE active_id = %s",
07164                         $ilDB->quote($active_id . "")
07165                 );
07166                 $result = $ilDB->query($query);
07167                 if ($result->numRows())
07168                 {
07169                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07170                         return $row["tries"];
07171                 }
07172                 else
07173                 {
07174                         return 0;
07175                 }
07176         }
07177 
07188         function _getBestPass($active_id)
07189         {
07190                 global $ilDB;
07191                 $query = sprintf("SELECT test_fi FROM tst_active WHERE active_id = %s",
07192                         $ilDB->quote($active_id . "")
07193                 );
07194                 $result = $ilDB->query($query);
07195                 if ($result->numRows())
07196                 {
07197                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07198                         $test_id = $row["test_fi"];
07199                         $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE, $active_id);
07200                         $participant =& $results->getParticipant($active_id);
07201                         if ($participant != null)
07202                         {
07203                                 return $participant->getBestPass();
07204                         }
07205                         else
07206                         {
07207                                 return 0;
07208                         }
07209                 }
07210                 else
07211                 {
07212                         return 0;
07213                 }
07214         }
07215 
07226         function _getResultPass($active_id)
07227         {
07228                 $counted_pass = NULL;
07229                 if (strcmp(ilObjTest::_getTestType($active_id), "tt_varying_randomtest") == 0)
07230                 {
07231                         if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS)
07232                         {
07233                                 $counted_pass = ilObjTest::_getBestPass($active_id);
07234                         }
07235                         else
07236                         {
07237                                 $counted_pass = ilObjTest::_getPass($active_id);
07238                                 global $ilDB;
07239                                 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
07240                                         $ilDB->quote($active_id . ""),
07241                                         $ilDB->quote($counted_pass . "")
07242                                 );
07243                                 $result = $ilDB->query($query);
07244                                 if ($result->numRows() == 0)
07245                                 {
07246                                         // There was no answer answered in the actual pass, so the last pass is
07247                                         // $counted_pass - 1
07248                                         $counted_pass -= 1;
07249                                 }
07250                                 if ($counted_pass < 0) $counted_pass = 0;
07251                         }
07252                 }
07253                 return $counted_pass;
07254         }
07255 
07267         function getAnsweredQuestionCount($active_id, $pass = NULL)
07268         {
07269                 if ($this->isRandomTest())
07270                 {
07271                         $this->loadQuestions($active_id, $pass);
07272                 }
07273                 include_once "./assessment/classes/class.assQuestion.php";
07274                 $workedthrough = 0;
07275                 foreach ($this->questions as $value)
07276                 {
07277                         if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
07278                         {
07279                                 $workedthrough += 1;
07280                         }
07281                 }
07282                 return $workedthrough;
07283         }
07284         
07296         function getPassFinishDate($active_id, $pass)
07297         {
07298                 global $ilDB;
07299                 if (is_null($pass)) $pass = 0;
07300                 $query = sprintf("SELECT tst_test_result.TIMESTAMP + 0 AS TIMESTAMP14 FROM tst_test_result WHERE active_fi = %s AND pass = %s ORDER BY tst_test_result.TIMESTAMP DESC",
07301                         $ilDB->quote($active_id . ""),
07302                         $ilDB->quote($pass . "")
07303                 );
07304                 $result = $ilDB->query($query);
07305                 if ($result->numRows())
07306                 {
07307                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07308                         return $row["TIMESTAMP14"];
07309                 }
07310                 else
07311                 {
07312                         return 0;
07313                 }
07314         }
07315 
07325         function isExecutable($user_id)
07326         {
07327                 $result = array(
07328                         "executable" => true,
07329                         "errormessage" => ""
07330                 );
07331                 if (!$this->startingTimeReached())
07332                 {
07333                         $result["executable"] = false;
07334                         $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilFormat::ftimestamp2datetimeDB($this->getStartingTime()));
07335                         return $result;
07336                 }
07337                 if ($this->endingTimeReached())
07338                 {
07339                         $result["executable"] = false;
07340                         $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilFormat::ftimestamp2datetimeDB($this->getEndingTime()));
07341                         return $result;
07342                 }
07343                 if ($this->getEnableProcessingTime())
07344                 {
07345                         $starting_time = $this->getStartingTimeOfUser($user_id);
07346                         if ($starting_time !== FALSE)
07347                         {
07348                                 if ($this->isMaxProcessingTimeReached($starting_time))
07349                                 {
07350                                         $result["executable"] = false;
07351                                         $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
07352                                         return $result;
07353                                 }
07354                         }
07355                 }
07356 
07357                 $active = $this->getActiveTestUser($user_id);
07358                 if ($this->hasNrOfTriesRestriction() && is_object($active) && $this->isNrOfTriesReached($active->tries))
07359                 {
07360                         $result["executable"] = false;
07361                         if ($this->isOnlineTest())
07362                         {
07363                                 // don't display an errormessage for online exams. It could confuse users
07364                                 // because they will get either a finish test button or a print test button
07365                                 $result["errormessage"] = "";
07366                         }
07367                         else
07368                         {
07369                                 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
07370                         }
07371                         return $result;
07372                 }
07373 
07374                 // TODO: max. processing time
07375 
07376                 return $result;
07377         }
07378 
07379         function canShowTestResults($user_id)
07380         {
07381                 $active = $this->getActiveTestUser($user_id);
07382                 $starting_time = $this->getStartingTimeOfUser($user_id);
07383                 $notimeleft = FALSE;
07384                 if ($starting_time !== FALSE)
07385                 {
07386                         if ($this->isMaxProcessingTimeReached($starting_time))
07387                         {
07388                                 $notimeleft = TRUE;
07389                         }
07390                 }
07391                 $result = TRUE;
07392                 if (!$this->isTestFinishedToViewResults($active->active_id, $active->tries) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
07393                 {
07394                         $result = FALSE;
07395                 }
07396                 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
07397                 $result = $result & $this->canViewResults();
07398                 if ($this->getTestType() == TYPE_ONLINE_TEST)
07399                 {
07400                         return $result && $this->isActiveTestSubmitted();
07401                 }
07402                 return $result;
07403         }
07404 
07405         function canEditMarks()
07406         {
07407                 $total = $this->evalTotalPersons();
07408                 if ($total > 0)
07409                 {
07410                         if ($this->getReportingDate())
07411                         {
07412                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
07413                                 {
07414                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07415                                         $now = mktime();
07416                                         if ($now < $epoch_time)
07417                                         {
07418                                                 return true;
07419                                         }
07420                                 }
07421                         }
07422                         return false;
07423                 }
07424                 else
07425                 {
07426                         return true;
07427                 }
07428         }
07429 
07439         function getStartingTimeOfUser($user_id)
07440         {
07441                 global $ilDB;
07442 
07443                 if ($user_id < 1) return FALSE;
07444                 $query = sprintf("SELECT tst_times.started FROM tst_times, tst_active WHERE tst_active.user_fi = %s AND tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.started",
07445                         $ilDB->quote($user_id . ""),
07446                         $ilDB->quote($this->getTestId() . "")
07447                 );
07448                 $result = $ilDB->query($query);
07449                 if ($result->numRows())
07450                 {
07451                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07452                         if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
07453                         {
07454                                 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07455                         }
07456                         else
07457                         {
07458                                 return FALSE;
07459                         }
07460                 }
07461                 else
07462                 {
07463                         return FALSE;
07464                 }
07465         }
07466 
07477         function isMaxProcessingTimeReached($starting_time)
07478         {
07479                 if ($this->getEnableProcessingTime())
07480                 {
07481                         $processing_time = $this->getProcessingTimeInSeconds();
07482                         $now = mktime();
07483                         if ($now > ($starting_time + $processing_time))
07484                         {
07485                                 return TRUE;
07486                         }
07487                         else
07488                         {
07489                                 return FALSE;
07490                         }
07491                 }
07492                 else
07493                 {
07494                         return FALSE;
07495                 }
07496         }
07497 
07498         function &getTestQuestions()
07499         {
07500                 global $ilDB;
07501                 $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type, tst_test_question WHERE qpl_questions.question_type_fi = qpl_question_type.question_type_id AND tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY sequence",
07502                         $ilDB->quote($this->getTestId() . "")
07503                 );
07504                 $query_result = $ilDB->query($query);
07505                 $removableQuestions = array();
07506                 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
07507                 {
07508                         array_push($removableQuestions, $row);
07509                 }
07510                 return $removableQuestions;
07511         }
07512 
07521         function getShuffleQuestions()
07522         {
07523                 return $this->shuffle_questions;
07524         }
07525 
07534         function setShuffleQuestions($a_shuffle)
07535         {
07536                 if ($a_shuffle)
07537                 {
07538                         $this->shuffle_questions = TRUE;
07539                 }
07540                 else
07541                 {
07542                         $this->shuffle_questions = FALSE;
07543                 }
07544         }
07545 
07554         function getShowSolutionDetails()
07555         {
07556                 return $this->show_solution_details;
07557         }
07558 
07567         function getShowSummary()
07568         {
07569                 return $this->show_summary;
07570         }
07571 
07580         function getShowSolutionPrintview()
07581         {
07582                 return $this->show_solution_printview;
07583         }
07584 
07593         function setShowSolutionDetails($a_details = TRUE)
07594         {
07595                 if ($a_details)
07596                 {
07597                         $this->show_solution_details = TRUE;
07598                 }
07599                 else
07600                 {
07601                         $this->show_solution_details = FALSE;
07602                 }
07603         }
07604 
07613         function setShowSummary($a_summary = TRUE)
07614         {
07615                 if ($a_summary)
07616                 {
07617                         $this->show_summary = TRUE;
07618                 }
07619                 else
07620                 {
07621                         $this->show_summary = FALSE;
07622                 }
07623         }
07624 
07633         function canShowSolutionPrintview($user_id = NULL)
07634         {
07635                 global $ilDB;
07636 
07637                 if (!is_numeric($user_id))
07638                 {
07639                         global $ilUser;
07640                         $user_id = $ilUser->getId();
07641                 }
07642 
07643                 if ($this->isOnlineTest())
07644                 {
07645                         $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
07646                                 $ilDB->quote($this->getTestId() . ""),
07647                                 $ilDB->quote($user_id . "")
07648                         );
07649                         $result = $ilDB->query($query);
07650                         return $result->numRows() == 1;
07651                 }
07652                 else
07653                 {
07654                         if (($this->canShowTestResults($user_id)) && ($this->getShowSolutionPrintview()))
07655                         {
07656                                 return TRUE;
07657                         }
07658                         else
07659                         {
07660                                 return FALSE;
07661                         }
07662                 }
07663                 return FALSE;
07664         }
07665 
07674         function setShowSolutionPrintview($a_printview = TRUE)
07675         {
07676                 if ($a_printview)
07677                 {
07678                         $this->show_solution_printview = TRUE;
07679                 }
07680                 else
07681                 {
07682                         $this->show_solution_printview = FALSE;
07683                 }
07684         }
07685 
07697         function &_getPassedUsers($a_obj_id)
07698         {
07699                 $passed_users = array();
07700                 $test_id =  ilObjTest::_getTestIDFromObjectID($a_obj_id);
07701                 $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE);
07702                 if (is_object($results))
07703                 {
07704                         $participants =& $results->getParticipants();
07705                         foreach ($participants as $active_id => $participant)
07706                         {
07707                                 if (is_object($participant) && $participant->getPassed())
07708                                 {
07709                                         array_push($passed_users, $active_id);
07710                                 }
07711                         }
07712                 }
07713                 return $passed_users;
07714         }
07715 
07721         function createNewAccessCode()
07722         {
07723                 // create a 5 character code
07724                 $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
07725                 mt_srand();
07726                 $code = "";
07727                 for ($i = 1; $i <=5; $i++)
07728                 {
07729                         $index = mt_rand(0, strlen($codestring)-1);
07730                         $code .= substr($codestring, $index, 1);
07731                 }
07732                 // verify it against the database
07733                 while ($this->isAccessCodeUsed($code))
07734                 {
07735                         $code = $this->createNewAccessCode();
07736                 }
07737                 return $code;
07738         }
07739 
07740         function isAccessCodeUsed($code)
07741         {
07742                 global $ilDB;
07743 
07744                 $query = sprintf("SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s",
07745                         $ilDB->quote($this->getTestId() . ""),
07746                         $ilDB->quote($code . "")
07747                 );
07748                 $result = $ilDB->query($query);
07749                 if ($result->numRows() > 0)
07750                 {
07751                         return TRUE;
07752                 }
07753                 else
07754                 {
07755                         return FALSE;
07756                 }
07757         }
07758 
07759         function _getUserIdFromActiveId($active_id)
07760         {
07761                 global $ilDB;
07762                 $query = sprintf("SELECT user_fi FROM tst_active WHERE active_id = %s",
07763                         $ilDB->quote($active_id . "")
07764                 );
07765                 $result = $ilDB->query($query);
07766                 if ($result->numRows())
07767                 {
07768                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07769                         return $row["user_fi"];
07770                 }
07771                 else
07772                 {
07773                         return -1;
07774                 }
07775         }
07776 
07777         function getAccessCodeSession()
07778         {
07779                 $id = $this->getTestId();
07780                 if (!is_array($_SESSION["tst_access_code"]))
07781                 {
07782                         return "";
07783                 }
07784                 else
07785                 {
07786                         return $_SESSION["tst_access_code"]["$id"];
07787                 }
07788         }
07789 
07790         function setAccessCodeSession($access_code)
07791         {
07792                 $id = $this->getTestId();
07793                 if (!is_array($_SESSION["tst_access_code"]))
07794                 {
07795                         $_SESSION["tst_access_code"] = array();
07796                 }
07797                 $_SESSION["tst_access_code"]["$id"] = $access_code;
07798         }
07799 
07800         function unsetAccessCodeSession()
07801         {
07802                 $id = $this->getTestId();
07803                 unset($_SESSION["tst_access_code"]["$id"]);
07804         }
07805 
07806         function getAllowedUsers()
07807         {
07808                 return $this->allowedUsers;
07809         }
07810 
07811         function setAllowedUsers($a_allowed_users)
07812         {
07813                 $this->allowedUsers = $a_allowed_users;
07814         }
07815 
07816         function getAllowedUsersTimeGap()
07817         {
07818                 return $this->allowedUsersTimeGap;
07819         }
07820 
07821         function setAllowedUsersTimeGap($a_allowed_users_time_gap)
07822         {
07823                 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
07824         }
07825 
07826         function checkMaximumAllowedUsers()
07827         {
07828                 global $ilDB;
07829 
07830                 $nr_of_users = $this->getAllowedUsers();
07831                 $time_gap = $this->getAllowedUsersTimeGap();
07832                 if (($nr_of_users > 0) && ($time_gap > 0))
07833                 {
07834                         $now = mktime();
07835                         $time_border = $now - $time_gap;
07836                         $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
07837                         $query = sprintf("SELECT DISTINCT tst_times.active_fi, tst_times.times_id FROM tst_times, tst_active WHERE tst_times.TIMESTAMP > %s AND tst_times.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
07838                                 $ilDB->quote($str_time_border),
07839                                 $ilDB->quote($this->getTestId() . "")
07840                         );
07841                         $result = $ilDB->query($query);
07842                         if ($result->numRows() >= $nr_of_users)
07843                         {
07844                                 include_once "./classes/class.ilObjAssessmentFolder.php";
07845                                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
07846                                 {
07847                                         $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
07848                                 }
07849                                 return FALSE;
07850                         }
07851                         else
07852                         {
07853                                 return TRUE;
07854                         }
07855                 }
07856                 return TRUE;
07857         }
07858 
07859         function _getLastAccess($active_id)
07860         {
07861                 global $ilDB;
07862 
07863                 $query = sprintf("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
07864                         $ilDB->quote($active_id . "")
07865                 );
07866                 $result = $ilDB->query($query);
07867                 if ($result->numRows())
07868                 {
07869                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07870                         return $row["finished"];
07871                 }
07872                 return "";
07873         }
07874 
07883         function isHTML($a_text)
07884         {
07885                 if (preg_match("/<[^>]*?>/", $a_text))
07886                 {
07887                         return TRUE;
07888                 }
07889                 else
07890                 {
07891                         return FALSE;
07892                 }
07893         }
07894 
07902         function QTIMaterialToString($a_material)
07903         {
07904                 $result = "";
07905                 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
07906                 {
07907                         $material = $a_material->getMaterial($i);
07908                         if (strcmp($material["type"], "mattext") == 0)
07909                         {
07910                                 $result .= $material["material"]->getContent();
07911                         }
07912                         if (strcmp($material["type"], "matimage") == 0)
07913                         {
07914                                 $matimage = $material["material"];
07915                                 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
07916                                 {
07917                                         // import an mediaobject which was inserted using tiny mce
07918                                         if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
07919                                         array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
07920                                 }
07921                         }
07922                 }
07923                 return $result;
07924         }
07925 
07934         function addQTIMaterial(&$a_xml_writer, $a_material)
07935         {
07936                 include_once "./Services/RTE/classes/class.ilRTE.php";
07937                 include_once("./content/classes/Media/class.ilObjMediaObject.php");
07938 
07939                 $a_xml_writer->xmlStartTag("material");
07940                 $attrs = array(
07941                         "texttype" => "text/plain"
07942                 );
07943                 if ($this->isHTML($a_material))
07944                 {
07945                         $attrs["texttype"] = "text/xhtml";
07946                 }
07947                 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
07948 
07949                 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
07950                 foreach ($mobs as $mob)
07951                 {
07952                         $mob_obj =& new ilObjMediaObject($mob);
07953                         $imgattrs = array(
07954                                 "label" => "il_" . IL_INST_ID . "_mob_" . $mob,
07955                                 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
07956                         );
07957                         $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
07958                 }
07959                 $a_xml_writer->xmlEndTag("material");
07960         }
07961 
07968         function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE)
07969         {
07970                 include_once "./classes/class.ilObjAdvancedEditing.php";
07971                 $result = $txt_output;
07972                 $is_html = $this->isHTML($result);
07973                 if ($prepare_for_latex_output)
07974                 {
07975                         $result = ilUtil::insertLatexImages($result, "<span class\=\"latex\">", "<\/span>", URL_TO_LATEX);
07976                         $result = ilUtil::insertLatexImages($result, "\[tex\]", "\[\/tex\]", URL_TO_LATEX);
07977                 }
07978 
07979                 // removed: did not work with magic_quotes_gpc = On
07980                 //$result = ilUtil::stripSlashes($result, true, ilObjAdvancedEditing::_getUsedHTMLTagsAsString("assessment"));
07981                 if (!$is_html)
07982                 {
07983                         // if the string does not contain HTML code, replace the newlines with HTML line breaks
07984                         $result = preg_replace("/[\n]/", "<br />", $result);
07985                 }
07986                 else
07987                 {
07988                         // patch for problems with the <pre> tags in tinyMCE
07989                         if (preg_match_all("/(<pre>.*?<\/pre>)/ims", $result, $matches))
07990                         {
07991                                 foreach ($matches[0] as $found)
07992                                 {
07993                                         $replacement = "";
07994                                         if (strpos("\n", $found) === FALSE)
07995                                         {
07996                                                 $replacement = "\n";
07997                                         }
07998                                         $removed = preg_replace("/<br\s*?\/>/ims", $replacement, $found);
07999                                         $result = str_replace($found, $removed, $result);
08000                                 }
08001                         }
08002                 }
08003                 $result = str_replace("{", "&#123;", $result);
08004                 $result = str_replace("}", "&#125;", $result);
08005                 $result = str_replace("\\", "&#92;", $result);
08006                 return $result;
08007         }
08008 
08017         function &evalResultsOverview()
08018         {
08019                 return $this->_evalResultsOverview($this->getTestId());
08020         }
08021 
08030         function &_evalResultsOverview($test_id)
08031         {
08032                 global $ilDB;
08033                 
08034                 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08035                         "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08036                         "qpl_questions.points AS maxpoints " .
08037                         "FROM tst_test_result, qpl_questions, tst_active " .
08038                         "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08039                         "WHERE tst_active.active_id = tst_test_result.active_fi " .
08040                         "AND qpl_questions.question_id = tst_test_result.question_fi " .
08041                         "AND tst_active.test_fi = %s " .
08042                         "ORDER BY active_id, pass, TIMESTAMP",
08043                         $ilDB->quote($test_id . "")
08044                 );
08045                 $result = $ilDB->query($query);
08046                 $overview = array();
08047                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08048                 {
08049                         if (!array_key_exists($row["active_fi"], $overview))
08050                         {
08051                                 $overview[$row["active_fi"]] = array();
08052                                 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
08053                                 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
08054                                 $overview[$row["active_fi"]]["title"] = $row["title"];
08055                                 $overview[$row["active_fi"]]["login"] = $row["login"];
08056                                 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
08057                                 $overview[$row["active_fi"]]["started"] = $row["started"];
08058                                 $overview[$row["active_fi"]]["finished"] = $row["finished"];
08059                         }
08060                         if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
08061                         {
08062                                 $overview[$row["active_fi"]][$row["pass"]] = array();
08063                                 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
08064                                 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
08065                         }
08066                         array_push($overview[$row["active_fi"]][$row["pass"]], $row);
08067                         $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
08068                 }
08069                 return $overview;
08070         }
08071 
08085         function buildName($user_id, $firstname, $lastname, $title)
08086         {
08087                 $name = "";
08088                 if (strlen($firstname.$lastname.$title) == 0)
08089                 {
08090                         $name = $this->lng->txt("deleted_user");
08091                 }
08092                 else
08093                 {
08094                         if ($user_id == ANONYMOUS_USER_ID)
08095                         {
08096                                 $name = $row["lastname"];
08097                         }
08098                         else
08099                         {
08100                                 $name = trim($lastname . ", " . $firstname . " " .  $title);
08101                         }
08102                         if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
08103                         {
08104                                 $name = $this->lng->txt("anonymous");
08105                         }
08106                 }
08107                 return $name;
08108         }
08109 
08123         function _buildName($test_type, $user_id, $firstname, $lastname, $title)
08124         {
08125                 global $lng;
08126                 $name = "";
08127                 if (strlen($firstname.$lastname.$title) == 0)
08128                 {
08129                         $name = $lng->txt("deleted_user");
08130                 }
08131                 else
08132                 {
08133                         if ($user_id == ANONYMOUS_USER_ID)
08134                         {
08135                                 $name = $lastname;
08136                         }
08137                         else
08138                         {
08139                                 $name = trim($lastname . ", " . $firstname . " " .  $title);
08140                         }
08141                         if ($test_type == TYPE_SELF_ASSESSMENT)
08142                         {
08143                                 $name = $lng->txt("anonymous");
08144                         }
08145                 }
08146                 return $name;
08147         }
08148 
08149         function &_getCompleteEvaluationData($test_id, $withStatistics = TRUE, $active_id = "")
08150         {
08151                 global $ilDB;
08152 
08153                 $testquery = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
08154                         $ilDB->quote($test_id . "")
08155                 );
08156                 $testres = $ilDB->query($testquery);
08157                 $testdata = array();
08158                 if ($testres->numRows())
08159                 {
08160                         $testdata = $testres->fetchRow(DB_FETCHMODE_ASSOC);
08161                 }
08162                 
08163                 include_once "./assessment/classes/class.assMarkSchema.php";
08164                 $mark_schema = new ASS_MarkSchema();
08165                 $mark_schema->loadFromDb($test_id);
08166 
08167                 include_once "./assessment/classes/class.ilTestEvaluationPassData.php";
08168                 include_once "./assessment/classes/class.ilTestEvaluationUserData.php";
08169                 include_once "./assessment/classes/class.ilTestEvaluationData.php";
08170                 if ($active_id > 0) $withStatistics = FALSE;
08171                 $data = new ilTestEvaluationData($test_id);
08172                 $query = "";
08173                 if ($active_id > 0)
08174                 {
08175                         $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08176                                 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08177                                 "qpl_questions.points AS maxpoints " .
08178                                 "FROM tst_test_result, qpl_questions, tst_active " .
08179                                 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08180                                 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08181                                 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08182                                 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
08183                                 "ORDER BY active_id, pass, TIMESTAMP",
08184                                 $ilDB->quote($test_id . ""),
08185                                 $ilDB->quote($active_id . "")
08186                         );
08187                 }
08188                 else
08189                 {
08190                         $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08191                                 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08192                                 "qpl_questions.points AS maxpoints " .
08193                                 "FROM tst_test_result, qpl_questions, tst_active " .
08194                                 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08195                                 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08196                                 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08197                                 "AND tst_active.test_fi = %s " .
08198                                 "ORDER BY active_id, pass, TIMESTAMP",
08199                                 $ilDB->quote($test_id . "")
08200                         );
08201                 }
08202                 $result = $ilDB->query($query);
08203                 $pass = NULL;
08204                 $participant = NULL;
08205                 $pass = NULL;
08206                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08207                 {
08208                         if (!$data->participantExists($row["active_fi"]))
08209                         {
08210                                 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
08211                                 $participant =& $data->getParticipant($row["active_fi"]);
08212                                 $participant->setName(ilObjTest::_buildName($testdata["test_type_fi"], $row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
08213                                 $participant->setLogin($row["login"]);
08214                                 $participant->setUserID($row["usr_id"]);
08215                         }
08216                         if (!is_object($participant->getPass($row["pass"])))
08217                         {
08218                                 $participant->addPass($row["pass"], new ilTestEvaluationPassData($row["pass"]));
08219                                 $pass =& $participant->getPass($row["pass"]);
08220                         }
08221                         $pass->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
08222                 }
08223                 if ($testdata["test_type_fi"] != TYPE_VARYING_RANDOMTEST)
08224                 {
08225                         // ILIAS fix to deal with "old style" tests where a user expects that in a new test pass
08226                         // the old question answers are part of this pass and only overwritten when a question is answered again
08227                         foreach ($data->getParticipantIds() as $active_id)
08228                         {
08229                                 $participant =& $data->getParticipant($active_id);
08230                                 $lastpass = $participant->getLastPass();
08231                                 if ($lastpass > 0)
08232                                 {
08233                                         $passdatalast =& $participant->getPass($lastpass);
08234                                         $answeredids = array();
08235                                         foreach ($passdatalast->getAnsweredQuestions() as $foundquestion)
08236                                         {
08237                                                 array_push($answeredids, $foundquestion["id"]);
08238                                         }
08239                                         $pointsarray = array();
08240                                         $reachedarray = array();
08241                                         for ($pc = 0; $pc <= $lastpass; $pc++)
08242                                         {
08243                                                 $passdataactual =& $participant->getPass($pc);
08244                                                 if ($passdataactual != null)
08245                                                 {
08246                                                         foreach ($passdataactual->getAnsweredQuestions() as $foundquestion)
08247                                                         {
08248                                                                 $pointsarray[$foundquestion["id"]] = $foundquestion["points"];
08249                                                                 $reachedarray[$foundquestion["id"]] = $foundquestion["reached"];
08250                                                         }
08251                                                 }
08252                                         }
08253                                         foreach ($pointsarray as $question_id => $question_points)
08254                                         {
08255                                                 if (!in_array($question_id, $answeredids))
08256                                                 {
08257                                                         $passdatalast->addAnsweredQuestion($question_id, $question_points, $reachedarray[$question_id]);
08258                                                 }
08259                                         }
08260                                 }
08261                         }
08262                 }
08263                 foreach ($data->getParticipantIds() as $active_id)
08264                 {
08265                         $participant =& $data->getParticipant($active_id);
08266                         if ($testdata["random_test"])
08267                         {
08268                                 for ($testpass = 0; $testpass <= $data->getLastPassOfParticipant($active_id); $testpass++)
08269                                 { 
08270                                         $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
08271                                                 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title, qpl_question_type.type_tag " .
08272                                                 "FROM tst_test_random_question, qpl_questions, qpl_question_type " .
08273                                                 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
08274                                                 "AND tst_test_random_question.pass = %s " .
08275                                                 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08276                                                 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
08277                                                 $ilDB->quote($testpass . ""),
08278                                                 $ilDB->quote($active_id . ""),
08279                                                 ilObjTest::_getQuestionCount($test_id)
08280                                         );
08281                                         $result = $ilDB->query($query);
08282                                         if ($result->numRows())
08283                                         {
08284                                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08285                                                 {
08286                                                         $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08287                                                         $data->addQuestionForParticipant($active_id, $row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08288                                                         $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08289                                                 }
08290                                         }
08291                                 }
08292                         }
08293                         else
08294                         {
08295                                 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
08296                                         "qpl_questions.points, qpl_questions.title, qpl_questions.original_id, qpl_question_type.type_tag " .
08297                                         "FROM tst_test_question, tst_active, qpl_questions, qpl_question_type " .
08298                                         "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
08299                                         "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08300                                         "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
08301                                         $ilDB->quote($active_id . "")
08302                                 );
08303                                 $result = $ilDB->query($query);
08304                                 if ($result->numRows())
08305                                 {
08306                                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08307                                         {
08308                                                 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08309                                                 $participant->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08310                                                 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08311                                         }
08312                                 }
08313                         }
08314                 }
08315 
08316                 $workingTimes =& ilObjTest::_getCompleteWorkingTimeOfParticipants($test_id);
08317 
08318                 foreach (array_keys($data->getParticipants()) as $active_id)
08319                 {
08320                         $xpass = 0;
08321                         $participant =& $data->getParticipant($active_id);
08322                         if ($testdata["pass_scoring"] == SCORE_BEST_PASS)
08323                         {
08324                                 $xpass = $participant->getBestPass();
08325                         }
08326                         else
08327                         {
08328                                 $xpass = $participant->getLastPass();
08329                         }
08330                         $participant->setReached($participant->getReachedPoints($xpass));
08331                         $participant->setMaxPoints($participant->getAvailablePoints($xpass));
08332                         $percentage = $participant->getMaxPoints() ? $participant->getReached() / $participant->getMaxPoints() * 100.0 : 0;
08333                         $mark = $mark_schema->getMatchingMark($percentage);
08334                         if (is_object($mark))
08335                         {
08336                                 $participant->setMark($mark->getShortName());
08337                                 $participant->setMarkOfficial($mark->getOfficialName());
08338                                 $participant->setPassed($mark->getPassed());
08339                         }
08340                         $userpass =& $participant->getPass($xpass);
08341                         if (is_object($userpass)) $participant->setQuestionsWorkedThrough($userpass->getAnsweredQuestionCount());
08342                         $questionpass = $xpass;
08343                         if (!is_array($participant->getQuestions($xpass)))
08344                         {
08345                                 $questionpass = 0;
08346                         }
08347                         $participant->setNumberOfQuestions(count($participant->getQuestions($questionpass)));
08348                         $participant->setTimeOfWork($workingTimes[$active_id]);
08349                         $visitingTime =& ilObjTest::_getVisitTimeOfParticipant($test_id, $active_id);
08350                         $participant->setFirstVisit($visitingTime["firstvisit"]);
08351                         $participant->setLastVisit($visitingTime["lastvisit"]);
08352                 }
08353                 $passed_points = array();
08354                 foreach (array_keys($data->getParticipants()) as $active_id)
08355                 {
08356                         $participant =& $data->getParticipant($active_id);
08357                         if ($participant->getPassed())
08358                         {
08359                                 array_push($passed_points, $participant->getReached());
08360                         }
08361                 }
08362                 foreach (array_keys($data->getParticipants()) as $active_id)
08363                 {
08364                         $participant =& $data->getParticipant($active_id);
08365                         if ($testdata["ects_output"])
08366                         {
08367                                 $ects_mark = ilObjTest::_getECTSGrade($passed_points, $participant->getReached(), $participant->getMaxPoints(), $testdata["ects_a"], $testdata["ects_b"], $testdata["ects_c"], $testdata["ects_d"], $testdata["ects_e"], $testdata["ects_fx"]);
08368                                 $participant->setECTSMark($ects_mark);
08369                         }
08370                 }
08371                 if ($withStatistics)
08372                 {
08373                         $data->calculateStatistics();
08374                 }
08375                 return $data;
08376         }
08377         
08378         function &getCompleteEvaluationData($withStatistics = TRUE)
08379         {
08380                 global $ilDB;
08381                 include_once "./assessment/classes/class.ilTestEvaluationPassData.php";
08382                 include_once "./assessment/classes/class.ilTestEvaluationUserData.php";
08383                 include_once "./assessment/classes/class.ilTestEvaluationData.php";
08384                 $data = new ilTestEvaluationData($this->getTestId());
08385                 
08386                 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08387                         "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08388                         "qpl_questions.points AS maxpoints " .
08389                         "FROM tst_test_result, qpl_questions, tst_active " .
08390                         "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08391                         "WHERE tst_active.active_id = tst_test_result.active_fi " .
08392                         "AND qpl_questions.question_id = tst_test_result.question_fi " .
08393                         "AND tst_active.test_fi = %s " .
08394                         "ORDER BY active_id, pass, TIMESTAMP",
08395                         $ilDB->quote($this->getTestId() . "")
08396                 );
08397                 $result = $ilDB->query($query);
08398                 $pass = NULL;
08399                 $participant = NULL;
08400                 $pass = NULL;
08401                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08402                 {
08403                         if (!$data->participantExists($row["active_fi"]))
08404                         {
08405                                 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
08406                                 $participant =& $data->getParticipant($row["active_fi"]);
08407                                 $participant->setName($this->buildName($row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
08408                                 $participant->setLogin($row["login"]);
08409                                 $participant->setUserID($row["usr_id"]);
08410                         }
08411                         if (!is_object($participant->getPass($row["pass"])))
08412                         {
08413                                 $participant->addPass($row["pass"], new ilTestEvaluationPassData($row["pass"]));
08414                                 $pass =& $participant->getPass($row["pass"]);
08415                         }
08416                         $pass->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
08417                 }
08418                 if ($this->getTestType() != TYPE_VARYING_RANDOMTEST)
08419                 {
08420                         // ILIAS fix to deal with "old style" tests where a user expects that in a new test pass
08421                         // the old question answers are part of this pass and only overwritten when a question is answered again
08422                         foreach ($data->getParticipantIds() as $active_id)
08423                         {
08424                                 $participant =& $data->getParticipant($active_id);
08425                                 $lastpass = $participant->getLastPass();
08426                                 if ($lastpass > 0)
08427                                 {
08428                                         $passdatalast =& $participant->getPass($lastpass);
08429                                         $answeredids = array();
08430                                         foreach ($passdatalast->getAnsweredQuestions() as $foundquestion)
08431                                         {
08432                                                 array_push($answeredids, $foundquestion["id"]);
08433                                         }
08434                                         $pointsarray = array();
08435                                         $reachedarray = array();
08436                                         for ($pc = 0; $pc <= $lastpass; $pc++)
08437                                         {
08438                                                 $passdataactual =& $participant->getPass($pc);
08439                                                 if ($passdataactual != null)
08440                                                 {
08441                                                         foreach ($passdataactual->getAnsweredQuestions() as $foundquestion)
08442                                                         {
08443                                                                 $pointsarray[$foundquestion["id"]] = $foundquestion["points"];
08444                                                                 $reachedarray[$foundquestion["id"]] = $foundquestion["reached"];
08445                                                         }
08446                                                 }
08447                                         }
08448                                         foreach ($pointsarray as $question_id => $question_points)
08449                                         {
08450                                                 if (!in_array($question_id, $answeredids))
08451                                                 {
08452                                                         $passdatalast->addAnsweredQuestion($question_id, $question_points, $reachedarray[$question_id]);
08453                                                 }
08454                                         }
08455                                 }
08456                         }
08457                 }
08458                 foreach ($data->getParticipantIds() as $active_id)
08459                 {
08460                         $participant =& $data->getParticipant($active_id);
08461                         if ($this->isRandomTest())
08462                         {
08463                                 for ($testpass = 0; $testpass <= $data->getLastPassOfParticipant($active_id); $testpass++)
08464                                 { 
08465                                         $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
08466                                                 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title, qpl_question_type.type_tag " .
08467                                                 "FROM tst_test_random_question, qpl_questions, qpl_question_type " .
08468                                                 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
08469                                                 "AND tst_test_random_question.pass = %s " .
08470                                                 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08471                                                 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
08472                                                 $ilDB->quote($testpass . ""),
08473                                                 $ilDB->quote($active_id . ""),
08474                                                 $this->getQuestionCount()
08475                                         );
08476                                         $result = $ilDB->query($query);
08477                                         if ($result->numRows())
08478                                         {
08479                                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08480                                                 {
08481                                                         $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08482                                                         $data->addQuestionForParticipant($active_id, $row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08483                                                         $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08484                                                 }
08485                                         }
08486                                 }
08487                         }
08488                         else
08489                         {
08490                                 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
08491                                         "qpl_questions.points, qpl_questions.title, qpl_questions.original_id, qpl_question_type.type_tag " .
08492                                         "FROM tst_test_question, tst_active, qpl_questions, qpl_question_type " .
08493                                         "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
08494                                         "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08495                                         "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
08496                                         $ilDB->quote($active_id . "")
08497                                 );
08498                                 $result = $ilDB->query($query);
08499                                 if ($result->numRows())
08500                                 {
08501                                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08502                                         {
08503                                                 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08504                                                 $participant->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08505                                                 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08506                                         }
08507                                 }
08508                         }
08509                 }
08510 
08511                 $workingTimes =& $this->getCompleteWorkingTimeOfParticipants();
08512 
08513                 foreach (array_keys($data->getParticipants()) as $active_id)
08514                 {
08515                         $xpass = 0;
08516                         $participant =& $data->getParticipant($active_id);
08517                         if ($this->getPassScoring() == SCORE_BEST_PASS)
08518                         {
08519                                 $xpass = $participant->getBestPass();
08520                         }
08521                         else
08522                         {
08523                                 $xpass = $participant->getLastPass();
08524                         }
08525                         $participant->setReached($participant->getReachedPoints($xpass));
08526                         $participant->setMaxPoints($participant->getAvailablePoints($xpass));
08527                         $percentage = $participant->getMaxPoints() ? $participant->getReached() / $participant->getMaxPoints() * 100.0 : 0;
08528                         $mark = $this->mark_schema->getMatchingMark($percentage);
08529                         if (is_object($mark))
08530                         {
08531                                 $participant->setMark($mark->getShortName());
08532                                 $participant->setMarkOfficial($mark->getOfficialName());
08533                                 $participant->setPassed($mark->getPassed());
08534                         }
08535                         if ($this->ects_output)
08536                         {
08537                                 // TODO: This is a performance killer!!!!
08538                                 $ects_mark = $this->getECTSGrade($participant->getReached(), $participant->getMaxPoints());
08539                                 $participant->setECTSMark($ects_mark);
08540                         }
08541                         $userpass =& $participant->getPass($xpass);
08542                         if (is_object($userpass)) $participant->setQuestionsWorkedThrough($userpass->getAnsweredQuestionCount());
08543                         $questionpass = $xpass;
08544                         if (!is_array($participant->getQuestions($xpass)))
08545                         {
08546                                 $questionpass = 0;
08547                         }
08548                         $participant->setNumberOfQuestions(count($participant->getQuestions($questionpass)));
08549                         $participant->setTimeOfWork($workingTimes[$active_id]);
08550                         $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
08551                         $participant->setFirstVisit($visitingTime["firstvisit"]);
08552                         $participant->setLastVisit($visitingTime["lastvisit"]);
08553                 }
08554                 if ($withStatistics)
08555                 {
08556                         $data->calculateStatistics();
08557                 }
08558                 return $data;
08559         }
08560         
08569         function &getCompleteWorkingTimeOfParticipants()
08570         {
08571                 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
08572         }
08573 
08582         function &_getCompleteWorkingTimeOfParticipants($test_id)
08583         {
08584                 global $ilDB;
08585 
08586                 $query = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.active_fi, tst_times.started",
08587                         $ilDB->quote($test_id . "")
08588                 );
08589                 $result = $ilDB->query($query);
08590                 $time = 0;
08591                 $times = array();
08592                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08593                 {
08594                         if (!array_key_exists($row["active_fi"], $times))
08595                         {
08596                                 $times[$row["active_fi"]] = 0;
08597                         }
08598                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
08599                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08600                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
08601                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08602                         $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
08603                 }
08604                 return $times;
08605         }
08606 
08615         function getVisitTimeOfParticipant($active_id)
08616         {
08617                 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
08618         }
08619 
08628         function _getVisitTimeOfParticipant($test_id, $active_id)
08629         {
08630                 global $ilDB;
08631 
08632                 $query = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.active_id = %s ORDER BY tst_times.started",
08633                         $ilDB->quote($test_id . ""),
08634                         $ilDB->quote($active_id . "")
08635                 );
08636                 $result = $ilDB->query($query);
08637                 $firstvisit = 0;
08638                 $lastvisit = 0;
08639                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08640                 {
08641                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
08642                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08643                         if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
08644                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
08645                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08646                         if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
08647                 }
08648                 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
08649         }
08650 
08651 } // END class.ilObjTest
08652 
08653 ?>

Generated on Fri Dec 13 2013 13:52:06 for ILIAS Release_3_7_x_branch .rev 46817 by  doxygen 1.7.1