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')
 
  278        'image/jpeg' => array(
'jpg', 
'jpeg'), 
'image/png' => array(
'png'), 
'image/gif' => array(
'gif')
 
  309        $this->original_id = 
null;
 
  315        if (!$this->author) {
 
  316            $this->author = $this->
ilias->account->fullname;
 
  319        if ($this->owner <= 0) {
 
  320            $this->owner = $this->
ilias->account->id;
 
  324        $this->suggested_solutions = array();
 
  326        $this->nr_of_tries = 0;
 
  328        $this->arrData = array();
 
  331        $this->questionActionCmd = 
'handleQuestionAction';
 
  333        $this->lastChange = 
null;
 
  335        require_once 
'Services/Randomization/classes/class.ilArrayElementOrderKeeper.php';
 
  355        return (
bool) count(self::getAllowedFileExtensionsForMimeType($mimeType));
 
  360        return current(explode(
';', $contentTypeString));
 
  365        foreach (self::$allowedFileExtensionsByMimeType as $allowedMimeType => $extensions) {
 
  366            $rexCharsets = implode(
'|', self::$allowedCharsetsByMimeType[$allowedMimeType]);
 
  367            $rexMimeType = preg_quote($allowedMimeType, 
'/');
 
  369            $rex = 
'/^' . $rexMimeType . 
'(;(\s)*charset=(' . $rexCharsets . 
'))*$/';
 
  371            if (!preg_match($rex, $mimeType)) {
 
  384            strtolower($fileExtension),
 
  385            self::getAllowedFileExtensionsForMimeType($mimeType)
 
  396        if (!isset(
$_POST[
'cmd']) || !isset(
$_POST[
'cmd'][$this->questionActionCmd])) {
 
  400        if (!is_array(
$_POST[
'cmd'][$this->questionActionCmd]) || !count(
$_POST[
'cmd'][$this->questionActionCmd])) {
 
  404        return key(
$_POST[
'cmd'][$this->questionActionCmd]);
 
  413        if (!isset(
$_POST[$postSubmissionFieldname])) {
 
  417        if (!is_array(
$_POST[$postSubmissionFieldname])) {
 
  421        if (!count(
$_POST[$postSubmissionFieldname])) {
 
  449        require_once 
'Modules/Test/classes/class.ilObjTest.php';
 
  463            "SELECT test_fi FROM tst_active WHERE active_id = %s",
 
  469            return $row[
"test_fi"];
 
  480    protected function log($active_id, $langVar)
 
  493        $extensions = array();
 
  495        foreach (self::$allowedImageMaterialFileExtensionsByMimeType as $mimeType => $mimeExtensions) {
 
  496            $extensions = array_merge($extensions, $mimeExtensions);
 
  498        return array_unique($extensions);
 
  544    public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
 
  546        include_once 
"./Modules/TestQuestionPool/classes/import/qti12/class." . $this->
getQuestionType() . 
"Import.php";
 
  548        $import = 
new $classname($this);
 
  549        $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
 
  558    public function toXML($a_include_header = 
true, $a_include_binary = 
true, $a_shuffle = 
false, $test_output = 
false, $force_image_references = 
false)
 
  560        include_once 
"./Modules/TestQuestionPool/classes/export/qti12/class." . $this->
getQuestionType() . 
"Export.php";
 
  562        $export = 
new $classname($this);
 
  563        return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
 
  590            "SELECT * FROM qpl_questions WHERE obj_fi = %s AND title = %s",
 
  591            array(
'integer',
'text'),
 
  592            array($questionpool_id, 
$title)
 
  594        return (
$result->numRows() > 0) ? true : 
false;
 
  630        $this->test_id = 
$id;
 
  686        $this->est_working_time = array(
"h" => (
int) $hour, 
"m" => (
int) $min, 
"s" => (
int) $sec);
 
  697        $this->est_working_time = array(
 
  698            'h' => (
int) substr($durationString, 0, 2),
 
  699            'm' => (
int) substr($durationString, 3, 2),
 
  700            's' => (
int) substr($durationString, 6, 2)
 
  714            foreach ($array as $key => $value) {
 
  715                if (strcmp($key, $searchkey) == 0) {
 
  769        require_once 
'Services/Utilities/classes/class.ilUtil.php';
 
  863        if (!$this->est_working_time) {
 
  864            $this->est_working_time = array(
"h" => 0, 
"m" => 0, 
"s" => 0);
 
  946        if (!strlen($this->external_id)) {
 
  947            if ($this->
getId() > 0) {
 
  948                return 'il_' . IL_INST_ID . 
'_qst_' . $this->
getId();
 
  950                return uniqid(
'', 
true);
 
  970            "SELECT points FROM qpl_questions WHERE question_id = %s",
 
  993            "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",
 
 1016            "SELECT suggested_solution_id FROM qpl_sol_sug WHERE question_fi = %s",
 
 1035        return $question->getSuggestedSolutionOutput();
 
 1041        foreach ($this->suggested_solutions as $solution) {
 
 1042            switch ($solution[
"type"]) {
 
 1050                    $possible_texts = array_values(array_filter(array(
 
 1053                        $this->lng->txt(
'tst_show_solution_suggested')
 
 1056                    require_once 
'Services/WebAccessChecker/classes/class.ilWACSignedPath.php';
 
 1061                    $solutionValue = $solution[
"value"];
 
 1062                    $solutionValue = $this->
fixSvgToPng($solutionValue);
 
 1068        return join(
"<br />", $output);
 
 1085            "SELECT * FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
 
 1086            array(
'integer',
'integer'),
 
 1087            array($question_id, $subquestion_index)
 
 1089        if (
$result->numRows() == 1) {
 
 1092                "internal_link" => $row[
"internal_link"],
 
 1093                "import_id" => $row[
"import_id"]
 
 1123        if (is_null(
$pass)) {
 
 1124            include_once 
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
 
 1128            "SELECT * FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
 
 1129            array(
'integer',
'integer',
'integer'),
 
 1130            array($active_id, $question_id, 
$pass)
 
 1132        if (
$result->numRows() == 1) {
 
 1149        return round(self::_getReachedPoints($active_id, $this->
getId(), 
$pass), 2);
 
 1176        if (is_null(
$pass)) {
 
 1177            include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1187        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
 
 1189        $requestsStatisticData = $hintTracking->getRequestStatisticDataByQuestionAndTestpass();
 
 1190        $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
 
 1195        return $reached_points;
 
 1213        if (is_null(
$pass)) {
 
 1214            include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1222        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
 
 1224        $requestsStatisticData = $questionHintTracking->getRequestStatisticDataByQuestionAndTestpass();
 
 1225        $reached_points = $reached_points - $requestsStatisticData->getRequestsPoints();
 
 1236        if (is_null($reached_points)) {
 
 1237            $reached_points = 0;
 
 1241        $existingSolutions = $this->lookupForExistingSolutions($active_id, 
$pass);
 
 1243        $this->
getProcessLocker()->executeUserQuestionResultUpdateOperation(
function () use (
$ilDB, $active_id, 
$pass, $reached_points, $requestsStatisticData, $isAnswered, $existingSolutions) {
 
 1245                        DELETE FROM             tst_test_result 
 1247                        WHERE                   active_fi = %s 
 1248                        AND                             question_fi = %s 
 1252            $types = array(
'integer', 
'integer', 
'integer');
 
 1253            $values = array($active_id, $this->
getId(), 
$pass);
 
 1255            if ($this->
getStep() !== 
null) {
 
 1260                $types[] = 
'integer';
 
 1265            if ($existingSolutions[
'authorized']) {
 
 1266                $next_id = 
$ilDB->nextId(
"tst_test_result");
 
 1268                    'test_result_id' => array(
'integer', $next_id),
 
 1269                    'active_fi' => array(
'integer', $active_id),
 
 1270                    'question_fi' => array(
'integer', $this->
getId()),
 
 1271                    'pass' => array(
'integer', 
$pass),
 
 1272                    'points' => array(
'float', $reached_points),
 
 1273                    'tstamp' => array(
'integer', time()),
 
 1274                    'hint_count' => array(
'integer', $requestsStatisticData->getRequestsCount()),
 
 1275                    'hint_points' => array(
'float', $requestsStatisticData->getRequestsPoints()),
 
 1276                    'answered' => array(
'integer', $isAnswered)
 
 1279                if ($this->
getStep() !== 
null) {
 
 1280                    $fieldData[
'step'] = array(
'integer', $this->
getStep());
 
 1283                $ilDB->insert(
'tst_test_result', $fieldData);
 
 1288        include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 1295                        "log_user_answered_question",
 
 1309        include_once 
'Modules/Course/classes/class.ilCourseObjectiveResult.php';
 
 1327        $saveStatus = 
false;
 
 1329        $this->
getProcessLocker()->executePersistWorkingStateLockOperation(
function () use ($active_id, 
$pass, $authorized, $obligationsEnabled, &$saveStatus) {
 
 1331            if (
$pass === 
null) {
 
 1332                require_once 
'Modules/Test/classes/class.ilObjTest.php';
 
 1386        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1387        include_once 
"./Modules/Test/classes/class.assMarkSchema.php";
 
 1392                        SELECT          tst_pass_result.* 
 1393                        FROM            tst_pass_result 
 1394                        WHERE           active_fi = %s 
 1400            array(
'integer',
'integer'),
 
 1401            array($active_id, 
$pass)
 
 1406        $max = $row[
'maxpoints'];
 
 1407        $reached = $row[
'points'];
 
 1409        $obligationsAnswered = (int) $row[
'obligations_answered'];
 
 1411        include_once 
"./Modules/Test/classes/class.assMarkSchema.php";
 
 1413        $percentage = (!$max) ? 0 : ($reached / $max) * 100.0;
 
 1415        $mark = ASS_MarkSchema::_getMatchingMarkFromActiveId($active_id, $percentage);
 
 1417        $isPassed = ($mark[
"passed"] ? 1 : 0);
 
 1418        $isFailed = (!$mark[
"passed"] ? 1 : 0);
 
 1420        $userTestResultUpdateCallback = 
function () use (
$ilDB, $active_id, 
$pass, $max, $reached, $isFailed, $isPassed, $obligationsAnswered, $row, $mark) {
 
 1421            $passedOnceBefore = 0;
 
 1422            $query = 
"SELECT passed_once FROM tst_result_cache WHERE active_fi = %s";
 
 1424            while ($row = 
$ilDB->fetchAssoc(
$res)) {
 
 1425                $passedOnceBefore = (int) $row[
'passed_once'];
 
 1428            $passedOnce = (int) ($isPassed || $passedOnceBefore);
 
 1431                "DELETE FROM tst_result_cache WHERE active_fi = %s",
 
 1436            $ilDB->insert(
'tst_result_cache', array(
 
 1437                'active_fi' => array(
'integer', $active_id),
 
 1438                'pass' => array(
'integer', strlen(
$pass) ? 
$pass : 0),
 
 1439                'max_points' => array(
'float', strlen($max) ? $max : 0),
 
 1440                'reached_points' => array(
'float', strlen($reached) ? $reached : 0),
 
 1441                'mark_short' => array(
'text', strlen($mark[
"short_name"]) ? $mark[
"short_name"] : 
" "),
 
 1442                'mark_official' => array(
'text', strlen($mark[
"official_name"]) ? $mark[
"official_name"] : 
" "),
 
 1443                'passed_once' => array(
'integer', $passedOnce),
 
 1444                'passed' => array(
'integer', $isPassed),
 
 1445                'failed' => array(
'integer', $isFailed),
 
 1446                'tstamp' => array(
'integer', time()),
 
 1447                'hint_count' => array(
'integer', $row[
'hint_count']),
 
 1448                'hint_points' => array(
'float', $row[
'hint_points']),
 
 1449                'obligations_answered' => array(
'integer', $obligationsAnswered)
 
 1454            $processLocker->executeUserTestResultUpdateLockOperation($userTestResultUpdateCallback);
 
 1456            $userTestResultUpdateCallback();
 
 1466        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1468        if (self::getResultGateway() !== 
null) {
 
 1481                        SELECT          SUM(points) reachedpoints, 
 1482                                                SUM(hint_count) hint_count, 
 1483                                                SUM(hint_points) hint_points, 
 1484                                                COUNT(DISTINCT(question_fi)) answeredquestions 
 1485                        FROM            tst_test_result 
 1486                        WHERE           active_fi = %s 
 1489            array(
'integer',
'integer'),
 
 1490            array($active_id, 
$pass)
 
 1494            if ($obligationsEnabled) {
 
 1496                                        SELECT          answered answ 
 1497                                        FROM            tst_test_question 
 1498                                          INNER JOIN    tst_active 
 1500                                                AND                     tst_test_question.test_fi = tst_active.test_fi 
 1501                                        LEFT JOIN       tst_test_result 
 1502                                                ON                      tst_test_result.active_fi = %s 
 1503                                                AND                     tst_test_result.pass = %s 
 1504                                                AND                     tst_test_question.question_fi = tst_test_result.question_fi 
 1505                                        WHERE           obligatory = 1';
 
 1507                $result_obligatory = 
$ilDB->queryF(
 
 1509                    array(
'integer',
'integer',
'integer'),
 
 1510                    array($active_id, $active_id, 
$pass)
 
 1513                $obligations_answered = 1;
 
 1515                while ($row_obligatory = 
$ilDB->fetchAssoc($result_obligatory)) {
 
 1516                    if (!(
int) $row_obligatory[
'answ']) {
 
 1517                        $obligations_answered = 0;
 
 1522                $obligations_answered = 1;
 
 1527            if ($row[
'reachedpoints'] === 
null) {
 
 1528                $row[
'reachedpoints'] = 0;
 
 1530            if ($row[
'hint_count'] === 
null) {
 
 1531                $row[
'hint_count'] = 0;
 
 1533            if ($row[
'hint_points'] === 
null) {
 
 1534                $row[
'hint_points'] = 0;
 
 1539            $updatePassResultCallback = 
function () use (
$ilDB, 
$data, $active_id, 
$pass, $row, $time, $obligations_answered, $exam_identifier) {
 
 1545                        'active_fi' => array(
'integer', $active_id),
 
 1546                        'pass' => array(
'integer', strlen(
$pass) ? 
$pass : 0)),
 
 1548                        'points' => array(
'float', $row[
'reachedpoints'] ? $row[
'reachedpoints'] : 0),
 
 1549                        'maxpoints' => array(
'float', 
$data[
'points']),
 
 1550                        'questioncount' => array(
'integer', 
$data[
'count']),
 
 1551                        'answeredquestions' => array(
'integer', $row[
'answeredquestions']),
 
 1552                        'workingtime' => array(
'integer', $time),
 
 1553                        'tstamp' => array(
'integer', time()),
 
 1554                        'hint_count' => array(
'integer', $row[
'hint_count']),
 
 1555                        'hint_points' => array(
'float', $row[
'hint_points']),
 
 1556                        'obligations_answered' => array(
'integer', $obligations_answered),
 
 1557                        'exam_id' => array(
'text', $exam_identifier)
 
 1563                $processLocker->executeUserPassResultUpdateLockOperation($updatePassResultCallback);
 
 1565                $updatePassResultCallback();
 
 1572            'active_fi' => $active_id,
 
 1574            'points' => ($row[
"reachedpoints"]) ? $row[
"reachedpoints"] : 0,
 
 1575            'maxpoints' => 
$data[
"points"],
 
 1576            'questioncount' => 
$data[
"count"],
 
 1577            'answeredquestions' => $row[
"answeredquestions"],
 
 1578            'workingtime' => $time,
 
 1580            'hint_count' => $row[
'hint_count'],
 
 1581            'hint_points' => $row[
'hint_points'],
 
 1582            'obligations_answered' => $obligations_answered,
 
 1583            'exam_id' => $exam_identifier
 
 1594    public static function logAction($logtext = 
"", $active_id = 
"", $question_id = 
"")
 
 1597        if (strlen($question_id)) {
 
 1601        require_once 
'Modules/Test/classes/class.ilObjAssessmentFolder.php';
 
 1602        require_once 
'Modules/Test/classes/class.ilObjTest.php';
 
 1622        $mediatempdir = CLIENT_WEB_DIR . 
"/assessment/temp";
 
 1623        if (!@is_dir($mediatempdir)) {
 
 1626        $temp_name = tempnam($mediatempdir, 
$name . 
"_____");
 
 1627        $temp_name = str_replace(
"\\", 
"/", $temp_name);
 
 1628        @unlink($temp_name);
 
 1643        return CLIENT_WEB_DIR . 
"/assessment/$this->obj_id/$this->id/solution/";
 
 1654        return CLIENT_WEB_DIR . 
"/assessment/$this->obj_id/$this->id/java/";
 
 1665        if ($question_id === 
null) {
 
 1669        if ($object_id === 
null) {
 
 1678        return CLIENT_WEB_DIR . 
"/assessment/{$parentObjectId}/{$questionId}/images/";
 
 1689        return CLIENT_WEB_DIR . 
"/assessment/$this->obj_id/$this->id/flash/";
 
 1700        include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 1712        include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 1727        if (!$this->export_image_path) {
 
 1728            include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 1744        include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 1766        if (!count($solution)) {
 
 1781        if (is_null(
$pass)) {
 
 1785        if ($this->
getStep() !== 
null) {
 
 1789                                WHERE active_fi = %s 
 1790                                AND question_fi = %s 
 1794                                ORDER BY solution_id";
 
 1798                array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer'),
 
 1799                array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
 
 1805                                WHERE active_fi = %s 
 1806                                AND question_fi = %s 
 1809                                ORDER BY solution_id 
 1814                array(
'integer', 
'integer', 
'integer', 
'integer'),
 
 1815                array($active_id, $this->
getId(), $pass, (
int) $authorized)
 
 1839        if ($question_id < 1) {
 
 1840            $question_id = $this->
getId();
 
 1843            "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",
 
 1848        $count = $row[
"question_count"];
 
 1852                        SELECT tst_active.test_fi 
 1854                        INNER JOIN tst_test_rnd_qst ON tst_test_rnd_qst.question_fi = qpl_questions.question_id 
 1855                        INNER JOIN tst_active ON tst_active.active_id = tst_test_rnd_qst.active_fi 
 1856                        WHERE qpl_questions.original_id = %s 
 1857                        GROUP BY tst_active.test_fi",
 
 1877        if ($question_id < 1) {
 
 1881            "SELECT original_id FROM qpl_questions WHERE question_id = %s",
 
 1886        return ($row[
"original_id"] > 0) ? true : 
false;
 
 1897        $keys = array_keys($array);
 
 1900        foreach (
$keys as $key) {
 
 1917            "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",
 
 1922        return $data[
"type_tag"];
 
 1959        if (!is_array($answer_table_name)) {
 
 1960            $answer_table_name = array($answer_table_name);
 
 1963        foreach ($answer_table_name as $table) {
 
 1964            if (strlen($table)) {
 
 1965                $affectedRows = 
$ilDB->manipulateF(
 
 1966                    "DELETE FROM $table WHERE question_fi = %s",
 
 1987        if (!is_array($additional_table_name)) {
 
 1988            $additional_table_name = array($additional_table_name);
 
 1991        foreach ($additional_table_name as $table) {
 
 1992            if (strlen($table)) {
 
 1993                $affectedRows = 
$ilDB->manipulateF(
 
 1994                    "DELETE FROM $table WHERE question_fi = %s",
 
 2010        include_once 
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
 
 2022    public function delete($question_id)
 
 2028        if ($question_id < 1) {
 
 2033            "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
 
 2037        if (
$result->numRows() == 1) {
 
 2045        } 
catch (Exception 
$e) {
 
 2046            $ilLog->write(
"EXCEPTION: Could not delete page of question $question_id: $e");
 
 2050        $affectedRows = 
$ilDB->manipulateF(
 
 2051            "DELETE FROM qpl_questions WHERE question_id = %s",
 
 2055        if ($affectedRows == 0) {
 
 2064        } 
catch (Exception 
$e) {
 
 2065            $ilLog->write(
"EXCEPTION: Could not delete additional table data of question $question_id: $e");
 
 2071            $affectedRows = 
$ilDB->manipulateF(
 
 2072                "DELETE FROM tst_test_question WHERE question_fi = %s",
 
 2076        } 
catch (Exception 
$e) {
 
 2077            $ilLog->write(
"EXCEPTION: Could not delete delete question $question_id from a test: $e");
 
 2083            $affectedRows = 
$ilDB->manipulateF(
 
 2084                "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
 
 2088        } 
catch (Exception 
$e) {
 
 2089            $ilLog->write(
"EXCEPTION: Could not delete suggested solutions of question $question_id: $e");
 
 2094            $directory = CLIENT_WEB_DIR . 
"/assessment/" . 
$obj_id . 
"/$question_id";
 
 2095            if (preg_match(
"/\d+/", 
$obj_id) and preg_match(
"/\d+/", $question_id) and is_dir($directory)) {
 
 2096                include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 2099        } 
catch (Exception 
$e) {
 
 2100            $ilLog->write(
"EXCEPTION: Could not delete question file directory $directory of question $question_id: $e");
 
 2105            include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
 
 2111            foreach (
$mobs as $mob) {
 
 2118        } 
catch (Exception 
$e) {
 
 2119            $ilLog->write(
"EXCEPTION: Error deleting the media objects of question $question_id: $e");
 
 2123        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
 
 2124        ilAssQuestionHintTracking::deleteRequestsByQuestionIds(array($question_id));
 
 2126        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
 
 2129        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
 
 2131        $assignmentList->setParentObjId(
$obj_id);
 
 2132        $assignmentList->setQuestionIdFilter($question_id);
 
 2133        $assignmentList->loadFromDb();
 
 2134        foreach ($assignmentList->getAssignmentsByQuestionId($question_id) as $assignment) {
 
 2136            $assignment->deleteFromDb();
 
 2143            include_once 
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
 
 2145        } 
catch (Exception 
$e) {
 
 2146            $ilLog->write(
"EXCEPTION: Error updating the question pool question count of question pool " . $this->
getObjId() . 
" when deleting question $question_id: $e");
 
 2157        require_once 
'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
 
 2158        require_once 
'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
 
 2161        foreach ($taxIds as $taxId) {
 
 2163            $taxNodeAssignment->deleteAssignmentsOfItem($this->
getId());
 
 2188            "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
 
 2189            array(
'integer',
'integer'),
 
 2190            array($a_q_id, $a_q_id)
 
 2192        if (
$result->numRows() == 0) {
 
 2195        $found_id = array();
 
 2197            array_push($found_id, $row[
"question_id"]);
 
 2200        $result = 
$ilDB->query(
"SELECT * FROM tst_test_result WHERE " . 
$ilDB->in(
'question_fi', $found_id, 
false, 
'integer'));
 
 2217            "SELECT question_id FROM qpl_questions WHERE original_id = %s OR question_id = %s",
 
 2218            array(
'integer',
'integer'),
 
 2219            array($a_q_id, $a_q_id)
 
 2221        if (
$result->numRows() == 0) {
 
 2224        $found_id = array();
 
 2226            array_push($found_id, $row[
"question_id"]);
 
 2228        $result = 
$ilDB->query(
"SELECT * FROM tst_test_result WHERE " . 
$ilDB->in(
'question_fi', $found_id, 
false, 
'integer'));
 
 2231            $reached = $row[
"points"];
 
 2232            include_once 
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
 
 2234            array_push($answers, array(
"reached" => $reached, 
"max" => $max));
 
 2238        foreach ($answers as $key => $value) {
 
 2239            $max += $value[
"max"];
 
 2240            $reached += $value[
"reached"];
 
 2243            return $reached / $max;
 
 2259            "SELECT title FROM qpl_questions WHERE question_id = %s",
 
 2263        if (
$result->numRows() == 1) {
 
 2265            return $row[
"title"];
 
 2281            "SELECT question_text FROM qpl_questions WHERE question_id = %s",
 
 2285        if (
$result->numRows() == 1) {
 
 2287            return $row[
"question_text"];
 
 2295        if (!file_exists($file)) {
 
 2299        if (!is_file($file)) {
 
 2303        if (!is_readable($file)) {
 
 2312        include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
 
 2314        foreach (
$mobs as $mob) {
 
 2321        include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
 
 2323        foreach (
$mobs as $mob) {
 
 2335        include_once 
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
 
 2337        $this->page->setId($this->
getId());
 
 2338        $this->page->setParentId($qpl_id);
 
 2339        $this->page->setXMLContent(
"<PageObject><PageContent>" .
 
 2340            "<Question QRef=\"il__qst_" . $this->
getId() . 
"\"/>" .
 
 2341            "</PageContent></PageObject>");
 
 2342        $this->page->create();
 
 2348            include_once 
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
 
 2351            $xml = str_replace(
"il__qst_" . $a_q_id, 
"il__qst_" . $this->
id, 
$page->getXMLContent());
 
 2352            $this->page->setXMLContent(
$xml);
 
 2353            $this->page->updateFromXML();
 
 2359        include_once 
"./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php";
 
 2361        return $page->getXMLContent();
 
 2374        if ($question_id < 1) {
 
 2378            "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",
 
 2382        if (
$result->numRows() == 1) {
 
 2384            return $data[
"type_tag"];
 
 2402        if ($question_id < 1) {
 
 2407            "SELECT title FROM qpl_questions WHERE qpl_questions.question_id = %s",
 
 2411        if (
$result->numRows() == 1) {
 
 2413            return $data[
"title"];
 
 2430        'ok.svg' => 
'ok.png', 
'not_ok.svg' => 
'not_ok.png',
 
 2431        'checkbox_checked.svg' => 
'checkbox_checked.png',
 
 2432        'checkbox_unchecked.svg' => 
'checkbox_unchecked.png',
 
 2433        'radiobutton_checked.svg' => 
'radiobutton_checked.png',
 
 2434        'radiobutton_unchecked.svg' => 
'radiobutton_unchecked.png' 
 2439        $needles = array_keys(self::$imageSourceFixReplaceMap);
 
 2440        $replacements = array_values(self::$imageSourceFixReplaceMap);
 
 2441        return str_replace($needles, $replacements, $imageFilenameContainingString);
 
 2448        if (preg_match_all(
'/src="(.*?)"/m', $html, $matches)) {
 
 2449            $sources = $matches[1];
 
 2451            $needleReplacementMap = array();
 
 2453            foreach ($sources as $src) {
 
 2456                if (file_exists($file)) {
 
 2460                $levels = explode(DIRECTORY_SEPARATOR, $src);
 
 2461                if (count($levels) < 5 || $levels[0] != 
'Customizing' || $levels[2] != 
'skin') {
 
 2467                if ($levels[4] == 
'Modules' || $levels[4] == 
'Services') {
 
 2468                    $component = $levels[4] . DIRECTORY_SEPARATOR . $levels[5];
 
 2474            if (count($needleReplacementMap)) {
 
 2475                $html = str_replace(array_keys($needleReplacementMap), array_values($needleReplacementMap), $html);
 
 2494            "SELECT external_id FROM qpl_questions WHERE question_id = %s",
 
 2498        if (
$result->numRows() == 1) {
 
 2500            $this->external_id = 
$data[
'external_id'];
 
 2504            "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
 
 2506            array($this->
getId())
 
 2508        $this->suggested_solutions = array();
 
 2510            include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 2513                $this->suggested_solutions[$row[
"subquestion_index"]] = array(
 
 2514                    "type" => $row[
"type"],
 
 2516                    "internal_link" => $row[
"internal_link"],
 
 2517                    "import_id" => $row[
"import_id"]
 
 2537        $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
 
 2540            if ($a_create_page) {
 
 2547            $next_id = 
$ilDB->nextId(
'qpl_questions');
 
 2548            $affectedRows = 
$ilDB->insert(
"qpl_questions", array(
 
 2549                "question_id" => array(
"integer", $next_id),
 
 2551                "obj_fi" => array(
"integer", 
$obj_id),
 
 2552                "title" => array(
"text", 
null),
 
 2553                "description" => array(
"text", 
null),
 
 2554                "author" => array(
"text", $this->
getAuthor()),
 
 2555                "owner" => array(
"integer", 
$ilUser->getId()),
 
 2556                "question_text" => array(
"clob", 
null),
 
 2557                "points" => array(
"float", 0),
 
 2559                "working_time" => array(
"text", $estw_time),
 
 2560                "complete" => array(
"text", $complete),
 
 2561                "created" => array(
"integer", time()),
 
 2562                "original_id" => array(
"integer", 
null),
 
 2563                "tstamp" => array(
"integer", $tstamp),
 
 2567            $this->
setId($next_id);
 
 2569            if ($a_create_page) {
 
 2577        return $this->
getId();
 
 2586        $estw_time = sprintf(
"%02d:%02d:%02d", $estw_time[
'h'], $estw_time[
'm'], $estw_time[
's']);
 
 2589        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 2590        if ($this->
getId() == -1) {
 
 2592            $next_id = 
$ilDB->nextId(
'qpl_questions');
 
 2593            $affectedRows = 
$ilDB->insert(
"qpl_questions", array(
 
 2594                "question_id" => array(
"integer", $next_id),
 
 2596                "obj_fi" => array(
"integer", $this->
getObjId()),
 
 2597                "title" => array(
"text", $this->
getTitle()),
 
 2598                "description" => array(
"text", $this->
getComment()),
 
 2599                "author" => array(
"text", $this->
getAuthor()),
 
 2600                "owner" => array(
"integer", $this->
getOwner()),
 
 2603                "working_time" => array(
"text", $estw_time),
 
 2604                "nr_of_tries" => array(
"integer", $this->
getNrOfTries()),
 
 2605                "created" => array(
"integer", time()),
 
 2607                "tstamp" => array(
"integer", time()),
 
 2611            $this->
setId($next_id);
 
 2616            $affectedRows = 
$ilDB->update(
"qpl_questions", array(
 
 2617                "obj_fi" => array(
"integer", $this->
getObjId()),
 
 2618                "title" => array(
"text", $this->
getTitle()),
 
 2619                "description" => array(
"text", $this->
getComment()),
 
 2620                "author" => array(
"text", $this->
getAuthor()),
 
 2623                "nr_of_tries" => array(
"integer", $this->
getNrOfTries()),
 
 2624                "working_time" => array(
"text", $estw_time),
 
 2625                "tstamp" => array(
"integer", time()),
 
 2626                'complete' => array(
'integer', $this->
isComplete()),
 
 2629            "question_id" => array(
"integer", $this->
getId())
 
 2644        $this->updateSuggestedSolutions();
 
 2654        $DIC->database()->update(
'qpl_questions', array(
 
 2655            'tstamp' => array(
'integer', time()),
 
 2656            'owner' => array(
'integer', ($this->
getOwner() <= 0 ? $this->
ilias->account->id : $this->getOwner())),
 
 2657            'complete' => array(
'integer', $complete),
 
 2658            'lifecycle' => array(
'text', $this->
getLifecycle()->getIdentifier()),
 
 2660            'question_id' => array(
'integer', $this->
getId())
 
 2664        include_once 
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
 
 2680        $query = 
"UPDATE qpl_questions SET tstamp = %s, original_id = %s WHERE question_id = %s";
 
 2682        $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
 
 2684            array(
'integer',
'integer', 
'text'),
 
 2685            array(time(), $originalId, $questionId)
 
 2691        $query = 
"UPDATE qpl_questions SET tstamp = %s, original_id = NULL WHERE question_id = %s";
 
 2693        $GLOBALS[
'DIC'][
'ilDB']->manipulateF(
 
 2695            array(
'integer', 
'text'),
 
 2696            array(time(), $questionId)
 
 2703    protected function onDuplicate($originalParentId, $originalQuestionId, $duplicateParentId, $duplicateQuestionId)
 
 2708        $this->feedbackOBJ->duplicateFeedback($originalQuestionId, $duplicateQuestionId);
 
 2724        $this->feedbackOBJ->syncFeedback($origQuestionId, $dupQuestionId);
 
 2730    protected function onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $targetQuestionId)
 
 2735        $this->feedbackOBJ->duplicateFeedback($sourceQuestionId, $targetQuestionId);
 
 2752        $affectedRows = 
$ilDB->manipulateF(
 
 2753            "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
 
 2755            array($this->
getId())
 
 2758        include_once 
"./Services/Link/classes/class.ilInternalLink.php";
 
 2760        $this->suggested_solutions = array();
 
 2773        if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
 
 2774            return $this->suggested_solutions[$subquestion_index];
 
 2790        if (array_key_exists($subquestion_index, $this->suggested_solutions)) {
 
 2791            $title = $this->suggested_solutions[$subquestion_index][
"internal_link"];
 
 2810        if (strcmp($solution_id, 
"") != 0) {
 
 2813                $import_id = $solution_id;
 
 2816            $this->suggested_solutions[$subquestion_index] = array(
 
 2817                "internal_link" => $solution_id,
 
 2818                "import_id" => $import_id
 
 2831        foreach ($this->suggested_solutions as 
$index => $solution) {
 
 2832            if (strcmp($solution[
"type"], 
"file") == 0) {
 
 2834                $filepath_original = str_replace(
 
 2835                    "/{$this->obj_id}/{$this->id}/solution",
 
 2836                    "/$parent_id/$question_id/solution",
 
 2839                if (!file_exists($filepath)) {
 
 2845                        $ilLog->write(
"File could not be duplicated!!!!", 
$ilLog->ERROR);
 
 2846                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
 2862        $filepath_original = str_replace(
"/$this->id/solution", 
"/$original_id/solution", $filepath);
 
 2864        foreach ($this->suggested_solutions as 
$index => $solution) {
 
 2865            if (strcmp($solution[
"type"], 
"file") == 0) {
 
 2866                if (!file_exists($filepath_original)) {
 
 2872                        $ilLog->write(
"File could not be duplicated!!!!", 
$ilLog->ERROR);
 
 2873                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
 2885        foreach ($this->suggested_solutions as 
$index => $solution) {
 
 2886            if (strcmp($solution[
"type"], 
"file") == 0) {
 
 2888                $filepath_original = str_replace(
"/$this->obj_id/$this->id/solution", 
"/$source_questionpool_id/$source_question_id/solution", $filepath);
 
 2889                if (!file_exists($filepath)) {
 
 2895                        $ilLog->write(
"File could not be copied!!!!", 
$ilLog->ERROR);
 
 2896                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
 2906    public function updateSuggestedSolutions(
$original_id = 
"")
 
 2912        include_once 
"./Services/Link/classes/class.ilInternalLink.php";
 
 2913        $affectedRows = 
$ilDB->manipulateF(
 
 2914            "DELETE FROM qpl_sol_sug WHERE question_fi = %s",
 
 2919        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 2920        foreach ($this->suggested_solutions as 
$index => $solution) {
 
 2921            $next_id = 
$ilDB->nextId(
'qpl_sol_sug');
 
 2926                                           'suggested_solution_id' => array( 
'integer',         $next_id ),
 
 2927                                           'question_fi' => array( 
'integer',   
$id ),
 
 2928                                           'type' => array( 
'text',             $solution[
'type'] ),
 
 2930                                           'internal_link' => array( 
'text',            $solution[
'internal_link'] ),
 
 2931                                           'import_id' => array( 
'text',                
null ),
 
 2932                                           'subquestion_index' => array( 
'integer',     
$index ),
 
 2933                                           'tstamp' => array( 
'integer',        time() ),
 
 2936            if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/", $solution[
"internal_link"], $matches)) {
 
 2955    public function saveSuggestedSolution(
$type, $solution_id = 
"", $subquestion_index = 0, $value = 
"")
 
 2960        $affectedRows = 
$ilDB->manipulateF(
 
 2961            "DELETE FROM qpl_sol_sug WHERE question_fi = %s AND subquestion_index = %s",
 
 2962            array(
"integer", 
"integer"),
 
 2969        $next_id = 
$ilDB->nextId(
'qpl_sol_sug');
 
 2970        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 2972        $affectedRows = 
$ilDB->insert(
 
 2975                                                       'suggested_solution_id' => array( 
'integer',     $next_id ),
 
 2976                                                       'question_fi' => array( 
'integer',       $this->
getId() ),
 
 2977                                                       'type' => array( 
'text',                 
$type ),
 
 2979                                                       'internal_link' => array( 
'text',                $solution_id ),
 
 2980                                                       'import_id' => array( 
'text',            
null ),
 
 2981                                                       'subquestion_index' => array( 
'integer',         $subquestion_index ),
 
 2982                                                       'tstamp' => array( 
'integer',    time() ),
 
 2985        if ($affectedRows == 1) {
 
 2986            $this->suggested_solutions[$subquestion_index] = array(
 
 2989                "internal_link" => $solution_id,
 
 2998        if (preg_match(
"/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches)) {
 
 2999            switch ($matches[2]) {
 
 3016            if (strcmp($resolved_link, 
"") == 0) {
 
 3017                $resolved_link = $internal_link;
 
 3020            $resolved_link = $internal_link;
 
 3022        return $resolved_link;
 
 3031            "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
 
 3037                $internal_link = $row[
"internal_link"];
 
 3038                include_once 
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
 
 3040                if (strcmp($internal_link, $resolved_link) != 0) {
 
 3042                    $affectedRows = 
$ilDB->manipulateF(
 
 3043                        "UPDATE qpl_sol_sug SET internal_link = %s WHERE suggested_solution_id = %s",
 
 3044                        array(
'text',
'integer'),
 
 3045                        array($resolved_link, $row[
"suggested_solution_id"])
 
 3051        if ($resolvedlinks) {
 
 3055            include_once 
"./Services/Link/classes/class.ilInternalLink.php";
 
 3059                "SELECT * FROM qpl_sol_sug WHERE question_fi = %s",
 
 3065                    if (preg_match(
"/il_(\d*?)_(\w+)_(\d+)/", $row[
"internal_link"], $matches)) {
 
 3078            "lm" => 
"LearningModule",
 
 3079            "pg" => 
"PageObject",
 
 3080            "st" => 
"StructureObject",
 
 3081            "git" => 
"GlossaryItem",
 
 3082            "mob" => 
"MediaObject" 
 3085        if (preg_match(
"/il__(\w+)_(\d+)/", $target, $matches)) {
 
 3086            $type = $matches[1];
 
 3088            include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 3089            switch ($linktypes[$matches[1]]) {
 
 3090                case "LearningModule":
 
 3094                case "StructureObject":
 
 3097                case "GlossaryItem":
 
 3101                    $href = 
"./ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[
$type] . 
"&cmd=media&ref_id=" . 
$_GET[
"ref_id"] . 
"&mob_id=" . 
$target_id;
 
 3120            "SELECT * FROM qpl_questions WHERE question_id = %s",
 
 3126            if ($row[
"original_id"] > 0) {
 
 3127                return $row[
"original_id"];
 
 3129                return $row[
"question_id"];
 
 3142                        SELECT COUNT(dupl.question_id) cnt 
 3143                        FROM qpl_questions dupl 
 3144                        INNER JOIN qpl_questions orig 
 3145                        ON orig.question_id = dupl.original_id 
 3146                        WHERE dupl.question_id = %s 
 3152        return $row[
'cnt'] > 0;
 
 3166        if (!$originalObjId) {
 
 3176        $this->
setId($original);
 
 3190        $this->updateSuggestedSolutions($original);
 
 3209        if ($question_id < 1) {
 
 3214            "SELECT question_id FROM qpl_questions WHERE question_id = %s",
 
 3218        if (
$result->numRows() == 1) {
 
 3237        if ($question_id < 1) {
 
 3242            "SELECT question_id FROM qpl_questions INNER JOIN object_data ON obj_fi = obj_id WHERE question_id = %s AND type = 'qpl'",
 
 3246        if (
$result->numRows() == 1) {
 
 3276        if (strcmp($question_id, 
"") != 0) {
 
 3278            if (!strlen($question_type)) {
 
 3301        if (strcmp($this->points, 
"") == 0) {
 
 3317        $this->points = $a_points;
 
 3350            "SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
 
 3351            array(
'integer',
'integer'),
 
 3352            array($active_id, $question_id)
 
 3354        if (
$result->numRows() == 1) {
 
 3356            return $row[
"maxpass"];
 
 3375        if (($question_id < 1) || ($user_id < 1)) {
 
 3380            "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
 
 3384        if (
$result->numRows() == 1) {
 
 3386            $qpl_object_id = $row[
"obj_fi"];
 
 3387            include_once 
"./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
 
 3405        if ($question_id < 1) {
 
 3409            "SELECT test_random_question_id FROM tst_test_rnd_qst WHERE question_fi = %s",
 
 3434        $requestsStatisticData = $hintTracking->getRequestStatisticData();
 
 3435        $reachedPoints = $reachedPoints - $requestsStatisticData->getRequestsPoints();
 
 3437        return $reachedPoints;
 
 3477        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 3479        if ($count_system == 1) {
 
 3485        if ($score_cutting == 0) {
 
 3511        if (is_null(
$pass)) {
 
 3512            include_once 
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
 
 3516            "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
 
 3517            array(
'integer',
'integer',
'integer'),
 
 3518            array($active_id, $question_id, 
$pass)
 
 3540            "SELECT DISTINCT(question_fi) FROM tst_test_result JOIN tst_active " .
 
 3541            "ON (active_id = active_fi) " .
 
 3542            "WHERE " . 
$ilDB->in(
'question_fi', $a_question_ids, 
false, 
'integer') .
 
 3543            " AND user_fi = %s",
 
 3547        return (
$res->numRows() == count($a_question_ids)) ? true : 
false;
 
 3571        include_once 
"./Services/Utilities/classes/class.ilUtil.php";
 
 3585        for (
$i = 0; 
$i < $a_material->getMaterialCount(); 
$i++) {
 
 3586            $material = $a_material->getMaterial(
$i);
 
 3587            if (strcmp($material[
"type"], 
"mattext") == 0) {
 
 3588                $result .= $material[
"material"]->getContent();
 
 3590            if (strcmp($material[
"type"], 
"matimage") == 0) {
 
 3591                $matimage = $material[
"material"];
 
 3592                if (preg_match(
"/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
 
 3594                    if (!is_array(
$_SESSION[
"import_mob_xhtml"])) {
 
 3595                        $_SESSION[
"import_mob_xhtml"] = array();
 
 3597                    array_push(
$_SESSION[
"import_mob_xhtml"], array(
"mob" => $matimage->getLabel(), 
"uri" => $matimage->getUri()));
 
 3612    public function addQTIMaterial(&$a_xml_writer, $a_material, $close_material_tag = 
true, $add_mobs = 
true)
 
 3614        include_once 
"./Services/RTE/classes/class.ilRTE.php";
 
 3615        include_once(
"./Services/MediaObjects/classes/class.ilObjMediaObject.php");
 
 3617        $a_xml_writer->xmlStartTag(
"material");
 
 3619            "texttype" => 
"text/plain" 
 3621        if ($this->
isHTML($a_material)) {
 
 3622            $attrs[
"texttype"] = 
"text/xhtml";
 
 3627            foreach (
$mobs as $mob) {
 
 3628                $moblabel = 
"il_" . IL_INST_ID . 
"_mob_" . $mob;
 
 3629                if (strpos($a_material, 
"mm_$mob") !== 
false) {
 
 3633                            "label" => $moblabel,
 
 3634                            "uri" => 
"objects/" . 
"il_" . IL_INST_ID . 
"_mob_" . $mob . 
"/" . $mob_obj->getTitle()
 
 3637                    $a_xml_writer->xmlElement(
"matimage", $imgattrs, 
null);
 
 3641        if ($close_material_tag) {
 
 3642            $a_xml_writer->xmlEndTag(
"material");
 
 3650        if (preg_match(
"/.*\.(png|jpg|gif|jpeg)$/i", $plain_image_filename, $matches)) {
 
 3651            $extension = 
"." . $matches[1];
 
 3655            $plain_image_filename = uniqid($plain_image_filename . microtime(
true));
 
 3658        $hashed_filename = md5($plain_image_filename) . $extension;
 
 3660        return $hashed_filename;
 
 3679            if (is_null(
$pass)) {
 
 3686                "SELECT points FROM tst_test_result WHERE active_fi = %s AND question_fi = %s AND pass = %s",
 
 3687                array(
'integer',
'integer',
'integer'),
 
 3688                array($active_id, $question_id, 
$pass)
 
 3690            $manual = ($manualscoring) ? 1 : 0;
 
 3691            $rowsnum = 
$result->numRows();
 
 3694                $old_points = $row[
"points"];
 
 3696                    $affectedRows = 
$ilDB->manipulateF(
 
 3697                        "UPDATE tst_test_result SET points = %s, manual = %s, tstamp = %s WHERE active_fi = %s AND question_fi = %s AND pass = %s",
 
 3698                        array(
'float', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer'),
 
 3699                        array(
$points, $manual, time(), $active_id, $question_id, 
$pass)
 
 3703                $next_id = 
$ilDB->nextId(
'tst_test_result');
 
 3704                $affectedRows = 
$ilDB->manipulateF(
 
 3705                    "INSERT INTO tst_test_result (test_result_id, active_fi, question_fi, points, pass, manual, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
 
 3706                    array(
'integer', 
'integer',
'integer', 
'float', 
'integer', 
'integer',
'integer'),
 
 3707                    array($next_id, $active_id, $question_id, 
$points, 
$pass, $manual, time())
 
 3711            if (self::isForcePassResultUpdateEnabled() || $old_points != 
$points || !$rowsnum) {
 
 3712                assQuestion::_updateTestPassResults($active_id, 
$pass, $obligationsEnabled);
 
 3714                include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 3715                include_once 
'./Modules/Course/classes/class.ilCourseObjectiveResult.php';
 
 3718                include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 3723                    include_once 
"./Modules/Test/classes/class.ilObjTestAccess.php";
 
 3783            "SELECT question_type_id FROM qpl_qst_type WHERE type_tag = %s",
 
 3787        if (
$result->numRows() == 1) {
 
 3789            return $row[
"question_type_id"];
 
 3794    public function syncHints()
 
 3801            "DELETE FROM qpl_hints WHERE qht_question_fi = %s",
 
 3803            array($this->original_id)
 
 3808            "SELECT * FROM qpl_hints WHERE qht_question_fi = %s",
 
 3810            array($this->
getId())
 
 3816                $next_id = 
$ilDB->nextId(
'qpl_hints');
 
 3821                        'qht_hint_id' => array(
'integer', $next_id),
 
 3822                        'qht_question_fi' => array(
'integer', $this->original_id),
 
 3823                        'qht_hint_index' => array(
'integer', $row[
"qht_hint_index"]),
 
 3824                        'qht_hint_points' => array(
'integer', $row[
"qht_hint_points"]),
 
 3825                        'qht_hint_text' => array(
'text', $row[
"qht_hint_text"]),
 
 3841        $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(), 
false);
 
 3842        $collected .= $this->feedbackOBJ->getGenericFeedbackContent($this->
getId(), 
true);
 
 3843        $collected .= $this->feedbackOBJ->getAllSpecificAnswerFeedbackContents($this->
getId());
 
 3845        foreach ($this->suggested_solutions as $solution_array) {
 
 3846            $collected .= $solution_array[
"value"];
 
 3849        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
 
 3851        foreach ($questionHintList as $questionHint) {
 
 3853            $collected .= $questionHint->getText();
 
 3866        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 3881            "SELECT question_id FROM qpl_questions WHERE original_id = %s",
 
 3883            array($this->
getId())
 
 3885        $instances = array();
 
 3888            array_push($ids, $row[
"question_id"]);
 
 3890        foreach ($ids as $question_id) {
 
 3893                "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",
 
 3902                "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",
 
 3910        include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 3911        foreach ($instances as $key => $value) {
 
 3919        include_once 
"./Modules/Test/classes/class.ilObjAssessmentFolder.php";
 
 3922        if (in_array($questiontype, $scoring)) {
 
 3941            "SELECT * FROM tst_active WHERE active_id = %s",
 
 3947            return array(
"user_id" => $row[
"user_fi"], 
"test_id" => $row[
"test_fi"]);
 
 3962        if (self::isCoreQuestionType($question_type)) {
 
 3971        return $questionType . 
'GUI';
 
 3976        return $questionType;
 
 3981        return str_replace(
'ass', 
'ilAss', $questionType) . 
'Feedback';
 
 3987        return file_exists(
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php");
 
 3992        if ($withGuiClass) {
 
 3994            require_once 
"Modules/TestQuestionPool/classes/class.{$guiClassName}.php";
 
 3999            require_once 
"Modules/TestQuestionPool/classes/class.{$objectClassName}.php";
 
 4003        require_once 
"Modules/TestQuestionPool/classes/feedback/class.{$feedbackClassName}.php";
 
 4009        $ilPluginAdmin = 
$DIC[
'ilPluginAdmin'];
 
 4012            self::getObjectClassNameByQuestionType($questionType),
 
 4013            self::getFeedbackClassNameByQuestionType($questionType)
 
 4016        if ($withGuiClass) {
 
 4020        $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE, 
"TestQuestionPool", 
"qst");
 
 4021        foreach ($pl_names as $pl_name) {
 
 4023            if (strcmp($pl->getQuestionType(), $questionType) == 0) {
 
 4024                foreach ($classes as $class) {
 
 4025                    $pl->includeClass(
"class.{$class}.php");
 
 4041        if (file_exists(
"./Modules/TestQuestionPool/classes/class." . $type_tag . 
".php")) {
 
 4044            return $lng->txt($type_tag);
 
 4047            $ilPluginAdmin = 
$DIC[
'ilPluginAdmin'];
 
 4048            $pl_names = $ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_MODULE, 
"TestQuestionPool", 
"qst");
 
 4049            foreach ($pl_names as $pl_name) {
 
 4051                if (strcmp($pl->getQuestionType(), $type_tag) == 0) {
 
 4052                    return $pl->getQuestionTypeTranslation();
 
 4088        if (strcmp($a_question_id, 
"") != 0) {
 
 4094            $question_gui = 
new $question_type_gui();
 
 4095            $question_gui->object->loadFromDb($a_question_id);
 
 4098            $question_gui->object->feedbackOBJ = 
new $feedbackObjectClassname($question_gui->object, 
$ilCtrl, 
$ilDB, 
$lng);
 
 4100            $assSettings = 
new ilSetting(
'assessment');
 
 4101            require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
 
 4103            $processLockerFactory->setQuestionId($question_gui->object->getId());
 
 4104            $processLockerFactory->setUserId(
$ilUser->getId());
 
 4105            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 4107            $question_gui->object->setProcessLocker($processLockerFactory->getLocker());
 
 4111            $ilLog->write(
'Instantiate question called without question id. (instantiateQuestionGUI@assQuestion)', 
$ilLog->WARNING);
 
 4114        return $question_gui;
 
 4129        $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord(0) . $startrow, $this->lng->txt($this->getQuestionType()));
 
 4130        $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord(1) . $startrow, $this->getTitle());
 
 4142                return $this->
getId();
 
 4162            case "est_working_time":
 
 4186            case "suggested_solutions":
 
 4193                if (array_key_exists($value, $this->arrData)) {
 
 4194                    return $this->arrData[$value];
 
 4209                $this->
setId($value);
 
 4229            case "est_working_time":
 
 4230                if (is_array($value)) {
 
 4250                $this->page = &$value;
 
 4253                $this->arrData[$key] = $value;
 
 4265        $this->nr_of_tries = $a_nr_of_tries;
 
 4270        $this->export_image_path = (string) $a_path;
 
 4278        if ($question_id < 1) {
 
 4283            "SELECT question_fi FROM tst_test_question WHERE question_fi = %s AND test_fi = %s",
 
 4284            array(
'integer', 
'integer'),
 
 4287        if (
$result->numRows() == 1) {
 
 4310        require_once 
'Modules/TestQuestionPool/classes/questions/class.ilAssSelfAssessmentQuestionFormatter.php';
 
 4311        return new \ilAssSelfAssessmentQuestionFormatter();
 
 4323        $this->prevent_rte_usage = $a_val;
 
 4345        $this->feedbackOBJ->migrateContentForLearningModule($migrator, $this->
getId());
 
 4371        $this->selfassessmenteditingmode = $a_selfassessmenteditingmode;
 
 4391        $this->defaultnroftries = $a_defaultnroftries;
 
 4416        $query = 
"SELECT obj_fi FROM qpl_questions WHERE question_id = %s";
 
 4418        $res = 
$ilDB->queryF(
$query, array(
'integer'), array((
int) $questionId));
 
 4421        return $row[
'obj_fi'];
 
 4441        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionHintList.php';
 
 4445            require_once 
'Modules/TestQuestionPool/classes/class.ilAssHintPage.php';
 
 4447            foreach ($hintIds as $originalHintId => $duplicateHintId) {
 
 4449                $originalXML = $originalPageObject->getXMLContent();
 
 4452                $duplicatePageObject->setId($duplicateHintId);
 
 4453                $duplicatePageObject->setParentId($this->
getId());
 
 4454                $duplicatePageObject->setXMLContent($originalXML);
 
 4455                $duplicatePageObject->createFromXML();
 
 4465        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
 
 4467        $assignmentList->setParentObjId($srcParentId);
 
 4468        $assignmentList->setQuestionIdFilter($srcQuestionId);
 
 4469        $assignmentList->loadFromDb();
 
 4471        foreach ($assignmentList->getAssignmentsByQuestionId($srcQuestionId) as $assignment) {
 
 4474            $assignment->setParentObjId($trgParentId);
 
 4475            $assignment->setQuestionId($trgQuestionId);
 
 4476            $assignment->saveToDb();
 
 4485        require_once 
'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
 
 4487        $assignmentList->setParentObjId($trgParentId);
 
 4488        $assignmentList->setQuestionIdFilter($trgQuestionId);
 
 4489        $assignmentList->loadFromDb();
 
 4491        foreach ($assignmentList->getAssignmentsByQuestionId($trgQuestionId) as $assignment) {
 
 4494            $assignment->deleteFromDb();
 
 4557                        SELECT          count(active_fi) cnt 
 4561                        WHERE           active_fi = %s 
 4562                        AND                     question_fi = %s 
 4568            array(
'integer',
'integer',
'integer'),
 
 4569            array($activeId, $questionId, 
$pass)
 
 4574        return (
int) $row[
'cnt'];
 
 4597            require_once 
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
 
 4640            self::ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT,
 
 4641            self::ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT
 
 4650        $this->questionChangeListeners[] = $listener;
 
 4664            $listener->notifyQuestionCreated($this);
 
 4671            $listener->notifyQuestionEdited($this);
 
 4678            $listener->notifyQuestionDeleted($this);
 
 4687        require_once 
'Services/Html/classes/class.ilHtmlPurifierFactory.php';
 
 4699                        SELECT          qpl_questions.*, 
 4700                                                {$this->getAdditionalTableName()}.* 
 4702                        LEFT JOIN       {$this->getAdditionalTableName()} 
 4703                        ON                      {$this->getAdditionalTableName()}.question_fi = qpl_questions.question_id 
 4704                        WHERE                   qpl_questions.question_id = %s 
 4733        if ($this->
getStep() !== 
null) {
 
 4737                                WHERE active_fi = %s 
 4738                                AND question_fi = %s 
 4744            return $ilDB->queryF(
 
 4746                array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer'),
 
 4747                array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
 
 4753                                WHERE active_fi = %s 
 4754                                AND question_fi = %s 
 4759            return $ilDB->queryF(
 
 4761                array(
'integer', 
'integer', 
'integer', 
'integer'),
 
 4762                array($active_id, $this->
getId(), $pass, (
int) $authorized)
 
 4778        return $ilDB->manipulateF(
 
 4779            "DELETE FROM tst_solutions WHERE solution_id = %s",
 
 4798            "SELECT * FROM tst_solutions WHERE solution_id = %s",
 
 4803        while ($row = 
$ilDB->fetchAssoc(
$res)) {
 
 4819        $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use ($active_id, 
$pass) {
 
 4837        if ($this->
getStep() !== 
null) {
 
 4839                                DELETE FROM tst_solutions 
 4840                                WHERE active_fi = %s 
 4841                                AND question_fi = %s 
 4847            return $ilDB->manipulateF(
 
 4849                array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer'),
 
 4850                array($active_id, $this->
getId(), $pass, $this->
getStep(), (
int) $authorized)
 
 4854                                DELETE FROM tst_solutions 
 4855                                WHERE active_fi = %s 
 4856                                AND question_fi = %s 
 4861            return $ilDB->manipulateF(
 
 4863                array(
'integer', 
'integer', 
'integer', 
'integer'),
 
 4864                array($active_id, $this->
getId(), $pass, (
int) $authorized)
 
 4886        $next_id = 
$ilDB->nextId(
"tst_solutions");
 
 4889            "solution_id" => array(
"integer", $next_id),
 
 4890            "active_fi" => array(
"integer", $active_id),
 
 4891            "question_fi" => array(
"integer", $this->
getId()),
 
 4892            "value1" => array(
"clob", $value1),
 
 4893            "value2" => array(
"clob", $value2),
 
 4894            "pass" => array(
"integer", 
$pass),
 
 4895            "tstamp" => array(
"integer", isset($tstamp) ? $tstamp : time()),
 
 4896            'authorized' => array(
'integer', (
int) $authorized)
 
 4899        if ($this->
getStep() !== 
null) {
 
 4900            $fieldData[
'step'] = array(
"integer", $this->
getStep());
 
 4903        return $ilDB->insert(
"tst_solutions", $fieldData);
 
 4923            "value1" => array(
"clob", $value1),
 
 4924            "value2" => array(
"clob", $value2),
 
 4925            "tstamp" => array(
"integer", time()),
 
 4926            'authorized' => array(
'integer', (
int) $authorized)
 
 4929        if ($this->
getStep() !== 
null) {
 
 4930            $fieldData[
'step'] = array(
"integer", $this->
getStep());
 
 4933        return $ilDB->update(
"tst_solutions", $fieldData, array(
 
 4934            'solution_id' => array(
'integer', $solutionId)
 
 4945            'authorized' => array(
'integer', (
int) $authorized)
 
 4949            $fieldData[
'tstamp'] = array(
'integer', time());
 
 4953            'question_fi' => array(
'integer', $this->
getId()),
 
 4954            'active_fi' => array(
'integer', $activeId),
 
 4955            'pass' => array(
'integer', 
$pass)
 
 4958        if ($this->
getStep() !== 
null) {
 
 4959            $whereData[
'step'] = array(
"integer", $this->
getStep());
 
 4962        return $ilDB->update(
'tst_solutions', $fieldData, $whereData);
 
 4974        return implode(self::getKeyValuesImplosionSeparator(), $keyValues);
 
 4978        return explode(self::getKeyValuesImplosionSeparator(), $keyValues);
 
 4983        foreach ($this->
getSolutionValues($activeId, $passIndex, 
false) as $solutionRec) {
 
 4984            if (0 == strlen($solutionRec[
'value1']) && 0 == strlen($solutionRec[
'value2'])) {
 
 4992        return !strlen($solutionRecord[
'value1']) && !strlen($solutionRecord[
'value2']);
 
 5000        $types = array(
"integer", 
"integer", 
"integer", 
"integer");
 
 5001        $values = array($activeId, $this->
getId(), $passIndex, (
int) $authorized);
 
 5002        $valuesCondition = array();
 
 5004        foreach ($matchValues as $valueField => $value) {
 
 5005            switch ($valueField) {
 
 5008                    $valuesCondition[] = 
"{$valueField} = %s";
 
 5014                    require_once 
'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
 
 5019        $valuesCondition = implode(
' AND ', $valuesCondition);
 
 5022                        DELETE FROM tst_solutions 
 5023                        WHERE active_fi = %s 
 5024                        AND question_fi = %s 
 5027                        AND $valuesCondition 
 5030        if ($this->
getStep() !== 
null) {
 
 5031            $query .= 
" AND step = %s ";
 
 5032            $types[] = 
'integer';
 
 5042            $this->
saveCurrentSolution($activeId, $passIndex, $rec[
'value1'], $rec[
'value2'], 
true, $rec[
'tstamp']);
 
 5050        if (!count($intermediateSolution)) {
 
 5058            if ($considerDummyRecordCreation) {
 
 5088        $this->step = 
$step;
 
 5108        return gmdate(
'H:i:s', $time);
 
 5118        $time_array = explode(
':', $time);
 
 5119        if (
sizeof($time_array) == 3) {
 
 5120            $sec += $time_array[0] * 3600;
 
 5121            $sec += $time_array[1] * 60;
 
 5122            $sec += $time_array[2];
 
 5129        return json_encode(array());
 
 5137        $solutionAvailability = $this->lookupForExistingSolutions($active_id, 
$pass);
 
 5138        return (
bool) $solutionAvailability[
'intermediate'];
 
 5142        $solutionAvailability = $this->lookupForExistingSolutions($active_id, 
$pass);
 
 5143        return (
bool) $solutionAvailability[
'authorized'];
 
 5147        $solutionAvailability = $this->lookupForExistingSolutions($active_id, 
$pass);
 
 5148        return (
bool) $solutionAvailability[
'authorized'] || (bool) $solutionAvailability[
'intermediate'];
 
 5157    protected function lookupMaxStep($active_id, 
$pass)
 
 5164            "SELECT MAX(step) max_step FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
 
 5165            array(
"integer", 
"integer", 
"integer"),
 
 5171        $maxStep = $row[
'max_step'];
 
 5183    public function lookupForExistingSolutions($activeId, 
$pass)
 
 5190            'authorized' => 
false,
 
 5191            'intermediate' => 
false 
 5195                        SELECT authorized, COUNT(*) cnt 
 5197                        WHERE active_fi = %s 
 5198                        AND question_fi = %s 
 5202        if ($this->
getStep() !== 
null) {
 
 5210        $result = 
$ilDB->queryF(
$query, array(
'integer', 
'integer', 
'integer'), array($activeId, $this->
getId(), $pass));
 
 5213            if ($row[
'authorized']) {
 
 5214                $return[
'authorized'] = $row[
'cnt'] > 0;
 
 5216                $return[
'intermediate'] = $row[
'cnt'] > 0;
 
 5236        $query = 
"DELETE FROM tst_solutions WHERE question_fi = %s";
 
 5238        $DIC->database()->manipulateF(
$query, array(
'integer'), array($this->
getId()));
 
 5247                        DELETE FROM tst_solutions 
 5248                        WHERE active_fi = %s 
 5249                        AND question_fi = %s 
 5253        if ($this->
getStep() !== 
null) {
 
 5257        return $ilDB->manipulateF(
 
 5259            array(
'integer', 
'integer', 
'integer'),
 
 5260            array($activeId, $this->
getId(), $pass)
 
 5269        $this->
log($activeId, 
"log_user_solution_willingly_deleted");
 
 5271        self::_updateTestPassResults(
 
 5286                        DELETE FROM tst_test_result 
 5287                        WHERE active_fi = %s 
 5288                        AND question_fi = %s 
 5292        if ($this->
getStep() !== 
null) {
 
 5296        return $ilDB->manipulateF(
 
 5298            array(
'integer', 
'integer', 
'integer'),
 
 5299            array($activeId, $this->
getId(), $pass)
 
 5308        $IN_questionIds = 
$ilDB->in(
'question_fi', $questionIds, 
false, 
'integer');
 
 5312                        FROM tst_test_result 
 5313                        WHERE active_fi = %s 
 5320            array(
'integer', 
'integer'),
 
 5321            array($activeId, 
$pass)
 
 5324        return $row[
'cnt'] < count($questionIds);
 
 5332        $IN_questionIds = 
$ilDB->in(
'question_fi', $questionIds, 
false, 
'integer');
 
 5336                        FROM tst_test_result 
 5337                        WHERE active_fi = %s 
 5344            array(
'integer', 
'integer'),
 
 5345            array($activeId, 
$pass)
 
 5348        $questionsHavingResultRecord = array();
 
 5350        while ($row = 
$ilDB->fetchAssoc(
$res)) {
 
 5351            $questionsHavingResultRecord[] = $row[
'question_fi'];
 
 5354        $questionsMissingResultRecordt = array_diff(
 
 5356            $questionsHavingResultRecord
 
 5359        return $questionsMissingResultRecordt;
 
 5369                        FROM tst_test_result 
 5370                        WHERE active_fi = %s 
 5371                        AND question_fi = %s 
 5375        $row = 
$ilDB->fetchAssoc(
$ilDB->queryF(
$query, array(
'integer', 
'integer', 
'integer'), array($activeId, $questionId, 
$pass)));
 
 5377        return $row[
'cnt'] > 0;
 
 5386        $valuePairs = array();
 
 5388        foreach ($indexedValues as $value1 => $value2) {
 
 5389            $valuePairs[] = array(
'value1' => $value1, 
'value2' => $value2);
 
 5401        $indexedValues = array();
 
 5403        foreach ($valuePairs as $valuePair) {
 
 5404            $indexedValues[ $valuePair[
'value1'] ] = $valuePair[
'value2'];
 
 5407        return $indexedValues;
 
 5432            "UPDATE qpl_questions SET tstamp = %s  WHERE question_id = %s",
 
 5433            array(
'integer', 
'integer'),
 
 5434            array(time(), $this->
getId())
 
 5455        if ($this->testQuestionConfigInstance === 
null) {
 
 5472        include_once(
'Modules/TestQuestionPool/classes/class.ilTestQuestionConfig.php');
 
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
An exception for terminatinating execution or to throw for unit testing.
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)
getQuestionTypeID()
Returns the question type of the question.
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.
static _getMaximumPoints($question_id)
Returns the maximum points, a learner can reach answering the question.
saveQuestionDataToDb($original_id="")
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.
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
deleteSolutionRecordByValues($activeId, $passIndex, $authorized, $matchValues)
isComplete()
Returns true, if a question is complete for use.
getHtmlQuestionContentPurifier()
const ADDITIONAL_CONTENT_EDITING_MODE_DEFAULT
constant for additional content editing mode "default"
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.
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.
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)
const ADDITIONAL_CONTENT_EDITING_MODE_PAGE_OBJECT
constant for additional content editing mode "pageobject"
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)
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assQuestion constructor
$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 _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)
redirection script todo: (a better solution should control the processing via a xml file)
foreach($_POST as $key=> $value) $res