65 $this->shuffleAnswersEnabled =
true;
66 $this->answerType = self::ANSWER_TYPE_SINGLE_LINE;
67 $this->thumbSize = self::DEFAULT_THUMB_SIZE;
68 $this->scorePartialSolutionEnabled =
true;
69 $this->optionLabel = self::OPTION_LABEL_RIGHT_WRONG;
70 $this->customTrueOptionLabel =
'';
71 $this->customFalseOptionLabel =
'';
75 $this->answers = array();
80 return 'assKprimChoice';
85 return "qpl_qst_kprim";
179 $answer->setAnswertext(
184 $this->answers = array_map($clean_answer_text,
$answers);
195 if ($answer->getPosition() == $position) {
208 $this->answers[] = $answer;
215 while (
$data = $this->db->fetchAssoc(
$res)) {
216 $this->
setId($questionId);
229 require_once
'Services/RTE/classes/class.ilRTE.php';
238 if (is_numeric($data[
'thumb_size'])) {
246 if ($data[
'custom_true'] !== null) {
250 if ($data[
'custom_false'] !== null) {
254 if ($data[
'score_partsol'] !== null) {
258 if (isset($data[
'feedback_setting'])) {
276 parent::loadFromDb($questionId);
282 $ilDB = $DIC[
'ilDB'];
284 $res = $this->db->queryF(
285 "SELECT * FROM {$this->getAnswerTableName()} WHERE question_fi = %s ORDER BY position ASC",
290 require_once
'Modules/TestQuestionPool/classes/class.ilAssKprimChoiceAnswer.php';
291 require_once
'Services/RTE/classes/class.ilRTE.php';
296 $answer->setPosition(
$data[
'position']);
300 $answer->setImageFile(
$data[
'imagefile']);
305 $answer->setCorrectness(
$data[
'correctness']);
307 $this->answers[$answer->getPosition()] = $answer;
310 for (
$i = count($this->answers);
$i < self::NUM_REQUIRED_ANSWERS;
$i++) {
313 $answer->setPosition(
$i);
315 $this->answers[$answer->getPosition()] = $answer;
321 if ($originalId ==
'') {
330 parent::saveToDb($originalId);
338 'question_fi' => array(
'integer', $this->
getId())
343 'thumb_size' => array(
'integer', $this->
getThumbSize()),
359 'question_fi' => array(
'integer', $this->
getId()),
360 'position' => array(
'integer', (
int) $answer->getPosition())
363 'answertext' => array(
'text', $answer->getAnswertext()),
364 'imagefile' => array(
'text', $answer->getImageFile()),
365 'correctness' => array(
'integer', (
int) $answer->getCorrectness())
375 foreach (array($this->title, $this->author, $this->question) as $text) {
376 if (!strlen($text)) {
381 if (!isset($this->points)) {
388 if (is_null($answer->getCorrectness())) {
393 (!is_string($answer->getAnswertext()) || $answer->getAnswertext() ===
'') &&
394 (!is_string($answer->getImageFile()) || $answer->getImageFile() ===
'')
411 public function saveWorkingData($active_id, $pass = null, $authorized =
true):
bool 416 if (is_null($pass)) {
417 include_once
"./Modules/Test/classes/class.ilObjTest.php";
423 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id, $pass, $authorized) {
428 foreach ($solutionSubmit as $answerIndex => $answerValue) {
429 $this->
saveCurrentSolution($active_id, $pass, (
int) $answerIndex, (
int) $answerValue, $authorized);
434 if ($entered_values) {
435 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
439 "log_user_entered_values",
441 ), $active_id, $this->
getId());
444 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
448 "log_user_not_entered_values",
450 ), $active_id, $this->
getId());
469 if ($returndetails) {
470 throw new ilTestException(
'return details not implemented for ' . __METHOD__);
474 $ilDB = $DIC[
'ilDB'];
476 $found_values = array();
477 if (is_null($pass)) {
484 $found_values[(
int)
$data[
'value1']] = (
int)
$data[
'value2'];
494 return array(self::ANSWER_TYPE_SINGLE_LINE, self::ANSWER_TYPE_MULTI_LINE);
515 self::ANSWER_TYPE_SINGLE_LINE => $lng->
txt(
'answers_singleline'),
516 self::ANSWER_TYPE_MULTI_LINE => $lng->
txt(
'answers_multiline')
523 self::OPTION_LABEL_RIGHT_WRONG,
524 self::OPTION_LABEL_PLUS_MINUS,
525 self::OPTION_LABEL_APPLICABLE_OR_NOT,
526 self::OPTION_LABEL_ADEQUATE_OR_NOT,
527 self::OPTION_LABEL_CUSTOM
534 self::OPTION_LABEL_RIGHT_WRONG => $lng->
txt(
'option_label_right_wrong'),
535 self::OPTION_LABEL_PLUS_MINUS => $lng->
txt(
'option_label_plus_minus'),
536 self::OPTION_LABEL_APPLICABLE_OR_NOT => $lng->
txt(
'option_label_applicable_or_not'),
537 self::OPTION_LABEL_ADEQUATE_OR_NOT => $lng->
txt(
'option_label_adequate_or_not'),
538 self::OPTION_LABEL_CUSTOM => $lng->
txt(
'option_label_custom')
551 case self::OPTION_LABEL_RIGHT_WRONG:
552 return $lng->
txt(
'option_label_right');
554 case self::OPTION_LABEL_PLUS_MINUS:
555 return $lng->
txt(
'option_label_plus');
557 case self::OPTION_LABEL_APPLICABLE_OR_NOT:
558 return $lng->
txt(
'option_label_applicable');
560 case self::OPTION_LABEL_ADEQUATE_OR_NOT:
561 return $lng->
txt(
'option_label_adequate');
563 case self::OPTION_LABEL_CUSTOM:
572 case self::OPTION_LABEL_RIGHT_WRONG:
573 return $lng->
txt(
'option_label_wrong');
575 case self::OPTION_LABEL_PLUS_MINUS:
576 return $lng->
txt(
'option_label_minus');
578 case self::OPTION_LABEL_APPLICABLE_OR_NOT:
579 return $lng->
txt(
'option_label_not_applicable');
581 case self::OPTION_LABEL_ADEQUATE_OR_NOT:
582 return $lng->
txt(
'option_label_not_adequate');
584 case self::OPTION_LABEL_CUSTOM:
593 $lng->
txt(
'kprim_instruction_text'),
601 return $labelValue == self::OPTION_LABEL_CUSTOM;
606 return self::THUMB_PREFIX;
613 if (strlen($answer->getImageFile())) {
627 switch (strtoupper($path_info[
'extension'])) {
647 if (!isset($files[$answer->getPosition()])) {
659 if (!file_exists($imagePath)) {
679 if (file_exists($answer->getImageFsPath())) {
683 if (file_exists($answer->getThumbFsPath())) {
687 $answer->setImageFile(null);
692 $solutionSubmit = [];
693 $post = $this->dic->http()->wrapper()->post();
696 if (
$post->has(
"kprim_choice_result_$index")) {
697 $value =
$post->retrieve(
698 "kprim_choice_result_$index",
699 $this->dic->refinery()->kindlyTo()->string()
701 if (is_numeric($value)) {
702 $solutionSubmit[] = $value;
706 return $solutionSubmit;
712 if ($found_values == null) {
716 if (!isset($found_values[$answer->getPosition()])) {
720 if ($found_values[$answer->getPosition()] == $answer->getCorrectness()) {
725 if ($numCorrect >= self::NUM_REQUIRED_ANSWERS) {
734 if (count($found_values) == 0) {
743 if ($this->
id <= 0) {
748 $this_id = $this->
getId();
752 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
756 if ((
int) $testObjId > 0) {
757 $clone->setObjId($testObjId);
778 $clone->copyPageOfQuestion($this_id);
780 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
782 $clone->cloneAnswerImages($this_id, $thisObjId, $clone->getId(), $clone->getObjId());
784 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
791 if ($this->
getId() <= 0) {
792 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
795 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
798 $sourceParentId = $this->
getObjId();
804 $clone->setObjId($targetParentId);
806 if ($targetQuestionTitle) {
807 $clone->setTitle($targetQuestionTitle);
812 $clone->copyPageOfQuestion($sourceQuestionId);
814 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
816 $clone->cloneAnswerImages($sourceQuestionId, $sourceParentId, $clone->getId(), $clone->getObjId());
818 $clone->onCopy($sourceParentId, $sourceQuestionId, $targetParentId, $clone->getId());
828 if ($this->
getId() <= 0) {
829 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
833 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
836 $source_questionpool_id = $this->
getObjId();
837 $clone->setObjId($target_questionpool_id);
847 $clone->cloneAnswerImages(
$original_id, $source_questionpool_id, $clone->getId(), $clone->getObjId());
849 $clone->onCopy($source_questionpool_id,
$original_id, $clone->getObjId(), $clone->getId());
856 parent::beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
858 $question = self::instantiateQuestion($origQuestionId);
860 foreach (
$question->getAnswers() as $answer) {
861 $question->removeAnswerImage($answer->getPosition());
867 parent::afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId);
869 $this->cloneAnswerImages($dupQuestionId, $dupParentObjId, $origQuestionId, $origParentObjId);
872 protected function cloneAnswerImages($sourceQuestionId, $sourceParentId, $targetQuestionId, $targetParentId):
void 878 $sourcePath = $this->
buildImagePath($sourceQuestionId, $sourceParentId);
879 $targetPath = $this->
buildImagePath($targetQuestionId, $targetParentId);
885 if (!file_exists($targetPath)) {
889 if (file_exists($sourcePath .
$filename)) {
890 if (!copy($sourcePath . $filename, $targetPath . $filename)) {
892 "Could not clone source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
893 $sourcePath . $filename,
894 $targetPath . $filename,
903 if (file_exists($sourcePath . $this->
getThumbPrefix() . $filename)) {
906 "Could not clone thumbnail source image '%s' to '%s' (srcQuestionId: %s|tgtQuestionId: %s|srcParentObjId: %s|tgtParentObjId: %s)",
922 $combinedText = parent::getRTETextWithMediaObjects();
925 $combinedText .= $answer->getAnswertext();
928 return $combinedText;
947 $this->
lng->loadLanguageModule(
'assessment');
949 require_once
'./Services/RTE/classes/class.ilRTE.php';
951 $result[
'id'] = $this->
getId();
961 $result[
'feedback'] = array(
962 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
963 'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
975 if (strlen((
string) $answer->getImageFile())) {
981 'correctness' => (
bool) $answer->getCorrectness(),
982 'order' => (
int) $answer->getPosition(),
983 'image' => (string) $answer->getImageFile(),
985 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0,
$key)
998 $result[
'mobs'] =
$mobs;
1000 return json_encode($result);
1006 return self::NUM_REQUIRED_ANSWERS - self::PARTIAL_SCORING_NUM_CORRECT_ANSWERS;
1014 return 'feedback_correct_kprim';
1026 return $numExistingSolutionRecords >= 4;
1034 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1040 $worksheet->
setCell($startrow +
$i, 0, $answer->getAnswertext());
1042 $correctness =
false;
1043 foreach ($solution as $solutionvalue) {
1044 if (
$id == $solutionvalue[
'value1']) {
1045 $correctness = $solutionvalue[
'value2'];
1049 $worksheet->
setCell($startrow +
$i, 2, $correctness);
1053 return $startrow +
$i + 1;
1058 if ($position < 0 || $position >= (self::NUM_REQUIRED_ANSWERS - 1)) {
1062 for (
$i = 0, $max = count($this->answers);
$i < $max;
$i++) {
1063 if (
$i == $position) {
1064 $movingAnswer = $this->answers[
$i];
1065 $targetAnswer = $this->answers[
$i + 1 ];
1067 $movingAnswer->setPosition($position + 1);
1068 $targetAnswer->setPosition($position);
1070 $this->answers[
$i + 1 ] = $movingAnswer;
1071 $this->answers[
$i] = $targetAnswer;
1079 if ($position <= 0 || $position > (self::NUM_REQUIRED_ANSWERS - 1)) {
1083 for (
$i = 0, $max = count($this->answers);
$i < $max;
$i++) {
1084 if (
$i == $position) {
1085 $movingAnswer = $this->answers[
$i];
1086 $targetAnswer = $this->answers[
$i - 1 ];
1088 $movingAnswer->setPosition($position - 1);
1089 $targetAnswer->setPosition($position);
1091 $this->answers[
$i - 1 ] = $movingAnswer;
1092 $this->answers[
$i] = $targetAnswer;
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
getValidOptionLabelsTranslated(ilLanguage $lng)
getSolutionValues($active_id, $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it.
setNrOfTries(int $a_nr_of_tries)
static getInstance($identifier)
setImageFsDir($imageFsDir)
isValidAnswerType($answerType)
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
getRTETextWithMediaObjects()
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
setScorePartialSolutionEnabled($scorePartialSolutionEnabled)
const OPTION_LABEL_RIGHT_WRONG
isCustomOptionLabel($labelValue)
Abstract basic class which is to be extended by the concrete assessment question type classes...
__construct($title='', $comment='', $author='', $owner=-1, $question='')
saveWorkingData(int $active_id, int $pass, bool $authorized=true)
Saves the learners input of the question to the database.
getColumnCoord(int $a_col)
Get column "name" from number.
const OPTION_LABEL_ADEQUATE_OR_NOT
const NUM_REQUIRED_ANSWERS
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getImagePathWeb()
Returns the web image path for web accessable images of a question.
const PARTIAL_SCORING_NUM_CORRECT_ANSWERS
removeAnswerImage($position)
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
getSpecificFeedbackSetting()
static _getOriginalId(int $question_id)
migrateToLmContent($content)
moveAnswerDown($position)
static getNumExistingSolutionRecords(int $activeId, int $pass, int $questionId)
copyObject($target_questionpool_id, $title="")
Copies an assMultipleChoice object.
getSpecificFeedbackAllCorrectOptionLabel()
setCustomTrueOptionLabel($customTrueOptionLabel)
isValidOptionLabel($optionLabel)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
loadAnswerData($questionId)
setComment(string $comment="")
getTrueOptionLabelTranslation(ilLanguage $lng, $optionLabel)
float $points
The maximum available points for the question.
beforeSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
addAnswer(ilAssKprimChoiceAnswer $answer)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setOptionLabel($optionLabel)
duplicate(bool $for_test=true, string $title="", string $author="", string $owner="", $testObjId=null)
const ANSWER_TYPE_MULTI_LINE
isScorePartialSolutionEnabled()
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
setBold(string $a_coords)
Set cell(s) to bold.
static _enabledAssessmentLogging()
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question.
buildHashedImageFilename(string $plain_image_filename, bool $unique=false)
isSingleLineAnswerType($answerType)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
getAnswerTypeSelectOptions(ilLanguage $lng)
static logAction(string $logtext, int $active_id, int $question_id)
isShuffleAnswersEnabled()
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass)
{}
setShuffleAnswersEnabled($shuffleAnswersEnabled)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const OPTION_LABEL_APPLICABLE_OR_NOT
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
getCustomFalseOptionLabel()
handleFileUploads($answers, $files)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
string $question
The question text.
static convertImage(string $a_from, string $a_to, string $a_target_format="", string $a_geometry="", string $a_background_color="")
convert image
setCustomFalseOptionLabel($customFalseOptionLabel)
getFalseOptionLabelTranslation(ilLanguage $lng, $optionLabel)
saveQuestionDataToDb(int $original_id=-1)
const OPTION_LABEL_CUSTOM
getSolutionMaxPass(int $active_id)
calculateReachedPointsForSolution($found_values, $active_id=0)
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
const FEEDBACK_SETTING_ALL
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
setSpecificFeedbackSetting($specificFeedbackSetting)
setOriginalId(?int $original_id)
buildImagePath($questionId, $parentObjectId)
setTitle(string $title="")
generateThumbForFile($path, $file)
setLastChange($lastChange)
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
setThumbSize(int $thumbSize)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
getCustomTrueOptionLabel()
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
handleFileUpload(ilAssKprimChoiceAnswer $answer, $fileData)
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
$scorePartialSolutionEnabled
ILIAS DI LoggingServices $ilLog
getHtmlQuestionContentPurifier()
setAuthor(string $author="")
const OPTION_LABEL_PLUS_MINUS
static isObligationPossible(int $questionId)
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
setAnswerType($answerType)
getInstructionTextTranslation(ilLanguage $lng, $optionLabel)
static getDraftInstance()
isAnswered(int $active_id, int $pass)
const ANSWER_TYPE_SINGLE_LINE
toJSON()
Returns a JSON representation of the question.
afterSyncWithOriginal($origQuestionId, $dupQuestionId, $origParentObjId, $dupParentObjId)
setAnswertext($answertext)
setQuestion(string $question="")