4include_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')
283 'image/jpeg' => array(
'jpg',
'jpeg'),
'image/png' => array(
'png'),
'image/gif' => array(
'gif')
317 $this->original_id =
null;
323 if (!$this->author) {
324 $this->author = $this->
ilias->account->fullname;
327 if ($this->owner <= 0) {
328 $this->owner = $this->
ilias->account->id;
332 $this->suggested_solutions = array();
334 $this->nr_of_tries = 0;
336 $this->arrData = array();
339 $this->questionActionCmd =
'handleQuestionAction';
341 $this->lastChange =
null;
343 require_once
'Services/Randomization/classes/class.ilArrayElementOrderKeeper.php';
363 return (
bool) count(self::getAllowedFileExtensionsForMimeType($mimeType));
368 return current(explode(
';', $contentTypeString));
373 foreach (self::$allowedFileExtensionsByMimeType as $allowedMimeType => $extensions) {
374 $rexCharsets = implode(
'|', self::$allowedCharsetsByMimeType[$allowedMimeType]);
375 $rexMimeType = preg_quote($allowedMimeType,
'/');
377 $rex =
'/^' . $rexMimeType .
'(;(\s)*charset=(' . $rexCharsets .
'))*$/';
379 if (!preg_match($rex, $mimeType)) {
392 strtolower($fileExtension),
393 self::getAllowedFileExtensionsForMimeType($mimeType)
404 if (!isset(
$_POST[
'cmd']) || !isset(
$_POST[
'cmd'][$this->questionActionCmd])) {
408 if (!is_array(
$_POST[
'cmd'][$this->questionActionCmd]) || !count(
$_POST[
'cmd'][$this->questionActionCmd])) {
412 return key(
$_POST[
'cmd'][$this->questionActionCmd]);
421 if (!isset(
$_POST[$postSubmissionFieldname])) {
425 if (!is_array(
$_POST[$postSubmissionFieldname])) {
429 if (!count(
$_POST[$postSubmissionFieldname])) {
457 require_once
'Modules/Test/classes/class.ilObjTest.php';
471 "SELECT test_fi FROM tst_active WHERE active_id = %s",
477 return $row[
"test_fi"];
488 protected function log($active_id, $langVar)
501 $extensions = array();
503 foreach (self::$allowedImageMaterialFileExtensionsByMimeType as $mimeType => $mimeExtensions) {
504 $extensions = array_merge($extensions, $mimeExtensions);
506 return array_unique($extensions);
559 array $solutionhints = []
561 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class." . $this->
getQuestionType() .
"Import.php";
563 $import =
new $classname($this);
564 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
566 foreach ($solutionhints as $hint) {
568 $h->setQuestionId($import->getQuestionId());
569 $h->setIndex($hint[
'index']);
570 $h->setPoints($hint[
'points']);
571 $h->setText($hint[
'txt']);
582 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
584 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class." . $this->
getQuestionType() .
"Export.php";
586 $export =
new $classname($this);
587 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
614 "SELECT * FROM qpl_questions WHERE obj_fi = %s AND title = %s",
615 array(
'integer',
'text'),
616 array($questionpool_id,
$title)
654 $this->test_id =
$id;
710 $this->est_working_time = array(
"h" => (
int) $hour,
"m" => (
int) $min,
"s" => (
int) $sec);
721 $this->est_working_time = array(
722 'h' => (
int) substr($durationString, 0, 2),
723 'm' => (
int) substr($durationString, 3, 2),
724 's' => (
int) substr($durationString, 6, 2)
738 foreach ($array as $key => $value) {
739 if (strcmp($key, $searchkey) == 0) {
793 require_once
'Services/Utilities/classes/class.ilUtil.php';
859 return $this->refinery->string()->stripTags()->transform($this->
comment ??
'');
892 if (!$this->est_working_time) {
893 $this->est_working_time = array(
"h" => 0,
"m" => 0,
"s" => 0);
912 return $this->refinery->string()->stripTags()->transform($this->author);
980 if (!strlen($this->external_id)) {
981 if ($this->
getId() > 0) {
984 return uniqid(
'',
true);
1004 "SELECT points FROM qpl_questions WHERE question_id = %s",
1008 if (
$result->numRows() == 1) {
1027 "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",
1050 "SELECT suggested_solution_id FROM qpl_sol_sug WHERE question_fi = %s",
1069 return $question->getSuggestedSolutionOutput();
1075 foreach ($this->suggested_solutions as $solution) {
1076 switch ($solution[
"type"]) {
1084 $possible_texts = array_values(array_filter(array(
1087 $this->lng->txt(
'tst_show_solution_suggested')
1090 require_once
'Services/WebAccessChecker/classes/class.ilWACSignedPath.php';
1095 $solutionValue = $solution[
"value"];
1096 $solutionValue = $this->
fixSvgToPng($solutionValue);
1102 return join(
"<br />", $output);
1119 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
1120 array(
'integer',
'integer'),
1121 array($question_id, $subquestion_index)
1123 if (
$result->numRows() == 1) {
1126 "internal_link" => $row[
"internal_link"],
1127 "import_id" => $row[
"import_id"]
1157 if (is_null(
$pass)) {
1158 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
1162 "SELECT * FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1163 array(
'integer',
'integer',
'integer'),
1164 array($active_id, $question_id,
$pass)
1166 if (
$result->numRows() == 1) {
1183 return round(self::_getReachedPoints($active_id, $this->
getId(),
$pass), 2);
1210 if (is_null(
$pass)) {
1211 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1221 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
1223 $requestsStatisticData = $hintTracking->getRequestStatisticDataByQuestionAndTestpass();
1224 $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
1229 return $reached_points;
1247 if (is_null(
$pass)) {
1248 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1256 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
1258 $requestsStatisticData = $questionHintTracking->getRequestStatisticDataByQuestionAndTestpass();
1259 $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
1270 if (is_null($reached_points)) {
1271 $reached_points = 0;
1275 $existingSolutions = $this->lookupForExistingSolutions($active_id,
$pass);
1277 $this->
getProcessLocker()->executeUserQuestionResultUpdateOperation(
function () use (
$ilDB, $active_id,
$pass, $reached_points, $requestsStatisticData, $isAnswered, $existingSolutions) {
1279 DELETE FROM tst_test_result
1281 WHERE active_fi = %s
1282 AND question_fi = %s
1286 $types = array(
'integer',
'integer',
'integer');
1287 $values = array($active_id, $this->
getId(),
$pass);
1289 if ($this->
getStep() !==
null) {
1294 $types[] =
'integer';
1299 if ($existingSolutions[
'authorized']) {
1300 $next_id =
$ilDB->nextId(
"tst_test_result");
1302 'test_result_id' => array(
'integer', $next_id),
1303 'active_fi' => array(
'integer', $active_id),
1304 'question_fi' => array(
'integer', $this->
getId()),
1305 'pass' => array(
'integer',
$pass),
1306 'points' => array(
'float', $reached_points),
1307 'tstamp' => array(
'integer', time()),
1308 'hint_count' => array(
'integer', $requestsStatisticData->getRequestsCount()),
1309 'hint_points' => array(
'float', $requestsStatisticData->getRequestsPoints()),
1310 'answered' => array(
'integer', $isAnswered)
1313 if ($this->
getStep() !==
null) {
1314 $fieldData[
'step'] = array(
'integer', $this->
getStep());
1317 $ilDB->insert(
'tst_test_result', $fieldData);
1322 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1329 "log_user_answered_question",
1343 include_once
'Modules/Course/classes/class.ilCourseObjectiveResult.php';
1361 $saveStatus =
false;
1363 $this->
getProcessLocker()->executePersistWorkingStateLockOperation(
function () use ($active_id,
$pass, $authorized, $obligationsEnabled, &$saveStatus) {
1364 if (
$pass ===
null) {
1365 require_once
'Modules/Test/classes/class.ilObjTest.php';
1419 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1420 include_once
"./Modules/Test/classes/class.assMarkSchema.php";
1424 if (
$pass !==
null) {
1426 SELECT tst_pass_result.*
1427 FROM tst_pass_result
1428 WHERE active_fi = %s
1434 array(
'integer',
'integer'),
1435 array($active_id,
$pass)
1440 $max = $row_result[
'maxpoints'];
1441 $reached = $row_result[
'points'];
1443 $obligationsAnswered = (int) $row_result[
'obligations_answered'];
1445 include_once
"./Modules/Test/classes/class.assMarkSchema.php";
1447 $percentage = (!$max) ? 0 : ($reached / $max) * 100.0;
1449 $mark = ASS_MarkSchema::_getMatchingMarkFromActiveId($active_id, $percentage);
1451 $isPassed = ($mark[
"passed"] ? 1 : 0);
1452 $isFailed = (!$mark[
"passed"] ? 1 : 0);
1454 $userTestResultUpdateCallback =
function () use (
1462 $obligationsAnswered,
1466 $passedOnceBefore = 0;
1467 $query =
"SELECT passed_once FROM tst_result_cache WHERE active_fi = %s";
1469 while ($row =
$ilDB->fetchAssoc(
$res)) {
1470 $passedOnceBefore = (int) $row[
'passed_once'];
1473 $passedOnce = (int) ($isPassed || $passedOnceBefore);
1476 "DELETE FROM tst_result_cache WHERE active_fi = %s",
1481 $ilDB->insert(
'tst_result_cache', array(
1482 'active_fi' => array(
'integer', $active_id),
1483 'pass' => array(
'integer', strlen(
$pass) ?
$pass : 0),
1484 'max_points' => array(
'float', strlen($max) ? $max : 0),
1485 'reached_points' => array(
'float', strlen($reached) ? $reached : 0),
1486 'mark_short' => array(
'text', strlen($mark[
"short_name"]) ? $mark[
"short_name"] :
" "),
1487 'mark_official' => array(
'text', strlen($mark[
"official_name"]) ? $mark[
"official_name"] :
" "),
1488 'passed_once' => array(
'integer', $passedOnce),
1489 'passed' => array(
'integer', $isPassed),
1490 'failed' => array(
'integer', $isFailed),
1491 'tstamp' => array(
'integer', time()),
1492 'hint_count' => array(
'integer', $row_result[
'hint_count']),
1493 'hint_points' => array(
'float', $row_result[
'hint_points']),
1494 'obligations_answered' => array(
'integer', $obligationsAnswered)
1499 $processLocker->executeUserTestResultUpdateLockOperation($userTestResultUpdateCallback);
1501 $userTestResultUpdateCallback();
1512 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1514 if (self::getResultGateway() !==
null) {
1527 SELECT SUM(points) reachedpoints,
1528 SUM(hint_count) hint_count,
1529 SUM(hint_points) hint_points,
1530 COUNT(DISTINCT(question_fi)) answeredquestions
1531 FROM tst_test_result
1532 WHERE active_fi = %s
1535 array(
'integer',
'integer'),
1536 array($active_id,
$pass)
1540 if ($obligationsEnabled) {
1542 SELECT answered answ
1543 FROM tst_test_question
1544 INNER JOIN tst_active
1546 AND tst_test_question.test_fi = tst_active.test_fi
1547 LEFT JOIN tst_test_result
1548 ON tst_test_result.active_fi = %s
1549 AND tst_test_result.pass = %s
1550 AND tst_test_question.question_fi = tst_test_result.question_fi
1551 WHERE obligatory = 1';
1553 $result_obligatory =
$ilDB->queryF(
1555 array(
'integer',
'integer',
'integer'),
1556 array($active_id, $active_id,
$pass)
1559 $obligations_answered = 1;
1561 while ($row_obligatory =
$ilDB->fetchAssoc($result_obligatory)) {
1562 if (!(
int) $row_obligatory[
'answ']) {
1563 $obligations_answered = 0;
1568 $obligations_answered = 1;
1573 if ($row[
'reachedpoints'] ===
null) {
1574 $row[
'reachedpoints'] = 0;
1576 if ($row[
'hint_count'] ===
null) {
1577 $row[
'hint_count'] = 0;
1579 if ($row[
'hint_points'] ===
null) {
1580 $row[
'hint_points'] = 0;
1585 $updatePassResultCallback =
function () use (
$ilDB,
$data, $active_id,
$pass, $row, $time, $obligations_answered, $exam_identifier) {
1591 'active_fi' => array(
'integer', $active_id),
1592 'pass' => array(
'integer', strlen(
$pass) ?
$pass : 0)),
1594 'points' => array(
'float', $row[
'reachedpoints'] ? $row[
'reachedpoints'] : 0),
1595 'maxpoints' => array(
'float',
$data[
'points']),
1596 'questioncount' => array(
'integer',
$data[
'count']),
1597 'answeredquestions' => array(
'integer', $row[
'answeredquestions']),
1598 'workingtime' => array(
'integer', $time),
1599 'tstamp' => array(
'integer', time()),
1600 'hint_count' => array(
'integer', $row[
'hint_count']),
1601 'hint_points' => array(
'float', $row[
'hint_points']),
1602 'obligations_answered' => array(
'integer', $obligations_answered),
1603 'exam_id' => array(
'text', $exam_identifier)
1609 $processLocker->executeUserPassResultUpdateLockOperation($updatePassResultCallback);
1611 $updatePassResultCallback();
1618 'active_fi' => $active_id,
1620 'points' => ($row[
"reachedpoints"]) ? $row[
"reachedpoints"] : 0,
1621 'maxpoints' =>
$data[
"points"],
1622 'questioncount' =>
$data[
"count"],
1623 'answeredquestions' => $row[
"answeredquestions"],
1624 'workingtime' => $time,
1626 'hint_count' => $row[
'hint_count'],
1627 'hint_points' => $row[
'hint_points'],
1628 'obligations_answered' => $obligations_answered,
1629 'exam_id' => $exam_identifier
1640 public static function logAction($logtext =
"", $active_id =
"", $question_id =
"")
1643 if (strlen($question_id)) {
1647 require_once
'Modules/Test/classes/class.ilObjAssessmentFolder.php';
1648 require_once
'Modules/Test/classes/class.ilObjTest.php';
1669 if (!@is_dir($mediatempdir)) {
1672 $temp_name = tempnam($mediatempdir,
$name .
"_____");
1673 $temp_name = str_replace(
"\\",
"/", $temp_name);
1674 @unlink($temp_name);
1689 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/solution/";
1700 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/java/";
1711 if ($question_id ===
null) {
1715 if ($object_id ===
null) {
1724 return CLIENT_WEB_DIR .
"/assessment/{$parentObjectId}/{$questionId}/images/";
1735 return CLIENT_WEB_DIR .
"/assessment/$this->obj_id/$this->id/flash/";
1746 $relative_path =
"assessment/$this->obj_id/$this->id/java/";
1757 $relative_path =
"assessment/$this->obj_id/$this->id/solution/";
1771 if (!$this->export_image_path) {
1772 $relative_path =
"assessment/$this->obj_id/$this->id/images/";
1787 $relative_path =
"assessment/$this->obj_id/$this->id/flash/";
1808 if (!count($solution)) {
1823 if (is_null(
$pass)) {
1827 if ($this->
getStep() !==
null) {
1831 WHERE active_fi = %s
1832 AND question_fi = %s
1836 ORDER BY solution_id";
1840 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
1841 array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
1847 WHERE active_fi = %s
1848 AND question_fi = %s
1851 ORDER BY solution_id
1856 array(
'integer',
'integer',
'integer',
'integer'),
1857 array($active_id, $this->
getId(), $pass, (
int) $authorized)
1881 if ($question_id < 1) {
1882 $question_id = $this->
getId();
1885 "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",
1890 $count = $row[
"question_count"];
1894 SELECT tst_active.test_fi
1896 INNER JOIN tst_test_rnd_qst ON tst_test_rnd_qst.question_fi = qpl_questions.question_id
1897 INNER JOIN tst_active ON tst_active.active_id = tst_test_rnd_qst.active_fi
1898 WHERE qpl_questions.original_id = %s
1899 GROUP BY tst_active.test_fi",
1919 if ($question_id < 1) {
1923 "SELECT original_id FROM qpl_questions WHERE question_id = %s",
1928 return ($row[
"original_id"] > 0) ?
true :
false;
1939 $keys = array_keys($array);
1942 foreach (
$keys as $key) {
1959 "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",
1964 return $data[
"type_tag"];
2001 if (!is_array($answer_table_name)) {
2002 $answer_table_name = array($answer_table_name);
2005 foreach ($answer_table_name as $table) {
2006 if (strlen($table)) {
2007 $affectedRows =
$ilDB->manipulateF(
2008 "DELETE FROM $table WHERE question_fi = %s",
2029 if (!is_array($additional_table_name)) {
2030 $additional_table_name = array($additional_table_name);
2033 foreach ($additional_table_name as $table) {
2034 if (strlen($table)) {
2035 $affectedRows =
$ilDB->manipulateF(
2036 "DELETE FROM $table WHERE question_fi = %s",
2052 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2064 public function delete($question_id)
2068 $ilLog =
$DIC[
'ilLog'];
2070 if ($question_id < 1) {
2075 "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
2079 if (
$result->numRows() == 1) {
2087 }
catch (Exception
$e) {
2088 $ilLog->write(
"EXCEPTION: Could not delete page of question $question_id: $e");
2092 $affectedRows =
$ilDB->manipulateF(
2093 "DELETE FROM qpl_questions WHERE question_id = %s",
2097 if ($affectedRows == 0) {
2106 }
catch (Exception
$e) {
2107 $ilLog->write(
"EXCEPTION: Could not delete additional table data of question $question_id: $e");
2113 $affectedRows =
$ilDB->manipulateF(
2114 "DELETE FROM tst_test_question WHERE question_fi = %s",
2118 }
catch (Exception
$e) {
2119 $ilLog->write(
"EXCEPTION: Could not delete delete question $question_id from a test: $e");
2125 $affectedRows =
$ilDB->manipulateF(
2126 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2130 }
catch (Exception
$e) {
2131 $ilLog->write(
"EXCEPTION: Could not delete suggested solutions of question $question_id: $e");
2137 if (preg_match(
"/\d+/",
$obj_id) and preg_match(
"/\d+/", $question_id) and is_dir($directory)) {
2138 include_once
"./Services/Utilities/classes/class.ilUtil.php";
2141 }
catch (Exception
$e) {
2142 $ilLog->write(
"EXCEPTION: Could not delete question file directory $directory of question $question_id: $e");
2147 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2153 foreach (
$mobs as $mob) {
2160 }
catch (Exception
$e) {
2161 $ilLog->write(
"EXCEPTION: Error deleting the media objects of question $question_id: $e");
2165 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
2166 ilAssQuestionHintTracking::deleteRequestsByQuestionIds(array($question_id));
2168 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
2171 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
2173 $assignmentList->setParentObjId(
$obj_id);
2174 $assignmentList->setQuestionIdFilter($question_id);
2175 $assignmentList->loadFromDb();
2176 foreach ($assignmentList->getAssignmentsByQuestionId($question_id) as $assignment) {
2178 $assignment->deleteFromDb();
2185 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
2187 }
catch (Exception
$e) {
2188 $ilLog->write(
"EXCEPTION: Error updating the question pool question count of question pool " . $this->
getObjId() .
" when deleting question $question_id: $e");
2199 require_once
'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
2200 require_once
'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
2203 foreach ($taxIds as $taxId) {
2205 $taxNodeAssignment->deleteAssignmentsOfItem($this->
getId());
2230 "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
2231 array(
'integer',
'integer'),
2232 array($a_q_id, $a_q_id)
2234 if (
$result->numRows() == 0) {
2237 $found_id = array();
2239 array_push($found_id, $row[
"question_id"]);
2242 $result =
$ilDB->query(
"SELECT * FROM tst_test_result WHERE " .
$ilDB->in(
'question_fi', $found_id,
false,
'integer'));
2259 "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
2260 array(
'integer',
'integer'),
2261 array($a_q_id, $a_q_id)
2263 if (
$result->numRows() == 0) {
2266 $found_id = array();
2268 array_push($found_id, $row[
"question_id"]);
2270 $result =
$ilDB->query(
"SELECT * FROM tst_test_result WHERE " .
$ilDB->in(
'question_fi', $found_id,
false,
'integer'));
2273 $reached = $row[
"points"];
2274 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
2276 array_push($answers, array(
"reached" => $reached,
"max" => $max));
2280 foreach ($answers as $key => $value) {
2281 $max += $value[
"max"];
2282 $reached += $value[
"reached"];
2285 return $reached / $max;
2301 "SELECT title FROM qpl_questions WHERE question_id = %s",
2305 if (
$result->numRows() == 1) {
2307 return $row[
"title"];
2323 "SELECT question_text FROM qpl_questions WHERE question_id = %s",
2327 if (
$result->numRows() == 1) {
2329 return $row[
"question_text"];
2337 if (!file_exists($file)) {
2341 if (!is_file($file)) {
2345 if (!is_readable($file)) {
2354 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2356 foreach (
$mobs as $mob) {
2363 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
2365 foreach (
$mobs as $mob) {
2377 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2379 $this->page->setId($this->
getId());
2380 $this->page->setParentId($qpl_id);
2381 $this->page->setXMLContent(
"<PageObject><PageContent>" .
2382 "<Question QRef=\"il__qst_" . $this->
getId() .
"\"/>" .
2383 "</PageContent></PageObject>");
2384 $this->page->create();
2390 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2393 $xml = str_replace(
"il__qst_" . $a_q_id,
"il__qst_" . $this->
id,
$page->getXMLContent());
2394 $this->page->setXMLContent(
$xml);
2395 $this->page->updateFromXML();
2401 include_once
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
2403 return $page->getXMLContent();
2416 if ($question_id < 1) {
2420 "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",
2424 if (
$result->numRows() == 1) {
2426 return $data[
"type_tag"];
2444 if ($question_id < 1) {
2449 "SELECT title FROM qpl_questions WHERE qpl_questions.question_id = %s",
2453 if (
$result->numRows() == 1) {
2455 return $data[
"title"];
2472 'ok.svg' =>
'ok.png',
'not_ok.svg' =>
'not_ok.png',
2473 'checkbox_checked.svg' =>
'checkbox_checked.png',
2474 'checkbox_unchecked.svg' =>
'checkbox_unchecked.png',
2475 'radiobutton_checked.svg' =>
'radiobutton_checked.png',
2476 'radiobutton_unchecked.svg' =>
'radiobutton_unchecked.png'
2481 $needles = array_keys(self::$imageSourceFixReplaceMap);
2482 $replacements = array_values(self::$imageSourceFixReplaceMap);
2483 return str_replace($needles, $replacements, $imageFilenameContainingString);
2490 if (preg_match_all(
'/src="(.*?)"/m', $html, $matches)) {
2491 $sources = $matches[1];
2493 $needleReplacementMap = array();
2495 foreach ($sources as $src) {
2498 if (file_exists($file)) {
2502 $levels = explode(DIRECTORY_SEPARATOR, $src);
2503 if (count($levels) < 5 || $levels[0] !=
'Customizing' || $levels[2] !=
'skin') {
2509 if ($levels[4] ==
'Modules' || $levels[4] ==
'Services') {
2510 $component = $levels[4] . DIRECTORY_SEPARATOR . $levels[5];
2516 if (count($needleReplacementMap)) {
2517 $html = str_replace(array_keys($needleReplacementMap), array_values($needleReplacementMap), $html);
2536 "SELECT external_id FROM qpl_questions WHERE question_id = %s",
2540 if (
$result->numRows() == 1) {
2542 $this->external_id =
$data[
'external_id'];
2546 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
2548 array($this->
getId())
2550 $this->suggested_solutions = array();
2552 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2555 $this->suggested_solutions[$row[
"subquestion_index"]] = array(
2556 "type" => $row[
"type"],
2558 "internal_link" => $row[
"internal_link"],
2559 "import_id" => $row[
"import_id"]
2579 $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
2582 if ($a_create_page) {
2589 $next_id =
$ilDB->nextId(
'qpl_questions');
2590 $affectedRows =
$ilDB->insert(
"qpl_questions", array(
2591 "question_id" => array(
"integer", $next_id),
2593 "obj_fi" => array(
"integer",
$obj_id),
2594 "title" => array(
"text",
null),
2595 "description" => array(
"text",
null),
2596 "author" => array(
"text", $this->
getAuthor()),
2597 "owner" => array(
"integer",
$ilUser->getId()),
2598 "question_text" => array(
"clob",
null),
2599 "points" => array(
"float", 0),
2601 "working_time" => array(
"text", $estw_time),
2602 "complete" => array(
"text", $complete),
2603 "created" => array(
"integer", time()),
2604 "original_id" => array(
"integer",
null),
2605 "tstamp" => array(
"integer", $tstamp),
2609 $this->
setId($next_id);
2611 if ($a_create_page) {
2619 return $this->
getId();
2628 $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
2631 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2632 if ($this->
getId() == -1) {
2634 $next_id =
$ilDB->nextId(
'qpl_questions');
2635 $affectedRows =
$ilDB->insert(
"qpl_questions", array(
2636 "question_id" => array(
"integer", $next_id),
2638 "obj_fi" => array(
"integer", $this->
getObjId()),
2639 "title" => array(
"text", $this->
getTitle()),
2640 "description" => array(
"text", $this->
getComment()),
2641 "author" => array(
"text", $this->
getAuthor()),
2642 "owner" => array(
"integer", $this->
getOwner()),
2645 "working_time" => array(
"text", $estw_time),
2646 "nr_of_tries" => array(
"integer", $this->
getNrOfTries()),
2647 "created" => array(
"integer", time()),
2649 "tstamp" => array(
"integer", time()),
2653 $this->
setId($next_id);
2658 $affectedRows =
$ilDB->update(
"qpl_questions", array(
2659 "obj_fi" => array(
"integer", $this->
getObjId()),
2660 "title" => array(
"text", $this->
getTitle()),
2661 "description" => array(
"text", $this->
getComment()),
2662 "author" => array(
"text", $this->
getAuthor()),
2665 "nr_of_tries" => array(
"integer", $this->
getNrOfTries()),
2666 "working_time" => array(
"text", $estw_time),
2667 "tstamp" => array(
"integer", time()),
2668 'complete' => array(
'integer', $this->
isComplete()),
2671 "question_id" => array(
"integer", $this->
getId())
2686 $this->updateSuggestedSolutions();
2696 $DIC->database()->update(
'qpl_questions', array(
2697 'tstamp' => array(
'integer', time()),
2698 'owner' => array(
'integer', ($this->
getOwner() <= 0 ? $this->
ilias->account->id : $this->getOwner())),
2699 'complete' => array(
'integer', $complete),
2700 'lifecycle' => array(
'text', $this->
getLifecycle()->getIdentifier()),
2702 'question_id' => array(
'integer', $this->
getId())
2706 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
2722 $query =
"UPDATE qpl_questions SET tstamp = %s, original_id = %s WHERE question_id = %s";
2724 $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
2726 array(
'integer',
'integer',
'text'),
2727 array(time(), $originalId, $questionId)
2733 $query =
"UPDATE qpl_questions SET tstamp = %s, original_id = NULL WHERE question_id = %s";
2735 $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
2737 array(
'integer',
'text'),
2738 array(time(), $questionId)
2745 protected function onDuplicate($originalParentId, $originalQuestionId, $duplicateParentId, $duplicateQuestionId)
2750 $this->feedbackOBJ->duplicateFeedback($originalQuestionId, $duplicateQuestionId);
2766 $this->feedbackOBJ->syncFeedback($origQuestionId, $dupQuestionId);
2772 protected function onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $targetQuestionId)
2777 $this->feedbackOBJ->duplicateFeedback($sourceQuestionId, $targetQuestionId);
2794 $affectedRows =
$ilDB->manipulateF(
2795 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2797 array($this->
getId())
2800 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2802 $this->suggested_solutions = array();
2815 if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
2816 return $this->suggested_solutions[$subquestion_index];
2832 if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
2833 $title = $this->suggested_solutions[$subquestion_index][
"internal_link"];
2852 if (strcmp($solution_id,
"") != 0) {
2855 $import_id = $solution_id;
2858 $this->suggested_solutions[$subquestion_index] = array(
2859 "internal_link" => $solution_id,
2860 "import_id" => $import_id
2871 $ilLog =
$DIC[
'ilLog'];
2873 foreach ($this->suggested_solutions as
$index => $solution) {
2874 if (strcmp($solution[
"type"],
"file") == 0) {
2876 $filepath_original = str_replace(
2877 "/{$this->obj_id}/{$this->id}/solution",
2878 "/$parent_id/$question_id/solution",
2881 if (!file_exists($filepath)) {
2887 $ilLog->write(
"File could not be duplicated!!!!", $ilLog->ERROR);
2888 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2901 $ilLog =
$DIC[
'ilLog'];
2904 $filepath_original = str_replace(
"/$this->id/solution",
"/$original_id/solution", $filepath);
2906 foreach ($this->suggested_solutions as
$index => $solution) {
2907 if (strcmp($solution[
"type"],
"file") == 0) {
2908 if (!file_exists($filepath_original)) {
2914 $ilLog->write(
"File could not be duplicated!!!!", $ilLog->ERROR);
2915 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2925 $ilLog =
$DIC[
'ilLog'];
2927 foreach ($this->suggested_solutions as
$index => $solution) {
2928 if (strcmp($solution[
"type"],
"file") == 0) {
2930 $filepath_original = str_replace(
"/$this->obj_id/$this->id/solution",
"/$source_questionpool_id/$source_question_id/solution", $filepath);
2931 if (!file_exists($filepath)) {
2937 $ilLog->write(
"File could not be copied!!!!", $ilLog->ERROR);
2938 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
2948 public function updateSuggestedSolutions(
$original_id =
"")
2954 include_once
"./Services/Link/classes/class.ilInternalLink.php";
2955 $affectedRows =
$ilDB->manipulateF(
2956 "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
2961 include_once(
"./Services/RTE/classes/class.ilRTE.php");
2962 foreach ($this->suggested_solutions as
$index => $solution) {
2963 $next_id =
$ilDB->nextId(
'qpl_sol_sug');
2968 'suggested_solution_id' => array(
'integer', $next_id ),
2969 'question_fi' => array(
'integer',
$id ),
2970 'type' => array(
'text', $solution[
'type'] ),
2972 'internal_link' => array(
'text', $solution[
'internal_link'] ),
2973 'import_id' => array(
'text',
null ),
2974 'subquestion_index' => array(
'integer',
$index ),
2975 'tstamp' => array(
'integer', time() ),
2978 if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/", $solution[
"internal_link"], $matches)) {
2997 public function saveSuggestedSolution(
$type, $solution_id =
"", $subquestion_index = 0, $value =
"")
3002 $affectedRows =
$ilDB->manipulateF(
3003 "DELETE FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
3004 array(
"integer",
"integer"),
3011 $next_id =
$ilDB->nextId(
'qpl_sol_sug');
3012 include_once(
"./Services/RTE/classes/class.ilRTE.php");
3014 $affectedRows =
$ilDB->insert(
3017 'suggested_solution_id' => array(
'integer', $next_id ),
3018 'question_fi' => array(
'integer', $this->
getId() ),
3019 'type' => array(
'text',
$type ),
3021 'internal_link' => array(
'text', $solution_id ),
3022 'import_id' => array(
'text',
null ),
3023 'subquestion_index' => array(
'integer', $subquestion_index ),
3024 'tstamp' => array(
'integer', time() ),
3027 if ($affectedRows == 1) {
3028 $this->suggested_solutions[$subquestion_index] = array(
3031 "internal_link" => $solution_id,
3040 if (preg_match(
"/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches)) {
3041 switch ($matches[2]) {
3058 if (strcmp($resolved_link,
"") == 0) {
3059 $resolved_link = $internal_link;
3062 $resolved_link = $internal_link;
3064 return $resolved_link;
3073 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
3079 $internal_link = $row[
"internal_link"];
3080 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
3082 if (strcmp($internal_link, $resolved_link) != 0) {
3084 $affectedRows =
$ilDB->manipulateF(
3085 "UPDATE qpl_sol_sug SET internal_link = %s WHERE suggested_solution_id = %s",
3086 array(
'text',
'integer'),
3087 array($resolved_link, $row[
"suggested_solution_id"])
3093 if ($resolvedlinks) {
3097 include_once
"./Services/Link/classes/class.ilInternalLink.php";
3101 "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
3107 if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/", $row[
"internal_link"], $matches)) {
3120 "lm" =>
"LearningModule",
3121 "pg" =>
"PageObject",
3122 "st" =>
"StructureObject",
3123 "git" =>
"GlossaryItem",
3124 "mob" =>
"MediaObject"
3127 if (preg_match(
"/il__(\w+)_(\d+)/", $target, $matches)) {
3128 $type = $matches[1];
3130 include_once
"./Services/Utilities/classes/class.ilUtil.php";
3131 switch ($linktypes[$matches[1]]) {
3132 case "LearningModule":
3136 case "StructureObject":
3139 case "GlossaryItem":
3143 $href =
"./ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[
$type] .
"&cmd=media&ref_id=" .
$_GET[
"ref_id"] .
"&mob_id=" .
$target_id;
3162 "SELECT * FROM qpl_questions WHERE question_id = %s",
3168 if ($row[
"original_id"] > 0) {
3169 return $row[
"original_id"];
3171 return $row[
"question_id"];
3184 SELECT COUNT(dupl.question_id) cnt
3185 FROM qpl_questions dupl
3186 INNER JOIN qpl_questions orig
3187 ON orig.question_id = dupl.original_id
3188 WHERE dupl.question_id = %s
3194 return $row[
'cnt'] > 0;
3208 if (!$originalObjId) {
3218 $this->
setId($original);
3232 $this->updateSuggestedSolutions($original);
3251 if ($question_id < 1) {
3256 "SELECT question_id FROM qpl_questions WHERE question_id = %s",
3260 if (
$result->numRows() == 1) {
3279 if ($question_id < 1) {
3284 "SELECT question_id FROM qpl_questions INNER JOIN object_data ON obj_fi = obj_id WHERE question_id = %s AND type = 'qpl'",
3288 if (
$result->numRows() == 1) {
3314 $ilCtrl =
$DIC[
'ilCtrl'];
3318 if (strcmp($question_id,
"") != 0) {
3320 if (!strlen($question_type)) {
3343 if (strcmp($this->points,
"") == 0) {
3359 $this->points = $a_points;
3392 "SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
3393 array(
'integer',
'integer'),
3394 array($active_id, $question_id)
3396 if (
$result->numRows() == 1) {
3398 return $row[
"maxpass"];
3417 if (($question_id < 1) || ($user_id < 1)) {
3422 "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
3426 if (
$result->numRows() == 1) {
3428 $qpl_object_id = $row[
"obj_fi"];
3429 include_once
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
3447 if ($question_id < 1) {
3451 "SELECT test_random_question_id FROM tst_test_rnd_qst WHERE question_fi = %s",
3476 $requestsStatisticData = $hintTracking->getRequestStatisticData();
3477 $reachedPoints = $reachedPoints - $requestsStatisticData->getRequestsPoints();
3479 return $reachedPoints;
3519 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3521 if ($count_system == 1) {
3527 if ($score_cutting == 0) {
3553 if (is_null(
$pass)) {
3554 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
3558 "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3559 array(
'integer',
'integer',
'integer'),
3560 array($active_id, $question_id,
$pass)
3582 "SELECT DISTINCT(question_fi) FROM tst_test_result JOIN tst_active " .
3583 "ON (active_id = active_fi) " .
3584 "WHERE " .
$ilDB->in(
'question_fi', $a_question_ids,
false,
'integer') .
3585 " AND user_fi = %s",
3589 return (
$res->numRows() == count($a_question_ids)) ?
true :
false;
3613 include_once
"./Services/Utilities/classes/class.ilUtil.php";
3627 for (
$i = 0;
$i < $a_material->getMaterialCount();
$i++) {
3628 $material = $a_material->getMaterial(
$i);
3629 if (strcmp($material[
"type"],
"mattext") == 0) {
3630 $result .= $material[
"material"]->getContent();
3632 if (strcmp($material[
"type"],
"matimage") == 0) {
3633 $matimage = $material[
"material"];
3634 if (preg_match(
"/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
3636 if (!is_array(
$_SESSION[
"import_mob_xhtml"])) {
3637 $_SESSION[
"import_mob_xhtml"] = array();
3639 array_push(
$_SESSION[
"import_mob_xhtml"], array(
"mob" => $matimage->getLabel(),
"uri" => $matimage->getUri()));
3654 public function addQTIMaterial(&$a_xml_writer, $a_material, $close_material_tag =
true, $add_mobs =
true)
3656 include_once
"./Services/RTE/classes/class.ilRTE.php";
3657 include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
3659 $a_xml_writer->xmlStartTag(
"material");
3661 "texttype" =>
"text/plain"
3663 if ($this->
isHTML($a_material)) {
3664 $attrs[
"texttype"] =
"text/xhtml";
3669 foreach (
$mobs as $mob) {
3670 $moblabel =
"il_" .
IL_INST_ID .
"_mob_" . $mob;
3671 if (strpos($a_material,
"mm_$mob") !==
false) {
3675 "label" => $moblabel,
3676 "uri" =>
"objects/" .
"il_" .
IL_INST_ID .
"_mob_" . $mob .
"/" . $mob_obj->getTitle()
3679 $a_xml_writer->xmlElement(
"matimage", $imgattrs,
null);
3683 if ($close_material_tag) {
3684 $a_xml_writer->xmlEndTag(
"material");
3692 if (preg_match(
"/.*\.(png|jpg|gif|jpeg)$/i", $plain_image_filename, $matches)) {
3693 $extension =
"." . $matches[1];
3697 $plain_image_filename = uniqid($plain_image_filename . microtime(
true));
3700 $hashed_filename = md5($plain_image_filename) . $extension;
3702 return $hashed_filename;
3721 $float_trafo =
$refinery->kindlyTo()->float();
3724 }
catch (
ILIAS\Refinery\ConstraintViolationException
$e) {
3729 if (is_null(
$pass)) {
3736 "SELECT points FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3737 array(
'integer',
'integer',
'integer'),
3738 array($active_id, $question_id,
$pass)
3740 $manual = ($manualscoring) ? 1 : 0;
3741 $rowsnum =
$result->numRows();
3744 $old_points = $row[
"points"];
3746 $affectedRows =
$ilDB->manipulateF(
3747 "UPDATE tst_test_result SET points = %s, manual = %s, tstamp = %s WHERE active_fi = %s AND question_fi = %s AND pass = %s",
3748 array(
'float',
'integer',
'integer',
'integer',
'integer',
'integer'),
3749 array(
$points, $manual, time(), $active_id, $question_id,
$pass)
3753 $next_id =
$ilDB->nextId(
'tst_test_result');
3754 $affectedRows =
$ilDB->manipulateF(
3755 "INSERT INTO tst_test_result (test_result_id, active_fi, question_fi, points, pass, manual, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
3756 array(
'integer',
'integer',
'integer',
'float',
'integer',
'integer',
'integer'),
3757 array($next_id, $active_id, $question_id,
$points,
$pass, $manual, time())
3761 if (self::isForcePassResultUpdateEnabled() || $old_points !=
$points || !$rowsnum) {
3762 assQuestion::_updateTestPassResults($active_id,
$pass, $obligationsEnabled);
3764 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3765 include_once
'./Modules/Course/classes/class.ilCourseObjectiveResult.php';
3768 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
3773 include_once
"./Modules/Test/classes/class.ilObjTestAccess.php";
3818 || !(
new ilSetting(
'advanced_editing'))->
get(
'advanced_editing_javascript_editor') ===
'tinymce') {
3819 $purified_content = nl2br($purified_content);
3849 "SELECT question_type_id FROM qpl_qst_type WHERE type_tag = %s",
3853 if (
$result->numRows() == 1) {
3855 return $row[
"question_type_id"];
3860 public function syncHints()
3867 "DELETE FROM qpl_hints WHERE qht_question_fi = %s",
3869 array($this->original_id)
3874 "SELECT * FROM qpl_hints WHERE qht_question_fi = %s",
3876 array($this->
getId())
3882 $next_id =
$ilDB->nextId(
'qpl_hints');
3887 'qht_hint_id' => array(
'integer', $next_id),
3888 'qht_question_fi' => array(
'integer', $this->original_id),
3889 'qht_hint_index' => array(
'integer', $row[
"qht_hint_index"]),
3890 'qht_hint_points' => array(
'integer', $row[
"qht_hint_points"]),
3891 'qht_hint_text' => array(
'text', $row[
"qht_hint_text"]),
3907 $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(),
false);
3908 $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(),
true);
3909 $collected .= $this->feedbackOBJ->getAllSpecificAnswerFeedbackContents($this->
getId());
3911 foreach ($this->suggested_solutions as $solution_array) {
3912 $collected .= $solution_array[
"value"];
3915 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
3917 foreach ($questionHintList as $questionHint) {
3919 $collected .= $questionHint->getText();
3932 include_once(
"./Services/RTE/classes/class.ilRTE.php");
3947 "SELECT question_id FROM qpl_questions WHERE original_id = %s",
3949 array($this->
getId())
3951 $instances = array();
3954 array_push($ids, $row[
"question_id"]);
3956 foreach ($ids as $question_id) {
3959 "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",
3968 "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",
3976 include_once
"./Modules/Test/classes/class.ilObjTest.php";
3977 foreach ($instances as $key => $value) {
3985 include_once
"./Modules/Test/classes/class.ilObjAssessmentFolder.php";
3988 if (in_array($questiontype, $scoring)) {
4007 "SELECT * FROM tst_active WHERE active_id = %s",
4013 return array(
"user_id" => $row[
"user_fi"],
"test_id" => $row[
"test_fi"]);
4028 if (self::isCoreQuestionType($question_type)) {
4037 return $questionType .
'GUI';
4042 return $questionType;
4047 return str_replace(
'ass',
'ilAss', $questionType) .
'Feedback';
4053 return file_exists(
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php");
4058 if ($withGuiClass) {
4060 require_once
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php";
4065 require_once
"Modules/TestQuestionPool/classes/class.{$objectClassName}.php";
4069 require_once
"Modules/TestQuestionPool/classes/feedback/class.{$feedbackClassName}.php";
4075 $ilPluginAdmin =
$DIC[
'ilPluginAdmin'];
4078 self::getObjectClassNameByQuestionType($questionType),
4079 self::getFeedbackClassNameByQuestionType($questionType)
4082 if ($withGuiClass) {
4086 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE,
"TestQuestionPool",
"qst");
4087 foreach ($pl_names as $pl_name) {
4089 if (strcmp($pl->getQuestionType(), $questionType) == 0) {
4090 foreach ($classes as $class) {
4091 $pl->includeClass(
"class.{$class}.php");
4107 if (file_exists(
"./Modules/TestQuestionPool/classes/class." . $type_tag .
".php")) {
4110 return $lng->txt($type_tag);
4113 $ilPluginAdmin =
$DIC[
'ilPluginAdmin'];
4114 $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE,
"TestQuestionPool",
"qst");
4115 foreach ($pl_names as $pl_name) {
4117 if (strcmp($pl->getQuestionType(), $type_tag) == 0) {
4118 return $pl->getQuestionTypeTranslation();
4149 $ilCtrl =
$DIC[
'ilCtrl'];
4154 if (strcmp($a_question_id,
"") != 0) {
4160 $question_gui =
new $question_type_gui();
4161 $question_gui->object->loadFromDb($a_question_id);
4164 $question_gui->object->feedbackOBJ =
new $feedbackObjectClassname($question_gui->object, $ilCtrl,
$ilDB,
$lng);
4166 $assSettings =
new ilSetting(
'assessment');
4167 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
4169 $processLockerFactory->setQuestionId($question_gui->object->getId());
4170 $processLockerFactory->setUserId(
$ilUser->getId());
4171 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
4173 $question_gui->object->setProcessLocker($processLockerFactory->getLocker());
4176 $ilLog =
$DIC[
'ilLog'];
4177 $ilLog->write(
'Instantiate question called without question id. (instantiateQuestionGUI@assQuestion)', $ilLog->WARNING);
4180 return $question_gui;
4195 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord(0) . $startrow, $this->lng->txt($this->getQuestionType()));
4196 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord(1) . $startrow, $this->getTitle());
4208 return $this->
getId();
4228 case "est_working_time":
4252 case "suggested_solutions":
4259 if (array_key_exists($value, $this->arrData)) {
4260 return $this->arrData[$value];
4275 $this->
setId($value);
4295 case "est_working_time":
4296 if (is_array($value)) {
4316 $this->page = &$value;
4319 $this->arrData[$key] = $value;
4331 $this->nr_of_tries = $a_nr_of_tries;
4336 $this->export_image_path = (string) $a_path;
4344 if ($question_id < 1) {
4349 "SELECT question_fi FROM tst_test_question WHERE question_fi = %s AND test_fi = %s",
4350 array(
'integer',
'integer'),
4353 if (
$result->numRows() == 1) {
4376 require_once
'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
4377 return new \ilAssSelfAssessmentQuestionFormatter();
4389 $this->prevent_rte_usage = $a_val;
4411 $this->feedbackOBJ->migrateContentForLearningModule($migrator, $this->
getId());
4437 $this->selfassessmenteditingmode = $a_selfassessmenteditingmode;
4457 $this->defaultnroftries = $a_defaultnroftries;
4482 $query =
"SELECT obj_fi FROM qpl_questions WHERE question_id = %s";
4484 $res =
$ilDB->queryF(
$query, array(
'integer'), array((
int) $questionId));
4487 return $row[
'obj_fi'];
4507 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
4511 require_once
'Modules/TestQuestionPool/classes/class.ilAssHintPage.php';
4513 foreach ($hintIds as $originalHintId => $duplicateHintId) {
4515 $originalXML = $originalPageObject->getXMLContent();
4518 $duplicatePageObject->setId($duplicateHintId);
4519 $duplicatePageObject->setParentId($this->
getId());
4520 $duplicatePageObject->setXMLContent($originalXML);
4521 $duplicatePageObject->createFromXML();
4531 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
4533 $assignmentList->setParentObjId($srcParentId);
4534 $assignmentList->setQuestionIdFilter($srcQuestionId);
4535 $assignmentList->loadFromDb();
4537 foreach ($assignmentList->getAssignmentsByQuestionId($srcQuestionId) as $assignment) {
4540 $assignment->setParentObjId($trgParentId);
4541 $assignment->setQuestionId($trgQuestionId);
4542 $assignment->saveToDb();
4551 require_once
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
4553 $assignmentList->setParentObjId($trgParentId);
4554 $assignmentList->setQuestionIdFilter($trgQuestionId);
4555 $assignmentList->loadFromDb();
4557 foreach ($assignmentList->getAssignmentsByQuestionId($trgQuestionId) as $assignment) {
4560 $assignment->deleteFromDb();
4623 SELECT count(active_fi) cnt
4627 WHERE active_fi = %s
4628 AND question_fi = %s
4634 array(
'integer',
'integer',
'integer'),
4635 array($activeId, $questionId,
$pass)
4640 return (
int) $row[
'cnt'];
4663 require_once
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
4706 self::ADDITIONAL_CONTENT_EDITING_MODE_RTE,
4707 self::ADDITIONAL_CONTENT_EDITING_MODE_IPE
4716 $this->questionChangeListeners[] = $listener;
4730 $listener->notifyQuestionCreated($this);
4737 $listener->notifyQuestionEdited($this);
4744 $listener->notifyQuestionDeleted($this);
4753 require_once
'Services/Html/classes/class.ilHtmlPurifierFactory.php';
4765 SELECT qpl_questions.*,
4766 {$this->getAdditionalTableName()}.*
4768 LEFT JOIN {$this->getAdditionalTableName()}
4769 ON {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id
4770 WHERE qpl_questions.question_id = %s
4799 if ($this->
getStep() !==
null) {
4803 WHERE active_fi = %s
4804 AND question_fi = %s
4810 return $ilDB->queryF(
4812 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
4813 array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
4819 WHERE active_fi = %s
4820 AND question_fi = %s
4825 return $ilDB->queryF(
4827 array(
'integer',
'integer',
'integer',
'integer'),
4828 array($active_id, $this->
getId(), $pass, (
int) $authorized)
4844 return $ilDB->manipulateF(
4845 "DELETE FROM tst_solutions WHERE solution_id = %s",
4864 "SELECT * FROM tst_solutions WHERE solution_id = %s",
4869 while ($row =
$ilDB->fetchAssoc(
$res)) {
4885 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use ($active_id,
$pass) {
4903 if ($this->
getStep() !==
null) {
4905 DELETE FROM tst_solutions
4906 WHERE active_fi = %s
4907 AND question_fi = %s
4913 return $ilDB->manipulateF(
4915 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
4916 array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
4920 DELETE FROM tst_solutions
4921 WHERE active_fi = %s
4922 AND question_fi = %s
4927 return $ilDB->manipulateF(
4929 array(
'integer',
'integer',
'integer',
'integer'),
4930 array($active_id, $this->
getId(), $pass, (
int) $authorized)
4952 $next_id =
$ilDB->nextId(
"tst_solutions");
4955 "solution_id" => array(
"integer", $next_id),
4956 "active_fi" => array(
"integer", $active_id),
4957 "question_fi" => array(
"integer", $this->
getId()),
4958 "value1" => array(
"clob", $value1),
4959 "value2" => array(
"clob", $value2),
4960 "pass" => array(
"integer",
$pass),
4961 "tstamp" => array(
"integer", isset($tstamp) ? $tstamp : time()),
4962 'authorized' => array(
'integer', (
int) $authorized)
4965 if ($this->
getStep() !==
null) {
4966 $fieldData[
'step'] = array(
"integer", $this->
getStep());
4969 return $ilDB->insert(
"tst_solutions", $fieldData);
4989 "value1" => array(
"clob", $value1),
4990 "value2" => array(
"clob", $value2),
4991 "tstamp" => array(
"integer", time()),
4992 'authorized' => array(
'integer', (
int) $authorized)
4995 if ($this->
getStep() !==
null) {
4996 $fieldData[
'step'] = array(
"integer", $this->
getStep());
4999 return $ilDB->update(
"tst_solutions", $fieldData, array(
5000 'solution_id' => array(
'integer', $solutionId)
5011 'authorized' => array(
'integer', (
int) $authorized)
5015 $fieldData[
'tstamp'] = array(
'integer', time());
5019 'question_fi' => array(
'integer', $this->
getId()),
5020 'active_fi' => array(
'integer', $activeId),
5021 'pass' => array(
'integer',
$pass)
5024 if ($this->
getStep() !==
null) {
5025 $whereData[
'step'] = array(
"integer", $this->
getStep());
5028 return $ilDB->update(
'tst_solutions', $fieldData, $whereData);
5040 return implode(self::getKeyValuesImplosionSeparator(), $keyValues);
5044 return explode(self::getKeyValuesImplosionSeparator(), $keyValues);
5049 foreach ($this->
getSolutionValues($activeId, $passIndex,
false) as $solutionRec) {
5050 if (0 == strlen($solutionRec[
'value1']) && 0 == strlen($solutionRec[
'value2'])) {
5058 return !strlen($solutionRecord[
'value1']) && !strlen($solutionRecord[
'value2']);
5066 $types = array(
"integer",
"integer",
"integer",
"integer");
5067 $values = array($activeId, $this->
getId(), $passIndex, (
int) $authorized);
5068 $valuesCondition = array();
5070 foreach ($matchValues as $valueField => $value) {
5071 switch ($valueField) {
5074 $valuesCondition[] =
"{$valueField} = %s";
5080 require_once
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
5085 $valuesCondition = implode(
' AND ', $valuesCondition);
5088 DELETE FROM tst_solutions
5089 WHERE active_fi = %s
5090 AND question_fi = %s
5093 AND $valuesCondition
5096 if ($this->
getStep() !==
null) {
5097 $query .=
" AND step = %s ";
5098 $types[] =
'integer';
5108 $this->
saveCurrentSolution($activeId, $passIndex, $rec[
'value1'], $rec[
'value2'],
true, $rec[
'tstamp']);
5116 if (!count($intermediateSolution)) {
5124 if ($considerDummyRecordCreation) {
5154 $this->step =
$step;
5174 return gmdate(
'H:i:s', $time);
5184 $time_array = explode(
':', $time);
5185 if (
sizeof($time_array) == 3) {
5186 $sec += $time_array[0] * 3600;
5187 $sec += $time_array[1] * 60;
5188 $sec += $time_array[2];
5195 return json_encode(array());
5203 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5204 return (
bool) $solutionAvailability[
'intermediate'];
5208 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5209 return (
bool) $solutionAvailability[
'authorized'];
5213 $solutionAvailability = $this->lookupForExistingSolutions($active_id,
$pass);
5214 return (
bool) $solutionAvailability[
'authorized'] || (bool) $solutionAvailability[
'intermediate'];
5223 protected function lookupMaxStep($active_id,
$pass)
5230 "SELECT MAX(step) max_step FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
5231 array(
"integer",
"integer",
"integer"),
5237 $maxStep = $row[
'max_step'];
5249 public function lookupForExistingSolutions($activeId,
$pass)
5256 'authorized' =>
false,
5257 'intermediate' =>
false
5261 SELECT authorized, COUNT(*) cnt
5263 WHERE active_fi = %s
5264 AND question_fi = %s
5268 if ($this->
getStep() !==
null) {
5276 $result =
$ilDB->queryF(
$query, array(
'integer',
'integer',
'integer'), array($activeId, $this->
getId(), $pass));
5279 if ($row[
'authorized']) {
5280 $return[
'authorized'] = $row[
'cnt'] > 0;
5282 $return[
'intermediate'] = $row[
'cnt'] > 0;
5302 $query =
"DELETE FROM tst_solutions WHERE question_fi = %s";
5304 $DIC->database()->manipulateF(
$query, array(
'integer'), array($this->
getId()));
5313 DELETE FROM tst_solutions
5314 WHERE active_fi = %s
5315 AND question_fi = %s
5319 if ($this->
getStep() !==
null) {
5323 return $ilDB->manipulateF(
5325 array(
'integer',
'integer',
'integer'),
5326 array($activeId, $this->
getId(), $pass)
5335 $this->
log($activeId,
"log_user_solution_willingly_deleted");
5337 self::_updateTestPassResults(
5352 DELETE FROM tst_test_result
5353 WHERE active_fi = %s
5354 AND question_fi = %s
5358 if ($this->
getStep() !==
null) {
5362 return $ilDB->manipulateF(
5364 array(
'integer',
'integer',
'integer'),
5365 array($activeId, $this->
getId(), $pass)
5374 $IN_questionIds =
$ilDB->in(
'question_fi', $questionIds,
false,
'integer');
5378 FROM tst_test_result
5379 WHERE active_fi = %s
5386 array(
'integer',
'integer'),
5387 array($activeId,
$pass)
5390 return $row[
'cnt'] < count($questionIds);
5398 $IN_questionIds =
$ilDB->in(
'question_fi', $questionIds,
false,
'integer');
5402 FROM tst_test_result
5403 WHERE active_fi = %s
5410 array(
'integer',
'integer'),
5411 array($activeId,
$pass)
5414 $questionsHavingResultRecord = array();
5416 while ($row =
$ilDB->fetchAssoc(
$res)) {
5417 $questionsHavingResultRecord[] = $row[
'question_fi'];
5420 $questionsMissingResultRecordt = array_diff(
5422 $questionsHavingResultRecord
5425 return $questionsMissingResultRecordt;
5435 FROM tst_test_result
5436 WHERE active_fi = %s
5437 AND question_fi = %s
5441 $row =
$ilDB->fetchAssoc(
$ilDB->queryF(
$query, array(
'integer',
'integer',
'integer'), array($activeId, $questionId,
$pass)));
5443 return $row[
'cnt'] > 0;
5452 $valuePairs = array();
5454 foreach ($indexedValues as $value1 => $value2) {
5455 $valuePairs[] = array(
'value1' => $value1,
'value2' => $value2);
5467 $indexedValues = array();
5469 foreach ($valuePairs as $valuePair) {
5470 $indexedValues[ $valuePair[
'value1'] ] = $valuePair[
'value2'];
5473 return $indexedValues;
5498 "UPDATE qpl_questions SET tstamp = %s WHERE question_id = %s",
5499 array(
'integer',
'integer'),
5500 array(time(), $this->
getId())
5521 if ($this->testQuestionConfigInstance ===
null) {
5538 include_once(
'Modules/TestQuestionPool/classes/class.ilTestQuestionConfig.php');
5552 $query =
'SELECT user_fi FROM tst_active ' . PHP_EOL
5553 .
'JOIN tst_test_question ON tst_test_question.test_fi = tst_active.test_fi ' . PHP_EOL
5554 .
'JOIN qpl_questions ON qpl_questions.question_id = tst_test_question.question_fi ' . PHP_EOL
5555 .
'WHERE qpl_questions.obj_fi = ' . $this->db->quote($this->
getObjId(),
'integer');
5558 return $res->numRows() > 0;
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
An exception for terminatinating execution or to throw for unit testing.
return true
Flag indicating whether or not HTTP headers will be sent when outputting captcha image/audio.
Abstract basic class which is to be extended by the concrete assessment question type classes.
getTotalAnswers()
get total number of answers
$export_image_path
(Web) Path to images
moveUploadedMediaFile($file, $name)
Move an uploaded media file to an public accessible temp dir to present it.
isNonEmptyItemListPostSubmission($postSubmissionFieldname)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass.
static includePluginClass($questionType, $withGuiClass)
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static getFeedbackClassNameByQuestionType($questionType)
setPreventRteUsage($a_val)
Set prevent rte usage.
removeResultRecord($activeId, $pass)
static _getOriginalId($question_id)
Returns the original id of a question.
$additinalContentEditingMode
const KEY_VALUES_IMPLOSION_SEPARATOR
setProcessLocker($processLocker)
formatSAQuestion($a_q)
Format self assessment question.
setShuffle($shuffle=true)
Sets the shuffle flag.
setId($id=-1)
Sets the id of the assQuestion object.
keyInArray($searchkey, $array)
returns TRUE if the key occurs in an array
setOriginalId($original_id)
static _instantiateQuestion($question_id)
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
constant for additional content editing mode "default"
getQuestionTypeID()
Returns the question type of the question.
getDescriptionForHTMLOutput()
static _getReachedPoints($active_id, $question_id, $pass=null)
Returns the points, a learner has reached answering the question.
setObjId($obj_id=0)
Set the object id of the container object.
static sumTimesInISO8601FormatH_i_s_Extended($time1, $time2)
static instantiateQuestionGUI($a_question_id)
Creates an instance of a question gui with a given question id.
static isAllowedImageFileExtension($mimeType, $fileExtension)
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
Creates an Excel worksheet for the detailed cumulated results of this question.
copySuggestedSolutionFiles($source_questionpool_id, $source_question_id)
getReachedPoints($active_id, $pass=null)
Returns the points, a learner has reached answering the question This is the fast way to get the poin...
static originalQuestionExists($questionId)
beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
static setForcePassResultUpdateEnabled($forcePassResultsUpdateEnabled)
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
setSuggestedSolution($solution_id="", $subquestion_index=0, $is_import=false)
Sets a suggested solution for the question.
const ADDITIONAL_CONTENT_EDITING_MODE_IPE
constant for additional content editing mode "pageobject"
static _getMaximumPoints($question_id)
Returns the maximum points, a learner can reach answering the question.
saveQuestionDataToDb($original_id="")
QTIMaterialToString($a_material)
Reads an QTI material tag an creates a text string.
syncSuggestedSolutionFiles($original_id)
Syncs the files of a suggested solution if the question is synced.
static _getSolutionMaxPass($question_id, $active_id)
Returns the maximum pass a users question solution.
isClone($question_id="")
Checks whether the question is a clone of another question or not.
static fetchMimeTypeIdentifier($contentTypeString)
fixUnavailableSkinImageSources($html)
deletePageOfQuestion($question_id)
Deletes the page object of a question with a given ID.
lmMigrateQuestionTypeGenericContent(ilAssSelfAssessmentMigrator $migrator)
duplicateSkillAssignments($srcParentId, $srcQuestionId, $trgParentId, $trgQuestionId)
savePreviewData(ilAssQuestionPreviewSession $previewSession)
persistWorkingState($active_id, $pass=null, $obligationsEnabled=false, $authorized=true)
persists the working state for current testactive and testpass
getQuestionForHTMLOutput()
deleteSolutionRecordByValues($activeId, $passIndex, $authorized, $matchValues)
isComplete()
Returns true, if a question is complete for use.
getHtmlQuestionContentPurifier()
addAnswerOptionValue($qIndex, $answerOptionValue, $points)
log($active_id, $langVar)
static _getSuggestedSolutionCount($question_id)
Returns the number of suggested solutions associated with a question.
adjustReachedPointsByScoringOptions($points, $active_id, $pass=null)
Adjust the given reached points by checks for all special scoring options in the test container.
isInUse($question_id="")
Checks whether the question is in use or not.
static resetOriginalId($questionId)
static _areAnswered($a_user_id, $a_question_ids)
Checks if an array of question ids is answered by an user or not.
isPreviewSolutionCorrect(ilAssQuestionPreviewSession $previewSession)
cleanupMediaObjectUsage()
synchronises appearances of media objects in the question with media object usage table
deleteDummySolutionRecord($activeId, $passIndex)
getId()
Gets the id of the assQuestion object.
static saveOriginalId($questionId, $originalId)
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
fetchValuePairsFromIndexedValues(array $indexedValues)
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
getObjId()
Get the object id of the container object.
isDummySolutionRecord($solutionRecord)
questionTitleExists($questionpool_id, $title)
Returns TRUE if the question title exists in the database.
supportsJavascriptOutput()
Returns true if the question type supports JavaScript output.
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
getSuggestedSolutionPath()
Returns the path for a suggested solution.
removeExistingSolutions($activeId, $pass)
areObligationsToBeConsidered()
setTitle($title="")
Sets the title string of the assQuestion object.
static _getTitle($a_q_id)
Returns the title of a question.
getOwner()
Gets the creator/owner ID of the assQuestion object.
getAdditionalContentEditingMode()
getter for additional content editing mode for this question
static _isUsedInRandomTest($question_id="")
Checks whether the question is used in a random test or not.
getSolutionRecordById($solutionId)
$testQuestionConfigInstance
isHTML($a_text)
Checks if a given string contains HTML or not.
buildTestPresentationConfig()
build basic test question configuration instance
setObligationsToBeConsidered($obligationsToBeConsidered)
persistPreviewState(ilAssQuestionPreviewSession $previewSession)
persists the preview state for current user and question
static $forcePassResultsUpdateEnabled
addQuestionChangeListener(ilQuestionChangeListener $listener)
syncXHTMLMediaObjectsOfQuestion()
onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $targetQuestionId)
Will be called when a question is copied (into another question pool)
duplicateIntermediateSolutionAuthorized($activeId, $passIndex)
authorizedOrIntermediateSolutionExists($active_id, $pass)
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.
resetUsersAnswer($activeId, $pass)
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
getJavaPath()
Returns the image path for web accessable images of a question.
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...
migrateContentForLearningModule(ilAssSelfAssessmentMigrator $migrator)
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second.
getHtmlUserSolutionPurifier()
fetchIndexedValuesFromValuePairs(array $valuePairs)
getSuggestedSolutionTitle($subquestion_index=0)
Returns the title of a suggested solution at a given subquestion_index.
static getObjectClassNameByQuestionType($questionType)
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
static $allowedImageMaterialFileExtensionsByMimeType
setExportImagePath($a_path)
isValidAdditionalContentEditingMode($additionalContentEditingMode)
returns the fact wether the passed additional content mode is valid or not
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
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.
setEstimatedWorkingTimeFromDurationString($durationString)
Sets the estimated working time of a question from a given datetime string.
getSuggestedSolutionPathWeb()
Returns the web path for a suggested solution.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
buildImagePath($questionId, $parentObjectId)
removeAllExistingSolutions()
static explodeKeyValues($keyValues)
getFlashPath()
Returns the image path for web accessable flash files of a question.
__get($value)
Object getter.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
removeCurrentSolution($active_id, $pass, $authorized=true)
getSuggestedSolution($subquestion_index=0)
Returns a suggested solution for a given subquestion index.
calculateResultsFromSolution($active_id, $pass=null, $obligationsEnabled=false)
Calculates the question results from a previously saved question solution.
$obligationsToBeConsidered
buildHashedImageFilename($plain_image_filename, $unique=false)
updateCurrentSolution($solutionId, $value1, $value2, $authorized=true)
removeSolutionRecordById($solutionId)
static getNumExistingSolutionRecords($activeId, $pass, $questionId)
returns the number of existing solution records for the given test active / pass and given question i...
static implodeKeyValues($keyValues)
static convertISO8601FormatH_i_s_ExtendedToSeconds($time)
duplicateSuggestedSolutionFiles($parent_id, $question_id)
Duplicates the files of a suggested solution if the question is duplicated.
setAuthor($author="")
Sets the authors name of the assQuestion object.
$arrData
Associative array to store properties.
static isFileAvailable($file)
getQuestionType()
Returns the question type of the question.
deleteSuggestedSolutions()
Deletes all suggestes solutions in the database.
getPoints()
Returns the maximum available points for the question.
getOutputType()
Gets the output type.
ensureCurrentTestPass($active_id, $pass)
static isCoreQuestionType($questionType)
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
getActiveUserData($active_id)
Returns the user id and the test id for a given active id.
static _updateTestResultCache($active_id, ilAssQuestionProcessLocker $processLocker=null)
@TODO Move this to a proper place.
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping, array $solutionhints=[])
Receives parameters from a QTI parser and creates a valid ILIAS question object.
setExternalId($external_id)
getValidAdditionalContentEditingModes()
getter for valid additional content editing modes
deleteTaxonomyAssignments()
static _getSuggestedSolutionOutput($question_id)
Returns the output of the suggested solution.
static _needsManualScoring($question_id)
prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
getQuestionChangeListeners()
intermediateSolutionExists($active_id, $pass)
_getTotalAnswers($a_q_id)
get number of answers for question id (static) note: do not use $this inside this method
static _questionExistsInTest($question_id, $test_id)
authorizedSolutionExists($active_id, $pass)
getJavaPathWeb()
Returns the web image path for web accessable java applets of a question.
onDuplicate($originalParentId, $originalQuestionId, $duplicateParentId, $duplicateQuestionId)
Will be called when a question is duplicated (inside a question pool or for insertion in a test)
getTestId()
Gets the test id of the assQuestion object.
setShuffler(ilArrayElementShuffler $shuffler)
__set($key, $value)
Object setter.
getTestOutputSolutions($activeId, $pass)
removeIntermediateSolution($active_id, $pass)
_resolveIntLinks($question_id)
static _getInternalLinkHref($target="")
getSelfAssessmentEditingMode()
Get Self-Assessment Editing Mode.
static $allowedCharsetsByMimeType
getTitleFilenameCompliant()
returns the object title prepared to be used as a filename
copyPageOfQuestion($a_q_id)
static isForcePassResultUpdateEnabled()
static lookupOriginalParentObjId($originalQuestionId)
returns the parent object id for given original question id (should be a qpl id, but theoretically it...
_resolveInternalLink($internal_link)
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
getTestPresentationConfig()
Get the test question configuration (initialised once)
static & _instanciateQuestionGUI($question_id)
Creates an instance of a question gui with a given question id.
_questionExistsInPool($question_id)
Returns true if the question already exists in the database and is assigned to a question pool.
setOutputType($outputType=OUTPUT_HTML)
Sets the output type.
static lookupParentObjId($questionId)
@global ilDBInterface $ilDB
forceExistingIntermediateSolution($activeId, $passIndex, $considerDummyRecordCreation)
static _getTotalRightAnswers($a_q_id)
get number of answers for question id (static) note: do not use $this inside this method
getSelfAssessmentFormatter()
static _getQuestionText($a_q_id)
Returns question text.
static $imageSourceFixReplaceMap
static getGuiClassNameByQuestionType($questionType)
getDefaultNrOfTries()
Get Default Nr of Tries.
purifyAndPrepareTextAreaOutput(string $content)
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...
setSelfAssessmentEditingMode($a_selfassessmenteditingmode)
Set Self-Assessment Editing Mode.
static $allowedFileExtensionsByMimeType
static setResultGateway($resultGateway)
getShuffle()
Gets the shuffle flag.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
getFlashPathWeb()
Returns the web image path for web accessable flash applications of a question.
static includeCoreClass($questionType, $withGuiClass)
createPageObject()
create page object of question
static missingResultRecordExists($activeId, $pass, $questionIds)
static getKeyValuesImplosionSeparator()
getUserSolutionPreferingIntermediate($active_id, $pass=null)
copyXHTMLMediaObjectsOfQuestion($a_q_id)
getSuggestedSolutions()
Return the suggested solutions.
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 ...
& _getSuggestedSolution($question_id, $subquestion_index=0)
Returns a suggested solution for a given subquestion index.
getAnswerTableName()
Returns the name of the answer table in the database.
isAddableAnswerOptionValue($qIndex, $answerOptionValue)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
fixSvgToPng($imageFilenameContainingString)
syncSkillAssignments($srcParentId, $srcQuestionId, $trgParentId, $trgQuestionId)
updateCurrentSolutionsAuthorization($activeId, $pass, $authorized, $keepTime=false)
static getQuestionsMissingResultRecord($activeId, $pass, $questionIds)
deleteAdditionalTableData($question_id)
Deletes datasets from the additional question table in the database.
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
$selfassessmenteditingmode
getTitle()
Gets the title string of the assQuestion object.
static _getQuestionTitle($question_id)
Returns the question title of a question with a given id.
setPoints($a_points)
Sets the maximum available points for the question.
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
isAdditionalContentEditingModePageObject()
isser for additional "pageobject" content editing mode
duplicateQuestionHints($originalQuestionId, $duplicateQuestionId)
setComment($comment="")
Sets the comment string of the assQuestion object.
static _getQuestionInfo($question_id)
Returns question information from the database.
getAdjustedReachedPoints($active_id, $pass=null, $authorizedSolution=true)
returns the reached points ...
getSuggestedSolutionOutput()
getComment()
Gets the comment string of the assQuestion object.
setTestId($id=-1)
Sets the test id of the assQuestion object.
getAuthor()
Gets the authors name of the assQuestion object.
static getQuestionTypeFromDb($question_id)
get question type for question id
setNrOfTries($a_nr_of_tries)
$nr_of_tries
Number of tries.
static _getQuestionType($question_id)
Returns the question type of a question with a given id.
getQuestion()
Gets the question string of the question object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
static isAllowedImageMimeType($mimeType)
isAnswered($active_id, $pass=null)
returns boolean wether the question is answered during test pass or not
saveToDb($original_id="")
Saves the question to the database.
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
static _isWriteable($question_id, $user_id)
Returns true if the question is writeable by a certain user.
_questionExists($question_id)
Returns true if the question already exists in the database.
pcArrayShuffle($array)
Shuffles the values of a given array.
setQuestion($question="")
Sets the question string of the question object.
getImagePathWeb()
Returns the web image path for web accessable images of a question.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
loadFromDb($question_id)
Loads the question from the database.
static getAllowedFileExtensionsForMimeType($mimeType)
static lookupResultRecordExist($activeId, $questionId, $pass)
setLastChange($lastChange)
static getResultGateway()
& getInstances()
Gets all instances of the question.
static getAllowedImageMaterialFileExtensions()
lookupCurrentTestPass($active_id, $pass)
getEstimatedWorkingTime()
Gets the estimated working time of a question.
getPreventRteUsage()
Get prevent rte usage.
deleteAnswers($question_id)
Deletes datasets from answers tables.
setDefaultNrOfTries($a_defaultnroftries)
Set Default Nr of Tries.
ensureNonNegativePoints($points)
Assessment hint page object.
static deleteHintsByQuestionIds($questionIds)
Deletes all question hints relating to questions included in given question ids.
static duplicateListForQuestion($originalQuestionId, $duplicateQuestionId)
duplicates a hint list from given original question id to given duplicate question id and returns an ...
static getListByQuestionId($questionId)
instantiates a question hint list for the passed question id
static getDraftInstance()
getParticipantsSolution()
setParticipantsSolution($participantSolution)
static _updateObjectiveResult($a_user_id, $a_active_id, $a_question_id)
static _getInstanceByType(string $type)
Factory method for creating purifier instances.
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
static _deleteAllLinksOfSource($a_source_type, $a_source_id, $a_lang="-")
Delete all links of a given source.
static _getIdForImportId($a_type, $a_target)
Get current id for an import id.
static _getIdForImportId($a_import_id)
get current object id for import id (static)
static _addLog($user_id, $object_id, $logtext, $question_id="", $original_id="", $test_only=false, $test_ref_id=null)
Add an assessment log entry.
static _getLogLanguage()
retrieve the log language for assessment logging
static _getManualScoringTypes()
Retrieve the manual scoring settings as type strings.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
static _isWriteable($object_id, $user_id)
Returns true, if the question pool is writeable by a given user.
static _updateQuestionCount($object_id)
Updates the number of available questions for a question pool in the database.
static getUsageOfObject($a_obj_id, $a_include_titles=false)
Get usage of object.
static _getParticipantData($active_id)
Retrieves a participant name from active id.
static _getResultPass($active_id)
Retrieves the pass number that should be counted for a given user.
static _getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
static getDataWebPath(string $relative_path='')
This is originally a fix for https://mantis.ilias.de/view.php?id=35707; in general,...
static _getCountSystem($active_id)
Gets the count system for the calculation of points.
static _lookupAuthor($obj_id)
Gets the authors name of the ilObjTest object.
static _getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static buildExamId($active_id, $pass, $test_obj_id=null)
static _getWorkingTimeOfParticipantForPass($active_id, $pass)
Returns the complete working time in seconds for a test participant.
static _getUserIdFromActiveId($active_id)
static _getScoreCutting($active_id)
Determines if the score of a question should be cut at 0 points or the score of the whole test.
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
static _lookupObjId($a_id)
static _lookupTitle($a_id)
lookup object title
static _getAllReferences($a_id)
get all reference ids of object
static getPluginObject(string $a_ctype, string $a_cname, string $a_slot_id, string $a_pname)
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...
static _cleanupMediaObjectUsage($a_text, $a_usage_type, $a_usage_id)
Synchronises appearances of media objects in $a_text with media object usage table.
Taxonomy node <-> item assignment.
Test Question configuration.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static isHTML($a_text)
Checks if a given string contains HTML or not.
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 getASCIIFilename($a_filename)
convert utf8 to ascii filename
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static removeTrailingPathSeparators($path)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
static createDirectory($a_dir, $a_mod=0755)
create directory
static signFile($path_to_file)
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
migrateToLmContent($content)
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Class ChatMainBarProvider \MainMenu\Provider.
redirection script todo: (a better solution should control the processing via a xml file)
foreach($_POST as $key=> $value) $res