4 include_once
"./Modules/Test/classes/inc.AssessmentConstants.php";
27 self::IMG_MIME_TYPE_JPG =>
array(
'jpg',
'jpeg'),
28 self::IMG_MIME_TYPE_PNG =>
array(
'png'),
29 self::IMG_MIME_TYPE_GIF =>
array(
'gif')
33 self::IMG_MIME_TYPE_JPG =>
array(
'binary'),
34 self::IMG_MIME_TYPE_PNG =>
array(
'binary'),
35 self::IMG_MIME_TYPE_GIF =>
array(
'binary')
273 'image/jpeg' =>
array(
'jpg',
'jpeg'),
'image/png' =>
array(
'png'),
'image/gif' =>
array(
'gif')
300 $this->original_id = null;
306 if (!$this->author) {
307 $this->author = $this->
ilias->account->fullname;
310 if ($this->owner <= 0) {
311 $this->owner = $this->
ilias->account->id;
315 $this->suggested_solutions =
array();
317 $this->nr_of_tries = 0;
319 $this->arrData =
array();
322 $this->questionActionCmd =
'handleQuestionAction';
324 $this->lastChange = null;
326 require_once
'Services/Randomization/classes/class.ilArrayElementOrderKeeper.php';
339 return self::$forcePassResultsUpdateEnabled;
344 return (
bool) count(self::getAllowedFileExtensionsForMimeType($mimeType));
349 return current(explode(
';', $contentTypeString));
354 foreach (self::$allowedFileExtensionsByMimeType as $allowedMimeType => $extensions) {
355 $rexCharsets = implode(
'|', self::$allowedCharsetsByMimeType[$allowedMimeType]);
356 $rexMimeType = preg_quote($allowedMimeType,
'/');
358 $rex =
'/^' . $rexMimeType .
'(;(\s)*charset=(' . $rexCharsets .
'))*$/';
360 if (!preg_match($rex, $mimeType)) {
373 strtolower($fileExtension),
374 self::getAllowedFileExtensionsForMimeType($mimeType)
385 if (!isset(
$_POST[
'cmd']) || !isset(
$_POST[
'cmd'][$this->questionActionCmd])) {
389 if (!is_array(
$_POST[
'cmd'][$this->questionActionCmd]) || !count(
$_POST[
'cmd'][$this->questionActionCmd])) {
393 return key(
$_POST[
'cmd'][$this->questionActionCmd]);
402 if (!isset(
$_POST[$postSubmissionFieldname])) {
406 if (!is_array(
$_POST[$postSubmissionFieldname])) {
410 if (!count(
$_POST[$postSubmissionFieldname])) {
438 require_once
'Modules/Test/classes/class.ilObjTest.php';
451 "SELECT test_fi FROM tst_active WHERE active_id = %s",
457 return $row[
"test_fi"];
468 protected function log($active_id, $langVar)
481 $extensions =
array();
483 foreach (self::$allowedImageMaterialFileExtensionsByMimeType as $mimeType => $mimeExtensions) {
484 $extensions = array_merge($extensions, $mimeExtensions);
486 return array_unique($extensions);
532 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
534 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class." . $this->
getQuestionType() .
"Import.php";
536 $import =
new $classname($this);
537 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
546 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
548 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class." . $this->
getQuestionType() .
"Export.php";
550 $export =
new $classname($this);
551 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
577 "SELECT * FROM qpl_questions WHERE obj_fi = %s AND title = %s",
578 array(
'integer',
'text'),
581 return (
$result->numRows() > 0) ?
true :
false;
617 $this->test_id =
$id;
673 $this->est_working_time =
array(
"h" => (
int) $hour,
"m" => (
int) $min,
"s" => (
int) $sec);
684 $this->est_working_time =
array(
685 'h' => (
int) substr($durationString, 0, 2),
686 'm' => (
int) substr($durationString, 3, 2),
687 's' => (
int) substr($durationString, 6, 2)
701 foreach ($array as
$key => $value) {
702 if (strcmp(
$key, $searchkey)==0) {
756 require_once
'Services/Utilities/classes/class.ilUtil.php';
850 if (!$this->est_working_time) {
851 $this->est_working_time =
array(
"h" => 0,
"m" => 0,
"s" => 0);
917 if (!strlen($this->external_id)) {
918 if ($this->
getId() > 0) {
919 return 'il_' . IL_INST_ID .
'_qst_' . $this->
getId();
921 return uniqid(
'',
true);
940 "SELECT points FROM qpl_questions WHERE question_id = %s",
962 "SELECT qpl_questions.*, qpl_qst_type.type_tag FROM qpl_qst_type, qpl_questions WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
967 return $ilDB->fetchAssoc(
$result);
984 "SELECT suggested_solution_id FROM qpl_sol_sug WHERE question_fi = %s",
1003 return $question->getSuggestedSolutionOutput();
1009 foreach ($this->suggested_solutions as $solution) {
1010 switch ($solution[
"type"]) {
1018 $possible_texts = array_values(array_filter(
array(
1021 $this->lng->txt(
'tst_show_solution_suggested')
1024 require_once
'Services/WebAccessChecker/classes/class.ilWACSignedPath.php';
1029 $solutionValue = $solution[
"value"];
1030 $solutionValue = $this->
fixSvgToPng($solutionValue);
1036 return join(
$output,
"<br />");
1052 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
1053 array(
'integer',
'integer'),
1054 array($question_id, $subquestion_index)
1056 if (
$result->numRows() == 1) {
1059 "internal_link" =>
$row[
"internal_link"],
1060 "import_id" =>
$row[
"import_id"]
1089 if (is_null(
$pass)) {
1090 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
1094 "SELECT * FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1095 array(
'integer',
'integer',
'integer'),
1098 if (
$result->numRows() == 1) {
1115 return round(self::_getReachedPoints($active_id, $this->
getId(),
$pass), 2);
1142 if (is_null(
$pass)) {
1143 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1153 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
1155 $requestsStatisticData = $hintTracking->getRequestStatisticDataByQuestionAndTestpass();
1156 $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
1161 return $reached_points;
1177 if (is_null(
$pass)) {
1178 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1186 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
1188 $requestsStatisticData = $questionHintTracking->getRequestStatisticDataByQuestionAndTestpass();
1189 $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
1200 if (is_null($reached_points)) {
1201 $reached_points = 0;
1205 $existingSolutions = $this->lookupForExistingSolutions($active_id,
$pass);
1207 $this->
getProcessLocker()->executeUserQuestionResultUpdateOperation(
function () use ($ilDB, $active_id,
$pass, $reached_points, $requestsStatisticData, $isAnswered, $existingSolutions) {
1209 DELETE FROM tst_test_result 1211 WHERE active_fi = %s 1212 AND question_fi = %s 1216 $types =
array(
'integer',
'integer',
'integer');
1219 if ($this->
getStep() !== null) {
1224 $types[] =
'integer';
1227 $ilDB->manipulateF(
$query, $types, $values);
1229 if ($existingSolutions[
'authorized']) {
1230 $next_id = $ilDB->nextId(
"tst_test_result");
1232 'test_result_id' =>
array(
'integer', $next_id),
1233 'active_fi' =>
array(
'integer', $active_id),
1234 'question_fi' =>
array(
'integer', $this->
getId()),
1236 'points' =>
array(
'float', $reached_points),
1238 'hint_count' =>
array(
'integer', $requestsStatisticData->getRequestsCount()),
1239 'hint_points' =>
array(
'float', $requestsStatisticData->getRequestsPoints()),
1240 'answered' =>
array(
'integer', $isAnswered)
1243 if ($this->
getStep() !== null) {
1244 $fieldData[
'step'] =
array(
'integer', $this->
getStep());
1247 $ilDB->insert(
'tst_test_result', $fieldData);
1252 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1259 "log_user_answered_question",
1273 include_once
'Modules/Course/classes/class.ilCourseObjectiveResult.php';
1287 if (
$pass === null) {
1288 require_once
'Modules/Test/classes/class.ilObjTest.php';
1296 $saveStatus =
false;
1298 $this->
getProcessLocker()->executePersistWorkingStateLockOperation(
function () use ($active_id,
$pass, $authorized, $obligationsEnabled, &$saveStatus) {
1359 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1360 include_once
"./Modules/Test/classes/class.assMarkSchema.php";
1365 SELECT tst_pass_result.* 1366 FROM tst_pass_result 1367 WHERE active_fi = %s 1373 array(
'integer',
'integer'),
1379 $max =
$row[
'maxpoints'];
1380 $reached =
$row[
'points'];
1382 $obligationsAnswered = (int)
$row[
'obligations_answered'];
1384 include_once
"./Modules/Test/classes/class.assMarkSchema.php";
1386 $percentage = (!$max) ? 0 : ($reached / $max) * 100.0;
1388 $mark = ASS_MarkSchema::_getMatchingMarkFromActiveId($active_id, $percentage);
1390 $isPassed = ($mark[
"passed"] ? 1 : 0);
1391 $isFailed = (!$mark[
"passed"] ? 1 : 0);
1393 $userTestResultUpdateCallback =
function () use ($ilDB, $active_id,
$pass, $max, $reached, $isFailed, $isPassed, $obligationsAnswered,
$row, $mark) {
1395 DELETE FROM tst_result_cache 1396 WHERE active_fi = %s 1404 $ilDB->insert(
'tst_result_cache',
array(
1405 'active_fi'=>
array(
'integer', $active_id),
1407 'max_points'=>
array(
'float', strlen($max) ? $max : 0),
1408 'reached_points'=>
array(
'float', strlen($reached) ? $reached : 0),
1409 'mark_short'=>
array(
'text', strlen($mark[
"short_name"]) ? $mark[
"short_name"] :
" "),
1410 'mark_official'=>
array(
'text', strlen($mark[
"official_name"]) ? $mark[
"official_name"] :
" "),
1411 'passed'=>
array(
'integer', $isPassed),
1412 'failed'=>
array(
'integer', $isFailed),
1414 'hint_count'=>
array(
'integer',
$row[
'hint_count']),
1415 'hint_points'=>
array(
'float',
$row[
'hint_points']),
1416 'obligations_answered' =>
array(
'integer', $obligationsAnswered)
1421 $processLocker->executeUserTestResultUpdateLockOperation($userTestResultUpdateCallback);
1423 $userTestResultUpdateCallback();
1432 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1434 if (self::getResultGateway() !== null) {
1435 $data = self::getResultGateway()->getQuestionCountAndPointsForPassOfParticipant($active_id,
$pass);
1436 $time = self::getResultGateway()->getWorkingTimeOfParticipantForPass($active_id,
$pass);
1447 SELECT SUM(points) reachedpoints, 1448 SUM(hint_count) hint_count, 1449 SUM(hint_points) hint_points, 1450 COUNT(DISTINCT(question_fi)) answeredquestions 1451 FROM tst_test_result 1452 WHERE active_fi = %s 1455 array(
'integer',
'integer'),
1460 if ($obligationsEnabled) {
1462 SELECT answered answ 1463 FROM tst_test_question 1464 INNER JOIN tst_active 1466 AND tst_test_question.test_fi = tst_active.test_fi 1467 LEFT JOIN tst_test_result 1468 ON tst_test_result.active_fi = %s 1469 AND tst_test_result.pass = %s 1470 AND tst_test_question.question_fi = tst_test_result.question_fi 1471 WHERE obligatory = 1';
1473 $result_obligatory = $ilDB->queryF(
1475 array(
'integer',
'integer',
'integer'),
1479 $obligations_answered = 1;
1481 while ($row_obligatory = $ilDB->fetchAssoc($result_obligatory)) {
1482 if (!(
int) $row_obligatory[
'answ']) {
1483 $obligations_answered = 0;
1488 $obligations_answered = 1;
1493 if (
$row[
'hint_count'] === null) {
1494 $row[
'hint_count'] = 0;
1496 if (
$row[
'hint_points'] === null) {
1497 $row[
'hint_points'] = 0;
1502 $updatePassResultCallback =
function () use ($ilDB,
$data, $active_id,
$pass,
$row,
$time, $obligations_answered, $exam_identifier) {
1508 'active_fi' =>
array(
'integer', $active_id),
1511 'points' =>
array(
'float',
$row[
'reachedpoints'] ?
$row[
'reachedpoints'] : 0),
1512 'maxpoints' =>
array(
'float',
$data[
'points']),
1513 'questioncount' =>
array(
'integer',
$data[
'count']),
1514 'answeredquestions' =>
array(
'integer', $row[
'answeredquestions']),
1517 'hint_count' =>
array(
'integer', $row[
'hint_count']),
1518 'hint_points' =>
array(
'float', $row[
'hint_points']),
1519 'obligations_answered' =>
array(
'integer', $obligations_answered),
1520 'exam_id' =>
array(
'text', $exam_identifier)
1526 $processLocker->executeUserPassResultUpdateLockOperation($updatePassResultCallback);
1528 $updatePassResultCallback();
1535 'active_fi' => $active_id,
1537 'points' => (
$row[
"reachedpoints"]) ?
$row[
"reachedpoints"] : 0,
1538 'maxpoints' =>
$data[
"points"],
1539 'questioncount' =>
$data[
"count"],
1540 'answeredquestions' => $row[
"answeredquestions"],
1541 'workingtime' =>
$time,
1543 'hint_count' => $row[
'hint_count'],
1544 'hint_points' => $row[
'hint_points'],
1545 'obligations_answered' => $obligations_answered,
1546 'exam_id' => $exam_identifier
1557 public static function logAction($logtext =
"", $active_id =
"", $question_id =
"")
1560 if (strlen($question_id)) {
1564 require_once
'Modules/Test/classes/class.ilObjAssessmentFolder.php';
1565 require_once
'Modules/Test/classes/class.ilObjTest.php';
1585 $mediatempdir = CLIENT_WEB_DIR .
"/assessment/temp";
1586 if (!@is_dir($mediatempdir)) {
1589 $temp_name = tempnam($mediatempdir,
$name .
"_____");
1590 $temp_name = str_replace(
"\\",
"/", $temp_name);
1591 @unlink($temp_name);
1592 if (!ilUtil::moveUploadedFile(
$file,
$name, $temp_name)) {
1606 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/solution/";
1617 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/java/";
1628 if ($question_id === null) {
1632 if ($object_id === null) {
1641 return CLIENT_WEB_DIR .
"/assessment/{$parentObjectId}/{$questionId}/images/";
1652 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/flash/";
1663 include_once
"./Services/Utilities/classes/class.ilUtil.php";
1675 include_once
"./Services/Utilities/classes/class.ilUtil.php";
1690 if (!$this->export_image_path) {
1691 include_once
"./Services/Utilities/classes/class.ilUtil.php";
1707 include_once
"./Services/Utilities/classes/class.ilUtil.php";
1729 if (!count($solution)) {
1743 if (is_null(
$pass)) {
1747 if ($this->
getStep() !== null) {
1751 WHERE active_fi = %s 1752 AND question_fi = %s 1756 ORDER BY solution_id";
1760 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
1767 WHERE active_fi = %s 1768 AND question_fi = %s 1771 ORDER BY solution_id 1776 array(
'integer',
'integer',
'integer',
'integer'),
1800 if ($question_id < 1) {
1801 $question_id = $this->
getId();
1804 "SELECT COUNT(qpl_questions.question_id) question_count FROM qpl_questions, tst_test_question WHERE qpl_questions.original_id = %s AND qpl_questions.question_id = tst_test_question.question_fi",
1809 $count =
$row[
"question_count"];
1813 SELECT tst_active.test_fi 1815 INNER JOIN tst_test_rnd_qst ON tst_test_rnd_qst.question_fi = qpl_questions.question_id 1816 INNER JOIN tst_active ON tst_active.active_id = tst_test_rnd_qst.active_fi 1817 WHERE qpl_questions.original_id = %s 1818 GROUP BY tst_active.test_fi",
1837 if ($question_id < 1) {
1841 "SELECT original_id FROM qpl_questions WHERE question_id = %s",
1846 return (
$row[
"original_id"] > 0) ? true :
false;
1857 $keys = array_keys($array);
1876 "SELECT qpl_qst_type.type_tag FROM qpl_qst_type, qpl_questions WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
1881 return $data[
"type_tag"];
1917 if (!is_array($answer_table_name)) {
1918 $answer_table_name =
array($answer_table_name);
1921 foreach ($answer_table_name as
$table) {
1922 if (strlen($table)) {
1923 $affectedRows = $ilDB->manipulateF(
1924 "DELETE FROM $table WHERE question_fi = %s",
1944 if (!is_array($additional_table_name)) {
1945 $additional_table_name =
array($additional_table_name);
1948 foreach ($additional_table_name as
$table) {
1949 if (strlen($table)) {
1950 $affectedRows = $ilDB->manipulateF(
1951 "DELETE FROM $table WHERE question_fi = %s",
1967 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
1979 public function delete($question_id)
1983 if ($question_id < 1) {
1988 "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
1992 if (
$result->numRows() == 1) {
2001 $ilLog->write(
"EXCEPTION: Could not delete page of question $question_id: $e");
2005 $affectedRows = $ilDB->manipulateF(
2006 "DELETE FROM qpl_questions WHERE question_id = %s",
2010 if ($affectedRows == 0) {
2020 $ilLog->write(
"EXCEPTION: Could not delete additional table data of question $question_id: $e");
2026 $affectedRows = $ilDB->manipulateF(
2027 "DELETE FROM tst_test_question WHERE question_fi = %s",
2032 $ilLog->write(
"EXCEPTION: Could not delete delete question $question_id from a test: $e");
2038 $affectedRows = $ilDB->manipulateF(
2039 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2044 $ilLog->write(
"EXCEPTION: Could not delete suggested solutions of question $question_id: $e");
2049 $directory = CLIENT_WEB_DIR .
"/assessment/" .
$obj_id .
"/$question_id";
2050 if (preg_match(
"/\d+/",
$obj_id) and preg_match(
"/\d+/", $question_id) and is_dir($directory)) {
2051 include_once
"./Services/Utilities/classes/class.ilUtil.php";
2055 $ilLog->write(
"EXCEPTION: Could not delete question file directory $directory of question $question_id: $e");
2060 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2066 foreach (
$mobs as $mob) {
2074 $ilLog->write(
"EXCEPTION: Error deleting the media objects of question $question_id: $e");
2078 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
2079 ilAssQuestionHintTracking::deleteRequestsByQuestionIds(
array($question_id));
2081 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
2084 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
2086 $assignmentList->setParentObjId(
$obj_id);
2087 $assignmentList->setQuestionIdFilter($question_id);
2088 $assignmentList->loadFromDb();
2089 foreach ($assignmentList->getAssignmentsByQuestionId($question_id) as $assignment) {
2091 $assignment->deleteFromDb();
2098 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
2101 $ilLog->write(
"EXCEPTION: Error updating the question pool question count of question pool " . $this->
getObjId() .
" when deleting question $question_id: $e");
2112 require_once
'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
2113 require_once
'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
2116 foreach ($taxIds as $taxId) {
2118 $taxNodeAssignment->deleteAssignmentsOfItem($this->
getId());
2142 "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
2143 array(
'integer',
'integer'),
2144 array($a_q_id, $a_q_id)
2146 if (
$result->numRows() == 0) {
2149 $found_id =
array();
2151 array_push($found_id,
$row[
"question_id"]);
2154 $result = $ilDB->query(
"SELECT * FROM tst_test_result WHERE " . $ilDB->in(
'question_fi', $found_id,
false,
'integer'));
2170 "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
2171 array(
'integer',
'integer'),
2172 array($a_q_id, $a_q_id)
2174 if (
$result->numRows() == 0) {
2177 $found_id =
array();
2179 array_push($found_id,
$row[
"question_id"]);
2181 $result = $ilDB->query(
"SELECT * FROM tst_test_result WHERE " . $ilDB->in(
'question_fi', $found_id,
false,
'integer'));
2184 $reached =
$row[
"points"];
2185 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
2187 array_push($answers,
array(
"reached" => $reached,
"max" => $max));
2191 foreach ($answers as
$key => $value) {
2192 $max += $value[
"max"];
2193 $reached += $value[
"reached"];
2196 return $reached / $max;
2211 "SELECT title FROM qpl_questions WHERE question_id = %s",
2215 if (
$result->numRows() == 1) {
2217 return $row[
"title"];
2232 "SELECT question_text FROM qpl_questions WHERE question_id = %s",
2236 if (
$result->numRows() == 1) {
2238 return $row[
"question_text"];
2246 if (!file_exists(
$file)) {
2250 if (!is_file(
$file)) {
2254 if (!is_readable(
$file)) {
2263 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2265 foreach (
$mobs as $mob) {
2272 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2274 foreach (
$mobs as $mob) {
2286 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2288 $this->page->setId($this->
getId());
2289 $this->page->setParentId($qpl_id);
2290 $this->page->setXMLContent(
"<PageObject><PageContent>" .
2291 "<Question QRef=\"il__qst_" . $this->
getId() .
"\"/>" .
2292 "</PageContent></PageObject>");
2293 $this->page->create();
2299 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2302 $xml = str_replace(
"il__qst_" . $a_q_id,
"il__qst_" . $this->
id,
$page->getXMLContent());
2303 $this->page->setXMLContent(
$xml);
2304 $this->page->updateFromXML();
2310 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2312 return $page->getXMLContent();
2324 if ($question_id < 1) {
2328 "SELECT type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
2332 if (
$result->numRows() == 1) {
2334 return $data[
"type_tag"];
2351 if ($question_id < 1) {
2356 "SELECT title FROM qpl_questions WHERE qpl_questions.question_id = %s",
2360 if (
$result->numRows() == 1) {
2362 return $data[
"title"];
2379 'ok.svg' =>
'ok.png',
'not_ok.svg' =>
'not_ok.png',
2380 'checkbox_checked.svg' =>
'checkbox_checked.png',
2381 'checkbox_unchecked.svg' =>
'checkbox_unchecked.png',
2382 'radiobutton_checked.svg' =>
'radiobutton_checked.png',
2383 'radiobutton_unchecked.svg' =>
'radiobutton_unchecked.png' 2388 $needles = array_keys(self::$imageSourceFixReplaceMap);
2389 $replacements = array_values(self::$imageSourceFixReplaceMap);
2390 return str_replace($needles, $replacements, $imageFilenameContainingString);
2397 if (preg_match_all(
'/src="(.*?)"/m',
$html, $matches)) {
2398 $sources = $matches[1];
2400 $needleReplacementMap =
array();
2402 foreach ($sources as $src) {
2405 if (file_exists(
$file)) {
2409 $levels = explode(DIRECTORY_SEPARATOR, $src);
2410 if (count($levels) < 5 || $levels[0] !=
'Customizing' || $levels[2] !=
'skin') {
2416 if ($levels[4] ==
'Modules' || $levels[4] ==
'Services') {
2417 $component = $levels[4] . DIRECTORY_SEPARATOR . $levels[5];
2423 if (count($needleReplacementMap)) {
2424 $html = str_replace(array_keys($needleReplacementMap), array_values($needleReplacementMap),
$html);
2442 "SELECT external_id FROM qpl_questions WHERE question_id = %s",
2446 if (
$result->numRows() == 1) {
2448 $this->external_id =
$data[
'external_id'];
2452 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
2456 $this->suggested_solutions =
array();
2458 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2461 $this->suggested_solutions[
$row[
"subquestion_index"]] =
array(
2462 "type" => $row[
"type"],
2464 "internal_link" => $row[
"internal_link"],
2465 "import_id" => $row[
"import_id"]
2483 $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
2486 if ($a_create_page) {
2493 $next_id = $ilDB->nextId(
'qpl_questions');
2494 $affectedRows = $ilDB->insert(
"qpl_questions",
array(
2495 "question_id" =>
array(
"integer", $next_id),
2498 "title" =>
array(
"text", null),
2499 "description" =>
array(
"text", null),
2501 "owner" =>
array(
"integer", $ilUser->getId()),
2502 "question_text" =>
array(
"clob", null),
2503 "points" =>
array(
"float", 0),
2505 "working_time" =>
array(
"text", $estw_time),
2506 "complete" =>
array(
"text", $complete),
2508 "original_id" =>
array(
"integer", null),
2509 "tstamp" =>
array(
"integer", $tstamp),
2513 $this->
setId($next_id);
2515 if ($a_create_page) {
2523 return $this->
getId();
2531 $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
2534 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2535 if ($this->
getId() == -1) {
2537 $next_id = $ilDB->nextId(
'qpl_questions');
2538 $affectedRows = $ilDB->insert(
"qpl_questions",
array(
2539 "question_id" =>
array(
"integer", $next_id),
2548 "working_time" =>
array(
"text", $estw_time),
2556 $this->
setId($next_id);
2561 $affectedRows = $ilDB->update(
"qpl_questions",
array(
2569 "working_time" =>
array(
"text", $estw_time),
2574 "question_id" =>
array(
"integer", $this->
getId())
2589 $this->updateSuggestedSolutions();
2600 $affectedRows = $ilDB->manipulateF(
2601 "UPDATE qpl_questions SET tstamp = %s, owner = %s, complete = %s WHERE question_id = %s",
2602 array(
'integer',
'integer',
'integer',
'text'),
2607 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
2618 self::saveOriginalId($this->
getId(), $newId);
2623 $query =
"UPDATE qpl_questions SET tstamp = %s, original_id = %s WHERE question_id = %s";
2625 $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
2627 array(
'integer',
'integer',
'text'),
2634 $query =
"UPDATE qpl_questions SET tstamp = %s, original_id = NULL WHERE question_id = %s";
2636 $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
2638 array(
'integer',
'text'),
2646 protected function onDuplicate($originalParentId, $originalQuestionId, $duplicateParentId, $duplicateQuestionId)
2651 $this->feedbackOBJ->duplicateFeedback($originalQuestionId, $duplicateQuestionId);
2667 $this->feedbackOBJ->syncFeedback($origQuestionId, $dupQuestionId);
2673 protected function onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $targetQuestionId)
2678 $this->feedbackOBJ->duplicateFeedback($sourceQuestionId, $targetQuestionId);
2694 $affectedRows = $ilDB->manipulateF(
2695 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2700 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2702 $this->suggested_solutions =
array();
2715 if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
2716 return $this->suggested_solutions[$subquestion_index];
2732 if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
2733 $title = $this->suggested_solutions[$subquestion_index][
"internal_link"];
2752 if (strcmp($solution_id,
"") != 0) {
2755 $import_id = $solution_id;
2758 $this->suggested_solutions[$subquestion_index] =
array(
2759 "internal_link" => $solution_id,
2760 "import_id" => $import_id
2772 foreach ($this->suggested_solutions as
$index => $solution) {
2773 if (strcmp($solution[
"type"],
"file") == 0) {
2775 $filepath_original = str_replace(
2776 "/{$this->obj_id}/{$this->id}/solution",
2777 "/$parent_id/$question_id/solution",
2780 if (!file_exists($filepath)) {
2785 if (!copy($filepath_original .
$filename, $filepath . $filename)) {
2786 $ilLog->write(
"File could not be duplicated!!!!", $ilLog->ERROR);
2787 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2802 $filepath_original = str_replace(
"/$this->id/solution",
"/$original_id/solution", $filepath);
2804 foreach ($this->suggested_solutions as
$index => $solution) {
2805 if (strcmp($solution[
"type"],
"file") == 0) {
2806 if (!file_exists($filepath_original)) {
2811 if (!@copy($filepath .
$filename, $filepath_original . $filename)) {
2812 $ilLog->write(
"File could not be duplicated!!!!", $ilLog->ERROR);
2813 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2824 foreach ($this->suggested_solutions as
$index => $solution) {
2825 if (strcmp($solution[
"type"],
"file") == 0) {
2827 $filepath_original = str_replace(
"/$this->obj_id/$this->id/solution",
"/$source_questionpool_id/$source_question_id/solution", $filepath);
2828 if (!file_exists($filepath)) {
2833 if (!copy($filepath_original .
$filename, $filepath . $filename)) {
2834 $ilLog->write(
"File could not be copied!!!!", $ilLog->ERROR);
2835 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2845 public function updateSuggestedSolutions(
$original_id =
"")
2850 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2851 $affectedRows = $ilDB->manipulateF(
2852 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2857 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2858 foreach ($this->suggested_solutions as
$index => $solution) {
2859 $next_id = $ilDB->nextId(
'qpl_sol_sug');
2864 'suggested_solution_id' =>
array(
'integer', $next_id ),
2865 'question_fi' =>
array(
'integer',
$id ),
2866 'type' =>
array(
'text', $solution[
'type'] ),
2868 'internal_link' =>
array(
'text', $solution[
'internal_link'] ),
2869 'import_id' =>
array(
'text', null ),
2870 'subquestion_index' =>
array(
'integer',
$index ),
2874 if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/", $solution[
"internal_link"], $matches)) {
2893 public function saveSuggestedSolution(
$type, $solution_id =
"", $subquestion_index = 0, $value =
"")
2897 $affectedRows = $ilDB->manipulateF(
2898 "DELETE FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
2899 array(
"integer",
"integer"),
2906 $next_id = $ilDB->nextId(
'qpl_sol_sug');
2907 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2909 $affectedRows = $ilDB->insert(
2912 'suggested_solution_id' =>
array(
'integer', $next_id ),
2913 'question_fi' =>
array(
'integer', $this->
getId() ),
2916 'internal_link' =>
array(
'text', $solution_id ),
2917 'import_id' =>
array(
'text', null ),
2918 'subquestion_index' =>
array(
'integer', $subquestion_index ),
2922 if ($affectedRows == 1) {
2923 $this->suggested_solutions[$subquestion_index] =
array(
2926 "internal_link" => $solution_id,
2935 if (preg_match(
"/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches)) {
2936 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2937 include_once
"./Modules/LearningModule/classes/class.ilLMObject.php";
2938 include_once
"./Modules/Glossary/classes/class.ilGlossaryTerm.php";
2939 switch ($matches[2]) {
2956 if (strcmp($resolved_link,
"") == 0) {
2957 $resolved_link = $internal_link;
2960 $resolved_link = $internal_link;
2962 return $resolved_link;
2970 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
2976 $internal_link =
$row[
"internal_link"];
2977 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
2979 if (strcmp($internal_link, $resolved_link) != 0) {
2981 $affectedRows = $ilDB->manipulateF(
2982 "UPDATE qpl_sol_sug SET internal_link = %s WHERE suggested_solution_id = %s",
2983 array(
'text',
'integer'),
2984 array($resolved_link,
$row[
"suggested_solution_id"])
2990 if ($resolvedlinks) {
2994 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2998 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
3004 if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/",
$row[
"internal_link"], $matches)) {
3016 "lm" =>
"LearningModule",
3017 "pg" =>
"PageObject",
3018 "st" =>
"StructureObject",
3019 "git" =>
"GlossaryItem",
3020 "mob" =>
"MediaObject" 3023 if (preg_match(
"/il__(\w+)_(\d+)/",
$target, $matches)) {
3024 $type = $matches[1];
3026 include_once
"./Services/Utilities/classes/class.ilUtil.php";
3027 switch ($linktypes[$matches[1]]) {
3028 case "LearningModule":
3032 case "StructureObject":
3035 case "GlossaryItem":
3039 $href =
"./ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[
$type] .
"&cmd=media&ref_id=" .
$_GET[
"ref_id"] .
"&mob_id=" .
$target_id;
3057 "SELECT * FROM qpl_questions WHERE question_id = %s",
3063 if (
$row[
"original_id"] > 0) {
3064 return $row[
"original_id"];
3066 return $row[
"question_id"];
3078 SELECT COUNT(dupl.question_id) cnt 3079 FROM qpl_questions dupl 3080 INNER JOIN qpl_questions orig 3081 ON orig.question_id = dupl.original_id 3082 WHERE dupl.question_id = %s 3088 return $row[
'cnt'] > 0;
3099 $originalObjId = self::lookupOriginalParentObjId($this->
getOriginalId());
3101 if (!$originalObjId) {
3111 $this->
setId($original);
3125 $this->updateSuggestedSolutions($original);
3147 if ($question_id < 1) {
3152 "SELECT question_id FROM qpl_questions WHERE question_id = %s",
3156 if (
$result->numRows() == 1) {
3174 if ($question_id < 1) {
3179 "SELECT question_id FROM qpl_questions INNER JOIN object_data ON obj_fi = obj_id WHERE question_id = %s AND type = 'qpl'",
3183 if (
$result->numRows() == 1) {
3199 return self::_instantiateQuestion($question_id);
3210 if (strcmp($question_id,
"") != 0) {
3212 if (!strlen($question_type)) {
3216 $objectClassname = self::getObjectClassNameByQuestionType($question_type);
3220 $feedbackObjectClassname = self::getFeedbackClassNameByQuestionType($question_type);
3221 $question->feedbackOBJ =
new $feedbackObjectClassname(
$question, $ilCtrl, $ilDB, $lng);
3235 if (strcmp($this->points,
"") == 0) {
3251 $this->points = $a_points;
3262 return self::_getSolutionMaxPass($this->
getId(), $active_id);
3283 "SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
3284 array(
'integer',
'integer'),
3285 array($active_id, $question_id)
3287 if (
$result->numRows() == 1) {
3289 return $row[
"maxpass"];
3307 if (($question_id < 1) || ($user_id < 1)) {
3312 "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
3316 if (
$result->numRows() == 1) {
3318 $qpl_object_id =
$row[
"obj_fi"];
3319 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
3336 if ($question_id < 1) {
3340 "SELECT test_random_question_id FROM tst_test_rnd_qst WHERE question_fi = %s",
3366 $reachedPoints = $reachedPoints - $requestsStatisticData->getRequestsPoints();
3368 return $reachedPoints;
3408 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3410 if ($count_system == 1) {
3416 if ($score_cutting == 0) {
3434 return self::lookupResultRecordExist($active_id, $question_id,
$pass);
3441 if (is_null(
$pass)) {
3442 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
3446 "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3447 array(
'integer',
'integer',
'integer'),
3468 $res = $ilDB->queryF(
3469 "SELECT DISTINCT(question_fi) FROM tst_test_result JOIN tst_active " .
3470 "ON (active_id = active_fi) " .
3471 "WHERE " . $ilDB->in(
'question_fi', $a_question_ids,
false,
'integer') .
3472 " AND user_fi = %s",
3476 return (
$res->numRows() == count($a_question_ids)) ?
true :
false;
3500 include_once
"./Services/Utilities/classes/class.ilUtil.php";
3514 for (
$i = 0;
$i < $a_material->getMaterialCount();
$i++) {
3515 $material = $a_material->getMaterial(
$i);
3516 if (strcmp($material[
"type"],
"mattext") == 0) {
3517 $result .= $material[
"material"]->getContent();
3519 if (strcmp($material[
"type"],
"matimage") == 0) {
3520 $matimage = $material[
"material"];
3521 if (preg_match(
"/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
3523 if (!is_array(
$_SESSION[
"import_mob_xhtml"])) {
3526 array_push(
$_SESSION[
"import_mob_xhtml"],
array(
"mob" => $matimage->getLabel(),
"uri" => $matimage->getUri()));
3541 public function addQTIMaterial(&$a_xml_writer, $a_material, $close_material_tag =
true, $add_mobs =
true)
3543 include_once
"./Services/RTE/classes/class.ilRTE.php";
3544 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
3546 $a_xml_writer->xmlStartTag(
"material");
3548 "texttype" =>
"text/plain" 3550 if ($this->
isHTML($a_material)) {
3551 $attrs[
"texttype"] =
"text/xhtml";
3556 foreach (
$mobs as $mob) {
3557 $moblabel =
"il_" . IL_INST_ID .
"_mob_" . $mob;
3558 if (strpos($a_material,
"mm_$mob") !==
false) {
3562 "label" => $moblabel,
3563 "uri" =>
"objects/" .
"il_" . IL_INST_ID .
"_mob_" . $mob .
"/" . $mob_obj->getTitle()
3566 $a_xml_writer->xmlElement(
"matimage", $imgattrs, null);
3570 if ($close_material_tag) {
3571 $a_xml_writer->xmlEndTag(
"material");
3579 if (preg_match(
"/.*\.(png|jpg|gif|jpeg)$/i", $plain_image_filename, $matches)) {
3580 $extension =
"." . $matches[1];
3584 $plain_image_filename = uniqid($plain_image_filename . microtime(
true));
3587 $hashed_filename = md5($plain_image_filename) . $extension;
3589 return $hashed_filename;
3607 if (is_null(
$pass)) {
3614 "SELECT points FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3615 array(
'integer',
'integer',
'integer'),
3618 $manual = ($manualscoring) ? 1 : 0;
3619 $rowsnum =
$result->numRows();
3622 $old_points =
$row[
"points"];
3624 $affectedRows = $ilDB->manipulateF(
3625 "UPDATE tst_test_result SET points = %s, manual = %s, tstamp = %s WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3626 array(
'float',
'integer',
'integer',
'integer',
'integer',
'integer'),
3631 $next_id = $ilDB->nextId(
'tst_test_result');
3632 $affectedRows = $ilDB->manipulateF(
3633 "INSERT INTO tst_test_result (test_result_id, active_fi, question_fi, points, pass, manual, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
3634 array(
'integer',
'integer',
'integer',
'float',
'integer',
'integer',
'integer'),
3639 if (self::isForcePassResultUpdateEnabled() || $old_points !=
$points || !$rowsnum) {
3640 assQuestion::_updateTestPassResults($active_id,
$pass, $obligationsEnabled);
3642 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3643 include_once
'./Modules/Course/classes/class.ilCourseObjectiveResult.php';
3646 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3649 include_once
"./Modules/Test/classes/class.ilObjTestAccess.php";
3705 "SELECT question_type_id FROM qpl_qst_type WHERE type_tag = %s",
3709 if (
$result->numRows() == 1) {
3711 return $row[
"question_type_id"];
3716 public function syncHints()
3722 "DELETE FROM qpl_hints WHERE qht_question_fi = %s",
3724 array($this->original_id)
3729 "SELECT * FROM qpl_hints WHERE qht_question_fi = %s",
3737 $next_id = $ilDB->nextId(
'qpl_hints');
3742 'qht_hint_id' =>
array(
'integer', $next_id),
3743 'qht_question_fi' =>
array(
'integer', $this->original_id),
3744 'qht_hint_index' =>
array(
'integer',
$row[
"qht_hint_index"]),
3745 'qht_hint_points' =>
array(
'integer',
$row[
"qht_hint_points"]),
3746 'qht_hint_text' =>
array(
'text',
$row[
"qht_hint_text"]),
3762 $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(),
false);
3763 $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(),
true);
3764 $collected .= $this->feedbackOBJ->getAllSpecificAnswerFeedbackContents($this->
getId());
3766 foreach ($this->suggested_solutions as $solution_array) {
3767 $collected .= $solution_array[
"value"];
3770 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
3772 foreach ($questionHintList as $questionHint) {
3774 $collected .= $questionHint->getText();
3787 include_once(
"./Services/RTE/classes/class.ilRTE.php");
3801 "SELECT question_id FROM qpl_questions WHERE original_id = %s",
3805 $instances =
array();
3808 array_push($ids,
$row[
"question_id"]);
3810 foreach ($ids as $question_id) {
3813 "SELECT tst_tests.obj_fi FROM tst_tests, tst_test_question WHERE tst_test_question.question_fi = %s AND tst_test_question.test_fi = tst_tests.test_id",
3822 "SELECT tst_tests.obj_fi FROM tst_tests, tst_test_rnd_qst, tst_active WHERE tst_test_rnd_qst.active_fi = tst_active.active_id AND tst_test_rnd_qst.question_fi = %s AND tst_tests.test_id = tst_active.test_fi",
3830 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3831 foreach ($instances as
$key => $value) {
3839 include_once
"./Modules/Test/classes/class.ilObjAssessmentFolder.php";
3842 if (in_array($questiontype, $scoring)) {
3860 "SELECT * FROM tst_active WHERE active_id = %s",
3866 return array(
"user_id" =>
$row[
"user_fi"],
"test_id" =>
$row[
"test_fi"]);
3881 if (self::isCoreQuestionType($question_type)) {
3882 self::includeCoreClass($question_type, $gui);
3884 self::includePluginClass($question_type, $gui);
3890 return $questionType .
'GUI';
3895 return $questionType;
3900 return str_replace(
'ass',
'ilAss', $questionType) .
'Feedback';
3905 $guiClassName = self::getGuiClassNameByQuestionType($questionType);
3906 return file_exists(
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php");
3911 if ($withGuiClass) {
3912 $guiClassName = self::getGuiClassNameByQuestionType($questionType);
3913 require_once
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php";
3917 $objectClassName = self::getObjectClassNameByQuestionType($questionType);
3918 require_once
"Modules/TestQuestionPool/classes/class.{$objectClassName}.php";
3921 $feedbackClassName = self::getFeedbackClassNameByQuestionType($questionType);
3922 require_once
"Modules/TestQuestionPool/classes/feedback/class.{$feedbackClassName}.php";
3927 global $ilPluginAdmin;
3930 self::getObjectClassNameByQuestionType($questionType),
3931 self::getFeedbackClassNameByQuestionType($questionType)
3934 if ($withGuiClass) {
3935 $classes[] = self::getGuiClassNameByQuestionType($questionType);
3938 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE,
"TestQuestionPool",
"qst");
3939 foreach ($pl_names as $pl_name) {
3941 if (strcmp($pl->getQuestionType(), $questionType) == 0) {
3942 foreach ($classes as $class) {
3943 $pl->includeClass(
"class.{$class}.php");
3959 if (file_exists(
"./Modules/TestQuestionPool/classes/class." . $type_tag .
".php")) {
3961 return $lng->txt($type_tag);
3963 global $ilPluginAdmin;
3964 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE,
"TestQuestionPool",
"qst");
3965 foreach ($pl_names as $pl_name) {
3967 if (strcmp($pl->getQuestionType(), $type_tag) == 0) {
3968 return $pl->getQuestionTypeTranslation();
3986 return self::instantiateQuestionGUI($question_id);
4000 if (strcmp($a_question_id,
"") != 0) {
4005 $question_type_gui = self::getGuiClassNameByQuestionType($question_type);
4006 $question_gui =
new $question_type_gui();
4007 $question_gui->object->loadFromDb($a_question_id);
4009 $feedbackObjectClassname = self::getFeedbackClassNameByQuestionType($question_type);
4010 $question_gui->object->feedbackOBJ =
new $feedbackObjectClassname($question_gui->object, $ilCtrl, $ilDB, $lng);
4012 $assSettings =
new ilSetting(
'assessment');
4013 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
4015 $processLockerFactory->setQuestionId($question_gui->object->getId());
4016 $processLockerFactory->setUserId($ilUser->getId());
4017 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
4019 $question_gui->object->setProcessLocker($processLockerFactory->getLocker());
4022 $ilLog->write(
'Instantiate question called without question id. (instantiateQuestionGUI@assQuestion)', $ilLog->WARNING);
4025 return $question_gui;
4053 return $this->
getId();
4073 case "est_working_time":
4097 case "suggested_solutions":
4104 if (array_key_exists($value, $this->arrData)) {
4105 return $this->arrData[$value];
4120 $this->
setId($value);
4140 case "est_working_time":
4141 if (is_array($value)) {
4161 $this->page =&$value;
4164 $this->arrData[
$key] = $value;
4176 $this->nr_of_tries = $a_nr_of_tries;
4181 $this->export_image_path = (
string) $a_path;
4188 if ($question_id < 1) {
4193 "SELECT question_fi FROM tst_test_question WHERE question_fi = %s AND test_fi = %s",
4194 array(
'integer',
'integer'),
4197 if (
$result->numRows() == 1) {
4220 require_once
'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
4221 return new \ilAssSelfAssessmentQuestionFormatter();
4233 $this->prevent_rte_usage = $a_val;
4255 $this->feedbackOBJ->migrateContentForLearningModule($migrator, $this->
getId());
4281 $this->selfassessmenteditingmode = $a_selfassessmenteditingmode;
4301 $this->defaultnroftries = $a_defaultnroftries;
4325 $query =
"SELECT obj_fi FROM qpl_questions WHERE question_id = %s";
4330 return $row[
'obj_fi'];
4345 return self::lookupParentObjId($originalQuestionId);
4350 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
4354 require_once
'Modules/TestQuestionPool/classes/class.ilAssHintPage.php';
4356 foreach ($hintIds as $originalHintId => $duplicateHintId) {
4358 $originalXML = $originalPageObject->getXMLContent();
4361 $duplicatePageObject->setId($duplicateHintId);
4362 $duplicatePageObject->setParentId($this->
getId());
4363 $duplicatePageObject->setXMLContent($originalXML);
4364 $duplicatePageObject->createFromXML();
4373 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
4375 $assignmentList->setParentObjId($srcParentId);
4376 $assignmentList->setQuestionIdFilter($srcQuestionId);
4377 $assignmentList->loadFromDb();
4379 foreach ($assignmentList->getAssignmentsByQuestionId($srcQuestionId) as $assignment) {
4382 $assignment->setParentObjId($trgParentId);
4383 $assignment->setQuestionId($trgQuestionId);
4384 $assignment->saveToDb();
4392 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
4394 $assignmentList->setParentObjId($trgParentId);
4395 $assignmentList->setQuestionIdFilter($trgQuestionId);
4396 $assignmentList->loadFromDb();
4398 foreach ($assignmentList->getAssignmentsByQuestionId($trgQuestionId) as $assignment) {
4401 $assignment->deleteFromDb();
4463 SELECT count(active_fi) cnt 4467 WHERE active_fi = %s 4468 AND question_fi = %s 4472 $res = $ilDB->queryF(
4474 array(
'integer',
'integer',
'integer'),
4480 return (
int)
$row[
'cnt'];
4503 require_once
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
4546 self::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT,
4547 self::ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT
4556 $this->questionChangeListeners[] = $listener;
4570 $listener->notifyQuestionCreated($this);
4577 $listener->notifyQuestionEdited($this);
4584 $listener->notifyQuestionDeleted($this);
4593 require_once
'Services/Html/classes/class.ilHtmlPurifierFactory.php';
4602 require_once
'Services/Html/classes/class.ilHtmlPurifierFactory.php';
4609 SELECT qpl_questions.*, 4610 {$this->getAdditionalTableName()}.* 4612 LEFT JOIN {$this->getAdditionalTableName()} 4613 ON {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id 4614 WHERE qpl_questions.question_id = %s 4642 if ($this->
getStep() !== null) {
4646 WHERE active_fi = %s 4647 AND question_fi = %s 4653 return $ilDB->queryF(
4655 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
4662 WHERE active_fi = %s 4663 AND question_fi = %s 4668 return $ilDB->queryF(
4670 array(
'integer',
'integer',
'integer',
'integer'),
4686 return $ilDB->manipulateF(
4687 "DELETE FROM tst_solutions WHERE solution_id = %s",
4705 "SELECT * FROM tst_solutions WHERE solution_id = %s",
4726 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use ($active_id,
$pass) {
4743 if ($this->
getStep() !== null) {
4745 DELETE FROM tst_solutions 4746 WHERE active_fi = %s 4747 AND question_fi = %s 4753 return $ilDB->manipulateF(
4755 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
4760 DELETE FROM tst_solutions 4761 WHERE active_fi = %s 4762 AND question_fi = %s 4767 return $ilDB->manipulateF(
4769 array(
'integer',
'integer',
'integer',
'integer'),
4791 $next_id = $ilDB->nextId(
"tst_solutions");
4794 "solution_id" =>
array(
"integer", $next_id),
4795 "active_fi" =>
array(
"integer", $active_id),
4796 "question_fi" =>
array(
"integer", $this->
getId()),
4797 "value1" =>
array(
"clob", $value1),
4798 "value2" =>
array(
"clob", $value2),
4800 "tstamp" =>
array(
"integer", isset($tstamp) ? $tstamp :
time()),
4801 'authorized' =>
array(
'integer', (
int) $authorized)
4804 if ($this->
getStep() !== null) {
4805 $fieldData[
'step'] =
array(
"integer", $this->
getStep());
4808 return $ilDB->insert(
"tst_solutions", $fieldData);
4827 "value1" =>
array(
"clob", $value1),
4828 "value2" =>
array(
"clob", $value2),
4830 'authorized' =>
array(
'integer', (
int) $authorized)
4833 if ($this->
getStep() !== null) {
4834 $fieldData[
'step'] =
array(
"integer", $this->
getStep());
4837 return $ilDB->update(
"tst_solutions", $fieldData,
array(
4838 'solution_id' =>
array(
'integer', $solutionId)
4848 'authorized' =>
array(
'integer', (
int) $authorized)
4852 $fieldData[
'tstamp'] =
array(
'integer',
time());
4856 'question_fi' =>
array(
'integer', $this->
getId()),
4857 'active_fi' =>
array(
'integer', $activeId),
4861 if ($this->
getStep() !== null) {
4862 $whereData[
'step'] =
array(
"integer", $this->
getStep());
4865 return $ilDB->update(
'tst_solutions', $fieldData, $whereData);
4873 return self::KEY_VALUES_IMPLOSION_SEPARATOR;
4877 return implode(self::getKeyValuesImplosionSeparator(), $keyValues);
4881 return explode(self::getKeyValuesImplosionSeparator(), $keyValues);
4886 foreach ($this->
getSolutionValues($activeId, $passIndex,
false) as $solutionRec) {
4887 if (0 == strlen($solutionRec[
'value1']) && 0 == strlen($solutionRec[
'value2'])) {
4897 $types =
array(
"integer",
"integer",
"integer",
"integer");
4898 $values =
array($activeId, $this->
getId(), $passIndex, (
int) $authorized);
4899 $valuesCondition =
array();
4901 foreach ($matchValues as $valueField => $value) {
4902 switch ($valueField) {
4905 $valuesCondition[] =
"{$valueField} = %s";
4911 require_once
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
4916 $valuesCondition = implode(
' AND ', $valuesCondition);
4919 DELETE FROM tst_solutions 4920 WHERE active_fi = %s 4921 AND question_fi = %s 4924 AND $valuesCondition 4927 if ($this->
getStep() !== null) {
4928 $query .=
" AND step = %s ";
4929 $types[] =
'integer';
4939 $this->
saveCurrentSolution($activeId, $passIndex, $rec[
'value1'], $rec[
'value2'],
true, $rec[
'tstamp']);
4947 if (!count($intermediateSolution)) {
4955 if ($considerDummyRecordCreation) {
4977 return self::$resultGateway;
4985 $this->step =
$step;
5005 return gmdate(
'H:i:s',
$time);
5015 $time_array = explode(
':',
$time);
5016 if (
sizeof($time_array) == 3) {
5017 $sec += $time_array[0] * 3600;
5018 $sec += $time_array[1] * 60;
5019 $sec += $time_array[2];
5026 return json_encode(
array());
5034 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5035 return (
bool) $solutionAvailability[
'intermediate'];
5039 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5040 return (
bool) $solutionAvailability[
'authorized'];
5044 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5045 return (
bool) $solutionAvailability[
'authorized'] || (bool) $solutionAvailability[
'intermediate'];
5054 protected function lookupMaxStep($active_id,
$pass)
5059 $res = $ilDB->queryF(
5060 "SELECT MAX(step) max_step FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
5061 array(
"integer",
"integer",
"integer"),
5067 $maxStep =
$row[
'max_step'];
5079 public function lookupForExistingSolutions($activeId,
$pass)
5085 'authorized' =>
false,
5086 'intermediate' =>
false 5090 SELECT authorized, COUNT(*) cnt 5092 WHERE active_fi = %s 5093 AND question_fi = %s 5097 if ($this->
getStep() !== null) {
5098 $query .=
" AND step = " . $ilDB->quote((
int) $this->
getStep(),
'integer') .
" ";
5108 if (
$row[
'authorized']) {
5109 $return[
'authorized'] =
$row[
'cnt'] > 0;
5111 $return[
'intermediate'] =
$row[
'cnt'] > 0;
5123 DELETE FROM tst_solutions 5124 WHERE active_fi = %s 5125 AND question_fi = %s 5129 if ($this->
getStep() !== null) {
5130 $query .=
" AND step = " . $ilDB->quote((
int) $this->
getStep(),
'integer') .
" ";
5133 return $ilDB->manipulateF(
5135 array(
'integer',
'integer',
'integer'),
5145 $this->
log($activeId,
"log_user_solution_willingly_deleted");
5147 self::_updateTestPassResults(
5161 DELETE FROM tst_test_result 5162 WHERE active_fi = %s 5163 AND question_fi = %s 5167 if ($this->
getStep() !== null) {
5168 $query .=
" AND step = " . $ilDB->quote((
int) $this->
getStep(),
'integer') .
" ";
5171 return $ilDB->manipulateF(
5173 array(
'integer',
'integer',
'integer'),
5182 $IN_questionIds = $ilDB->in(
'question_fi', $questionIds,
false,
'integer');
5186 FROM tst_test_result 5187 WHERE active_fi = %s 5192 $row = $ilDB->fetchAssoc($ilDB->queryF(
5194 array(
'integer',
'integer'),
5198 return $row[
'cnt'] < count($questionIds);
5205 $IN_questionIds = $ilDB->in(
'question_fi', $questionIds,
false,
'integer');
5209 FROM tst_test_result 5210 WHERE active_fi = %s 5215 $res = $ilDB->queryF(
5217 array(
'integer',
'integer'),
5221 $questionsHavingResultRecord =
array();
5223 while (
$row = $ilDB->fetchAssoc(
$res)) {
5224 $questionsHavingResultRecord[] =
$row[
'question_fi'];
5227 $questionsMissingResultRecordt = array_diff(
5229 $questionsHavingResultRecord
5232 return $questionsMissingResultRecordt;
5241 FROM tst_test_result 5242 WHERE active_fi = %s 5243 AND question_fi = %s 5247 $row = $ilDB->fetchAssoc($ilDB->queryF(
$query,
array(
'integer',
'integer',
'integer'),
array($activeId, $questionId,
$pass)));
5249 return $row[
'cnt'] > 0;
5258 $valuePairs =
array();
5260 foreach ($indexedValues as $value1 => $value2) {
5261 $valuePairs[] =
array(
'value1' => $value1,
'value2' => $value2);
5273 $indexedValues =
array();
5275 foreach ($valuePairs as $valuePair) {
5276 $indexedValues[ $valuePair[
'value1'] ] = $valuePair[
'value2'];
5279 return $indexedValues;
5303 "UPDATE qpl_questions SET tstamp = %s WHERE question_id = %s",
5304 array(
'integer',
'integer'),
5326 if ($this->testQuestionConfigInstance === null) {
5343 include_once(
'Modules/TestQuestionPool/classes/class.ilTestQuestionConfig.php');
static _getUserIdFromActiveId($active_id)
isInUse($question_id="")
Checks whether the question is in use or not.
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
static isCoreQuestionType($questionType)
static resetOriginalId($questionId)
static getPluginObject($a_ctype, $a_cname, $a_slot_id, $a_pname)
Get plugin object.
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
deletePageOfQuestion($question_id)
Deletes the page object of a question with a given ID.
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
getId()
Gets the id of the assQuestion object.
static _getManualScoringTypes()
Retrieve the manual scoring settings as type strings.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
saveToDb($original_id="")
Saves the question to the database.
static getListByQuestionId($questionId)
instantiates a question hint list for the passed question id
static _getWorkingTimeOfParticipantForPass($active_id, $pass)
Returns the complete working time in seconds for a test participant.
static isFileAvailable($file)
$export_image_path
(Web) Path to images
Test Question configuration.
static _getQuestionText($a_q_id)
Returns question text.
getFlashPathWeb()
Returns the web image path for web accessable flash applications of a question.
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
static getAllowedImageMaterialFileExtensions()
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
setSuggestedSolution($solution_id="", $subquestion_index=0, $is_import=false)
Sets a suggested solution for the question.
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Receives parameters from a QTI parser and creates a valid ILIAS question object.
static getObjectClassNameByQuestionType($questionType)
Taxonomy node <-> item assignment.
migrateContentForLearningModule(ilAssSelfAssessmentMigrator $migrator)
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
static _updateTestResultCache($active_id, ilAssQuestionProcessLocker $processLocker=null)
Move this to a proper place.
static getQuestionTypeFromDb($question_id)
get question type for question id
static _isWriteable($object_id, $user_id)
Returns true, if the question pool is writeable by a given user.
forceExistingIntermediateSolution($activeId, $passIndex, $considerDummyRecordCreation)
_getTotalAnswers($a_q_id)
get number of answers for question id (static) note: do not use $this inside this method ...
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static sumTimesInISO8601FormatH_i_s_Extended($time1, $time2)
static _getParticipantData($active_id)
Retrieves a participant name from active id.
_questionExistsInPool($question_id)
Returns true if the question already exists in the database and is assigned to a question pool...
copySuggestedSolutionFiles($source_questionpool_id, $source_question_id)
static getNumExistingSolutionRecords($activeId, $pass, $questionId)
returns the number of existing solution records for the given test active / pass and given question i...
duplicateIntermediateSolutionAuthorized($activeId, $passIndex)
buildHashedImageFilename($plain_image_filename, $unique=false)
getSuggestedSolutionPath()
Returns the path for a suggested solution.
getTitleFilenameCompliant()
returns the object title prepared to be used as a filename
static _getQuestionType($question_id)
Returns the question type of a question with a given id.
static _getSolutionMaxPass($question_id, $active_id)
Returns the maximum pass a users question solution.
static getUsageOfObject($a_obj_id, $a_include_titles=false)
Get usage of object.
static lookupResultRecordExist($activeId, $questionId, $pass)
getQuestionType()
Returns the question type of the question.
static includeCoreClass($questionType, $withGuiClass)
syncSkillAssignments($srcParentId, $srcQuestionId, $trgParentId, $trgQuestionId)
static _getTotalRightAnswers($a_q_id)
get number of answers for question id (static) note: do not use $this inside this method ...
getPoints()
Returns the maximum available points for the question.
static originalQuestionExists($questionId)
static _isUsedInRandomTest($question_id="")
Checks whether the question is used in a random test or not.
copyPageOfQuestion($a_q_id)
questionTitleExists($questionpool_id, $title)
Returns TRUE if the question title exists in the database.
toXML($a_include_header=true, $a_include_binary=true, $a_shuffle=false, $test_output=false, $force_image_references=false)
Returns a QTI xml representation of the question.
const ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT
constant for additional content editing mode "pageobject"
buildTestPresentationConfig()
build basic test question configuration instance
static getQuestionsMissingResultRecord($activeId, $pass, $questionIds)
__set($key, $value)
Object setter.
__get($value)
Object getter.
Abstract basic class which is to be extended by the concrete assessment question type classes...
static _needsManualScoring($question_id)
& _getSuggestedSolution($question_id, $subquestion_index=0)
Returns a suggested solution for a given subquestion index.
setDefaultNrOfTries($a_defaultnroftries)
Set Default Nr of Tries.
addQTIMaterial(&$a_xml_writer, $a_material, $close_material_tag=true, $add_mobs=true)
Creates a QTI material tag from a plain text or xhtml text.
static prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
static _getIdForImportId($a_import_id)
get current object id for import id (static)
createPageObject()
create page object of question
intermediateSolutionExists($active_id, $pass)
adjustReachedPointsByScoringOptions($points, $active_id, $pass=null)
Adjust the given reached points by checks for all special scoring options in the test container...
ensureNonNegativePoints($points)
deleteAnswers($question_id)
Deletes datasets from answers tables.
deleteDummySolutionRecord($activeId, $passIndex)
calculateResultsFromSolution($active_id, $pass=null, $obligationsEnabled=false)
Calculates the question results from a previously saved question solution.
static & _instanciateQuestionGUI($question_id)
Creates an instance of a question gui with a given question id.
static _areAnswered($a_user_id, $a_question_ids)
Checks if an array of question ids is answered by an user or not.
getSuggestedSolutionTitle($subquestion_index=0)
Returns the title of a suggested solution at a given subquestion_index.
$additinalContentEditingMode
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
getQuestionChangeListeners()
setId($id=-1)
Sets the id of the assQuestion object.
copyXHTMLMediaObjectsOfQuestion($a_q_id)
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
duplicateSkillAssignments($srcParentId, $srcQuestionId, $trgParentId, $trgQuestionId)
static isForcePassResultUpdateEnabled()
static _getSuggestedSolutionCount($question_id)
Returns the number of suggested solutions associated with a question.
getUserSolutionPreferingIntermediate($active_id, $pass=null)
getImagePathWeb()
Returns the web image path for web accessable images of a question.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
removeResultRecord($activeId, $pass)
createRandomSolution($test_id, $user_id)
createNewQuestion($a_create_page=true)
Creates a new question without an owner when a new question is created This assures that an ID is giv...
static includePluginClass($questionType, $withGuiClass)
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
migrateToLmContent($content)
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
static _lookupTitle($a_id)
lookup object title
static _getIdForImportId($a_type, $a_target)
Get current id for an import id.
syncSuggestedSolutionFiles($original_id)
Syncs the files of a suggested solution if the question is synced.
syncXHTMLMediaObjectsOfQuestion()
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assQuestion constructor
beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
getAdditionalContentEditingMode()
getter for additional content editing mode for this question
getJavaPath()
Returns the image path for web accessable images of a question.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
deleteAdditionalTableData($question_id)
Deletes datasets from the additional question table in the database.
getParticipantsSolution()
isAnswered($active_id, $pass=null)
returns boolean wether the question is answered during test pass or not
setEstimatedWorkingTimeFromDurationString($durationString)
Sets the estimated working time of a question from a given datetime string.
getSelfAssessmentEditingMode()
Get Self-Assessment Editing Mode.
setNrOfTries($a_nr_of_tries)
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
static lookupParentObjId($questionId)
ilDBInterface $ilDB
isHTML($a_text)
Checks if a given string contains HTML or not.
static _getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
loadFromDb($question_id)
Loads the question from the database.
persistPreviewState(ilAssQuestionPreviewSession $previewSession)
persists the preview state for current user and question
authorizedSolutionExists($active_id, $pass)
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
setShuffle($shuffle=true)
Sets the shuffle flag.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
getObjId()
Get the object id of the container object.
getValidAdditionalContentEditingModes()
getter for valid additional content editing modes
static _getMaximumPoints($question_id)
Returns the maximum points, a learner can reach answering the question.
getShuffle()
Gets the shuffle flag.
$arrData
Associative array to store properties.
static _getAllReferences($a_id)
get all reference ids of object
isValidAdditionalContentEditingMode($additionalContentEditingMode)
returns the fact wether the passed additional content mode is valid or not
& getInstances()
Gets all instances of the question.
fetchIndexedValuesFromValuePairs(array $valuePairs)
setParticipantsSolution($participantSolution)
setProcessLocker($processLocker)
static _getInternalLinkHref($target="")
isPreviewSolutionCorrect(ilAssQuestionPreviewSession $previewSession)
static _getQuestionInfo($question_id)
Returns question information from the database.
static convertISO8601FormatH_i_s_ExtendedToSeconds($time)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
static deleteHintsByQuestionIds($questionIds)
Deletes all question hints relating to questions included in given question ids.
getSuggestedSolution($subquestion_index=0)
Returns a suggested solution for a given subquestion index.
authorizedOrIntermediateSolutionExists($active_id, $pass)
removeSolutionRecordById($solutionId)
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
duplicateQuestionHints($originalQuestionId, $duplicateQuestionId)
static _getLogLanguage()
retrieve the log language for assessment logging
persistWorkingState($active_id, $pass=null, $obligationsEnabled=false, $authorized=true)
persists the working state for current testactive and testpass
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
getJavaPathWeb()
Returns the web image path for web accessable java applets of a question.
getFlashPath()
Returns the image path for web accessable flash files of a question.
static isAllowedImageMimeType($mimeType)
getTestId()
Gets the test id of the assQuestion object.
setAuthor($author="")
Sets the authors name of the assQuestion object.
setObligationsToBeConsidered($obligationsToBeConsidered)
catch(Exception $e) $message
Assessment hint page object.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
getAuthor()
Gets the authors name of the assQuestion object.
getTotalAnswers()
get total number of answers
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
Reworks the allready saved working data if neccessary.
getQuestionTypeID()
Returns the question type of the question.
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
static _updateQuestionCount($object_id)
Updates the number of available questions for a question pool in the database.
foreach($_POST as $key=> $value) $res
static _getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
areObligationsToBeConsidered()
static setForcePassResultUpdateEnabled($forcePassResultsUpdateEnabled)
updateCurrentSolutionsAuthorization($activeId, $pass, $authorized, $keepTime=false)
static _isWorkedThrough($active_id, $question_id, $pass=null)
Returns true if the question was worked through in the given pass Worked through means that the user ...
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
static _addLog($user_id, $object_id, $logtext, $question_id="", $original_id="", $test_only=false, $test_ref_id=null)
Add an assessment log entry.
log($active_id, $langVar)
static _getScoreCutting($active_id)
Determines if the score of a question should be cut at 0 points or the score of the whole test...
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
static explodeKeyValues($keyValues)
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
static _lookupObjId($a_id)
setOutputType($outputType=OUTPUT_HTML)
Sets the output type.
isComplete()
Returns true, if a question is complete for use.
static _getCountSystem($active_id)
Gets the count system for the calculation of points.
static setResultGateway($resultGateway)
static implodeKeyValues($keyValues)
static $forcePassResultsUpdateEnabled
getQuestion()
Gets the question string of the question object.
getComment()
Gets the comment string of the assQuestion object.
static lookupOriginalParentObjId($originalQuestionId)
returns the parent object id for given original question id (should be a qpl id, but theoretically it...
redirection script todo: (a better solution should control the processing via a xml file) ...
getHtmlUserSolutionPurifier()
static createDirectory($a_dir, $a_mod=0755)
create directory
static saveOriginalId($questionId, $originalId)
$nr_of_tries
Number of tries.
static _lookupAuthor($obj_id)
Gets the authors name of the ilObjTest object.
getSuggestedSolutionPathWeb()
Returns the web path for a suggested solution.
static _updateObjectiveResult($a_user_id, $a_active_id, $a_question_id)
static signFile($path_to_file)
moveUploadedMediaFile($file, $name)
Move an uploaded media file to an public accessible temp dir to present it.
getDefaultNrOfTries()
Get Default Nr of Tries.
isClone($question_id="")
Checks whether the question is a clone of another question or not.
updateCurrentSolution($solutionId, $value1, $value2, $authorized=true)
static removeTrailingPathSeparators($path)
cleanupMediaObjectUsage()
synchronises appearances of media objects in the question with media object usage table ...
deleteSuggestedSolutions()
Deletes all suggestes solutions in the database.
Create styles array
The data for the language used.
setPreventRteUsage($a_val)
Set prevent rte usage.
fixSvgToPng($imageFilenameContainingString)
static _instantiateQuestion($question_id)
setExternalId($external_id)
fetchValuePairsFromIndexedValues(array $indexedValues)
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
static duplicateListForQuestion($originalQuestionId, $duplicateQuestionId)
duplicates a hint list from given original question id to given duplicate question id and returns an ...
isAdditionalContentEditingModePageObject()
isser for additional "pageobject" content editing mode
getTestOutputSolutions($activeId, $pass)
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
static $allowedCharsetsByMimeType
const ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT
constant for additional content editing mode "default"
static _questionExistsInTest($question_id, $test_id)
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
_resolveIntLinks($question_id)
static _getSuggestedSolutionOutput($question_id)
Returns the output of the suggested solution.
const KEY_VALUES_IMPLOSION_SEPARATOR
onDuplicate($originalParentId, $originalQuestionId, $duplicateParentId, $duplicateQuestionId)
Will be called when a question is duplicated (inside a question pool or for insertion in a test) ...
_questionExists($question_id)
Returns true if the question already exists in the database.
static _getInstanceByType($a_type)
Factory method for creating purifier instances.
static $imageSourceFixReplaceMap
getOwner()
Gets the creator/owner ID of the assQuestion object.
static isAllowedImageFileExtension($mimeType, $fileExtension)
lmMigrateQuestionTypeGenericContent(ilAssSelfAssessmentMigrator $migrator)
lookupCurrentTestPass($active_id, $pass)
resetUsersAnswer($activeId, $pass)
getEstimatedWorkingTime()
Gets the estimated working time of a question.
setQuestion($question="")
Sets the question string of the question object.
removeCurrentSolution($active_id, $pass, $authorized=true)
setTestId($id=-1)
Sets the test id of the assQuestion object.
ensureCurrentTestPass($active_id, $pass)
prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
deleteSolutionRecordByValues($activeId, $passIndex, $authorized, $matchValues)
$testQuestionConfigInstance
getTestPresentationConfig()
Get the test question configuration (initialised once)
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
Creates an Excel worksheet for the detailed cumulated results of this question.
buildImagePath($questionId, $parentObjectId)
getRequestStatisticData()
removeExistingSolutions($activeId, $pass)
setOriginalId($original_id)
static getResultGateway()
setLastChange($lastChange)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
getAnswerTableName()
Returns the name of the answer table in the database.
static _deleteAllLinksOfSource($a_source_type, $a_source_id, $a_lang="-")
Delete all links of a given source.
static buildExamId($active_id, $pass, $test_obj_id=null)
removeIntermediateSolution($active_id, $pass)
getReachedPoints($active_id, $pass=null)
Returns the points, a learner has reached answering the question This is the fast way to get the poin...
$selfassessmenteditingmode
static getGuiClassNameByQuestionType($questionType)
getTitle()
Gets the title string of the assQuestion object.
static _cleanupMediaObjectUsage($a_text, $a_usage_type, $a_usage_id)
Synchronises appearances of media objects in $a_text with media object usage table.
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
getAdjustedReachedPoints($active_id, $pass=null, $authorizedSolution=true)
returns the reached points ...
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
deleteTaxonomyAssignments()
addQuestionChangeListener(ilQuestionChangeListener $listener)
static isHTML($a_text)
Checks if a given string contains HTML or not.
static fetchMimeTypeIdentifier($contentTypeString)
if(empty($password)) $table
$obligationsToBeConsidered
static _getReachedPoints($active_id, $question_id, $pass=null)
Returns the points, a learner has reached answering the question.
pcArrayShuffle($array)
Shuffles the values of a given array.
duplicateSuggestedSolutionFiles($parent_id, $question_id)
Duplicates the files of a suggested solution if the question is duplicated.
static _saveLink( $a_source_type, $a_source_id, $a_target_type, $a_target_id, $a_target_inst=0, $a_source_lang="-")
save internal link information
getOutputType()
Gets the output type.
onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $targetQuestionId)
Will be called when a question is copied (into another question pool)
getSuggestedSolutions()
Return the suggested solutions.
getHtmlQuestionContentPurifier()
static $allowedImageMaterialFileExtensionsByMimeType
_resolveInternalLink($internal_link)
setTitle($title="")
Sets the title string of the assQuestion object.
fixUnavailableSkinImageSources($html)
setObjId($obj_id=0)
Set the object id of the container object.
getActiveUserData($active_id)
Returns the user id and the test id for a given active id.
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
setExportImagePath($a_path)
setComment($comment="")
Sets the comment string of the assQuestion object.
setShuffler(ilArrayElementShuffler $shuffler)
static $allowedFileExtensionsByMimeType
static getFeedbackClassNameByQuestionType($questionType)
static _getQuestionTitle($question_id)
Returns the question title of a question with a given id.
static getKeyValuesImplosionSeparator()
static _setReachedPoints($active_id, $question_id, $points, $maxpoints, $pass, $manualscoring, $obligationsEnabled)
Sets the points, a learner has reached answering the question Additionally objective results are upda...
static _getTitle($a_q_id)
Returns the title of a question.
static instantiateQuestionGUI($a_question_id)
Creates an instance of a question gui with a given question id.
keyInArray($searchkey, $array)
returns TRUE if the key occurs in an array
QTIMaterialToString($a_material)
Reads an QTI material tag an creates a text string.
getSuggestedSolutionOutput()
getSelfAssessmentFormatter()
isNonEmptyItemListPostSubmission($postSubmissionFieldname)
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
setSelfAssessmentEditingMode($a_selfassessmenteditingmode)
Set Self-Assessment Editing Mode.
static missingResultRecordExists($activeId, $pass, $questionIds)
getSolutionRecordById($solutionId)
getPreventRteUsage()
Get prevent rte usage.
static _isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.
static getAllowedFileExtensionsForMimeType($mimeType)