19declare(strict_types=1);
138 $this->minAutoComplete = $min_auto_complete;
148 if (strlen($this->title)
150 && $this->long_menu_text
151 &&
sizeof($this->answers) > 0
152 &&
sizeof($this->correct_answers) > 0
177 if ($correct_answers ===
null
179 || $hidden_text_files ===
null
180 || $hidden_text_files === []) {
190 if (!is_array($correct_answers_row[0]) || $correct_answers_row[0] === []) {
193 if ($correct_answers_row[1] > 0) {
194 array_push(
$points, $correct_answers_row[1]);
216 foreach (
$answers[0] as $key => $answer) {
217 if (!in_array($answer, $answer_options)) {
237 $sum += (float) $add[1];
246 $this->db->manipulateF(
251 $this->db->manipulateF(
253 ) .
" (question_fi, long_menu_text, feedback_setting, min_auto_complete, identical_scoring) VALUES (%s, %s, %s, %s, %s)",
254 [
"integer",
"text",
"integer",
"integer",
"integer"],
273 foreach ($gap[0] as $position => $answer) {
274 if ($type_array ==
null) {
277 $type = $type_array[$gap_number];
282 'question_fi' => [
'integer', $this->
getId()],
283 'gap_number' => [
'integer', (
int) $gap_number],
284 'position' => [
'integer', (
int) $position]
287 'answer_text' => [
'text', $answer],
288 'points' => [
'float', $gap[1]],
289 'type' => [
'integer', (
int) $type]
302 foreach ($array as $gap => $values) {
304 if (is_array($values)) {
305 foreach ($values as $key => $value) {
306 $file_content .= $value .
"\n";
308 $file_content = rtrim($file_content,
"\n");
310 fwrite($file, $file_content);
320 if ($files ===
false) {
326 foreach ($files as $file) {
327 $gap = str_replace(
'.txt',
'', basename($file));
328 $answers[(
int) $gap] = explode(
"\n", file_get_contents($file));
348 throw new ilException(
'Cannot create export directory');
352 !is_dir($folder_name) ||
353 !is_readable($folder_name) ||
354 !is_writable($folder_name)
356 throw new ilException(
'Cannot create export directory');
362 $result = $this->db->queryF(
367 if ($result->numRows() == 1) {
368 $data = $this->db->fetchAssoc($result);
369 $this->
setId($question_id);
373 $this->
setComment((
string) $data[
'description']);
381 $this->
setMinAutoComplete($data[
'min_auto_complete'] ?? self::MIN_LENGTH_AUTOCOMPLETE);
382 if (isset(
$data[
'feedback_setting'])) {
400 parent::loadFromDb($question_id);
405 $res = $this->db->queryF(
406 "SELECT * FROM {$this->getAnswerTableName()} WHERE question_fi = %s ORDER BY gap_number, position ASC",
412 while (
$data = $this->db->fetchAssoc(
$res)) {
424 $res = $this->db->queryF(
425 'SELECT gap_number, answer_text FROM ' . $this->
getAnswerTableName() .
' WHERE question_fi = %s',
429 while (
$data = $this->db->fetchAssoc(
$res)) {
432 $correct_answers[
$data[
'gap_number']] .= rtrim(
$data[
'answer_text']);
443 $res = $this->db->queryF(
444 'SELECT answer_text FROM ' . $this->
getAnswerTableName() .
' WHERE question_fi = %s AND gap_number = %s',
445 [
'integer',
'integer'],
446 [$question_id, $gap_id]
448 while (
$data = $this->db->fetchAssoc(
$res)) {
457 $res = $this->db->queryF(
458 'SELECT points FROM ' . $this->
getAnswerTableName() .
' WHERE question_fi = %s AND gap_number = %s GROUP BY gap_number, points',
459 [
'integer',
'integer'],
460 [$question_id, $gap_id]
462 while (
$data = $this->db->fetchAssoc(
$res)) {
483 bool $authorized_solution =
true
486 if (is_null($pass)) {
490 while (
$data = $this->db->fetchAssoc($result)) {
499 if ($found_values ==
null) {
503 $solution_values_text = [];
504 foreach ($found_values as $key => $answer) {
505 if ($answer ===
'') {
509 $correct_answers = $this->getCorrectAnswersForGap($this->
id, $key);
510 if (!in_array($answer, $correct_answers)) {
514 $points_gap = $this->getPointsForGap($this->
id, $key);
515 if (!$this->getIdenticalScoring()
516 && in_array($answer, $solution_values_text)
521 $points += $points_gap;
522 array_push($solution_values_text, $answer);
531 bool $authorized =
true
533 if (is_null($pass)) {
537 $answer = $this->getSolutionSubmit();
538 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(
539 function () use ($answer, $active_id, $pass, $authorized) {
540 $this->removeCurrentSolution($active_id, $pass, $authorized);
542 foreach ($answer as $key => $value) {
546 $this->saveCurrentSolution($active_id, $pass, $key, $value, $authorized);
562 'authorized' =>
false,
563 'intermediate' => false
567 SELECT authorized, COUNT(*) cnt
569 WHERE active_fi = " . $this->db->quote($activeId,
'integer') .
"
570 AND question_fi = " . $this->db->quote($this->
getId(),
'integer') .
"
571 AND pass = " . $this->db->quote($pass,
'integer') .
"
575 if ($this->getStep() !==
null) {
576 $query .=
" AND step = " . $this->db->quote((
int) $this->getStep(),
'integer') .
" ";
583 $result = $this->db->query($query);
585 while ($row = $this->db->fetchAssoc($result)) {
586 if ($row[
'authorized']) {
587 $return[
'authorized'] = $row[
'cnt'] > 0;
589 $return[
'intermediate'] = $row[
'cnt'] > 0;
599 $solution_submit = [];
600 foreach ($this->questionpool_request->strArray(
'answer') as $key => $value) {
601 $solution_submit[$key] = $value;
603 return $solution_submit;
608 $answer = $this->questionpool_request->strArray(
'answer');
619 return "assLongMenu";
624 return 'qpl_qst_lome';
633 return parent::getRTETextWithMediaObjects() . $this->getLongMenuTextValue();
648 $points = $this->calculateReachedPoints($active_id, $pass);
649 $max_points = $this->getMaximumPoints();
651 $result->setReachedPercentage(($points / $max_points) * 100);
666 return $this->createArrayFromFile();
676 $this->db->manipulateF(
677 'DELETE FROM ' . $this->getAnswerTableName() .
' WHERE question_fi = %s',
683 public function delete(
int $question_id):
void
685 parent::delete($question_id);
686 $this->clearFolder(
false);
694 $this->setLongMenuTextValue($migrator->
migrateToLmContent($this->getLongMenuTextValue()));
703 $result[
'id'] = $this->
getId();
704 $result[
'type'] = (string) $this->getQuestionType();
705 $result[
'title'] = $this->getTitleForHTMLOutput();
706 $result[
'question'] = $this->formatSAQuestion($this->getQuestion());
707 $replaced_quesiton_text = $this->getLongMenuTextValue();
708 $result[
'lmtext'] = $this->formatSAQuestion($replaced_quesiton_text);
709 $result[
'nr_of_tries'] = $this->getNrOfTries();
710 $result[
'shuffle'] = $this->getShuffle();
711 $result[
'feedback'] = [
712 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
713 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
717 $result[
'answers'] = $this->getAnswers();
718 $result[
'correct_answers'] = $this->getCorrectAnswers();
719 $result[
'mobs'] = $mobs;
720 return json_encode($result);
725 return $this->identical_scoring;
730 $this->identical_scoring = $identical_scoring;
736 AdditionalInformationGenerator::KEY_QUESTION_TYPE => (string) $this->getQuestionType(),
737 AdditionalInformationGenerator::KEY_QUESTION_TITLE => $this->getTitleForHTMLOutput(),
738 AdditionalInformationGenerator::KEY_QUESTION_TEXT => $this->formatSAQuestion($this->getQuestion()),
739 AdditionalInformationGenerator::KEY_QUESTION_LONGMENU_TEXT => $this->formatSAQuestion($this->getLongMenuTextValue()),
740 AdditionalInformationGenerator::KEY_QUESTION_SHUFFLE_ANSWER_OPTIONS => $additional_info
742 AdditionalInformationGenerator::KEY_FEEDBACK => [
743 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_INCOMPLETE => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
744 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_COMPLETE => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
746 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTIONS => $this->getAnswersForLog($additional_info),
747 AdditionalInformationGenerator::KEY_QUESTION_CORRECT_ANSWER_OPTIONS => $this->getCorrectAnswersForLog($additional_info)
756 static function (
string $c, array $v) use ($additional_info, &$i):
string {
758 .
' ' . $i++ .
': ' . implode(
',', $v) .
'; ';
767 self::ANSWER_TYPE_SELECT_VAL => $additional_info->
getTagForLangVar(
'answers_select'),
768 self::ANSWER_TYPE_TEXT_VAL => $additional_info->
getTagForLangVar(
'answers_text_box')
773 $this->getCorrectAnswers(),
774 static function (
string $c, array $v) use ($additional_info, $answer_types, &$i):
string {
776 .
' ' . $i++ .
': ' . implode(
',', $v[0]) .
', '
778 . $additional_info->
getTagForLangVar(
'type') .
': ' . $answer_types[$v[2]] .
'; ';
786 array $solution_values
788 $parsed_solution = [];
789 foreach ($this->getCorrectAnswers() as $gap_index => $gap) {
790 foreach ($solution_values as $solution) {
791 if ($gap_index !== (
int) $solution[
'value1']) {
794 $value = $solution[
'value2'];
795 if ($gap[2] === self::ANSWER_TYPE_SELECT_VAL
796 && $value ===
'-1') {
799 $parsed_solution[$gap_index + 1] = $value;
803 return $parsed_solution;
808 $parsed_solution = [];
810 foreach ($this->getCorrectAnswers() as $gap_index => $gap) {
811 foreach ($solution_values as $solution) {
812 if ($gap_index !== (
int) $solution[
'value1']) {
815 $value = $solution[
'value2'];
816 if ($gap[2] === self::ANSWER_TYPE_SELECT_VAL
817 && $value ===
'-1') {
820 $parsed_solution[] = $this->
lng->txt(
'gap') .
' ' . $gap_index + 1 .
': ' . $value;
824 return $parsed_solution;
829 $correct_answers = [];
830 foreach ($this->getCorrectAnswers() as $gap_index => $gap) {
831 $correct_answers[] = $this->
lng->txt(
'gap')
832 .
' ' . $gap_index .
': ' . implode(
',', $gap[0]);
834 return $correct_answers;
setOriginalId(?int $original_id)
getHtmlQuestionContentPurifier()
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
setQuestion(string $question="")
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
setAuthor(string $author="")
setComment(string $comment="")
getSolutionMaxPass(int $active_id)
setNrOfTries(int $a_nr_of_tries)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
setTitle(string $title="")
saveQuestionDataToDb(?int $original_id=null)
const FEEDBACK_SETTING_ALL
static getDraftInstance()
static getInstance($identifier)
setParticipantsSolution($participantSolution)
Base class for ILIAS Exception handling.
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getDataDir()
get data directory (outside webspace)
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
migrateToLmContent($content)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if(!file_exists('../ilias.ini.php'))