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());
428 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
430 if (array_key_exists($order, $this->answers)) {
433 $newchoices = array();
434 for (
$i = 0;
$i < $order;
$i++) {
435 array_push($newchoices, $this->answers[
$i]);
437 array_push($newchoices, $answer);
438 for (
$i = $order;
$i < count($this->answers);
$i++) {
443 $this->answers = $newchoices;
447 array_push($this->answers, $answer);
460 return count($this->answers);
477 if (count($this->answers) < 1) {
480 if (
$index >= count($this->answers)) {
484 return $this->answers[
$index];
500 if (count($this->answers) < 1) {
503 if (
$index >= count($this->answers)) {
506 $answer = $this->answers[
$index];
507 if (strlen($answer->getImage())) {
510 unset($this->answers[
$index]);
511 $this->answers = array_values($this->answers);
512 for (
$i = 0;
$i < count($this->answers);
$i++) {
513 if ($this->answers[
$i]->getOrder() >
$index) {
514 $this->answers[
$i]->setOrder(
$i);
527 $this->answers = array();
539 foreach ($this->answers as $key => $value) {
540 if ($value->getPoints() >
$points) {
559 if ($returndetails) {
560 throw new ilTestException(
'return details not implemented for ' . __METHOD__);
566 $found_values = array();
567 if (is_null(
$pass)) {
572 if (strcmp(
$data[
"value1"],
"") != 0) {
573 array_push($found_values,
$data[
"value1"]);
577 foreach ($this->answers as $key => $answer) {
578 if (count($found_values) > 0) {
579 if (in_array($key, $found_values)) {
580 $points += $answer->getPoints();
594 foreach ($this->answers as $key => $answer) {
595 if (is_numeric($participantSolution) && $key == $participantSolution) {
596 $points = $answer->getPoints();
619 if (is_null(
$pass)) {
620 include_once
"./Modules/Test/classes/class.ilObjTest.php";
626 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values,
$ilDB, $active_id,
$pass, $authorized) {
629 $update = $row[
"solution_id"];
632 if (strlen(
$_POST[
"multiple_choice_result"])) {
639 if (strlen(
$_POST[
"multiple_choice_result"])) {
646 if ($entered_values) {
647 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
652 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
663 if (strlen(
$_POST[
'multiple_choice_result' . $this->
getId() .
'ID'])) {
680 array( $this->
getId() )
685 ) .
" (question_fi, shuffle, allow_images, thumb_size) VALUES (%s, %s, %s, %s)",
686 array(
"integer",
"text",
"text",
"integer" ),
690 ($this->isSingleline) ?
"0" :
"1",
707 if (!$this->isSingleline) {
712 "SELECT * FROM qpl_fb_specific WHERE question_fi = %s",
722 "SELECT answer_id, aorder FROM qpl_a_sc WHERE question_fi = %s",
729 $post_answer_order_for_id = [];
730 foreach ($this->answers as $answer){
732 if ($answer->getId() !==
null && !in_array($answer->getId(), array_keys($post_answer_order_for_id))) {
734 if ($answer->getId() == -1) {
737 $post_answer_order_for_id[$answer->getId()] = $answer->getOrder();
743 if (
sizeof($post_answer_order_for_id) >= 1) {
744 $db_answer_order_for_id = [];
745 $db_answer_id_for_order = [];
746 foreach ($db_answers as $db_answer){
747 $db_answer_order_for_id[intval($db_answer[
'answer_id'])] = intval($db_answer[
'aorder']);
748 $db_answer_id_for_order[intval($db_answer[
'aorder'])] = intval($db_answer[
'answer_id']);
754 $db_answer_ids = array_keys($db_answer_order_for_id);
755 $post_answer_ids = array_keys($post_answer_order_for_id);
756 $diff_db_post_answer_ids = array_diff($db_answer_ids, $post_answer_ids);
757 $unused_answer_ids = array_keys($diff_db_post_answer_ids);
760 $this->feedbackOBJ->deleteSpecificAnswerFeedbacks($this->
getId(),
false);
762 foreach ($db_feedback as $feedback_option) {
764 if (in_array(intval($feedback_option[
'answer']), $unused_answer_ids)) {
769 $feedback_order_db = intval($feedback_option[
'answer']);
770 $db_answer_id = $db_answer_id_for_order[$feedback_order_db];
774 if (is_null($db_answer_id) || $db_answer_id < 0) {
777 $feedback_order_post = $post_answer_order_for_id[$db_answer_id];
778 $feedback_option[
'answer'] = $feedback_order_post;
781 $next_id =
$ilDB->nextId(
'qpl_fb_specific');
783 "INSERT INTO qpl_fb_specific (feedback_id, question_fi, answer, tstamp, feedback, question)
784 VALUES (%s, %s, %s, %s, %s, %s)",
785 [
'integer',
'integer',
'integer',
'integer',
'text',
'integer'],
788 $feedback_option[
'question_fi'],
789 $feedback_option[
'answer'],
791 $feedback_option[
'feedback'],
792 $feedback_option[
'question']
801 "DELETE FROM qpl_a_sc WHERE question_fi = %s",
807 foreach ($this->answers as $key => $value) {
809 $answer_obj = $this->answers[$key];
810 $next_id =
$ilDB->nextId(
'qpl_a_sc');
812 "INSERT INTO qpl_a_sc (answer_id, question_fi, answertext, points, aorder, imagefile, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
813 [
'integer',
'integer',
'text',
'float',
'integer',
'text',
'integer'],
818 $answer_obj->getPoints(),
819 $answer_obj->getOrder(),
820 $answer_obj->getImage(),
836 return "assSingleChoice";
869 public function setImageFile($image_filename, $image_tempfilename =
"")
872 if (!empty($image_tempfilename)) {
873 $image_filename = str_replace(
" ",
"_", $image_filename);
875 if (!file_exists($imagepath)) {
882 include_once
"./Services/MediaObjects/classes/class.ilObjMediaObject.php";
884 if (!preg_match(
"/^image/", $mimetype)) {
885 unlink($imagepath . $image_filename);
907 @unlink($imagepath . $image_filename);
908 $thumbpath = $imagepath . $this->
getThumbPrefix() . $image_filename;
915 $ilLog =
$DIC[
'ilLog'];
917 $imagepath_original = str_replace(
"/$this->id/images",
"/$question_id/images", $imagepath);
919 if ((
int) $objectId > 0) {
920 $imagepath_original = str_replace(
"/$this->obj_id/",
"/$objectId/", $imagepath_original);
923 foreach ($this->answers as $answer) {
926 if (!file_exists($imagepath)) {
930 $ilLog->write(
"image could not be duplicated!!!!", $ilLog->ERROR);
931 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
933 if (@file_exists($imagepath_original . $this->
getThumbPrefix() . $filename)) {
935 $ilLog->write(
"image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
936 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
943 public function copyImages($question_id, $source_questionpool)
947 $ilLog =
$DIC[
'ilLog'];
950 $imagepath_original = str_replace(
"/$this->id/images",
"/$question_id/images", $imagepath);
951 $imagepath_original = str_replace(
"/$this->obj_id/",
"/$source_questionpool/", $imagepath_original);
952 foreach ($this->answers as $answer) {
955 if (!file_exists($imagepath)) {
959 if (file_exists($imagepath_original .
$filename)) {
961 $ilLog->warning(sprintf(
962 "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
967 $source_questionpool,
973 if (file_exists($imagepath_original . $this->
getThumbPrefix() . $filename)) {
975 $ilLog->warning(sprintf(
976 "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
981 $source_questionpool,
996 $ilLog =
$DIC[
'ilLog'];
999 $imagepath_original = str_replace(
"/$this->id/images",
"/$question_id/images", $imagepath);
1001 foreach ($this->answers as $answer) {
1004 if (@file_exists($imagepath .
$filename)) {
1005 if (!file_exists($imagepath)) {
1008 if (!file_exists($imagepath_original)) {
1012 $ilLog->write(
"image could not be duplicated!!!!", $ilLog->ERROR);
1013 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
1016 if (@file_exists($imagepath . $this->
getThumbPrefix() . $filename)) {
1018 $ilLog->write(
"image thumbnail could not be duplicated!!!!", $ilLog->ERROR);
1019 $ilLog->write(
"object: " . print_r($this,
true), $ilLog->ERROR);
1032 $text = parent::getRTETextWithMediaObjects();
1033 foreach ($this->answers as
$index => $answer) {
1034 $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->
getId(), 0,
$index);
1035 $answer_obj = $this->answers[
$index];
1036 $text .= $answer_obj->getAnswertext();
1054 parent::setExportDetailsXLS($worksheet, $startrow, $active_id,
$pass);
1059 $worksheet->setCell($startrow +
$i, 0, $answer->getAnswertext());
1060 $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow +
$i));
1062 count($solution) > 0 &&
1063 isset($solution[0]) &&
1064 is_array($solution[0]) &&
1065 strlen($solution[0][
'value1']) > 0 &&
$id == $solution[0][
'value1']
1067 $worksheet->setCell($startrow +
$i, 2, 1);
1069 $worksheet->setCell($startrow +
$i, 2, 0);
1074 return $startrow +
$i + 1;
1084 $this->thumb_size = $a_size;
1103 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1113 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1114 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1119 foreach ($this->
getAnswers() as $key => $answer_obj) {
1120 if ((
string) $answer_obj->getImage()) {
1124 "answertext" => (
string) $this->
formatSAQuestion($answer_obj->getAnswertext()),
1125 'html_id' => (
int) $this->getId() .
'_' . $key,
1126 "points" => (
float) $answer_obj->getPoints(),
1127 "order" => (
int) $answer_obj->getOrder(),
1128 "image" => (
string) $answer_obj->getImage(),
1129 "feedback" => $this->formatSAQuestion(
1130 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
1148 $answer = $this->answers[
$index];
1149 if (is_object($answer)) {
1151 $answer->setImage(
'');
1160 $multilineAnswerSetting =
$ilUser->getPref(
"tst_multiline_answers");
1161 if ($multilineAnswerSetting != 1) {
1162 $multilineAnswerSetting = 0;
1164 return $multilineAnswerSetting;
1171 $ilUser->writePref(
"tst_multiline_answers", $a_setting);
1185 $this->feedback_setting = $a_feedback_setting;
1199 if ($this->feedback_setting) {
1208 return 'feedback_correct_sc_mc';
1225 return $numExistingSolutionRecords > 0;
1253 require_once
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1285 $maxStep = $this->lookupMaxStep($active_id,
$pass);
1287 if ($maxStep !==
null) {
1289 "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1290 array(
"integer",
"integer",
"integer",
"integer"),
1291 array($active_id,
$pass, $this->
getId(), $maxStep)
1295 "SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1296 array(
"integer",
"integer",
"integer"),
1305 $result->addKeyValue($row[
"value1"], $row[
"value1"]);
1338 parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
1340 $origImagePath = $this->
buildImagePath($origQuestionId, $origParentObjId);
1341 $dupImagePath = $this->
buildImagePath($dupQuestionId, $dupParentObjId);
1344 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.
getAdditionalContentEditingMode()
getter for additional content editing mode for this question
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.
addAnswer( $answertext="", $points=0.0, $order=0, $answerimage="", $answer_id=-1)
Adds a possible answer for a single choice question.
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
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