4 require_once
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8 require_once
'./Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9 require_once
'./Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
50 $this->errortext =
'';
51 $this->textsize = 100.0;
52 $this->errordata =
array();
62 if (strlen($this->title)
90 $ilDB->manipulateF(
"DELETE FROM qpl_a_errortext WHERE question_fi = %s",
96 foreach ($this->errordata as $object)
98 $next_id = $ilDB->nextId(
'qpl_a_errortext' );
99 $ilDB->manipulateF(
"INSERT INTO qpl_a_errortext (answer_id, question_fi, text_wrong, text_correct, points, sequence) VALUES (%s, %s, %s, %s, %s, %s)",
100 array(
'integer',
'integer',
'text',
'text',
'float',
'integer' ),
105 $object->text_correct,
127 $ilDB->manipulateF(
"INSERT INTO " . $this->
getAdditionalTableName() .
" (question_fi, errortext, textsize, points_wrong) VALUES (%s, %s, %s, %s)",
128 array(
"integer",
"text",
"float",
"float"),
155 $this->
setId($question_id);
164 include_once(
"./Services/RTE/classes/class.ilRTE.php");
180 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_errortext WHERE question_fi = %s ORDER BY sequence ASC",
184 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
193 parent::loadFromDb($question_id);
207 $this_id = $this->
getId();
211 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
215 if( (
int)$testObjId > 0 )
217 $clone->setObjId($testObjId);
243 $clone->copyPageOfQuestion($this_id);
245 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
247 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
263 $thisId = $this->
getId();
267 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
270 $clone->setObjId($target_questionpool_id);
282 $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
295 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
298 $sourceParentId = $this->
getObjId();
304 $clone->setObjId($targetParentId);
306 if ($targetQuestionTitle)
308 $clone->setTitle($targetQuestionTitle);
313 $clone->copyPageOfQuestion($sourceQuestionId);
315 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
317 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
330 foreach ($this->errordata as $object)
332 if ($object->points > 0) $maxpoints += $object->points;
351 throw new ilTestException(
'return details not implemented for '.__METHOD__);
357 $positions =
array();
358 if (is_null(
$pass)) {
364 array_push($positions,
$row[
'value1']);
392 include_once
"./Modules/Test/classes/class.ilObjTest.php";
396 $entered_values =
false;
398 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function() use (&$entered_values, $active_id,
$pass, $authorized) {
404 $selected = explode(
",",
$_POST[
"qst_" . $this->
getId()]);
405 foreach ($selected as $position)
409 $entered_values =
true;
416 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
424 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
438 $selection = explode(
',',
$_POST[
"qst_{$this->getId()}"]);
442 $selection =
array();
463 return "assErrorText";
473 return "qpl_qst_errortext";
483 return "qpl_a_errortext";
492 $text = parent::getRTETextWithMediaObjects();
504 $selections =
array();
506 if (is_array($solutions))
508 foreach ($solutions as $solution)
510 array_push($selections, $solution[
'value1']);
512 $errortext_value = join(
",", $selections);
519 return $startrow + $i + 1;
534 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
536 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php";
538 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
547 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
549 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class.assErrorTextExport.php";
551 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
561 $user_solution =
array();
562 return $user_solution;
567 if (strlen($a_text) == 0)
573 $a_text = str_replace(
array(
"((",
"))"),
array(
"~",
"~"), $a_text);
577 $r_passage =
"/(~([^~]+)~|#([^\s]+))/";
579 preg_match_all($r_passage, $a_text, $matches);
581 if (is_array($matches[0]) && !empty($matches[0])) {
586 $matches = array_intersect_key($matches,
array(2 =>
'', 3 =>
''));
589 $matches[2] = array_diff($matches[2],
array(
''));
590 $matches[3] = array_diff($matches[3],
array(
''));
593 "passages" => $matches[2],
594 "words" => $matches[3],);
602 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
604 $this->errordata =
array();
605 foreach ($a_data as $err_type =>
$errors) {
612 foreach ($temp as $object) {
613 if (strcmp($object->text_wrong,
$error) == 0) {
614 $text_correct = $object->text_correct;
622 ksort($this->errordata);
625 public function createErrorTextOutput($selections = null, $graphicalOutput =
false, $correct_solution =
false, $use_link_tags =
true)
629 include_once
"./Services/Utilities/classes/class.ilStr.php";
630 if (!is_array($selections)) $selections =
array();
631 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
633 foreach ($textarray as $textidx =>
$text)
636 $passage_end =
false;
637 $items = preg_split(
"/\s+/",
$text);
638 foreach ($items as $idx => $item)
643 ($posHash = strpos($item,
'#')) === 0 ||
644 ($posOpeningBrackets = strpos($item,
'((')) === 0 ||
645 ($posClosingBrackets = strpos($item,
'))')) !==
false 650 if($posHash !==
false)
652 $item = ilStr::substr($item, 1, ilStr::strlen($item) - 1);
653 $passage_end =
false;
655 else if($posOpeningBrackets !==
false)
659 $items_in_passage =
array();
660 $passage_end =
false;
661 $item = ilStr::substr($item, 2, ilStr::strlen($item) - 2);
665 if(strpos($item,
'))') !==
false)
667 $item = str_replace(
"))",
"", $item);
674 $item = str_replace(
"))",
"", $item);
677 if($correct_solution && !$in_passage)
679 $errorobject = $this->errordata[$errorcounter];
680 if (is_object($errorobject) )
682 $item = strlen($errorobject->text_correct) ? $errorobject->text_correct :
' ';
688 if($in_passage && !$passage_end)
690 $items_in_passage[$idx] = $item;
696 if($in_passage && $passage_end)
699 $passage_end =
false;
700 if($correct_solution)
703 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem" 706 $errorobject = $this->errordata[$errorcounter];
707 if (is_object($errorobject) )
709 $item = strlen($errorobject->text_correct) ? $errorobject->text_correct :
' ';
717 $group_selected =
true;
720 $start_idx = $passage_start_idx;
721 foreach($items_in_passage as $tmp_idx => $tmp_item)
725 $group_selected =
false;
735 $group_selected =
false;
740 $item_stack =
array();
741 $start_idx = $passage_start_idx;
742 foreach($items_in_passage as $tmp_idx => $tmp_item)
745 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem" 751 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem" 757 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_right") .
'" title="' . $this->lng->txt(
"answer_is_right") .
'" /> ';
761 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_not_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_wrong") .
'" title="' . $this->lng->txt(
"answer_is_wrong") .
'" /> ';
766 $item_stack = trim(implode(
" ", $item_stack));
767 $item_stack = strlen($item_stack) ? $item_stack :
' ';
771 $items[$idx] =
'<span class="selGroup">'.$item_stack.
'</span>';
775 $items[$idx] = $item_stack;
783 $class =
'ilc_qetitem_ErrorTextItem';
787 $class =
"ilc_qetitem_ErrorTextSelected";
792 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_right") .
'" title="' . $this->lng->txt(
"answer_is_right") .
'" /> ';
796 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_not_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_wrong") .
'" title="' . $this->lng->txt(
"answer_is_wrong") .
'" /> ';
804 $textarray[$textidx] =
'<p>' . implode(
" ", $items) .
'</p>';
807 return implode(
"\n", $textarray);
812 foreach($selection as
$data)
814 if( !is_array($data) )
834 include_once
"./Services/Utilities/classes/class.ilStr.php";
835 if (!is_array($selections)) $selections =
array();
836 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
837 foreach ($textarray as $textidx =>
$text)
839 $items = preg_split(
"/\s+/",
$text);
840 foreach ($items as $idx => $item)
842 if (($posHash = strpos($item,
'#')) === 0
843 || ($posOpeningBrackets = strpos($item,
'((')) === 0
844 || ($posClosingBrackets = strpos($item,
'))')) !==
false) {
847 if ($posHash !==
false)
848 $item = ilStr::substr($item, 1, ilStr::strlen($item) - 1);
849 elseif ($posOpeningBrackets !==
false) {
850 $item = ilStr::substr($item, 2, ilStr::strlen($item) - 2);
854 if (strpos($item,
'))') !==
false)
855 $item = ilStr::substr($item, 0, ilStr::strlen($item) - 2);
859 if ($item{$posClosingBrackets+2} ==
',')
862 $item = ilStr::substr($item, 0, $posClosingBrackets) . $appendComma;
867 if (in_array(
$counter, $selections))
872 if (in_array(
$counter, $selections))
876 $items[$idx] = $word;
879 $textarray[$textidx] = join($items,
" ");
881 return join($textarray,
"\n");
890 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
891 foreach ($textarray as $textidx =>
$text)
893 $items = preg_split(
"/\s+/",
$text);
895 foreach ($items as $word)
898 $isErrorItem =
false;
899 if (strpos($word,
'#') === 0)
902 $errorobject = $this->errordata[$errorcounter];
903 if (is_object($errorobject))
905 $points = $errorobject->points;
910 elseif (($posOpeningBracket = strpos($word,
'((')) === 0
911 || ($posClosingBracket = strpos($word,
'))')) !==
false 916 if ($posOpeningBracket !==
false)
918 $passages[] =
array(
'begin_pos' =>
$counter,
'cnt_words' => 0);
921 elseif ($posClosingBracket !==
false)
924 $cur_pidx = count($passages) - 1;
925 $passages[$cur_pidx][
'end_pos'] =
$counter;
927 $errorobject = $this->errordata[$errorcounter];
928 if (is_object($errorobject))
930 $passages[$cur_pidx][
'score'] = $errorobject->points;
931 $passages[$cur_pidx][
'isError'] =
true;
937 $cur_pidx = count($passages) - 1;
938 $passages[$cur_pidx][
'cnt_words']++;
947 $selections =
array();
948 foreach ($passages as $cnt => $pdata)
950 if (!$withPositivePointsOnly && $pdata[
'isError'] || $withPositivePointsOnly && $pdata[
'score'] > 0)
952 $indexes =
range($pdata[
'begin_pos'], $pdata[
'end_pos']);
953 $selections[$pdata[
'begin_pos']] = $indexes;
957 foreach ($words as $idx => $word)
959 if (!$withPositivePointsOnly && $word[
'isError'] || $withPositivePointsOnly && $word[
'points'] > 0)
961 $selections[$idx] =
array($idx);
967 $selections = array_values($selections);
978 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
979 foreach ($textarray as $textidx =>
$text)
981 $items = preg_split(
"/\s+/",
$text);
983 foreach ($items as $word)
986 if (strpos($word,
'#') === 0)
989 $errorobject = $this->errordata[$errorcounter];
990 if (is_object($errorobject))
992 $points = $errorobject->points;
996 elseif (($posOpeningBracket = strpos($word,
'((')) === 0
997 || ($posClosingBracket = strpos($word,
'))')) !==
false 1002 if ($posOpeningBracket !==
false)
1004 $passages[] =
array(
'begin_pos' =>
$counter,
'cnt_words' => 0);
1007 elseif ($posClosingBracket !==
false)
1010 $cur_pidx = count($passages) - 1;
1011 $passages[$cur_pidx][
'end_pos'] =
$counter;
1013 $errorobject = $this->errordata[$errorcounter];
1014 if (is_object($errorobject))
1016 $passages[$cur_pidx][
'score'] = $errorobject->points;
1021 $cur_pidx = count($passages) - 1;
1022 $passages[$cur_pidx][
'cnt_words']++;
1033 foreach ($positions as $position)
1038 $total += $words[$position][
'points'];
1041 foreach ($passages as $cnt => $p_data)
1047 $isSelected = in_array($p_data[
'begin_pos'], $positions);
1049 for ($i = 0; $i < $p_data[
'cnt_words']; $i++)
1051 $current_pos = $p_data[
'begin_pos'] + $i;
1052 $isSelected = $isSelected && in_array($current_pos, $positions);
1055 $total += $isSelected ? $p_data[
'score'] : 0;
1066 $this->errordata =
array();
1071 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
1102 $this->errortext = $a_value;
1123 if($a_value === null)
1127 $this->textsize = $a_value;
1147 $this->points_wrong = $a_value;
1163 case "points_wrong":
1167 return parent::__get($value);
1185 case "points_wrong":
1189 parent::__set($key, $value);
1200 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1210 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1211 'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1217 array_push($answers,
array(
1218 "answertext_wrong" => (
string) $answer_obj->text_wrong,
1219 "answertext_correct" => (
string) $answer_obj->text_correct,
1220 "points" => (
float)$answer_obj->points,
1221 "order" => (
int)$idx+1
1224 $result[
'correct_answers'] = $answers;
1227 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
1228 foreach ($textarray as $textidx =>
$text)
1230 $items = preg_split(
"/\s+/", trim(
$text));
1231 foreach ($items as $idx => $item)
1233 if(substr($item, 0, 1) ==
"#")
1235 $item = substr($item, 1);
1238 foreach(
$result[
"correct_answers"] as $aidx => $answer)
1240 if($answer[
"answertext_wrong"] == $item && !$answer[
"pos"])
1242 $result[
"correct_answers"][$aidx][
"pos"] = $this->
getId().
"_".$textidx.
"_".($idx+1);
1247 array_push($answers,
array(
1249 "order" => $this->
getId().
"_".$textidx.
"_".($idx+1)
1252 if($textidx !=
sizeof($textarray)-1)
1254 array_push($answers,
array(
1255 "answertext" =>
"###",
1256 "order" => $this->
getId().
"_".$textidx.
"_".($idx+2)
1260 $result[
'answers'] = $answers;
1278 require_once
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1310 $data = $ilDB->queryF(
1311 "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = ( 1312 SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s 1314 array(
"integer",
"integer",
"integer",
"integer",
"integer",
"integer"),
1341 $error_text_array = explode(
' ', $this->errortext);
1345 if(array_key_exists($index, $error_text_array))
1347 return $error_text_array[$index];
1353 return $error_text_array;
getErrorText()
Get error text.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getId()
Gets the id of the assQuestion object.
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms public
getErrorData()
Get error data.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
const PercentageResultExpression
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
{}
Class iQuestionCondition.
setTextSize($a_value)
Set text size in percent.
toJSON()
Returns a JSON representation of the question.
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
const NumberOfResultExpression
const ExclusiveResultExpression
getTextSize()
Set text size in percent.
createErrorTextExport($selections=null)
Abstract basic class which is to be extended by the concrete assessment question type classes...
loadFromDb($question_id)
Loads the object from the database.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
toXML($a_include_header=true, $a_include_binary=true, $a_shuffle=false, $test_output=false, $force_image_references=false)
Returns a QTI xml representation of the question and sets the internal domxml variable with the DOM X...
__get($value)
Object getter.
createErrorTextOutput($selections=null, $graphicalOutput=false, $correct_solution=false, $use_link_tags=true)
ensureNonNegativePoints($points)
saveToDb($original_id="")
Saves a the object to the database.
isTokenSelected($counter, array $selection)
getErrorsFromText($a_text="")
setId($id=-1)
Sets the id of the assQuestion object.
setErrorText($a_value)
Set error text.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
Add rich text string
The name of the decorator.
copyObject($target_questionpool_id, $title="")
Copies an object.
getQuestionType()
Returns the question type of the question.
Class for error text answers.
getParticipantsSolution()
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
setNrOfTries($a_nr_of_tries)
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
Class for error text question exports.
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...
__construct( $title='', $comment='', $author='', $owner=-1, $question='')
assErorText constructor
getObjId()
Get the object id of the container object.
getShuffle()
Gets the shuffle flag.
Base Exception for all Exceptions relating to Modules/Test.
setParticipantsSolution($participantSolution)
getPointsWrong()
Get wrong points.
isComplete()
Returns true, if a single choice question is complete for use.
static _getLogLanguage()
retrieve the log language for assessment logging
setAuthor($author="")
Sets the authors name of the assQuestion object.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
getPointsForSelectedPositions($positions)
Class ilUserQuestionResult.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
setPointsWrong($a_value)
Set wrong points.
saveWorkingData($active_id, $pass=NULL, $authorized=true)
Saves the learners input of the question to the database.
getOperators($expression)
Get all available operations for a specific question.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
Class for error text questions.
Interface ilObjAnswerScoringAdjustable.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates the object.
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
getQuestion()
Gets the question string of the question object.
getExpressionTypes()
Get all available expression types for a specific question.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
getAdditionalTableName()
Returns the name of the additional question data table in the database.
Create styles array
The data for the language used.
static getOperatorsByExpression($expression)
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{}
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
setQuestion($question="")
Sets the question string of the question object.
Interface ilObjQuestionScoringAdjustable.
removeCurrentSolution($active_id, $pass, $authorized=true)
getBestSelection($withPositivePointsOnly=true)
setOriginalId($original_id)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
__set($key, $value)
Object setter.
getSolutionValues($active_id, $pass=NULL, $authorized=true)
Loads solutions of a given user from the database an returns it.
getTitle()
Gets the title string of the assQuestion object.
calculateReachedPoints($active_id, $pass=NULL, $authorizedSolution=true, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
saveAdditionalQuestionDataToDb()
Saves the data for the additional data table.
addErrorData($text_wrong, $text_correct, $points)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
setTitle($title="")
Sets the title string of the assQuestion object.
setObjId($obj_id=0)
Set the object id of the container object.
flushErrorData()
Flush error data.
setComment($comment="")
Sets the comment string of the assQuestion object.
getAnswerTableName()
Returns the name of the answer table in the database.
getErrorTokenHtml($item, $class, $useLinkTags)
Class for error text question imports.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
const EmptyAnswerExpression