19 declare(strict_types=1);
67 for ($i = count($this->answers); $i < self::NUM_REQUIRED_ANSWERS; $i++) {
69 $answer->setPosition($i);
70 $this->answers[$answer->getPosition()] = $answer;
76 return 'assKprimChoice';
81 return "qpl_qst_kprim";
175 $answer->setAnswertext(
194 if ($answer->getPosition() == $position) {
207 $this->answers[] = $answer;
214 while (
$data = $this->db->fetchAssoc(
$res)) {
215 $this->
setId($questionId);
236 if (is_numeric($data[
'thumb_size'])) {
244 if ($data[
'custom_true'] !==
null) {
248 if ($data[
'custom_false'] !==
null) {
252 if ($data[
'score_partsol'] !==
null) {
256 if (isset($data[
'feedback_setting'])) {
274 parent::loadFromDb($questionId);
279 $res = $this->db->queryF(
280 "SELECT * FROM {$this->getAnswerTableName()} WHERE question_fi = %s ORDER BY position ASC",
285 while (
$data = $this->db->fetchAssoc(
$res)) {
288 $answer->setPosition(
$data[
'position']);
292 $answer->setImageFile(
$data[
'imagefile']);
293 $answer->setThumbPrefix($this->getThumbPrefix());
297 $answer->setCorrectness(
$data[
'correctness']);
299 $this->answers[$answer->getPosition()] = $answer;
317 'question_fi' => [
'integer', $this->
getId()]
338 'question_fi' => [
'integer', $this->
getId()],
339 'position' => [
'integer', (
int) $answer->getPosition()]
342 'answertext' => [
'text', $answer->getAnswertext()],
343 'imagefile' => [
'text', $answer->getImageFile()],
344 'correctness' => [
'integer', (
int) $answer->getCorrectness()]
352 foreach ([$this->title, $this->author, $this->question] as $text) {
353 if (!strlen($text)) {
358 if (!isset($this->points)) {
365 if (is_null($answer->getCorrectness())) {
370 (!is_string($answer->getAnswertext()) || $answer->getAnswertext() ===
'') &&
371 (!is_string($answer->getImageFile()) || $answer->getImageFile() ===
'')
383 bool $authorized =
true 385 if ($pass ===
null) {
391 function () use ($answer, $active_id, $pass, $authorized) {
393 foreach ($answer as $index => $value) {
394 if ($value !==
null) {
407 bool $authorized_solution =
true 410 if (is_null($pass)) {
416 while (
$data = $this->db->fetchAssoc($result)) {
417 $found_values[(
int)
$data[
'value1']] = (
int)
$data[
'value2'];
427 return [self::ANSWER_TYPE_SINGLE_LINE, self::ANSWER_TYPE_MULTI_LINE];
433 return in_array($answerType, $validTypes);
448 self::ANSWER_TYPE_SINGLE_LINE => $lng->
txt(
'answers_singleline'),
449 self::ANSWER_TYPE_MULTI_LINE => $lng->
txt(
'answers_multiline')
456 self::OPTION_LABEL_RIGHT_WRONG,
457 self::OPTION_LABEL_PLUS_MINUS,
458 self::OPTION_LABEL_APPLICABLE_OR_NOT,
459 self::OPTION_LABEL_ADEQUATE_OR_NOT,
460 self::OPTION_LABEL_CUSTOM
468 function (array
$c,
string $option_label) use ($lng): array {
478 return match ($option_label) {
479 self::OPTION_LABEL_RIGHT_WRONG =>
'option_label_right_wrong',
480 self::OPTION_LABEL_PLUS_MINUS =>
'option_label_plus_minus',
481 self::OPTION_LABEL_APPLICABLE_OR_NOT =>
'option_label_applicable_or_not',
482 self::OPTION_LABEL_ADEQUATE_OR_NOT =>
'option_label_adequate_or_not',
483 self::OPTION_LABEL_CUSTOM =>
'option_label_custom' 490 return in_array($option_label, $valid_labels);
495 if ($option_label === self::OPTION_LABEL_CUSTOM) {
506 switch ($option_label) {
507 case self::OPTION_LABEL_RIGHT_WRONG:
508 return 'option_label_right';
510 case self::OPTION_LABEL_PLUS_MINUS:
511 return 'option_label_plus';
513 case self::OPTION_LABEL_APPLICABLE_OR_NOT:
514 return 'option_label_applicable';
516 case self::OPTION_LABEL_ADEQUATE_OR_NOT:
517 return 'option_label_adequate';
520 throw new \ErrorException(
'Invalide Option Label');
526 if ($option_label === self::OPTION_LABEL_CUSTOM) {
537 switch ($option_label) {
538 case self::OPTION_LABEL_RIGHT_WRONG:
539 return 'option_label_wrong';
541 case self::OPTION_LABEL_PLUS_MINUS:
542 return 'option_label_minus';
544 case self::OPTION_LABEL_APPLICABLE_OR_NOT:
545 return 'option_label_not_applicable';
547 case self::OPTION_LABEL_ADEQUATE_OR_NOT:
548 return 'option_label_not_adequate';
551 throw new \ErrorException(
'Invalide Option Label');
558 $lng->
txt(
'kprim_instruction_text'),
566 return $labelValue == self::OPTION_LABEL_CUSTOM;
574 if (!isset($files[$answer->getPosition()])) {
586 if (!file_exists($imagePath)) {
608 if (file_exists($answer->getImageFsPath())) {
612 if (file_exists($answer->getThumbFsPath())) {
616 $answer->setImageFile(
null);
621 $solutionSubmit = [];
622 $post = $this->dic->http()->wrapper()->post();
625 if (
$post->has(
"kprim_choice_result_$index")) {
626 $value =
$post->retrieve(
627 "kprim_choice_result_$index",
628 $this->dic->refinery()->kindlyTo()->string()
630 if (is_numeric($value)) {
631 $solutionSubmit[] = $value;
634 $solutionSubmit[] =
null;
637 return $solutionSubmit;
643 if ($found_values ===
null) {
647 if (!isset($found_values[$answer->getPosition()])) {
651 if ($found_values[$answer->getPosition()] == $answer->getCorrectness()) {
656 if ($numCorrect >= self::NUM_REQUIRED_ANSWERS) {
665 if (count($found_values) == 0) {
687 $combinedText = parent::getRTETextWithMediaObjects();
690 $combinedText .= $answer->getAnswertext();
693 return $combinedText;
712 $this->
lng->loadLanguageModule(
'assessment');
715 $result[
'id'] = $this->
getId();
725 $result[
'feedback'] = [
726 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
727 'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
738 foreach ($this->
getAnswers() as $key => $answer) {
739 if (strlen((
string) $answer->getImageFile())) {
745 'correctness' => (
bool) $answer->getCorrectness(),
746 'order' => (
int) $answer->getPosition(),
747 'image' => (string) $answer->getImageFile(),
749 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
762 $result[
'mobs'] = $mobs;
764 return json_encode($result);
770 return self::NUM_REQUIRED_ANSWERS - self::PARTIAL_SCORING_NUM_CORRECT_ANSWERS;
778 return 'feedback_correct_kprim';
783 if ($position < 0 || $position >= (self::NUM_REQUIRED_ANSWERS - 1)) {
787 for ($i = 0, $max = count($this->answers); $i < $max; $i++) {
788 if ($i == $position) {
789 $movingAnswer = $this->answers[$i];
790 $targetAnswer = $this->answers[ $i + 1 ];
792 $movingAnswer->setPosition($position + 1);
793 $targetAnswer->setPosition($position);
795 $this->answers[ $i + 1 ] = $movingAnswer;
796 $this->answers[$i] = $targetAnswer;
804 if ($position <= 0 || $position > (self::NUM_REQUIRED_ANSWERS - 1)) {
808 for ($i = 0, $max = count($this->answers); $i < $max; $i++) {
809 if ($i == $position) {
810 $movingAnswer = $this->answers[$i];
811 $targetAnswer = $this->answers[ $i - 1 ];
813 $movingAnswer->setPosition($position - 1);
814 $targetAnswer->setPosition($position);
816 $this->answers[ $i - 1 ] = $movingAnswer;
817 $this->answers[$i] = $targetAnswer;
827 AdditionalInformationGenerator::KEY_QUESTION_TYPE => (string) $this->
getQuestionType(),
830 AdditionalInformationGenerator::KEY_QUESTION_KPRIM_OPTION_LABEL => $additional_info
832 AdditionalInformationGenerator::KEY_QUESTION_SHUFFLE_ANSWER_OPTIONS => $additional_info
834 AdditionalInformationGenerator::KEY_FEEDBACK => [
835 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_INCOMPLETE => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
836 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_COMPLETE => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
840 $result[AdditionalInformationGenerator::KEY_QUESTION_KPRIM_SCORE_PARTIAL_SOLUTION_ENABLED] = $additional_info
844 foreach ($this->
getAnswers() as $key => $answer) {
846 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION => $this->
formatSAQuestion($answer->getAnswertext()),
847 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION_CORRECTNESS => $additional_info->
getTrueFalseTagForBool((
bool) $answer->getCorrectness()),
848 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION_ORDER => (
int) $answer->getPosition(),
849 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION_IMAGE => (string) $answer->getImageFile(),
851 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
856 $result[AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTIONS] =
$answers;
863 array $solution_values
865 $parsed_solution = [];
866 $true_option_label = $this->
getOptionLabel() === self::OPTION_LABEL_CUSTOM
869 $false_option_label = $this->
getOptionLabel() === self::OPTION_LABEL_CUSTOM
874 foreach ($solution_values as $solution) {
875 if ($solution[
'value1'] !== (
string)
$id) {
879 $value = $false_option_label;
880 if ($solution[
'value2'] ===
'1') {
881 $value = $true_option_label;
885 $parsed_solution[$answer->getAnswertext()] = $value;
887 return $parsed_solution;
892 $parsed_solution = [];
896 $value = $this->
lng->txt(
'none');
897 foreach ($solution_values as $solution) {
898 if ($solution[
'value1'] !== (
string)
$id) {
902 $value = $false_option_label;
903 if ($solution[
'value2'] ===
'1') {
904 $value = $true_option_label;
908 $parsed_solution[] =
"{$answer->getAnswertext()} ({$value})";
910 return $parsed_solution;
919 .
' (' . $v->
getCorrectness() ? $true_option_label : $false_option_label .
')',
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)
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...
setImageFile(?string $imageFile)
setScorePartialSolutionEnabled($scorePartialSolutionEnabled)
const OPTION_LABEL_RIGHT_WRONG
isCustomOptionLabel($labelValue)
loadAnswerData(int $question_id)
__construct($title='', $comment='', $author='', $owner=-1, $question='')
isValidOptionLabel(?string $option_label)
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)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getSpecificFeedbackSetting()
migrateToLmContent($content)
moveAnswerDown($position)
setOptionLabel(string $option_label)
getSpecificFeedbackAllCorrectOptionLabel()
setCustomTrueOptionLabel($customTrueOptionLabel)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
setComment(string $comment="")
addAnswer(ilAssKprimChoiceAnswer $answer)
toLog(AdditionalInformationGenerator $additional_info)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
const ANSWER_TYPE_MULTI_LINE
isScorePartialSolutionEnabled()
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
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)
getAnswerTypeSelectOptions(ilLanguage $lng)
saveWorkingData(int $active_id, ?int $pass=null, bool $authorized=true)
calculateReachedPoints(int $active_id, ?int $pass=null, bool $authorized_solution=true)
getTrueOptionLabel(string $option_label)
bool $shuffle_answers_enabled
cloneQuestionTypeSpecificProperties(\assQuestion $target)
isShuffleAnswersEnabled()
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
setLastChange(int $lastChange)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const OPTION_LABEL_APPLICABLE_OR_NOT
solutionValuesToLog(AdditionalInformationGenerator $additional_info, array $solution_values)
getTrueOptionLabelTranslation(ilLanguage $lng, string $option_label)
getCustomFalseOptionLabel()
handleFileUploads($answers, $files)
getFalseOptionLabel(string $option_label)
setSpecificFeedbackSetting(int $specific_feedback_setting)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
saveQuestionDataToDb(?int $original_id=null)
string $customFalseOptionLabel
getInstructionTextTranslation(ilLanguage $lng, $option_label)
calculateReachedPointsForSolution(?array $found_values, int $active_id=0)
setShuffleAnswersEnabled(bool $shuffle_answers_enabled)
setCustomFalseOptionLabel($customFalseOptionLabel)
const OPTION_LABEL_CUSTOM
getSolutionMaxPass(int $active_id)
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
saveToDb(?int $original_id=null)
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)
setOriginalId(?int $original_id)
setTitle(string $title="")
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
setThumbSize(int $thumbSize)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
bool $scorePartialSolutionEnabled
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.
solutionValuesToText(array $solution_values)
string $customTrueOptionLabel
getFalseOptionLabelTranslation(ilLanguage $lng, string $option_label)
int $specific_feedback_setting
getHtmlQuestionContentPurifier()
setAuthor(string $author="")
getCorrectSolutionForTextOutput(int $active_id, int $pass)
const OPTION_LABEL_PLUS_MINUS
getLangVarForOptionLabel(string $option_label)
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
setAnswerType($answerType)
static getDraftInstance()
const ANSWER_TYPE_SINGLE_LINE
toJSON()
Returns a JSON representation of the question.
setAnswertext($answertext)
setQuestion(string $question="")