ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assQuestion.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
25 
37 {
45  var $id;
46 
54  var $title;
55 
63  var $comment;
64 
73  var $owner;
74 
83  var $author;
84 
92  var $question;
93 
103  var $points;
104 
113 
121  var $shuffle;
122 
130  var $test_id;
131 
139  var $obj_id;
140 
148  var $ilias;
149 
157  var $tpl;
158 
166  var $lng;
167 
175  var $domxml;
176 
185 
199  function assQuestion(
200  $title = "",
201  $comment = "",
202  $author = "",
203  $owner = -1,
204  $question = ""
205  )
206  {
207  global $ilias;
208  global $lng;
209  global $tpl;
210 
211  $this->ilias =& $ilias;
212  $this->lng =& $lng;
213  $this->tpl =& $tpl;
214 
215  $this->original_id = null;
216  $this->title = $title;
217  $this->comment = $comment;
218  $this->author = $author;
219  $this->setQuestion($question);
220  if (!$this->author)
221  {
222  $this->author = $this->ilias->account->fullname;
223  }
224  $this->owner = $owner;
225  if ($this->owner == -1)
226  {
227  $this->owner = $this->ilias->account->id;
228  }
229  $this->id = -1;
230  $this->test_id = -1;
231  $this->suggested_solutions = array();
232  $this->shuffle = 1;
233  $this->setEstimatedWorkingTime(0,1,0);
234  $this->outputType = OUTPUT_HTML;
235  register_shutdown_function(array(&$this, '_assQuestion'));
236  }
237 
238  function _assQuestion()
239  {
240  if (!empty($this->domxml))
241  {
242  $this->domxml->free();
243  }
244  }
245 
259  function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
260  {
261  include_once "./Modules/TestQuestionPool/classes/import/qti12/class." . $this->getQuestionType() . "Import.php";
262  $classname = $this->getQuestionType() . "Import";
263  $import = new $classname($this);
264  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
265  }
266 
276  function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
277  {
278  include_once "./Modules/TestQuestionPool/classes/export/qti12/class." . $this->getQuestionType() . "Export.php";
279  $classname = $this->getQuestionType() . "Export";
280  $export = new $classname($this);
281  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
282  }
283 
292  function isComplete()
293  {
294  return false;
295  }
296 
306  function questionTitleExists($questionpool_id, $title)
307  {
308  global $ilDB;
309 
310  $query = sprintf("SELECT * FROM qpl_questions WHERE obj_fi = %s AND title = %s",
311  $ilDB->quote($questionpool_id . ""),
312  $ilDB->quote($title)
313  );
314  $result = $ilDB->query($query);
315  if ($result->numRows() == 1)
316  {
317  return TRUE;
318  }
319  return FALSE;
320  }
321 
331  function setTitle($title = "")
332  {
333  $this->title = $title;
334  }
335 
345  function setId($id = -1)
346  {
347  $this->id = $id;
348  }
349 
359  function setTestId($id = -1)
360  {
361  $this->test_id = $id;
362  }
363 
373  function setComment($comment = "")
374  {
375  $this->comment = $comment;
376  }
377 
388  {
389  $this->outputType = $outputType;
390  }
391 
392 
402  function setShuffle($shuffle = true)
403  {
404  if ($shuffle)
405  {
406  $this->shuffle = 1;
407  }
408  else
409  {
410  $this->shuffle = 0;
411  }
412  }
413 
425  function setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
426  {
427  $this->est_working_time = array("h" => (int)$hour, "m" => (int)$min, "s" => (int)$sec);
428  }
429 
439  function keyInArray($searchkey, $array)
440  {
441  if ($searchKey)
442  {
443  foreach ($array as $key => $value)
444  {
445  if (strcmp($key, $searchkey)==0)
446  {
447  return true;
448  }
449  }
450  }
451  return false;
452  }
453 
463  function setAuthor($author = "")
464  {
465  if (!$author)
466  {
467  $author = $this->ilias->account->fullname;
468  }
469  $this->author = $author;
470  }
471 
481  function setOwner($owner = "")
482  {
483  $this->owner = $owner;
484  }
485 
495  function getTitle()
496  {
497  return $this->title;
498  }
499 
509  function getId()
510  {
511  return $this->id;
512  }
513 
523  function getShuffle()
524  {
525  return $this->shuffle;
526  }
527 
537  function getTestId()
538  {
539  return $this->test_id;
540  }
541 
551  function getComment()
552  {
553  return $this->comment;
554  }
555 
565  function getOutputType()
566  {
567  return $this->outputType;
568  }
569 
579  {
580  return FALSE;
581  }
582 
593  {
594  if (!$this->est_working_time)
595  {
596  $this->est_working_time = array("h" => 0, "m" => 0, "s" => 0);
597  }
599  }
600 
610  function getAuthor()
611  {
612  return $this->author;
613  }
614 
624  function getOwner()
625  {
626  return $this->owner;
627  }
628 
638  function getObjId()
639  {
640  return $this->obj_id;
641  }
642 
652  function setObjId($obj_id = 0)
653  {
654  $this->obj_id = $obj_id;
655  }
656 
660  function createPageObject()
661  {
662  $qpl_id = $this->getObjId();
663 
664  include_once "./Services/COPage/classes/class.ilPageObject.php";
665  $this->page = new ilPageObject("qpl", 0);
666  $this->page->setId($this->getId());
667  $this->page->setParentId($qpl_id);
668  $this->page->setXMLContent("<PageObject><PageContent>".
669  "<Question QRef=\"il__qst_".$this->getId()."\"/>".
670  "</PageContent></PageObject>");
671  $this->page->create();
672  }
673 
683  {
684  global $ilDB;
685 
686  // get maximum sequence index in test
687  $query = sprintf("SELECT MAX(sequence) AS seq FROM dum_test_question WHERE test_fi=%s",
688  $ilDB->quote($test_id)
689  );
690  $result = $ilDB->query($query);
691  $sequence = 1;
692  if ($result->numRows() == 1)
693  {
694  $data = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
695  $sequence = $data->seq + 1;
696  }
697  $query = sprintf("INSERT INTO dum_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
698  $ilDB->quote($test_id),
699  $ilDB->quote($this->getId()),
700  $ilDB->quote($sequence)
701  );
702  $result = $ilDB->query($query);
703  if (PEAR::isError($result))
704  {
705  global $ilias;
706  $ilias->raiseError($result->getMessage());
707  }
708  }
709 
719  function _getMaximumPoints($question_id)
720  {
721  global $ilDB;
722 
723  $points = 0;
724  $query = sprintf("SELECT points FROM qpl_questions WHERE question_id = %s",
725  $ilDB->quote($question_id . "")
726  );
727  $result = $ilDB->query($query);
728  if ($result->numRows() == 1)
729  {
730  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
731  $points = $row["points"];
732  }
733  return $points;
734  }
735 
745  function &_getQuestionInfo($question_id)
746  {
747  global $ilDB;
748 
749  $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_question_type, qpl_questions WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
750  $ilDB->quote($question_id . "")
751  );
752  $result = $ilDB->query($query);
753  if ($result->numRows())
754  {
755  return $result->fetchRow(MDB2_FETCHMODE_ASSOC);
756  }
757  else return array();
758  }
759 
769  function _getSuggestedSolutionCount($question_id)
770  {
771  global $ilDB;
772 
773  $query = sprintf("SELECT suggested_solution_id FROM qpl_suggested_solutions WHERE question_fi = %s",
774  $ilDB->quote($question_id . "")
775  );
776  $result = $ilDB->query($query);
777  return $result->numRows();
778  }
779 
790  function &_getSuggestedSolution($question_id, $subquestion_index = 0)
791  {
792  global $ilDB;
793 
794  $query = sprintf("SELECT * FROM qpl_suggested_solutions WHERE question_fi = %s AND subquestion_index = %s",
795  $ilDB->quote($question_id . ""),
796  $ilDB->quote($subquestion_index . "")
797  );
798  $result = $ilDB->query($query);
799  if ($result->numRows() == 1)
800  {
801  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
802  return array(
803  "internal_link" => $row["internal_link"],
804  "import_id" => $row["import_id"]
805  );
806  }
807  else
808  {
809  return array();
810  }
811  }
812 
823  function _getReachedPoints($active_id, $question_id, $pass = NULL)
824  {
825  global $ilDB;
826 
827  $points = 0;
828  if (is_null($pass))
829  {
830  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
831  $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
832  }
833  $query = sprintf("SELECT * FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
834  $ilDB->quote($active_id . ""),
835  $ilDB->quote($question_id . ""),
836  $ilDB->quote($pass . "")
837  );
838  $result = $ilDB->query($query);
839  if ($result->numRows() == 1)
840  {
841  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
842  $points = $row["points"];
843  }
844  return $points;
845  }
846 
857  function getReachedPoints($active_id, $pass = NULL)
858  {
859  return $this->_getReachedPoints($active_id, $this->getId(), $pass);
860  }
861 
870  function getMaximumPoints()
871  {
872  return 0;
873  }
874 
884  function saveWorkingData($active_id, $pass = NULL)
885  {
886  global $ilDB;
887  global $ilUser;
888  if (is_null($pass))
889  {
890  include_once "./Modules/Test/classes/class.ilObjTest.php";
891  $pass = ilObjTest::_getPass($active_id);
892  }
893  $reached_points = $this->calculateReachedPoints($active_id, $pass);
894  $query = sprintf("REPLACE INTO tst_test_result (active_fi, question_fi, pass, points) VALUES (%s, %s, %s, %s)",
895  $ilDB->quote($active_id . ""),
896  $ilDB->quote($this->getId() . ""),
897  $ilDB->quote($pass . ""),
898  $ilDB->quote($reached_points . "")
899  );
900  $result = $ilDB->query($query);
901  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
903  {
904  $this->logAction(sprintf($this->lng->txtlng("assessment", "log_user_answered_question", ilObjAssessmentFolder::_getLogLanguage()), $reached_points), $active_id, $this->getId());
905  }
906 
907  // update test pass results
908  $this->_updateTestPassResults($active_id, $pass);
909 
910  // Update objective status
911  include_once 'Modules/Course/classes/class.ilCourseObjectiveResult.php';
912  ilCourseObjectiveResult::_updateObjectiveResult($ilUser->getId(),$active_id,$this->getId());
913 
914  }
915 
916  function _updateTestPassResults($active_id, $pass)
917  {
918  global $ilDB;
919  include_once "./Modules/Test/classes/class.ilObjTest.php";
922  // update test pass results
923  $query = sprintf("SELECT SUM(points) AS reachedpoints, COUNT(question_fi) AS answeredquestions FROM tst_test_result WHERE active_fi = %s AND pass = %s",
924  $ilDB->quote($active_id . ""),
925  $ilDB->quote($pass . "")
926  );
927  $result = $ilDB->query($query);
928  if ($result->numRows() > 0)
929  {
930  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
931  $newresultquery = sprintf("REPLACE INTO tst_test_pass_result SET active_fi = %s, pass = %s, points = %s, maxpoints = %s, questioncount = %s, answeredquestions = %s, workingtime = %s",
932  $ilDB->quote($active_id . ""),
933  $ilDB->quote($pass . ""),
934  $ilDB->quote((($row["reachedpoints"]) ? $row["reachedpoints"] : 0) . ""),
935  $ilDB->quote($data["points"]),
936  $ilDB->quote($data["count"]),
937  $ilDB->quote($row["answeredquestions"]),
938  $ilDB->quote($time)
939  );
940  $ilDB->query($newresultquery);
941  }
942  }
952  function logAction($logtext = "", $active_id = "", $question_id = "")
953  {
954  global $ilUser;
955 
956  $original_id = "";
957  if (strcmp($question_id, "") != 0)
958  {
959  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
961  }
962  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
963  include_once "./Modules/Test/classes/class.ilObjTest.php";
964  ilObjAssessmentFolder::_addLog($ilUser->id, ilObjTest::_getObjectIDFromActiveID($active_id), $logtext, $question_id, $original_id);
965  }
966 
976  function _logAction($logtext = "", $active_id = "", $question_id = "")
977  {
978  global $ilUser;
979 
980  $original_id = "";
981  if (strcmp($question_id, "") != 0)
982  {
983  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
985  }
986  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
987  include_once "./Modules/Test/classes/class.ilObjTest.php";
988  ilObjAssessmentFolder::_addLog($ilUser->id, ilObjTest::_getObjectIDFromActiveID($active_id), $logtext, $question_id, $original_id);
989  }
990 
998  function moveUploadedMediaFile($file, $name)
999  {
1000  $mediatempdir = CLIENT_WEB_DIR . "/assessment/temp";
1001  if (!@is_dir($mediatempdir)) ilUtil::createDirectory($mediatempdir);
1002  $temp_name = tempnam($mediatempdir, $name . "_____");
1003  $temp_name = str_replace("\\", "/", $temp_name);
1004  @unlink($temp_name);
1005  if (!ilUtil::moveUploadedFile($file, $name, $temp_name))
1006  {
1007  return FALSE;
1008  }
1009  else
1010  {
1011  return $temp_name;
1012  }
1013  }
1014 
1023  function getJavaPath() {
1024  return CLIENT_WEB_DIR . "/assessment/$this->obj_id/$this->id/java/";
1025  }
1026 
1035  function getImagePath()
1036  {
1037  return CLIENT_WEB_DIR . "/assessment/$this->obj_id/$this->id/images/";
1038  }
1039 
1048  function getFlashPath()
1049  {
1050  return CLIENT_WEB_DIR . "/assessment/$this->obj_id/$this->id/flash/";
1051  }
1052 
1061  function getJavaPathWeb()
1062  {
1063  include_once "./Services/Utilities/classes/class.ilUtil.php";
1064  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/$this->obj_id/$this->id/java/";
1066  }
1067 
1076  function getImagePathWeb()
1077  {
1078  include_once "./Services/Utilities/classes/class.ilUtil.php";
1079  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/$this->obj_id/$this->id/images/";
1081  }
1082 
1091  function getFlashPathWeb()
1092  {
1093  include_once "./Services/Utilities/classes/class.ilUtil.php";
1094  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/$this->obj_id/$this->id/flash/";
1096  }
1097 
1107  function &getSolutionValues($active_id, $pass = NULL)
1108  {
1109  global $ilDB;
1110 
1111  $values = array();
1112 
1113  if (is_null($pass))
1114  {
1115  $pass = $this->getSolutionMaxPass($active_id);
1116  /*
1117  $query = sprintf("SELECT MAX(pass) AS maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
1118  $ilDB->quote($active_id . ""),
1119  $ilDB->quote($this->getId() . "")
1120  );
1121  $result = $ilDB->query($query);
1122  if ($result->numRows())
1123  {
1124  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
1125  $pass = $row["maxpass"];
1126  }
1127  else
1128  {
1129  return $values;
1130  }
1131  */
1132  }
1133 
1134  $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1135  $ilDB->quote($active_id . ""),
1136  $ilDB->quote($this->getId() . ""),
1137  $ilDB->quote($pass . "")
1138  );
1139  $result = $ilDB->query($query);
1140  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
1141  {
1142  array_push($values, $row);
1143  }
1144 
1145  return $values;
1146  }
1147 
1156  function isInUse($question_id = "")
1157  {
1158  global $ilDB;
1159 
1160  if ($question_id < 1) $question_id = $this->id;
1161  $query = sprintf("SELECT COUNT(qpl_questions.question_id) AS question_count FROM qpl_questions, tst_test_question WHERE qpl_questions.original_id = %s AND qpl_questions.question_id = tst_test_question.question_fi",
1162  $ilDB->quote($question_id . "")
1163  );
1164  $result = $ilDB->query($query);
1165  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
1166  $count = $row["question_count"];
1167 
1168  $query = sprintf("SELECT DISTINCT tst_active.test_fi, qpl_questions.question_id FROM qpl_questions, tst_test_random_question, tst_active WHERE qpl_questions.original_id = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.active_fi = tst_active.active_id",
1169  $ilDB->quote($question_id . "")
1170  );
1171  $result = $ilDB->query($query);
1172  $count += $result->numRows();
1173 
1174  return $count;
1175  }
1176 
1185  function isClone($question_id = "")
1186  {
1187  global $ilDB;
1188 
1189  if ($question_id < 1) $question_id = $this->id;
1190  $query = sprintf("SELECT original_id FROM qpl_questions WHERE question_id = %s",
1191  $ilDB->quote($question_id . "")
1192  );
1193  $result = $ilDB->query($query);
1194  $row = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
1195  if ($row->original_id > 0)
1196  {
1197  return TRUE;
1198  }
1199  else
1200  {
1201  return FALSE;
1202  }
1203  }
1204 
1213  function pcArrayShuffle($array)
1214  {
1215  mt_srand((double)microtime()*1000000);
1216  $i = count($array);
1217  if ($i > 0)
1218  {
1219  while(--$i)
1220  {
1221  $j = mt_rand(0, $i);
1222  if ($i != $j)
1223  {
1224  // swap elements
1225  $tmp = $array[$j];
1226  $array[$j] = $array[$i];
1227  $array[$i] = $tmp;
1228  }
1229  }
1230  }
1231  return $array;
1232  }
1233 
1239  function getQuestionTypeFromDb($question_id)
1240  {
1241  global $ilDB;
1242 
1243  $query = sprintf("SELECT qpl_question_type.type_tag FROM qpl_question_type, qpl_questions WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
1244  $ilDB->quote($question_id));
1245 
1246  $result = $ilDB->query($query);
1247  $data = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
1248 
1249  return $data->type_tag;
1250  }
1251 
1261  {
1262  return "";
1263  }
1264 
1274  {
1275  return "";
1276  }
1277 
1286  function deleteAnswers($question_id)
1287  {
1288  global $ilDB;
1289  $answer_table_name = $this->getAnswerTableName();
1290  if (is_array($answer_table_name))
1291  {
1292  foreach ($answer_table_name as $table)
1293  {
1294  if (strlen($table))
1295  {
1296  $query = sprintf("DELETE FROM $table WHERE question_fi = %s",
1297  $ilDB->quote($question_id . "")
1298  );
1299  $result = $ilDB->query($query);
1300  }
1301  }
1302  }
1303  else
1304  {
1305  if (strlen($answer_table_name))
1306  {
1307  $query = sprintf("DELETE FROM $answer_table_name WHERE question_fi = %s",
1308  $ilDB->quote($question_id . "")
1309  );
1310  $result = $ilDB->query($query);
1311  }
1312  }
1313  }
1314 
1323  function deleteAdditionalTableData($question_id)
1324  {
1325  global $ilDB;
1326  $additional_table_name = $this->getAdditionalTableName();
1327  if (is_array($additional_table_name))
1328  {
1329  foreach ($additional_table_name as $table)
1330  {
1331  if (strlen($table))
1332  {
1333  $query = sprintf("DELETE FROM $table WHERE question_fi = %s",
1334  $ilDB->quote($question_id . "")
1335  );
1336  $result = $ilDB->query($query);
1337  }
1338  }
1339  }
1340  else
1341  {
1342  if (strlen($additional_table_name))
1343  {
1344  $query = sprintf("DELETE FROM $additional_table_name WHERE question_fi = %s",
1345  $ilDB->quote($question_id . "")
1346  );
1347  $result = $ilDB->query($query);
1348  }
1349  }
1350  }
1351 
1358  protected function deletePageOfQuestion($question_id)
1359  {
1360  include_once "./Services/COPage/classes/class.ilPageObject.php";
1361  $page = new ilPageObject("qpl", $question_id);
1362  $page->delete();
1363  }
1364 
1371  function delete($question_id)
1372  {
1373  global $ilDB;
1374 
1375  if ($question_id < 1)
1376  return;
1377 
1378  $query = sprintf("SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
1379  $ilDB->quote($question_id)
1380  );
1381  $result = $ilDB->query($query);
1382  if ($result->numRows() == 1)
1383  {
1384  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
1385  $obj_id = $row["obj_fi"];
1386  }
1387  else
1388  {
1389  return;
1390  }
1391  $this->deletePageOfQuestion($question_id);
1392  $query = sprintf("DELETE FROM qpl_questions WHERE question_id = %s",
1393  $ilDB->quote($question_id)
1394  );
1395  $result = $ilDB->query($query);
1396 
1397  $this->deleteAdditionalTableData($question_id);
1398  $this->deleteAnswers($question_id);
1399 
1400  // delete the question in the tst_test_question table (list of test questions)
1401  $querydelete = sprintf("DELETE FROM tst_test_question WHERE question_fi = %s", $ilDB->quote($question_id));
1402  $deleteresult = $ilDB->query($querydelete);
1403 
1404  // delete suggested solutions contained in the question
1405  $querydelete = sprintf("DELETE FROM qpl_suggested_solutions WHERE question_fi = %s", $ilDB->quote($question_id));
1406  $deleteresult = $ilDB->query($querydelete);
1407 
1408  $directory = CLIENT_WEB_DIR . "/assessment/" . $obj_id . "/$question_id";
1409  if (preg_match("/\d+/", $obj_id) and preg_match("/\d+/", $question_id) and is_dir($directory))
1410  {
1411  include_once "./Services/Utilities/classes/class.ilUtil.php";
1412  ilUtil::delDir($directory);
1413  }
1414 
1415  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1416  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $question_id);
1417  // remaining usages are not in text anymore -> delete them
1418  // and media objects (note: delete method of ilObjMediaObject
1419  // checks whether object is used in another context; if yes,
1420  // the object is not deleted!)
1421  foreach($mobs as $mob)
1422  {
1423  ilObjMediaObject::_removeUsage($mob, "qpl:html", $question_id);
1424  if (ilObjMediaObject::_exists($mob))
1425  {
1426  $mob_obj =& new ilObjMediaObject($mob);
1427  $mob_obj->delete();
1428  }
1429  }
1430 
1431  // update question count of question pool
1432  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1434  }
1435 
1439  function getTotalAnswers()
1440  {
1441  return $this->_getTotalAnswers($this->id);
1442  }
1443 
1450  function _getTotalAnswers($a_q_id)
1451  {
1452  global $ilDB;
1453 
1454  // get all question references to the question id
1455  $query = sprintf("SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
1456  $ilDB->quote($a_q_id),
1457  $ilDB->quote($a_q_id)
1458  );
1459 
1460  $result = $ilDB->query($query);
1461 
1462  if ($result->numRows() == 0)
1463  {
1464  return 0;
1465  }
1466  $found_id = array();
1467  while ($row = $result->fetchRow(MDB2_FETCHMODE_OBJECT))
1468  {
1469  array_push($found_id, $row->question_id);
1470  }
1471 
1472  $query = sprintf("SELECT * FROM tst_test_result WHERE question_fi IN ('%s')",
1473  join($found_id, "','"));
1474  $result = $ilDB->query($query);
1475 
1476  return $result->numRows();
1477  }
1478 
1479 
1486  function _getTotalRightAnswers($a_q_id)
1487  {
1488  global $ilDB;
1489  $query = sprintf("SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
1490  $ilDB->quote($a_q_id),
1491  $ilDB->quote($a_q_id)
1492  );
1493  $result = $ilDB->query($query);
1494  if ($result->numRows() == 0)
1495  {
1496  return 0;
1497  }
1498  $found_id = array();
1499  while ($row = $result->fetchRow(MDB2_FETCHMODE_OBJECT))
1500  {
1501  array_push($found_id, $row->question_id);
1502  }
1503  $query = sprintf("SELECT * FROM tst_test_result WHERE question_fi IN ('%s')",
1504  join($found_id, "','"));
1505  $result = $ilDB->query($query);
1506  $answers = array();
1507  while ($row = $result->fetchRow(MDB2_FETCHMODE_OBJECT))
1508  {
1509  $reached = $row->points;
1510  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1511  $max = assQuestion::_getMaximumPoints($row->question_fi);
1512  array_push($answers, array("reached" => $reached, "max" => $max));
1513  }
1514  $max = 0.0;
1515  $reached = 0.0;
1516  foreach ($answers as $key => $value)
1517  {
1518  $max += $value["max"];
1519  $reached += $value["reached"];
1520  }
1521  if ($max > 0)
1522  {
1523  return $reached / $max;
1524  }
1525  else
1526  {
1527  return 0;
1528  }
1529  }
1530 
1536  function _getTitle($a_q_id)
1537  {
1538  global $ilDB;
1539  $query = sprintf("SELECT title FROM qpl_questions WHERE question_id = %s",
1540  $ilDB->quote($a_q_id)
1541  );
1542  $result = $ilDB->query($query);
1543  if ($result->numRows() == 1)
1544  {
1545  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
1546  return $row["title"];
1547  }
1548  else
1549  {
1550  return "";
1551  }
1552  }
1553 
1555  {
1556  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1557  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $a_q_id);
1558  foreach ($mobs as $mob)
1559  {
1560  ilObjMediaObject::_saveUsage($mob, "qpl:html", $this->getId());
1561  }
1562  }
1563 
1565  {
1566  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1567  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
1568  foreach ($mobs as $mob)
1569  {
1570  ilObjMediaObject::_saveUsage($mob, "qpl:html", $this->original_id);
1571  }
1572  }
1573 
1574  function copyPageOfQuestion($a_q_id)
1575  {
1576  if ($a_q_id > 0)
1577  {
1578  include_once "./Services/COPage/classes/class.ilPageObject.php";
1579  $page = new ilPageObject("qpl", $a_q_id);
1580 
1581  $xml = str_replace("il__qst_".$a_q_id, "il__qst_".$this->id,
1582  $page->getXMLContent());
1583  $this->page->setXMLContent($xml);
1584  $this->page->saveMobUsage($xml);
1585  $this->page->updateFromXML();
1586  }
1587  }
1588 
1590  {
1591  include_once "./Services/COPage/classes/class.ilPageObject.php";
1592  $page = new ilPageObject("qpl", $this->id);
1593  return $page->getXMLContent();
1594  }
1595 
1605  function _getQuestionType($question_id) {
1606  global $ilDB;
1607 
1608  if ($question_id < 1)
1609  return "";
1610 
1611  $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",
1612  $ilDB->quote($question_id)
1613  );
1614  $result = $ilDB->query($query);
1615  if ($result->numRows() == 1) {
1616  $data = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
1617  return $data->type_tag;
1618  } else {
1619  return "";
1620  }
1621  }
1622 
1632  function _getQuestionTitle($question_id) {
1633  global $ilDB;
1634 
1635  if ($question_id < 1)
1636  return "";
1637 
1638  $query = sprintf("SELECT title FROM qpl_questions WHERE qpl_questions.question_id = %s",
1639  $ilDB->quote($question_id)
1640  );
1641  $result = $ilDB->query($query);
1642  if ($result->numRows() == 1) {
1643  $data = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
1644  return $data["title"];
1645  } else {
1646  return "";
1647  }
1648  }
1649 
1651  {
1652  $this->original_id = $original_id;
1653  }
1654 
1655  function getOriginalId()
1656  {
1657  return $this->original_id;
1658  }
1659 
1668  function loadFromDb($question_id)
1669  {
1670  global $ilDB;
1671 
1672  $query = sprintf("SELECT * FROM qpl_suggested_solutions WHERE question_fi = %s",
1673  $ilDB->quote($this->getId() . "")
1674  );
1675  $result = $ilDB->query($query);
1676  $this->suggested_solutions = array();
1677  if ($result->numRows())
1678  {
1679  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
1680  {
1681  $this->suggested_solutions[$row["subquestion_index"]] = array(
1682  "internal_link" => $row["internal_link"],
1683  "import_id" => $row["import_id"]
1684  );
1685  }
1686  }
1687  }
1688 
1697  function saveToDb($original_id = "")
1698  {
1699  global $ilDB;
1700 
1701  include_once "./Services/COPage/classes/class.ilInternalLink.php";
1702  $query = sprintf("DELETE FROM qpl_suggested_solutions WHERE question_fi = %s",
1703  $ilDB->quote($this->getId() . "")
1704  );
1705  $result = $ilDB->query($query);
1707  foreach ($this->suggested_solutions as $index => $solution)
1708  {
1709  $query = sprintf("INSERT INTO qpl_suggested_solutions (suggested_solution_id, question_fi, internal_link, import_id, subquestion_index, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
1710  $ilDB->quote($this->getId() . ""),
1711  $ilDB->quote($solution["internal_link"] . ""),
1712  $ilDB->quote($solution["import_id"] . ""),
1713  $ilDB->quote($index . "")
1714  );
1715  $ilDB->query($query);
1716  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
1717  {
1718  ilInternalLink::_saveLink("qst", $this->getId(), $matches[2], $matches[3], $matches[1]);
1719  }
1720  }
1721  // remove unused media objects from ILIAS
1722  $this->cleanupMediaObjectUsage();
1723  // update question count of question pool
1724  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
1726 
1727  // update the question time stamp
1728  $query = sprintf("UPDATE qpl_questions SET TIMESTAMP = NULL WHERE question_id = %s",
1729  $this->getId()
1730  );
1731  $ilDB->query($query);
1732  }
1733 
1742  {
1743  global $ilDB;
1744  // delete the links in the qpl_suggested_solutions table
1745  $query = sprintf("DELETE FROM qpl_suggested_solutions WHERE question_fi = %s",
1746  $ilDB->quote($this->getId() . "")
1747  );
1748  $result = $ilDB->query($query);
1749  // delete the links in the int_link table
1750  include_once "./Services/COPage/classes/class.ilInternalLink.php";
1752  $this->suggested_solutions = array();
1753  }
1754 
1764  function getSuggestedSolution($subquestion_index = 0)
1765  {
1766  if (array_key_exists($subquestion_index, $this->suggested_solutions))
1767  {
1768  return $this->suggested_solutions[$subquestion_index];
1769  }
1770  else
1771  {
1772  return array();
1773  }
1774  }
1775 
1786  function getSuggestedSolutionTitle($subquestion_index = 0)
1787  {
1788  if (array_key_exists($subquestion_index, $this->suggested_solutions))
1789  {
1790  $title = $this->suggested_solutions[$subquestion_index]["internal_link"];
1791  // TO DO: resolve internal link an get link type and title
1792  }
1793  else
1794  {
1795  $title = "";
1796  }
1797  return $title;
1798  }
1799 
1811  function setSuggestedSolution($solution_id = "", $subquestion_index = 0, $is_import = false)
1812  {
1813  if (strcmp($solution_id, "") != 0)
1814  {
1815  $import_id = "";
1816  if ($is_import)
1817  {
1818  $import_id = $solution_id;
1819  $solution_id = $this->_resolveInternalLink($import_id);
1820  }
1821  $this->suggested_solutions[$subquestion_index] = array(
1822  "internal_link" => $solution_id,
1823  "import_id" => $import_id
1824  );
1825  }
1826  }
1827 
1837  function saveSuggestedSolution($solution_id = "", $subquestion_index = 0)
1838  {
1839  global $ilDB;
1840 
1841  $statement = $ilDB->prepareManip("DELETE FROM qpl_suggested_solutions WHERE question_fi = ? AND subquestion_index = ?",
1842  array("integer", "integer")
1843  );
1844  $data = array(
1845  $this->getId(),
1846  $subquestion_index
1847  );
1848  $affectedRows = $ilDB->execute($statement, $data);
1849 
1850  $statement = $ilDB->prepareManip("INSERT INTO qpl_suggested_solutions (question_fi, internal_link, import_id, subquestion_index) VALUES (?, ?, ?, ?)",
1851  array("integer", "text", "text", "integer")
1852  );
1853  $data = array(
1854  $this->getId(),
1855  $solution_id,
1856  "",
1857  $subquestion_index
1858  );
1859  $affectedRows = $ilDB->execute($statement, $data);
1860  }
1861 
1862  function _resolveInternalLink($internal_link)
1863  {
1864  if (preg_match("/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches))
1865  {
1866  include_once "./Services/COPage/classes/class.ilInternalLink.php";
1867  include_once "./Modules/LearningModule/classes/class.ilLMObject.php";
1868  include_once "./Modules/Glossary/classes/class.ilGlossaryTerm.php";
1869  switch ($matches[2])
1870  {
1871  case "lm":
1872  $resolved_link = ilLMObject::_getIdForImportId($internal_link);
1873  break;
1874  case "pg":
1875  $resolved_link = ilInternalLink::_getIdForImportId("PageObject", $internal_link);
1876  break;
1877  case "st":
1878  $resolved_link = ilInternalLink::_getIdForImportId("StructureObject", $internal_link);
1879  break;
1880  case "git":
1881  $resolved_link = ilInternalLink::_getIdForImportId("GlossaryItem", $internal_link);
1882  break;
1883  case "mob":
1884  $resolved_link = ilInternalLink::_getIdForImportId("MediaObject", $internal_link);
1885  break;
1886  }
1887  if (strcmp($resolved_link, "") == 0)
1888  {
1889  $resolved_link = $internal_link;
1890  }
1891  }
1892  else
1893  {
1894  $resolved_link = $internal_link;
1895  }
1896  return $resolved_link;
1897  }
1898 
1899  function _resolveIntLinks($question_id)
1900  {
1901  global $ilDB;
1902  $resolvedlinks = 0;
1903  $query = sprintf("SELECT * FROM qpl_suggested_solutions WHERE question_fi = %s",
1904  $ilDB->quote($question_id . "")
1905  );
1906  $result = $ilDB->query($query);
1907  if ($result->numRows())
1908  {
1909  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
1910  {
1911  $internal_link = $row["internal_link"];
1912  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1913  $resolved_link = assQuestion::_resolveInternalLink($internal_link);
1914  if (strcmp($internal_link, $resolved_link) != 0)
1915  {
1916  // internal link was resolved successfully
1917  $queryupdate = sprintf("UPDATE qpl_suggested_solutions SET internal_link = %s WHERE suggested_solution_id = %s",
1918  $ilDB->quote($resolved_link),
1919  $ilDB->quote($row["suggested_solution_id"] . "")
1920  );
1921  $updateresult = $ilDB->query($queryupdate);
1922  $resolvedlinks++;
1923  }
1924  }
1925  }
1926  if ($resolvedlinks)
1927  {
1928  // there are resolved links -> reenter theses links to the database
1929 
1930  // delete all internal links from the database
1931  include_once "./Services/COPage/classes/class.ilInternalLink.php";
1932  ilInternalLink::_deleteAllLinksOfSource("qst", $question_id);
1933 
1934  $query = sprintf("SELECT * FROM qpl_suggested_solutions WHERE question_fi = %s",
1935  $ilDB->quote($question_id . "")
1936  );
1937  $result = $ilDB->query($query);
1938  if ($result->numRows())
1939  {
1940  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
1941  {
1942  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $row["internal_link"], $matches))
1943  {
1944  ilInternalLink::_saveLink("qst", $question_id, $matches[2], $matches[3], $matches[1]);
1945  }
1946  }
1947  }
1948  }
1949  }
1950 
1951  function _getInternalLinkHref($target = "")
1952  {
1953  global $ilDB;
1954  $linktypes = array(
1955  "lm" => "LearningModule",
1956  "pg" => "PageObject",
1957  "st" => "StructureObject",
1958  "git" => "GlossaryItem",
1959  "mob" => "MediaObject"
1960  );
1961  $href = "";
1962  if (preg_match("/il__(\w+)_(\d+)/", $target, $matches))
1963  {
1964  $type = $matches[1];
1965  $target_id = $matches[2];
1966  include_once "./Services/Utilities/classes/class.ilUtil.php";
1967  switch($linktypes[$matches[1]])
1968  {
1969  case "LearningModule":
1970  $href = "./goto.php?target=" . $type . "_" . $target_id;
1971  break;
1972  case "PageObject":
1973  case "StructureObject":
1974  $href = "./goto.php?target=" . $type . "_" . $target_id;
1975  break;
1976  case "GlossaryItem":
1977  $href = "./goto.php?target=" . $type . "_" . $target_id;
1978  break;
1979  case "MediaObject":
1980  $href = "./ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[$type] . "&cmd=media&ref_id=".$_GET["ref_id"]."&mob_id=".$target_id;
1981  break;
1982  }
1983  }
1984  return $href;
1985  }
1986 
1996  function _getOriginalId($question_id)
1997  {
1998  global $ilDB;
1999  $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
2000  $ilDB->quote($question_id . "")
2001  );
2002  $result = $ilDB->query($query);
2003  if ($result->numRows() > 0)
2004  {
2005  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2006  if ($row["original_id"] > 0)
2007  {
2008  return $row["original_id"];
2009  }
2010  else
2011  {
2012  return $row["question_id"];
2013  }
2014  }
2015  else
2016  {
2017  return "";
2018  }
2019  }
2020 
2021  function syncWithOriginal()
2022  {
2023  global $ilDB;
2024 
2025  if ($this->getOriginalId())
2026  {
2027  $id = $this->getId();
2028  $original = $this->getOriginalId();
2029 
2030  $this->setId($this->getOriginalId());
2031  $this->setOriginalId(NULL);
2032  $this->saveToDb();
2033  $this->deletePageOfQuestion($original);
2034  $this->createPageObject();
2035  $this->copyPageOfQuestion($id);
2036 
2037  $this->setId($id);
2038  $this->setOriginalId($original);
2039 
2040  include_once "./Services/COPage/classes/class.ilInternalLink.php";
2041  $query = sprintf("DELETE FROM qpl_suggested_solutions WHERE question_fi = %s",
2042  $ilDB->quote($this->getOriginalId() . "")
2043  );
2044  $result = $ilDB->query($query);
2045  ilInternalLink::_deleteAllLinksOfSource("qst", $this->original_id);
2046  foreach ($this->suggested_solutions as $index => $solution)
2047  {
2048  $query = sprintf("INSERT INTO qpl_suggested_solutions (suggested_solution_id, question_fi, internal_link, import_id, subquestion_index, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
2049  $ilDB->quote($this->getOriginalId() . ""),
2050  $ilDB->quote($solution["internal_link"] . ""),
2051  $ilDB->quote($solution["import_id"] . ""),
2052  $ilDB->quote($index . "")
2053  );
2054  $ilDB->query($query);
2055  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
2056  {
2057  ilInternalLink::_saveLink("qst", $this->getOriginalId(), $matches[2], $matches[3], $matches[1]);
2058  }
2059  }
2060  $this->syncFeedbackGeneric();
2062  }
2063  }
2064 
2065  function createRandomSolution($test_id, $user_id)
2066  {
2067  }
2068 
2078  function _questionExists($question_id)
2079  {
2080  global $ilDB;
2081 
2082  if ($question_id < 1)
2083  {
2084  return false;
2085  }
2086 
2087  $query = sprintf("SELECT question_id FROM qpl_questions WHERE question_id = %s",
2088  $ilDB->quote($question_id)
2089  );
2090  $result = $ilDB->query($query);
2091  if ($result->numRows() == 1)
2092  {
2093  return true;
2094  }
2095  else
2096  {
2097  return false;
2098  }
2099  }
2100 
2110  function &_instanciateQuestion($question_id)
2111  {
2112  if (strcmp($question_id, "") != 0)
2113  {
2114  $question_type = assQuestion::_getQuestionType($question_id);
2115  assQuestion::_includeClass($question_type);
2116  $question = new $question_type();
2117  $question->loadFromDb($question_id);
2118  return $question;
2119  }
2120  }
2121 
2130  function getPoints()
2131  {
2132  if (strcmp($this->points, "") == 0)
2133  {
2134  return 0;
2135  }
2136  else
2137  {
2138  return $this->points;
2139  }
2140  }
2141 
2142 
2151  function setPoints($a_points)
2152  {
2153  $this->points = $a_points;
2154  }
2155 
2164  function getSolutionMaxPass($active_id)
2165  {
2166  return $this->_getSolutionMaxPass($this->getId(), $active_id);
2167  }
2168 
2177  function _getSolutionMaxPass($question_id, $active_id)
2178  {
2179 /* include_once "./Modules/Test/classes/class.ilObjTest.php";
2180  $pass = ilObjTest::_getPass($active_id);
2181  return $pass;*/
2182 
2183  // the following code was the old solution which added the non answered
2184  // questions of a pass from the answered questions of the previous pass
2185  // with the above solution, only the answered questions of the last pass are counted
2186  global $ilDB;
2187 
2188  $query = sprintf("SELECT MAX(pass) as maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
2189  $ilDB->quote($active_id . ""),
2190  $ilDB->quote($question_id . "")
2191  );
2192  $result = $ilDB->query($query);
2193  if ($result->numRows() == 1)
2194  {
2195  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2196  return $row["maxpass"];
2197  }
2198  else
2199  {
2200  return 0;
2201  }
2202  }
2203 
2214  function _isWriteable($question_id, $user_id)
2215  {
2216  global $ilDB;
2217 
2218  if (($question_id < 1) || ($user_id < 1))
2219  {
2220  return false;
2221  }
2222 
2223  $query = sprintf("SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
2224  $ilDB->quote($question_id . "")
2225  );
2226  $result = $ilDB->query($query);
2227  if ($result->numRows() == 1)
2228  {
2229  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2230  $qpl_object_id = $row["obj_fi"];
2231  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
2232  return ilObjQuestionPool::_isWriteable($qpl_object_id, $user_id);
2233  }
2234  else
2235  {
2236  return false;
2237  }
2238  }
2239 
2248  function _isUsedInRandomTest($question_id = "")
2249  {
2250  global $ilDB;
2251 
2252  if ($question_id < 1) return 0;
2253  $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE question_fi = %s",
2254  $ilDB->quote($question_id . "")
2255  );
2256  $result = $ilDB->query($query);
2257  return $result->numRows();
2258  }
2259 
2271  function calculateReachedPoints($active_id, $pass = NULL, $points = 0)
2272  {
2273  include_once "./Modules/Test/classes/class.ilObjTest.php";
2274  $count_system = ilObjTest::_getCountSystem($active_id);
2275  if ($count_system == 1)
2276  {
2277  if ($points != $this->getMaximumPoints())
2278  {
2279  $points = 0;
2280  }
2281  }
2282  $score_cutting = ilObjTest::_getScoreCutting($active_id);
2283  if ($score_cutting == 0)
2284  {
2285  if ($points < 0)
2286  {
2287  $points = 0;
2288  }
2289  }
2290  return $points;
2291  }
2292 
2304  function _isWorkedThrough($active_id, $question_id, $pass = NULL)
2305  {
2306  global $ilDB;
2307 
2308  $points = 0;
2309  if (is_null($pass))
2310  {
2311  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
2312  $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
2313  }
2314  $query = sprintf("SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
2315  $ilDB->quote($active_id . ""),
2316  $ilDB->quote($question_id . ""),
2317  $ilDB->quote($pass . "")
2318  );
2319  $result = $ilDB->query($query);
2320  if ($result->numRows())
2321  {
2322  return TRUE;
2323  }
2324  else
2325  {
2326  return FALSE;
2327  }
2328  }
2329 
2331  {
2332  global $ilUser;
2333 
2334  $multilineAnswerSetting = $ilUser->getPref("tst_multiline_answers");
2335  if ($multilineAnswerSetting != 1)
2336  {
2337  $multilineAnswerSetting = 0;
2338  }
2339  return $multilineAnswerSetting;
2340  }
2341 
2342  function setMultilineAnswerSetting($a_setting = 0)
2343  {
2344  global $ilUser;
2345  $ilUser->writePref("tst_multiline_answers", $a_setting);
2346  }
2356  function _areAnswered($a_user_id,$a_question_ids)
2357  {
2358  global $ilDB;
2359 
2360  $query = "SELECT DISTINCT(question_fi) FROM tst_test_result JOIN tst_active ".
2361  "ON (active_id = active_fi) ".
2362  "WHERE question_fi IN ('".implode("','",$a_question_ids)."') ".
2363  "AND user_fi = '".$a_user_id."'";
2364  $res = $ilDB->query($query);
2365  return ($res->numRows() == count($a_question_ids)) ? true : false;
2366  }
2367 
2375  function isHTML($a_text)
2376  {
2377  if (preg_match("/<[^>]*?>/", $a_text))
2378  {
2379  return TRUE;
2380  }
2381  else
2382  {
2383  return FALSE;
2384  }
2385  }
2386 
2393  function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE)
2394  {
2395  include_once "./Services/Utilities/classes/class.ilUtil.php";
2396  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
2397  }
2398 
2406  function QTIMaterialToString($a_material)
2407  {
2408  $result = "";
2409  for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
2410  {
2411  $material = $a_material->getMaterial($i);
2412  if (strcmp($material["type"], "mattext") == 0)
2413  {
2414  $result .= $material["material"]->getContent();
2415  }
2416  if (strcmp($material["type"], "matimage") == 0)
2417  {
2418  $matimage = $material["material"];
2419  if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
2420  {
2421  // import an mediaobject which was inserted using tiny mce
2422  if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
2423  array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
2424  }
2425  }
2426  }
2427  return $result;
2428  }
2429 
2438  function addQTIMaterial(&$a_xml_writer, $a_material, $close_material_tag = TRUE, $add_mobs = TRUE)
2439  {
2440  include_once "./Services/RTE/classes/class.ilRTE.php";
2441  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2442 
2443  $a_xml_writer->xmlStartTag("material");
2444  $attrs = array(
2445  "texttype" => "text/plain"
2446  );
2447  if ($this->isHTML($a_material))
2448  {
2449  $attrs["texttype"] = "text/xhtml";
2450  }
2451  $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
2452  if ($add_mobs)
2453  {
2454  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
2455  foreach ($mobs as $mob)
2456  {
2457  $moblabel = "il_" . IL_INST_ID . "_mob_" . $mob;
2458  if (strpos($a_material, "mm_$mob") !== FALSE)
2459  {
2460  if (ilObjMediaObject::_exists($mob))
2461  {
2462  $mob_obj =& new ilObjMediaObject($mob);
2463  $imgattrs = array(
2464  "label" => $moblabel,
2465  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
2466  );
2467  }
2468  $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
2469  }
2470  }
2471  }
2472  if ($close_material_tag) $a_xml_writer->xmlEndTag("material");
2473  }
2474 
2475  function createNewImageFileName($image_filename)
2476  {
2477  $extension = "";
2478  if (preg_match("/.*\.(png|jpg|gif|jpeg)$/i", $image_filename, $matches))
2479  {
2480  $extension = "." . $matches[1];
2481  }
2482  $image_filename = md5($image_filename) . $extension;
2483  return $image_filename;
2484  }
2485 
2498  function _setReachedPoints($active_id, $question_id, $points, $maxpoints, $pass = NULL)
2499  {
2500  global $ilDB;
2501 
2502  if ($points <= $maxpoints)
2503  {
2504  if (is_null($pass))
2505  {
2506  $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
2507  }
2508 
2509  // retrieve the already given points
2510  $old_points = 0;
2511  $query = sprintf("SELECT points FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
2512  $ilDB->quote($active_id . ""),
2513  $ilDB->quote($question_id . ""),
2514  $ilDB->quote($pass . "")
2515  );
2516  $result = $ilDB->query($query);
2517  if ($result->numRows())
2518  {
2519  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2520  $old_points = $row["points"];
2521  $query = sprintf("UPDATE tst_test_result SET points = %s WHERE active_fi = %s AND question_fi = %s AND pass = %s",
2522  $ilDB->quote($points . ""),
2523  $ilDB->quote($active_id . ""),
2524  $ilDB->quote($question_id . ""),
2525  $ilDB->quote($pass . "")
2526  );
2527  }
2528  else
2529  {
2530  $query = sprintf("INSERT INTO tst_test_result (active_fi, question_fi, points, pass) VALUES (%s, %s, %s, %s)",
2531  $ilDB->quote($active_id . ""),
2532  $ilDB->quote($question_id . ""),
2533  $ilDB->quote($points . ""),
2534  $ilDB->quote($pass . "")
2535  );
2536  }
2537  $result = $ilDB->query($query);
2538  if (PEAR::isError($result))
2539  {
2540  global $ilias;
2541  $ilias->raiseError($result->getMessage());
2542  }
2544  // finally update objective result
2545  include_once "./Modules/Test/classes/class.ilObjTest.php";
2546  include_once './Modules/Course/classes/class.ilCourseObjectiveResult.php';
2548 
2549  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
2551  {
2552  global $lng, $ilUser;
2553  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
2554  $username = ilObjTestAccess::_getParticipantData($active_id);
2555  assQuestion::_logAction(sprintf($lng->txtlng("assessment", "log_answer_changed_points", ilObjAssessmentFolder::_getLogLanguage()), $username, $old_points, $points, $ilUser->getFullname() . " (" . $ilUser->getLogin() . ")"), $active_id, $question_id);
2556  }
2557 
2558  return TRUE;
2559  }
2560  else
2561  {
2562  return FALSE;
2563  }
2564  }
2565 
2575  function getQuestion()
2576  {
2577  return $this->question;
2578  }
2579 
2589  function setQuestion($question = "")
2590  {
2591  $this->question = $question;
2592  }
2593 
2602  function getQuestionType()
2603  {
2604  // must be overwritten in every parent class
2605  return "";
2606  }
2607 
2617  {
2618  global $ilDB;
2619 
2620  $query = sprintf("SELECT question_type_id FROM qpl_question_type WHERE type_tag = %s",
2621  $ilDB->quote($this->getQuestionType() . "")
2622  );
2623  $result = $ilDB->query($query);
2624  if ($result->numRows() == 1)
2625  {
2626  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2627  return $row["question_type_id"];
2628  }
2629  return 0;
2630  }
2631 
2643  function saveFeedbackGeneric($correctness, $feedback)
2644  {
2645  global $ilDB;
2646 
2647  switch ($correctness)
2648  {
2649  case 0:
2650  $correctness = 0;
2651  break;
2652  case 1:
2653  default:
2654  $correctness = 1;
2655  break;
2656  }
2657  $query = sprintf("DELETE FROM qpl_feedback_generic WHERE question_fi = %s AND correctness = %s",
2658  $ilDB->quote($this->getId() . ""),
2659  $ilDB->quote($correctness . "")
2660  );
2661  $result = $ilDB->query($query);
2662  if (strlen($feedback))
2663  {
2664  include_once("./Services/RTE/classes/class.ilRTE.php");
2665  $query = sprintf("INSERT INTO qpl_feedback_generic VALUES (NULL, %s, %s, %s, NULL)",
2666  $ilDB->quote($this->getId() . ""),
2667  $ilDB->quote($correctness . ""),
2668  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($feedback, 0))
2669  );
2670  $result = $ilDB->query($query);
2671  }
2672  }
2673 
2685  function getFeedbackGeneric($correctness)
2686  {
2687  global $ilDB;
2688 
2689  $feedback = "";
2690  $query = sprintf("SELECT * FROM qpl_feedback_generic WHERE question_fi = %s AND correctness = %s",
2691  $ilDB->quote($this->getId() . ""),
2692  $ilDB->quote($correctness . "")
2693  );
2694  $result = $ilDB->query($query);
2695  if ($result->numRows())
2696  {
2697  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2698  include_once("./Services/RTE/classes/class.ilRTE.php");
2699  $feedback = ilRTE::_replaceMediaObjectImageSrc($row["feedback"], 1);
2700  }
2701  return $feedback;
2702  }
2703 
2713  {
2714  global $ilDB;
2715 
2716  $feedback = "";
2717  $query = sprintf("SELECT * FROM qpl_feedback_generic WHERE question_fi = %s",
2718  $ilDB->quote($original_id . "")
2719  );
2720  $result = $ilDB->query($query);
2721  if ($result->numRows())
2722  {
2723  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2724  {
2725  $duplicatequery = sprintf("INSERT INTO qpl_feedback_generic VALUES (NULL, %s, %s, %s, NULL)",
2726  $ilDB->quote($this->getId() . ""),
2727  $ilDB->quote($row["correctness"] . ""),
2728  $ilDB->quote($row["feedback"] . "")
2729  );
2730  $duplicateresult = $ilDB->query($duplicatequery);
2731  }
2732  }
2733  }
2734 
2736  {
2737  global $ilDB;
2738 
2739  $feedback = "";
2740 
2741  // delete generic feedback of the original
2742  $deletequery = sprintf("DELETE FROM qpl_feedback_generic WHERE question_fi = %s",
2743  $ilDB->quote($this->original_id . "")
2744  );
2745  $result = $ilDB->query($deletequery);
2746 
2747  // get generic feedback of the actual question
2748  $query = sprintf("SELECT * FROM qpl_feedback_generic WHERE question_fi = %s",
2749  $ilDB->quote($this->getId() . "")
2750  );
2751  $result = $ilDB->query($query);
2752 
2753  // save generic feedback to the original
2754  if ($result->numRows())
2755  {
2756  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2757  {
2758  $duplicatequery = sprintf("INSERT INTO qpl_feedback_generic VALUES (NULL, %s, %s, %s, NULL)",
2759  $ilDB->quote($this->original_id . ""),
2760  $ilDB->quote($row["correctness"] . ""),
2761  $ilDB->quote($row["feedback"] . "")
2762  );
2763  $duplicateresult = $ilDB->query($duplicatequery);
2764  }
2765  }
2766  }
2767 
2773  {
2774  // must be called in parent classes. add additional RTE text in the parent
2775  // classes and call this method to add the standard RTE text
2776  $collected = $this->getQuestion();
2777  $collected .= $this->getFeedbackGeneric(0);
2778  $collected .= $this->getFeedbackGeneric(1);
2779  return $collected;
2780  }
2781 
2787  {
2788  $combinedtext = $this->getRTETextWithMediaObjects();
2789  include_once("./Services/RTE/classes/class.ilRTE.php");
2790  ilRTE::_cleanupMediaObjectUsage($combinedtext, "qpl:html", $this->getId());
2791  }
2792 
2798  function &getInstances()
2799  {
2800  global $ilDB;
2801  $query = sprintf("SELECT question_id FROM qpl_questions WHERE original_id = %s",
2802  $ilDB->quote($this->getId())
2803  );
2804  $result = $ilDB->query($query);
2805  $instances = array();
2806  $ids = array();
2807  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2808  {
2809  array_push($ids, $row["question_id"]);
2810  }
2811  foreach ($ids as $question_id)
2812  {
2813  $query = sprintf("SELECT DISTINCT object_data.obj_id, object_data.title FROM tst_test_question, object_data, tst_tests WHERE question_fi = %s AND tst_tests.test_id = tst_test_question.test_fi AND object_data.obj_id = tst_tests.obj_fi",
2814  $ilDB->quote($question_id . "")
2815  );
2816  $result = $ilDB->query($query);
2817  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2818  {
2819  $instances[$row["obj_id"]] = $row["title"];
2820  }
2821  $query = sprintf("SELECT DISTINCT object_data.obj_id, object_data.title FROM tst_test_random_question, tst_active, object_data, tst_tests WHERE tst_test_random_question.active_fi = tst_active.active_id AND tst_test_random_question.question_fi = %s AND tst_tests.test_id = tst_active.test_fi AND object_data.obj_id = tst_tests.obj_fi",
2822  $ilDB->quote($question_id . "")
2823  );
2824  $result = $ilDB->query($query);
2825  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2826  {
2827  $instances[$row["obj_id"]] = $row["title"];
2828  }
2829  }
2830  include_once "./Modules/Test/classes/class.ilObjTest.php";
2831  foreach ($instances as $key => $value)
2832  {
2833  $query = sprintf("SELECT object_reference.ref_id FROM object_reference WHERE obj_id = %s",
2834  $ilDB->quote($key . "")
2835  );
2836  $result = $ilDB->query($query);
2837  $refs = array();
2838  while ($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
2839  {
2840  array_push($refs, $row["ref_id"]);
2841  }
2842  $instances[$key] = array("obj_id" => $key, "title" => $value, "author" => ilObjTest::_lookupAuthor($key), "refs" => $refs);
2843  }
2844  return $instances;
2845  }
2846 
2847  function _needsManualScoring($question_id)
2848  {
2849  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
2851  $questiontype = assQuestion::_getQuestionType($question_id);
2852  if (in_array($questiontype, $scoring))
2853  {
2854  return TRUE;
2855  }
2856  else
2857  {
2858  return FALSE;
2859  }
2860  }
2861 
2869  function getActiveUserData($active_id)
2870  {
2871  global $ilDB;
2872  $query = sprintf("SELECT * FROM tst_active WHERE active_id = %s",
2873  $ilDB->quote($active_id . "")
2874  );
2875  $result = $ilDB->query($query);
2876  if ($result->numRows())
2877  {
2878  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
2879  return array("user_id" => $row["user_fi"], "test_id" => $row["test_fi"]);
2880  }
2881  else
2882  {
2883  return array();
2884  }
2885  }
2886 
2894  static function _includeClass($question_type, $gui = 0)
2895  {
2896  $type = $question_type;
2897  if ($gui) $type .= "GUI";
2898  if (file_exists("./Modules/TestQuestionPool/classes/class.".$type.".php"))
2899  {
2900  include_once "./Modules/TestQuestionPool/classes/class.".$type.".php";
2901  }
2902  else
2903  {
2904  global $ilPluginAdmin;
2905  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
2906  foreach ($pl_names as $pl_name)
2907  {
2908  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
2909  if (strcmp($pl->getQuestionType(), $question_type) == 0)
2910  {
2911  $pl->includeClass("class.".$type.".php");
2912  }
2913  }
2914  }
2915  }
2916 
2923  static function _getQuestionTypeName($type_tag)
2924  {
2925  if (file_exists("./Modules/TestQuestionPool/classes/class.".$type_tag.".php"))
2926  {
2927  global $lng;
2928  return $lng->txt($type_tag);
2929  }
2930  else
2931  {
2932  global $ilPluginAdmin;
2933  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
2934  foreach ($pl_names as $pl_name)
2935  {
2936  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
2937  if (strcmp($pl->getQuestionType(), $type_tag) == 0)
2938  {
2939  return $pl->getQuestionTypeTranslation();
2940  }
2941  }
2942  }
2943  return "";
2944  }
2945 
2955  function &_instanciateQuestionGUI($question_id)
2956  {
2957  if (strcmp($question_id, "") != 0)
2958  {
2959  $question_type = assQuestion::_getQuestionType($question_id);
2960  $question_type_gui = $question_type . "GUI";
2961  assQuestion::_includeClass($question_type, 1);
2962  $question_gui = new $question_type_gui();
2963  $question_gui->object->loadFromDb($question_id);
2964  return $question_gui;
2965  }
2966  }
2967 
2980  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
2981  {
2982  return $startrow;
2983  }
2984 }
2985 
2986 ?>