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

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

Generated on Fri Dec 13 2013 17:56:53 for ILIAS Release_3_9_x_branch .rev 46835 by  doxygen 1.7.1