4require_once 
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
 
    5require_once 
'./Modules/Test/classes/inc.AssessmentConstants.php';
 
    6require_once 
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
 
    7require_once 
'./Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
 
    8require_once 
'./Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
 
    9require_once 
'./Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
 
   10require_once 
'Modules/TestQuestionPool/interfaces/interface.ilAssSpecificFeedbackOptionLabelProvider.php';
 
   84        $this->thumb_size = 150;
 
   86        $this->answers = array();
 
   88        $this->feedback_setting = 2;
 
   99        if (strlen($this->title) and ($this->author) and ($this->question) and (count($this->answers)) and ($this->
getMaximumPoints() > 0)) {
 
  100            foreach ($this->answers as $answer) {
 
  101                if ((strlen($answer->getAnswertext()) == 0) && (strlen($answer->getImage()) == 0)) {
 
  132                array($this->
getId())
 
  136                $oldthumbsize = 
$data[
'thumb_size'];
 
  155                if (strlen($answer->getImage())) {
 
  174            switch (strtoupper($path_info[
'extension'])) {
 
  210            $this->
setId($question_id);
 
  219            include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
  225            $this->isSingleline = (
$data[
'allow_images']) ? 
false : 
true;
 
  226            $this->lastChange = 
$data[
'tstamp'];
 
  227            $this->feedback_setting = 
$data[
'feedback_setting'];
 
  242            "SELECT * FROM qpl_a_sc WHERE question_fi = %s ORDER BY aorder ASC",
 
  246        include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
 
  250                if (!@file_exists($imagefilename)) {
 
  251                    $data[
"imagefile"] = 
"";
 
  253                include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
  259        parent::loadFromDb($question_id);
 
  269        if ($this->
id <= 0) {
 
  274        $this_id = $this->
getId();
 
  278        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  282        if ((
int) $testObjId > 0) {
 
  283            $clone->setObjId($testObjId);
 
  303        $clone->copyPageOfQuestion($this_id);
 
  306        $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
 
  308        $clone->duplicateImages($this_id, $thisObjId);
 
  310        $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
 
  322        if ($this->
id <= 0) {
 
  328        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  331        $source_questionpool_id = $this->
getObjId();
 
  332        $clone->setObjId($target_questionpool_id);
 
  342        $clone->copyImages(
$original_id, $source_questionpool_id);
 
  344        $clone->onCopy($source_questionpool_id, 
$original_id, $clone->getObjId(), $clone->getId());
 
  351        if ($this->
id <= 0) {
 
  356        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  359        $sourceParentId = $this->
getObjId();
 
  365        $clone->setObjId($targetParentId);
 
  367        if ($targetQuestionTitle) {
 
  368            $clone->setTitle($targetQuestionTitle);
 
  373        $clone->copyPageOfQuestion($sourceQuestionId);
 
  375        $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
 
  377        $clone->copyImages($sourceQuestionId, $sourceParentId);
 
  379        $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
 
  427        include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
 
  429        if (array_key_exists($order, $this->answers)) {
 
  432            $newchoices = array();
 
  433            for (
$i = 0; 
$i < $order; 
$i++) {
 
  434                array_push($newchoices, $this->answers[
$i]);
 
  436            array_push($newchoices, $answer);
 
  437            for (
$i = $order; 
$i < count($this->answers); 
$i++) {
 
  442            $this->answers = $newchoices;
 
  446            array_push($this->answers, $answer);
 
  459        return count($this->answers);
 
  476        if (count($this->answers) < 1) {
 
  479        if (
$index >= count($this->answers)) {
 
  483        return $this->answers[
$index];
 
  499        if (count($this->answers) < 1) {
 
  502        if (
$index >= count($this->answers)) {
 
  505        $answer = $this->answers[
$index];
 
  506        if (strlen($answer->getImage())) {
 
  509        unset($this->answers[
$index]);
 
  510        $this->answers = array_values($this->answers);
 
  511        for (
$i = 0; 
$i < count($this->answers); 
$i++) {
 
  512            if ($this->answers[
$i]->getOrder() > 
$index) {
 
  513                $this->answers[
$i]->setOrder(
$i);
 
  526        $this->answers = array();
 
  538        foreach ($this->answers as $key => $value) {
 
  539            if ($value->getPoints() > 
$points) {
 
  558        if ($returndetails) {
 
  559            throw new ilTestException(
'return details not implemented for ' . __METHOD__);
 
  565        $found_values = array();
 
  566        if (is_null(
$pass)) {
 
  571            if (strcmp(
$data[
"value1"], 
"") != 0) {
 
  572                array_push($found_values, 
$data[
"value1"]);
 
  576        foreach ($this->answers as $key => $answer) {
 
  577            if (count($found_values) > 0) {
 
  578                if (in_array($key, $found_values)) {
 
  579                    $points += $answer->getPoints();
 
  593        foreach ($this->answers as $key => $answer) {
 
  594            if (is_numeric($participantSolution) && $key == $participantSolution) {
 
  595                $points = $answer->getPoints();
 
  618        if (is_null(
$pass)) {
 
  619            include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
  625        $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, 
$ilDB, $active_id, 
$pass, $authorized) {
 
  628            $update = $row[
"solution_id"];
 
  631                if (strlen(
$_POST[
"multiple_choice_result"])) {
 
  638                if (strlen(
$_POST[
"multiple_choice_result"])) {
 
  645        if ($entered_values) {
 
  646            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
  651            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
  662        if (strlen(
$_POST[
'multiple_choice_result' . $this->
getId() . 
'ID'])) {
 
  679            array( $this->
getId() )
 
  684                                                                               ) . 
" (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
 
  685            array( 
"integer", 
"text", 
"text", 
"integer" ),
 
  689                                ($this->isSingleline) ? 
"0" : 
"1",
 
  700        if (!$this->isSingleline) {
 
  704            "DELETE FROM qpl_a_sc WHERE question_fi = %s",
 
  706            array( $this->
getId() )
 
  709        foreach ($this->answers as $key => $value) {
 
  711            $answer_obj = $this->answers[$key];
 
  712            $next_id = 
$ilDB->nextId(
'qpl_a_sc');
 
  714                "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
 
  715                array( 
'integer', 
'integer', 
'text', 
'float', 
'integer', 
'text', 
'integer' ),
 
  720                                    $answer_obj->getPoints(),
 
  721                                    $answer_obj->getOrder(),
 
  722                                    $answer_obj->getImage(),
 
  738        return "assSingleChoice";
 
  771    public function setImageFile($image_filename, $image_tempfilename = 
"")
 
  774        if (!empty($image_tempfilename)) {
 
  775            $image_filename = str_replace(
" ", 
"_", $image_filename);
 
  777            if (!file_exists($imagepath)) {
 
  784                include_once 
"./Services/MediaObjects/classes/class.ilObjMediaObject.php";
 
  786                if (!preg_match(
"/^image/", $mimetype)) {
 
  787                    unlink($imagepath . $image_filename);
 
  809        @unlink($imagepath . $image_filename);
 
  810        $thumbpath = $imagepath . $this->
getThumbPrefix() . $image_filename;
 
  819        $imagepath_original = str_replace(
"/$this->id/images", 
"/$question_id/images", $imagepath);
 
  821        if ((
int) $objectId > 0) {
 
  822            $imagepath_original = str_replace(
"/$this->obj_id/", 
"/$objectId/", $imagepath_original);
 
  825        foreach ($this->answers as $answer) {
 
  828                if (!file_exists($imagepath)) {
 
  832                    $ilLog->write(
"image could not be duplicated!!!!", 
$ilLog->ERROR);
 
  833                    $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
  835                if (@file_exists($imagepath_original . $this->
getThumbPrefix() . $filename)) {
 
  837                        $ilLog->write(
"image thumbnail could not be duplicated!!!!", 
$ilLog->ERROR);
 
  838                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
  845    public function copyImages($question_id, $source_questionpool)
 
  852        $imagepath_original = str_replace(
"/$this->id/images", 
"/$question_id/images", $imagepath);
 
  853        $imagepath_original = str_replace(
"/$this->obj_id/", 
"/$source_questionpool/", $imagepath_original);
 
  854        foreach ($this->answers as $answer) {
 
  857                if (!file_exists($imagepath)) {
 
  861                if (file_exists($imagepath_original . 
$filename)) {
 
  864                            "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
 
  869                            $source_questionpool,
 
  875                if (file_exists($imagepath_original . $this->
getThumbPrefix() . $filename)) {
 
  878                            "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
 
  883                            $source_questionpool,
 
  901        $imagepath_original = str_replace(
"/$this->id/images", 
"/$question_id/images", $imagepath);
 
  903        foreach ($this->answers as $answer) {
 
  906                if (@file_exists($imagepath . 
$filename)) {
 
  907                    if (!file_exists($imagepath)) {
 
  910                    if (!file_exists($imagepath_original)) {
 
  914                        $ilLog->write(
"image could not be duplicated!!!!", 
$ilLog->ERROR);
 
  915                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
  918                if (@file_exists($imagepath . $this->
getThumbPrefix() . $filename)) {
 
  920                        $ilLog->write(
"image thumbnail could not be duplicated!!!!", 
$ilLog->ERROR);
 
  921                        $ilLog->write(
"object: " . print_r($this, 
true), 
$ilLog->ERROR);
 
  934        $text = parent::getRTETextWithMediaObjects();
 
  935        foreach ($this->answers as 
$index => $answer) {
 
  936            $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->
getId(), 0, 
$index);
 
  937            $answer_obj = $this->answers[
$index];
 
  938            $text .= $answer_obj->getAnswertext();
 
  956        parent::setExportDetailsXLS($worksheet, $startrow, $active_id, 
$pass);
 
  961            $worksheet->setCell($startrow + 
$i, 0, $answer->getAnswertext());
 
  962            $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + 
$i));
 
  964                count($solution) > 0 &&
 
  965                isset($solution[0]) &&
 
  966                is_array($solution[0]) &&
 
  967                strlen($solution[0][
'value1']) > 0 && 
$id == $solution[0][
'value1']
 
  969                $worksheet->setCell($startrow + 
$i, 1, 1);
 
  971                $worksheet->setCell($startrow + 
$i, 1, 0);
 
  976        return $startrow + 
$i + 1;
 
  986        $this->thumb_size = $a_size;
 
 1005        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 1015            'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
false)),
 
 1016            'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
true))
 
 1021        foreach ($this->
getAnswers() as $key => $answer_obj) {
 
 1022            if ((
string) $answer_obj->getImage()) {
 
 1026                "answertext" => (
string) $this->
formatSAQuestion($answer_obj->getAnswertext()),
 
 1027                'html_id' => (
int) $this->getId() . 
'_' . $key,
 
 1028                "points" => (
float) $answer_obj->getPoints(),
 
 1029                "order" => (
int) $answer_obj->getOrder(),
 
 1030                "image" => (
string) $answer_obj->getImage(),
 
 1031                "feedback" => $this->formatSAQuestion(
 
 1032                    $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
 
 1050        $answer = $this->answers[
$index];
 
 1051        if (is_object($answer)) {
 
 1053            $answer->setImage(
'');
 
 1062        $multilineAnswerSetting = 
$ilUser->getPref(
"tst_multiline_answers");
 
 1063        if ($multilineAnswerSetting != 1) {
 
 1064            $multilineAnswerSetting = 0;
 
 1066        return $multilineAnswerSetting;
 
 1073        $ilUser->writePref(
"tst_multiline_answers", $a_setting);
 
 1087        $this->feedback_setting = $a_feedback_setting;
 
 1101        if ($this->feedback_setting) {
 
 1110        return 'feedback_correct_sc_mc';
 
 1127        return $numExistingSolutionRecords > 0;
 
 1155        require_once 
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
 
 1187        $maxStep = $this->lookupMaxStep($active_id, 
$pass);
 
 1189        if ($maxStep !== 
null) {
 
 1191                "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
 
 1192                array(
"integer", 
"integer", 
"integer",
"integer"),
 
 1193                array($active_id, 
$pass, $this->
getId(), $maxStep)
 
 1197                "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
 
 1198                array(
"integer", 
"integer", 
"integer"),
 
 1207            $result->addKeyValue($row[
"value1"], $row[
"value1"]);
 
 1240        parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
 
 1242        $origImagePath = $this->
buildImagePath($origQuestionId, $origParentObjId);
 
 1243        $dupImagePath = $this->
buildImagePath($dupQuestionId, $dupParentObjId);
 
 1246        if (is_dir($dupImagePath)) {
 
Class for answers with a binary state indicator.
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.
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
setShuffle($shuffle=true)
Sets the shuffle flag.
setId($id=-1)
Sets the id of the assQuestion object.
setOriginalId($original_id)
setObjId($obj_id=0)
Set the object id of the container object.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
saveQuestionDataToDb($original_id="")
getHtmlQuestionContentPurifier()
getId()
Gets the id of the assQuestion object.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
getObjId()
Get the object id of the container object.
setTitle($title="")
Sets the title string of the assQuestion object.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
buildImagePath($questionId, $parentObjectId)
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.
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...
setAuthor($author="")
Sets the authors name of the assQuestion object.
getShuffle()
Gets the shuffle flag.
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getTitle()
Gets the title string of the assQuestion object.
setPoints($a_points)
Sets the maximum available points for the question.
setComment($comment="")
Sets the comment string of the assQuestion object.
setNrOfTries($a_nr_of_tries)
getQuestion()
Gets the question string of the question object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
saveToDb($original_id="")
Saves the question to the database.
setQuestion($question="")
Sets the question string of the question object.
getImagePathWeb()
Returns the web image path for web accessable images of a question.
ensureNonNegativePoints($points)
Class for single choice questions.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
loadFromDb($question_id)
Loads a assSingleChoice object from a database.
deleteImage($image_filename)
Deletes an image file.
setOutputType($output_type=OUTPUT_ORDER)
Sets the output type of the assSingleChoice object.
getQuestionType()
Returns the question type of the question.
getAnswerCount()
Returns the number of answers.
toJSON()
Returns a JSON representation of the question.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
generateThumbForFile($path, $file)
syncImages()
Sync images of a MC question on synchronisation with the original question.
setSpecificFeedbackSetting($a_feedback_setting)
Sets the feedback settings in effect for the question.
removeAnswerImage($index)
getOutputType()
Gets the single choice output type which is either OUTPUT_ORDER (=0) or OUTPUT_RANDOM (=1).
getSpecificFeedbackAllCorrectOptionLabel()
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
isAnswered($active_id, $pass=null)
returns boolean wether the question is answered during test pass or not
addAnswer( $answertext="", $points=0.0, $order=0, $answerimage="")
Adds a possible answer for a single choice question.
getSpecificFeedbackSetting()
Gets the current feedback settings in effect for the question.
getOperators($expression)
Get all available operations for a specific question.
setMultilineAnswerSetting($a_setting=0)
getExpressionTypes()
Get all available expression types for a specific question.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
{}
& getAnswers()
Returns a reference to the answers array.
isComplete()
Returns true, if a single choice question is complete for use.
deleteAnswer($index=0)
Deletes an answer with a given index.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
setImageFile($image_filename, $image_tempfilename="")
Sets the image file and uploads the image to the object's image directory.
copyObject($target_questionpool_id, $title="")
Copies an assSingleChoice object.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
__construct( $title="", $comment="", $author="", $owner=-1, $question="", $output_type=OUTPUT_ORDER)
assSingleChoice constructor
flushAnswers()
Deletes all answers.
getMultilineAnswerSetting()
getAnswer($index=0)
Returns an answer with a given index.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
duplicateImages($question_id, $objectId=null)
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assSingleChoiceQuestion.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
getAnswerTableName()
Returns the name of the answer table in the database.
static getDraftInstance()
static getInstance($identifier)
getParticipantsSolution()
setParticipantsSolution($participantSolution)
static _getLogLanguage()
retrieve the log language for assessment logging
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static getOperatorsByExpression($expression)
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...
Base Exception for all Exceptions relating to Modules/Test.
Class ilUserQuestionResult.
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 convertImage( $a_from, $a_to, $a_target_format="", $a_geometry="", $a_background_color="")
convert image
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static makeDirParents($a_dir)
Create a new directory and all parent directories.
Class iQuestionCondition.
const PercentageResultExpression
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
const EmptyAnswerExpression
const NumberOfResultExpression
migrateToLmContent($content)
Interface ilObjAnswerScoringAdjustable.
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
Interface ilObjQuestionScoringAdjustable.
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc