private function populateSpecificFeedbackInline($user_solution, $answer_id, $template) { require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php'; if ($this->object->getSpecificFeedbackSetting() == ilAssConfigurableMultiOptionQuestionFeedback::FEEDBACK_SETTING_CHECKED) { foreach ($user_solution as $mc_solution) { if (strcmp($mc_solution, $answer_id) == 0) { $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id); if (strlen($fb)) { $template->setCurrentBlock("feedback"); $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true)); $template->parseCurrentBlock(); } } } } if ($this->object->getSpecificFeedbackSetting() == ilAssConfigurableMultiOptionQuestionFeedback::FEEDBACK_SETTING_ALL) { $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id); if (strlen($fb)) { $template->setCurrentBlock("feedback"); $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true)); $template->parseCurrentBlock(); } } if ($this->object->getSpecificFeedbackSetting() == ilAssConfigurableMultiOptionQuestionFeedback::FEEDBACK_SETTING_CORRECT) { $answer = $this->object->getAnswer($answer_id); if ($answer->getPoints() > 0) { $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id); if (strlen($fb)) { $template->setCurrentBlock("feedback"); $template->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($fb, true)); $template->parseCurrentBlock(); } } } }
public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping) { global $ilUser; unset($_SESSION["import_mob_xhtml"]); $duration = $item->getDuration(); $shuffle = 0; $answers = array(); $presentation = $item->getPresentation(); foreach ($presentation->order as $entry) { switch ($entry["type"]) { case "response": $response = $presentation->response[$entry["index"]]; $rendertype = $response->getRenderType(); switch (strtolower(get_class($response->getRenderType()))) { case "ilqtirenderchoice": $shuffle = $rendertype->getShuffle(); $answerorder = 0; $foundimage = FALSE; foreach ($rendertype->response_labels as $response_label) { $ident = $response_label->getIdent(); $answertext = ""; $answerimage = array(); foreach ($response_label->material as $mat) { $embedded = false; for ($m = 0; $m < $mat->getMaterialCount(); $m++) { $foundmat = $mat->getMaterial($m); if (strcmp($foundmat["type"], "mattext") == 0) { } if (strcmp($foundmat["type"], "matimage") == 0) { if (strlen($foundmat["material"]->getEmbedded())) { $embedded = true; } } } if ($embedded) { for ($m = 0; $m < $mat->getMaterialCount(); $m++) { $foundmat = $mat->getMaterial($m); if (strcmp($foundmat["type"], "mattext") == 0) { $answertext .= $foundmat["material"]->getContent(); } if (strcmp($foundmat["type"], "matimage") == 0) { $foundimage = TRUE; $answerimage = array("imagetype" => $foundmat["material"]->getImageType(), "label" => $foundmat["material"]->getLabel(), "content" => $foundmat["material"]->getContent()); } } } else { $answertext = $this->object->QTIMaterialToString($mat); } } $answers[$ident] = array("answertext" => $answertext, "imagefile" => $answerimage, "answerorder" => $ident); } break; } break; } } $feedbacks = array(); $feedbacksgeneric = array(); foreach ($item->resprocessing as $resprocessing) { foreach ($resprocessing->outcomes->decvar as $decvar) { if ($decvar->getVarname() == 'SCORE') { $this->object->setPoints($decvar->getMaxvalue()); if ($decvar->getMinvalue() > 0) { $this->object->setScorePartialSolutionEnabled(true); } } } foreach ($resprocessing->respcondition as $respcondition) { if (!count($respcondition->setvar)) { foreach ($respcondition->getConditionvar()->varequal as $varequal) { $ident = $varequal->respident; $answers[$ident]['correctness'] = (bool) $varequal->getContent(); break; } foreach ($respcondition->displayfeedback as $feedbackpointer) { if (strlen($feedbackpointer->getLinkrefid())) { foreach ($item->itemfeedback as $ifb) { if (strcmp($ifb->getIdent(), $feedbackpointer->getLinkrefid()) == 0) { // found a feedback for the identifier if (count($ifb->material)) { foreach ($ifb->material as $material) { $feedbacks[$ident] = $material; } } if (count($ifb->flow_mat) > 0) { foreach ($ifb->flow_mat as $fmat) { if (count($fmat->material)) { foreach ($fmat->material as $material) { $feedbacks[$ident] = $material; } } } } } } } } } else { foreach ($respcondition->displayfeedback as $feedbackpointer) { if (strlen($feedbackpointer->getLinkrefid())) { foreach ($item->itemfeedback as $ifb) { if ($ifb->getIdent() == "response_allcorrect") { // found a feedback for the identifier if (count($ifb->material)) { foreach ($ifb->material as $material) { $feedbacksgeneric[1] = $material; } } if (count($ifb->flow_mat) > 0) { foreach ($ifb->flow_mat as $fmat) { if (count($fmat->material)) { foreach ($fmat->material as $material) { $feedbacksgeneric[1] = $material; } } } } } else { if ($ifb->getIdent() == "response_onenotcorrect") { // found a feedback for the identifier if (count($ifb->material)) { foreach ($ifb->material as $material) { $feedbacksgeneric[0] = $material; } } if (count($ifb->flow_mat) > 0) { foreach ($ifb->flow_mat as $fmat) { if (count($fmat->material)) { foreach ($fmat->material as $material) { $feedbacksgeneric[0] = $material; } } } } } } } } } } } } $this->addGeneralMetadata($item); $this->object->setTitle($item->getTitle()); $this->object->setNrOfTries($item->getMaxattempts()); $this->object->setComment($item->getComment()); $this->object->setAuthor($item->getAuthor()); $this->object->setOwner($ilUser->getId()); $this->object->setQuestion($this->object->QTIMaterialToString($item->getQuestiontext())); $this->object->setObjId($questionpool_id); $this->object->setEstimatedWorkingTime($duration["h"], $duration["m"], $duration["s"]); $this->object->setShuffleAnswersEnabled($shuffle); $this->object->setAnswerType($item->getMetadataEntry("answer_type")); $this->object->setOptionLabel($item->getMetadataEntry("option_label_setting")); $this->object->setCustomTrueOptionLabel($item->getMetadataEntry("custom_true_option_label")); $this->object->setCustomFalseOptionLabel($item->getMetadataEntry("custom_false_option_label")); $this->object->setThumbSize($item->getMetadataEntry("thumb_size")); $this->object->saveToDb(); foreach ($answers as $answerData) { $answer = new ilAssKprimChoiceAnswer(); $answer->setImageFsDir($this->object->getImagePath()); $answer->setImageWebDir($this->object->getImagePathWeb()); $answer->setPosition($answerData['answerorder']); $answer->setAnswertext($answerData['answertext']); $answer->setCorrectness($answerData['correctness']); if (isset($answerData['imagefile']['label'])) { $answer->setImageFile($answerData['imagefile']['label']); } $this->object->addAnswer($answer); } // additional content editing mode information $this->object->setAdditionalContentEditingMode($this->fetchAdditionalContentEditingModeInformation($item)); $this->object->saveToDb(); foreach ($answers as $answer) { if (is_array($answer["imagefile"]) && count($answer["imagefile"]) > 0) { $image =& base64_decode($answer["imagefile"]["content"]); $imagepath = $this->object->getImagePath(); include_once "./Services/Utilities/classes/class.ilUtil.php"; if (!file_exists($imagepath)) { ilUtil::makeDirParents($imagepath); } $imagepath .= $answer["imagefile"]["label"]; if ($fh = fopen($imagepath, "wb")) { $imagefile = fwrite($fh, $image); fclose($fh); } } } $feedbackSetting = $item->getMetadataEntry('feedback_setting'); if (!is_null($feedbackSetting)) { $this->object->feedbackOBJ->saveSpecificFeedbackSetting($this->object->getId(), $feedbackSetting); } // handle the import of media objects in XHTML code foreach ($feedbacks as $ident => $material) { $m = $this->object->QTIMaterialToString($material); $feedbacks[$ident] = $m; } foreach ($feedbacksgeneric as $correctness => $material) { $m = $this->object->QTIMaterialToString($material); $feedbacksgeneric[$correctness] = $m; } $questiontext = $this->object->getQuestion(); $answers =& $this->object->getAnswers(); if (is_array($_SESSION["import_mob_xhtml"])) { include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php"; include_once "./Services/RTE/classes/class.ilRTE.php"; foreach ($_SESSION["import_mob_xhtml"] as $mob) { if ($tst_id > 0) { $importfile = $this->getTstImportArchivDirectory() . '/' . $mob["uri"]; } else { $importfile = $this->getQplImportArchivDirectory() . '/' . $mob["uri"]; } $GLOBALS['ilLog']->write(__METHOD__ . ': import mob from dir: ' . $importfile); $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE); ilObjMediaObject::_saveUsage($media_object->getId(), "qpl:html", $this->object->getId()); $questiontext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $questiontext); foreach ($answers as $key => $value) { $answer_obj =& $answers[$key]; $answer_obj->setAnswertext(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $answer_obj->getAnswertext())); } foreach ($feedbacks as $ident => $material) { $feedbacks[$ident] = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $material); } foreach ($feedbacksgeneric as $correctness => $material) { $feedbacksgeneric[$correctness] = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $material); } } } $this->object->setQuestion(ilRTE::_replaceMediaObjectImageSrc($questiontext, 1)); foreach ($answers as $key => $value) { $answer_obj =& $answers[$key]; $answer_obj->setAnswertext(ilRTE::_replaceMediaObjectImageSrc($answer_obj->getAnswertext(), 1)); } foreach ($feedbacks as $ident => $material) { $this->object->feedbackOBJ->importSpecificAnswerFeedback($this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)); } foreach ($feedbacksgeneric as $correctness => $material) { $this->object->feedbackOBJ->importGenericFeedback($this->object->getId(), $correctness, ilRTE::_replaceMediaObjectImageSrc($material, 1)); } $this->object->saveToDb(); if (count($item->suggested_solutions)) { foreach ($item->suggested_solutions as $suggested_solution) { $this->object->setSuggestedSolution($suggested_solution["solution"]->getContent(), $suggested_solution["gap_index"], true); } $this->object->saveToDb(); } if ($tst_id > 0) { $q_1_id = $this->object->getId(); $question_id = $this->object->duplicate(true, null, null, null, $tst_id); $tst_object->questions[$question_counter++] = $question_id; $import_mapping[$item->getIdent()] = array("pool" => $q_1_id, "test" => $question_id); } else { $import_mapping[$item->getIdent()] = array("pool" => $this->object->getId(), "test" => 0); } //$ilLog->write(strftime("%D %T") . ": finished import multiple choice question (single response)"); }
public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false) { global $ilias; include_once "./Services/Xml/classes/class.ilXmlWriter.php"; $xml = new ilXmlWriter(); // set xml header $xml->xmlHeader(); $xml->xmlStartTag("questestinterop"); $attrs = array("ident" => "il_" . IL_INST_ID . "_qst_" . $this->object->getId(), "title" => $this->object->getTitle(), "maxattempts" => $this->object->getNrOfTries()); $xml->xmlStartTag("item", $attrs); // add question description $xml->xmlElement("qticomment", NULL, $this->object->getComment()); // add estimated working time $workingtime = $this->object->getEstimatedWorkingTime(); $duration = sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]); $xml->xmlElement("duration", NULL, $duration); // add ILIAS specific metadata $xml->xmlStartTag("itemmetadata"); $xml->xmlStartTag("qtimetadata"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "ILIAS_VERSION"); $xml->xmlElement("fieldentry", NULL, $ilias->getSetting("ilias_version")); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "QUESTIONTYPE"); $xml->xmlElement("fieldentry", NULL, KPRIM_CHOICE_QUESTION_IDENTIFIER); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "AUTHOR"); $xml->xmlElement("fieldentry", NULL, $this->object->getAuthor()); $xml->xmlEndTag("qtimetadatafield"); // additional content editing information $this->addAdditionalContentEditingModeInformation($xml); $this->addGeneralMetadata($xml); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "answer_type"); $xml->xmlElement("fieldentry", NULL, $this->object->getAnswerType()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "thumb_size"); $xml->xmlElement("fieldentry", NULL, $this->object->getThumbSize()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "option_label_setting"); $xml->xmlElement("fieldentry", NULL, $this->object->getOptionLabel()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "custom_true_option_label"); $xml->xmlElement("fieldentry", NULL, $this->object->getCustomTrueOptionLabel()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "custom_false_option_label"); $xml->xmlElement("fieldentry", NULL, $this->object->getCustomFalseOptionLabel()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlStartTag("qtimetadatafield"); $xml->xmlElement("fieldlabel", NULL, "feedback_setting"); $xml->xmlElement("fieldentry", NULL, $this->object->getSpecificFeedbackSetting()); $xml->xmlEndTag("qtimetadatafield"); $xml->xmlEndTag("qtimetadata"); $xml->xmlEndTag("itemmetadata"); // PART I: qti presentation $attrs = array("label" => $this->object->getTitle()); $xml->xmlStartTag("presentation", $attrs); // add flow to presentation $xml->xmlStartTag("flow"); // add material with question text to presentation $this->object->addQTIMaterial($xml, $this->object->getQuestion()); // add answers to presentation $attrs = array("ident" => "MCMR", "rcardinality" => "Multiple"); $xml->xmlStartTag("response_lid", $attrs); $solution = $this->object->getSuggestedSolution(0); if (count($solution)) { if (preg_match("/il_(\\d*?)_(\\w+)_(\\d+)/", $solution["internal_link"], $matches)) { $xml->xmlStartTag("material"); $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3]; if (strcmp($matches[1], "") != 0) { $intlink = $solution["internal_link"]; } $attrs = array("label" => "suggested_solution"); $xml->xmlElement("mattext", $attrs, $intlink); $xml->xmlEndTag("material"); } } // shuffle output $attrs = array(); if ($this->object->isShuffleAnswersEnabled()) { $attrs = array("shuffle" => "Yes"); } else { $attrs = array("shuffle" => "No"); } $xml->xmlStartTag("render_choice", $attrs); // add answers $answers =& $this->object->getAnswers(); $akeys = array_keys($answers); foreach ($akeys as $index) { $answer = $this->object->getAnswer($index); $xml->xmlStartTag('response_label', array('ident' => $answer->getPosition())); if (strlen($answer->getImageFile())) { $this->object->addQTIMaterial($xml, $answer->getAnswertext(), FALSE, FALSE); $imagetype = "image/jpeg"; if (preg_match("/.*\\.(png|gif)\$/", $answer->getImageFile(), $matches)) { $imagetype = "image/" . $matches[1]; } if ($force_image_references) { $attrs = array("imagtype" => $imagetype, "label" => $answer->getImageFile(), "uri" => $answer->getImageWebPath()); $xml->xmlElement("matimage", $attrs); } else { $imagepath = $answer->getImageFsPath(); $fh = @fopen($imagepath, "rb"); if ($fh != false) { $imagefile = fread($fh, filesize($imagepath)); fclose($fh); $base64 = base64_encode($imagefile); $attrs = array("imagtype" => $imagetype, "label" => $answer->getImageFile(), "embedded" => "base64"); $xml->xmlElement("matimage", $attrs, $base64, FALSE, FALSE); } } $xml->xmlEndTag("material"); } else { $this->object->addQTIMaterial($xml, $answer->getAnswertext()); } $xml->xmlEndTag("response_label"); } $xml->xmlEndTag("render_choice"); $xml->xmlEndTag("response_lid"); $xml->xmlEndTag("flow"); $xml->xmlEndTag("presentation"); // PART II: qti resprocessing $xml->xmlStartTag('resprocessing'); $xml->xmlStartTag('outcomes'); $xml->xmlElement('decvar', array('varname' => 'SCORE', 'vartype' => 'Decimal', 'defaultval' => '0', 'minvalue' => $this->getMinPoints(), 'maxvalue' => $this->getMaxPoints())); $xml->xmlEndTag('outcomes'); foreach ($answers as $answer) { $xml->xmlStartTag('respcondition', array('continue' => 'Yes')); $xml->xmlStartTag('conditionvar'); $xml->xmlElement('varequal', array('respident' => $answer->getPosition()), $answer->getCorrectness()); $xml->xmlEndTag('conditionvar'); $xml->xmlElement('displayfeedback', array('feedbacktype' => 'Response', 'linkrefid' => "response_{$answer->getPosition()}")); $xml->xmlEndTag('respcondition'); } $feedback_allcorrect = $this->object->feedbackOBJ->getGenericFeedbackExportPresentation($this->object->getId(), true); $xml->xmlStartTag('respcondition', array('continue' => 'Yes')); $xml->xmlStartTag('conditionvar'); $xml->xmlStartTag('and'); foreach ($answers as $answer) { $xml->xmlElement('varequal', array('respident' => $answer->getPosition()), $answer->getCorrectness()); } $xml->xmlEndTag('and'); $xml->xmlEndTag('conditionvar'); $xml->xmlElement('setvar', array('action' => 'Add'), $this->object->getPoints()); if (strlen($feedback_allcorrect)) { $xml->xmlElement('displayfeedback', array('feedbacktype' => 'Response', 'linkrefid' => 'response_allcorrect')); } $xml->xmlEndTag('respcondition'); $feedback_onenotcorrect = $this->object->feedbackOBJ->getGenericFeedbackExportPresentation($this->object->getId(), false); $xml->xmlStartTag('respcondition', array('continue' => 'Yes')); $xml->xmlStartTag('conditionvar'); $xml->xmlStartTag('or'); foreach ($answers as $answer) { $xml->xmlStartTag('not'); $xml->xmlElement('varequal', array('respident' => $answer->getPosition()), $answer->getCorrectness()); $xml->xmlEndTag('not'); } $xml->xmlEndTag('or'); $xml->xmlEndTag('conditionvar'); $xml->xmlElement('setvar', array('action' => 'Add'), 0); if (strlen($feedback_onenotcorrect)) { $xml->xmlElement('displayfeedback', array('feedbacktype' => 'Response', 'linkrefid' => 'response_onenotcorrect')); } $xml->xmlEndTag('respcondition'); $xml->xmlEndTag('resprocessing'); foreach ($answers as $answer) { $xml->xmlStartTag('itemfeedback', array('ident' => "response_{$answer->getPosition()}", 'view' => 'All')); $xml->xmlStartTag('flow_mat'); $this->object->addQTIMaterial($xml, $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->object->getId(), $answer->getPosition())); $xml->xmlEndTag('flow_mat'); $xml->xmlEndTag('itemfeedback'); } if (strlen($feedback_allcorrect)) { $xml->xmlStartTag('itemfeedback', array('ident' => 'response_allcorrect', 'view' => 'All')); $xml->xmlStartTag('flow_mat'); $this->object->addQTIMaterial($xml, $feedback_allcorrect); $xml->xmlEndTag('flow_mat'); $xml->xmlEndTag('itemfeedback'); } if (strlen($feedback_onenotcorrect)) { $xml->xmlStartTag('itemfeedback', array('ident' => 'response_onenotcorrect', 'view' => 'All')); $xml->xmlStartTag('flow_mat'); $this->object->addQTIMaterial($xml, $feedback_onenotcorrect); $xml->xmlEndTag('flow_mat'); $xml->xmlEndTag('itemfeedback'); } $xml->xmlEndTag("item"); $xml->xmlEndTag("questestinterop"); $xml = $xml->xmlDumpMem(FALSE); if (!$a_include_header) { $pos = strpos($xml, "?>"); $xml = substr($xml, $pos + 2); } return $xml; }