19 declare(strict_types=1);
82 self::CMD_SAVE_AND_RETURN
164 $this->
lng = $DIC[
'lng'];
165 $this->tpl = $DIC[
'tpl'];
166 $this->
ctrl = $DIC[
'ilCtrl'];
167 $this->
ui = $DIC->ui();
168 $this->ilObjDataCache = $DIC[
'ilObjDataCache'];
169 $this->
access = $DIC->access();
170 $this->
ilHelp = $DIC[
'ilHelp'];
171 $this->tabs_gui = $DIC[
'ilTabs'];
172 $this->rbacsystem = $DIC[
'rbacsystem'];
173 $this->tree = $DIC[
'tree'];
174 $this->db = $DIC->database();
175 $this->
logger = $DIC[
'ilLog'];
176 $this->component_repository = $DIC[
'component.repository'];
179 $local_dic = QuestionPoolDIC::dic();
181 $this->request_data_collector = $local_dic[
'request_data_collector'];
182 $this->questionrepository = $local_dic[
'question.general_properties.repository'];
184 $this->errormessage = $this->
lng->txt(
"fill_out_all_required_fields");
185 $this->notes_gui = $DIC->notes()->gui();
189 bool $checkonly =
false,
190 ?
bool $is_save_cmd =
null 202 bool $graphical_output =
false,
203 bool $result_output =
false,
204 bool $show_question_only =
true,
205 bool $show_feedback =
false,
206 bool $show_correct_solution =
false,
207 bool $show_manual_scoring =
false,
208 bool $show_question_text =
true,
209 bool $show_inline_feedback =
true 213 bool $show_question_only =
false,
214 bool $show_inline_feedback =
false 220 bool $is_question_postponed =
false,
221 array|
bool $user_post_solutions =
false,
222 bool $show_specific_inline_feedback =
false 226 mixed $user_solutions,
229 bool $graphical_output =
false,
230 bool $result_output =
false,
231 bool $show_question_only =
true,
232 bool $show_feedback =
false,
233 bool $show_correct_solution =
false,
234 bool $show_manual_scoring =
false,
235 bool $show_question_text =
true,
236 bool $show_autosave_title =
false,
237 bool $show_inline_feedback =
false,
258 $this->
object = $question;
263 $this->copy_to_existing_pool_on_save = $pool_ref_id;
273 $this->copy_to_new_pool_on_save = $pool_title;
283 $this->move_after_question_with_id = $question_id;
302 echo $this->
getHeaderAction() . $this->
ui->mainTemplate()->getOnLoadCodeForAsynch();
308 $parentObjType = $this->ilObjDataCache->lookupType($this->
object->getObjId());
314 $this->request_data_collector->getRefId(),
315 $this->
object->getObjId()
320 $ha = $dispatcher->initHeaderAction();
321 $ha->enableComments(
true,
false);
323 return $ha->getHeaderAction($this->
ui->mainTemplate());
328 $comment_gui =
new ilCommentGUI($this->
object->getObjId(), $this->
object->getId(),
'quest');
334 $this->
ilHelp->setScreenIdComponent(
'qpl');
336 $next_class = $this->
ctrl->getNextClass($this);
338 switch ($next_class) {
339 case 'ilformpropertydispatchgui':
342 $form_prop_dispatch->setItem($form->getItemByPostVar(
ilUtil::stripSlashes($this->request_data_collector->string(
'postvar'))));
343 $this->
ctrl->forwardCommand($form_prop_dispatch);
346 $cmd = $this->
ctrl->getCmd(
'editQuestion');
348 case self::SUGGESTED_SOLUTION_COMMANDS_CANCEL:
349 case self::SUGGESTED_SOLUTION_COMMANDS_SAVE:
350 case self::SUGGESTED_SOLUTION_COMMANDS_DEFAULT:
351 case 'saveSuggestedSolutionType':
352 case 'saveContentsSuggestedSolution':
353 case 'deleteSuggestedSolution':
355 case 'cancelExplorer':
356 case 'outSolutionExplorer':
362 case self::CMD_SYNC_QUESTION:
363 case self::CMD_SYNC_QUESTION_AND_RETURN:
368 if (method_exists($this, $cmd)) {
377 return static::HAS_SPECIAL_QUESTION_COMMANDS;
537 if (is_object($this->
object)) {
561 $this->tpl->setContent(implode(
'<br />', [
562 $stats_table->getHTML(),
563 $usage_table->getHTML()
573 $ilCtrl = $DIC[
'ilCtrl'];
574 $ilDB = $DIC[
'ilDB'];
577 if (($question_type ===
'') && ($question_id > 0)) {
578 $question_type = QuestionPoolDIC::dic()[
'question.general_properties.repository']
579 ->getForQuestionId($question_id)?->getClassName();
582 if ($question_type ===
null || $question_type ===
'') {
586 $question_type_gui = $question_type .
'GUI';
587 $question =
new $question_type_gui();
590 $question->object->feedbackOBJ =
new $feedbackObjectClassname($question->object, $ilCtrl,
$ilDB, $lng);
592 if ($question_id > 0) {
593 $question->object->loadFromDb($question_id);
614 if (!$this->tpl->blockExists(
'adm_content')) {
615 $this->tpl->addBlockFile(
'ADM_CONTENT',
'adm_content',
'tpl.il_as_question.html',
'components/ILIAS/TestQuestionPool');
633 $page_gui->setQuestionHTML(
634 [$this->
object->getId() => $html]
636 $presentation = $page_gui->presentation();
637 $presentation = preg_replace(
"/src=\"\\.\\//ims",
"src=\"" . ILIAS_HTTP_PATH .
"/", $presentation);
638 return $presentation;
641 public function outQuestionPage($a_temp_var, $a_postponed =
false, $active_id =
"", $html =
"", $inlineFeedbackEnabled =
false): string
643 if ($this->
object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
647 } elseif ($this->
object->getTestPresentationConfig()->isUnchangedAnswerPossible()) {
651 $this->
lng->loadLanguageModule(
"content");
655 $page_gui->setOutputMode(
'presentation');
656 $page_gui->setTemplateTargetVar($a_temp_var);
660 $page_gui->setQuestionActionsHTML($this->
getNavigationGUI()->getActionsHTML());
664 $page_gui->setQuestionHTML([$this->
object->getId() => $html]);
667 $page_gui->setPresentationTitle($this->questionHeaderBlockBuilder->getPresentationTitle());
668 $page_gui->setQuestionInfoHTML($this->questionHeaderBlockBuilder->getQuestionInfoHTML());
670 return $page_gui->presentation();
675 $tpl =
new ilTemplate(
'tpl.tst_question_additional_behaviour_checkbox.html',
true,
true,
'components/ILIAS/TestQuestionPool');
676 $tpl->
setVariable(
'TXT_FORCE_FORM_DIFF_LABEL', $this->
object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
682 return $this->
lng->txt(
'use_previous_solution_advice');
687 $tpl =
new ilTemplate(
'tpl.tst_question_additional_behaviour_checkbox.html',
true,
true,
'components/ILIAS/TestQuestionPool');
688 $tpl->
setVariable(
'TXT_FORCE_FORM_DIFF_LABEL', $this->
lng->txt(
'use_previous_solution'));
694 $original_id = $this->
object->getOriginalId();
695 if ($original_id !==
null) {
696 $this->
object->syncWithOriginal();
697 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"msg_obj_modified"),
true);
703 $old_id = $this->request_data_collector->getQuestionId();
707 $this->tabs_gui->setTabActive(
'edit_question');
711 $this->
object->getCurrentUser()->setPref(
'tst_lastquestiontype', $this->
object->getQuestionType());
712 $this->
object->getCurrentUser()->writePref(
'tst_lastquestiontype', $this->
object->getQuestionType());
713 $this->
object->saveToDb($old_id);
715 $this->questionrepository->questionExistsInPool($this->
object->getOriginalId());
716 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'msg_obj_modified'),
true);
724 $this->tabs_gui->activateTab(
'edit_question');
730 $this->
object->getCurrentUser()->setPref(
'tst_lastquestiontype', $this->
object->getQuestionType());
731 $this->
object->getCurrentUser()->writePref(
'tst_lastquestiontype', $this->
object->getQuestionType());
733 if ($this->request_data_collector->getQuestionId() === 0) {
734 if ($this->
object->getId() < 1) {
735 $this->
object->createNewQuestion();
741 $cmd = strpos($this->
ctrl->getCmd(),
'Return') ===
false 742 ? self::CMD_SYNC_QUESTION
743 : self::CMD_SYNC_QUESTION_AND_RETURN;
747 $this->
object->saveToDb();
753 $additional_content_editing_mode = $this->request_data_collector->string(
'additional_content_editing_mode');
754 if ($additional_content_editing_mode !==
'' 755 && in_array($additional_content_editing_mode, $this->
object->getValidAdditionalContentEditingModes())) {
756 $this->
object->setAdditionalContentEditingMode($additional_content_editing_mode);
762 if ($this->request_data_collector->isset(
'pool_ref')) {
763 $this->copy_to_existing_pool_on_save = $this->request_data_collector->int(
'pool_ref');
766 if ($this->request_data_collector->isset(
'pool_title')) {
767 $this->copy_to_new_pool_on_save = $this->request_data_collector->string(
'pool_title');
770 if ($this->request_data_collector->isset(
'move_after_question_with_id')) {
771 $this->move_after_question_with_id = $this->request_data_collector->int(
'move_after_question_with_id');
778 public function getContextPath($cont_obj,
int $a_endnode_id,
int $a_startnode_id = 1): string
782 $tmpPath = $cont_obj->getLMTree()->getPathFull($a_endnode_id, $a_startnode_id);
785 for ($i = 1; $i < (count($tmpPath) - 1); $i++) {
790 $path .= $tmpPath[$i][
"title"];
798 $this->sequence_no = $nr;
808 $this->question_count = $a_question_count;
828 $this->errormessage .= ((strlen($this->errormessage)) ?
"<br />" :
"") .
$errormessage;
833 return $this->
object->getQuestionType();
839 if (strlen($a_value)) {
840 $result =
" value=\"$a_value\" ";
847 if (!$this->
object->getSelfAssessmentEditingMode()) {
856 $title->setMaxLength(100);
857 $title->setValue($this->
object->getTitle());
858 $title->setRequired(
true);
861 if (!$this->
object->getSelfAssessmentEditingMode()) {
864 $author->setValue($this->
object->getAuthor());
865 $author->setMaxLength(512);
866 $author->setRequired(
true);
871 $description->setValue($this->
object->getComment());
872 $description->setRequired(
false);
873 $description->setMaxLength(1000);
879 if (trim($author) ==
"") {
882 $hi->setValue($author);
895 $question->setRequired(
true);
896 $question->setRows(10);
897 $question->setCols(80);
899 if (!$this->
object->getSelfAssessmentEditingMode()) {
901 $question->setUseRte(
true);
903 $question->setRTESupport($this->
object->getId(),
'qpl',
'assessment');
907 $question->setUseTagsForRteOnly(
false);
909 $question->setInfo($this->
lng->txt(
'latex_edit_info'));
914 $form->
addItem($question_type);
916 if ($this->copy_to_existing_pool_on_save !==
null) {
918 $pool_ref->setValue((
string) $this->copy_to_existing_pool_on_save);
922 if ($this->copy_to_new_pool_on_save !==
null) {
924 $pool_title->setValue($this->copy_to_new_pool_on_save);
928 if ($this->move_after_question_with_id !==
null) {
929 $move_after_question_id =
new ilHiddenInputGUI(
'move_after_question_with_id');
930 $move_after_question_id->setValue((
string) $this->move_after_question_with_id);
931 $form->
addItem($move_after_question_id);
934 $additional_content_editing_mode =
new ilHiddenInputGUI(
'additional_content_editing_mode');
935 $additional_content_editing_mode->setValue($this->
object->getAdditionalContentEditingMode());
936 $form->
addItem($additional_content_editing_mode);
943 if (!$this->
object->getSelfAssessmentEditingMode()) {
947 $nr_tries = $this->
object->getNrOfTries() ?? $this->
object->getDefaultNrOfTries();
957 $ni->setMaxLength(5);
965 $postvar =
"tax_node_assign_$taxonomyId";
969 $tax_node_assign->saveInput(
"qpl", $this->
object->getObjId(),
"quest", $this->
object->getId());
978 $sectHeader->setTitle($this->
lng->txt(
'qpl_qst_edit_form_taxonomy_section'));
983 $label = sprintf($this->
lng->txt(
'qpl_qst_edit_form_taxonomy'), $taxonomy->getTitle());
984 $postvar =
"tax_node_assign_$taxonomyId";
993 $taxSelect->setValue(
array_map(
function ($assignedNode) {
994 return $assignedNode[
'node_id'];
1007 if ($manual_feedback !==
'') {
1008 return $manual_feedback;
1013 if ($this->
object->isAdditionalContentEditingModePageObject()) {
1023 if ($pass ===
null) {
1026 $reached_points = $this->
object->calculateReachedPoints($active_id, $pass);
1027 $max_points = $this->
object->getMaximumPoints();
1029 $is_correct =
false;
1030 if ($reached_points == $max_points) {
1034 return $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation(
1043 $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(),
true),
1052 $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(),
false),
1060 $count = $this->questionrepository->usageCount($this->
object->getId());
1062 if ($this->questionrepository->questionExistsInPool($this->object->getId()) && $count) {
1063 if ($this->rbacsystem->checkAccess(
"write", $this->request_data_collector->getRefId())) {
1064 $this->tpl->setOnScreenMessage(
'info', sprintf($this->
lng->txt(
"qpl_question_is_in_use"), $count));
1068 return $this->
lng->txt($this->
object->getQuestionType());
1073 foreach (SuggestedSolution::TYPES as $k => $v) {
1074 $options[$k] = $this->
lng->txt($v);
1091 if ($save && $this->request_data_collector->int(
'deleteSuggestedSolution') === 1) {
1092 $this->
object->deleteSuggestedSolutions();
1093 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"msg_obj_modified"),
true);
1094 $this->
ctrl->redirect($this,
'suggestedsolution');
1099 $solution = $this->
object->getSuggestedSolution();
1102 $solution_type = $this->
ctrl->getCmd() ===
'cancelSuggestedSolution' 1103 ? $solution->getType()
1104 : $this->request_data_collector->string(
'solutiontype');
1105 if ($solution_type === SuggestedSolution::TYPE_FILE
1106 && ($solution ===
null || $solution->getType() !== SuggestedSolution::TYPE_FILE)
1110 SuggestedSolution::TYPE_FILE
1114 $solution_filename = $this->request_data_collector->string(
'filename');
1115 if ($save && !empty($solution_filename)) {
1116 $solution = $solution->withTitle($solution_filename);
1119 if ($solution !==
null) {
1121 $form->setFormAction($this->
ctrl->getFormAction($this));
1122 $form->setTitle($this->
lng->txt(
'solution_hint'));
1123 $form->setMultipart(
true);
1124 $form->setTableWidth(
'100%');
1125 $form->setId(
'suggestedsolutiondisplay');
1129 'tpl.il_as_qpl_suggested_solution_input_presentation.html',
1132 'components/ILIAS/TestQuestionPool' 1135 if ($solution->isOfTypeLink()) {
1136 $href = $this->
object->getInternalLinkHref($solution->getInternalLink());
1137 $template->setCurrentBlock(
'preview');
1138 $template->setVariable(
'TEXT_SOLUTION', $this->
lng->txt(
'suggested_solution'));
1139 $template->setVariable(
1141 " <a href='{$href}' target='content'>{$this->lng->txt('view')}</a> " 1143 $template->parseCurrentBlock();
1145 $solution->isOfTypeFile()
1146 && $solution->getFilename()
1148 $href = $this->
object->getSuggestedSolutionPathWeb() . $solution->getFilename();
1149 $link =
" <a href='{$href}' target='content'>" 1152 $template->setCurrentBlock(
'preview');
1153 $template->setVariable(
'TEXT_SOLUTION', $this->
lng->txt(
'suggested_solution'));
1154 $template->setVariable(
'VALUE_SOLUTION', $link);
1155 $template->parseCurrentBlock();
1158 $template->setVariable(
'TEXT_TYPE', $this->
lng->txt(
'type'));
1159 $template->setVariable(
'VALUE_TYPE', $options[$solution->getType()]);
1161 $title->
setHtml($template->get());
1163 $deletesolution->setOptionTitle($this->
lng->txt(
'deleteSuggestedSolution'));
1164 $title->addSubItem($deletesolution);
1165 $form->addItem($title);
1167 if ($solution->isOfTypeFile()) {
1170 $file->enableFileNameSelection(
'filename');
1172 if ($save && $_FILES && $_FILES[
'file'][
'tmp_name'] && $file->checkInput()) {
1173 if (!file_exists($this->
object->getSuggestedSolutionPath())) {
1178 $_FILES[
'file'][
'tmp_name'],
1179 $_FILES[
'file'][
'name'],
1180 $this->
object->getSuggestedSolutionPath() . $_FILES[
'file'][
'name']
1186 if ($solution->getFilename()) {
1187 @unlink($this->
object->getSuggestedSolutionPath() . $solution->getFilename());
1190 $file->setValue($_FILES[
'file'][
'name']);
1191 $solution = $solution
1192 ->withFilename($_FILES[
'file'][
'name'])
1193 ->withMime($_FILES[
'file'][
'type'])
1194 ->withSize($_FILES[
'file'][
'size'])
1195 ->withTitle($this->request_data_collector->string(
'filename'));
1199 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'suggested_solution_added_successfully'),
true);
1200 $this->
ctrl->redirect($this,
'suggestedsolution');
1203 $this->tpl->setOnScreenMessage(
'info', $res);
1206 if ($solution->getFilename()) {
1207 $file->setValue($solution->getFilename());
1208 $file->setFilename($solution->getTitle());
1211 $form->addItem($file);
1213 $hidden->setValue(
'file');
1214 $form->addItem($hidden);
1216 if ($this->
access->checkAccess(
'write',
'', $this->request_data_collector->getRefId())) {
1217 $form->addCommandButton(
'cancelSuggestedSolution', $this->
lng->txt(
'cancel'));
1218 $form->addCommandButton(
'saveSuggestedSolution', $this->
lng->txt(
'save'));
1222 if ($form->checkInput()) {
1223 if ($solution->isOfTypeFile()) {
1224 $solution = $solution->withTitle($this->request_data_collector->string(
'filename'));
1227 if (!$solution->isOfTypeLink()) {
1231 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'msg_obj_modified'),
true);
1232 $this->
ctrl->redirect($this,
'suggestedsolution');
1236 $output = $form->getHTML();
1239 $savechange = $this->
ctrl->getCmd() ===
'saveSuggestedSolutionType';
1242 if ($this->
access->checkAccess(
'write',
'', $this->request_data_collector->getRefId())) {
1244 $formchange->setFormAction($this->
ctrl->getFormAction($this));
1246 $title = $solution ? $this->
lng->txt(
'changeSuggestedSolution') : $this->
lng->txt(
'addSuggestedSolution');
1247 $formchange->setTitle($title);
1248 $formchange->setMultipart(
false);
1249 $formchange->setTableWidth(
'100%');
1250 $formchange->setId(
'suggestedsolution');
1253 foreach ($options as $opt_value => $opt_caption) {
1257 $solutiontype->setValue($solution->getType());
1259 $solutiontype->setRequired(
true);
1260 $formchange->addItem($solutiontype);
1262 $formchange->addCommandButton(
'saveSuggestedSolutionType', $this->
lng->txt(
'select'));
1265 $formchange->checkInput();
1267 $changeoutput = $formchange->getHTML();
1269 $this->tabs_gui->activateTab(
'suggested_solution');
1270 $this->tpl->setVariable(
'ADM_CONTENT', $changeoutput . $output);
1275 $type = $this->request_data_collector->string(
"link_new_type");
1276 $search = $this->request_data_collector->string(
"search_link_type");
1277 $this->
ctrl->setParameter($this,
"link_new_type", $type);
1278 $this->
ctrl->setParameter($this,
"search_link_type", $search);
1279 $this->
ctrl->saveParameter($this, [
"subquestion_index",
"link_new_type",
"search_link_type"]);
1281 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
"select_object_to_link"));
1283 $parent_ref_id = $this->tree->getParentId($this->request_data_collector->getRefId());
1285 $exp->
setExpand($this->request_data_collector->raw(
'expand_sol') ? $this->request_data_collector->raw(
'expand_sol') : $parent_ref_id);
1286 $exp->setExpandTarget($this->
ctrl->getLinkTarget($this,
'outSolutionExplorer'));
1287 $exp->setTargetGet(
"ref_id");
1288 $exp->setRefId($this->request_data_collector->getRefId());
1289 $exp->addFilter($type);
1290 $exp->setSelectableType($type);
1291 if ($this->request_data_collector->isset(
'expandCurrentPath') && $this->request_data_collector->raw(
'expandCurrentPath')) {
1292 $exp->expandPathByRefId($parent_ref_id);
1298 $template =
new ilTemplate(
"tpl.il_as_qpl_explorer.html",
true,
true,
"components/ILIAS/TestQuestionPool");
1299 $template->setVariable(
"EXPLORER_TREE", $exp->getOutput());
1300 $template->setVariable(
"BUTTON_CANCEL", $this->
lng->txt(
"cancel"));
1301 $template->setVariable(
"FORMACTION", $this->
ctrl->getFormAction($this,
"suggestedsolution"));
1302 $this->tpl->setVariable(
"ADM_CONTENT", $template->get());
1307 $solution_type = $this->request_data_collector->string(
'solutiontype');
1309 switch ($solution_type) {
1333 if (isset($solution_type)) {
1334 $this->
ctrl->setParameter($this,
'expandCurrentPath', 1);
1336 $this->
ctrl->setParameter($this,
'link_new_type', $type);
1337 $this->
ctrl->setParameter($this,
'search_link_type', $search);
1338 $this->
ctrl->redirect($this,
'outSolutionExplorer');
1343 $this->
ctrl->redirect($this,
'suggestedsolution');
1348 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1350 $cont_obj_gui =
new ilObjContentObjectGUI(
'', $this->request_data_collector->int(
'source_id'),
true);
1354 $tree = $cont_obj->getLMTree();
1359 foreach ($chapters as $chapter) {
1361 foreach ($chapterpages as $page) {
1362 if ($page[
'type'] == $this->request_data_collector->raw(
'search_link_type')) {
1363 array_push($shownpages, $page[
'obj_id']);
1365 if ($tree->
isInTree($page[
'obj_id'])) {
1371 $this->
ctrl->setParameter($this, $page[
'type'], $page[
'obj_id']);
1373 'title' => $page[
'title'],
1375 'text_add' => $this->
lng->txt(
'add'),
1376 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($page[
'type']))
1381 foreach ($pages as $page) {
1382 if (!in_array($page[
'obj_id'], $shownpages)) {
1383 $this->
ctrl->setParameter($this, $page[
'type'], $page[
'obj_id']);
1385 'title' => $page[
'title'],
1386 'description' =>
'---',
1387 'text_add' => $this->
lng->txt(
'add'),
1388 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($page[
'type']))
1394 $table->setTitle($this->
lng->txt(
'obj_' .
ilUtil::stripSlashes($this->request_data_collector->string(
'search_link_type'))));
1395 $table->setData($rows);
1397 $this->tpl->setContent($table->getHTML());
1402 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1404 $cont_obj_gui =
new ilObjContentObjectGUI(
'', $this->request_data_collector->int(
'source_id'),
true);
1406 $ctree = $cont_obj->getLMTree();
1407 $nodes = $ctree->getSubtree($ctree->getNodeData($ctree->getRootId()));
1411 foreach ($nodes as $node) {
1412 if ($node[
'type'] == $this->request_data_collector->raw(
'search_link_type')) {
1413 $this->
ctrl->setParameter($this, $node[
'type'], $node[
'obj_id']);
1415 'title' => $node[
'title'],
1416 'description' =>
'',
1417 'text_add' => $this->
lng->txt(
'add'),
1418 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($node[
'type']))
1424 $table->setTitle($this->
lng->txt(
'obj_' .
ilUtil::stripSlashes($this->request_data_collector->string(
'search_link_type'))));
1425 $table->setData($rows);
1427 $this->tpl->setContent($table->getHTML());
1432 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1434 $glossary =
new ilObjGlossary($this->request_data_collector->int(
'source_id'),
true);
1439 foreach ($terms as $term) {
1440 $this->
ctrl->setParameter($this,
'git', $term[
'id']);
1442 'title' => $term[
'term'],
1443 'description' =>
'',
1444 'text_add' => $this->
lng->txt(
'add'),
1445 'href_add' => $this->
ctrl->getLinkTarget($this,
'addGIT')
1450 $table->setTitle($this->
lng->txt(
'glossary_term'));
1451 $table->setData($rows);
1453 $this->tpl->setContent($table->getHTML());
1459 $question_id = $this->
object->getId();
1460 $subquestion_index = $this->request_data_collector->int(
'subquestion_index');
1461 $subquestion_index = ($subquestion_index > 0) ? $subquestion_index : 0;
1463 $solution = $repo->create($question_id, $type)
1464 ->withSubquestionIndex($subquestion_index)
1465 ->withInternalLink($target);
1467 $repo->update([$solution]);
1472 $this->
ctrl->saveParameter($this, [
"subquestion_index",
"link_new_type",
"search_link_type"]);
1473 switch ($this->request_data_collector->string(
"search_link_type")) {
1484 $target =
"il__lm_" . $this->request_data_collector->raw(
"source_id");
1486 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1487 $this->
ctrl->redirect($this,
'suggestedsolution');
1494 $target =
"il__pg_" . $this->request_data_collector->raw(
"pg");
1496 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1497 $this->
ctrl->redirect($this,
'suggestedsolution');
1502 $target =
"il__st_" . $this->request_data_collector->raw(
"st");
1504 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1505 $this->
ctrl->redirect($this,
'suggestedsolution');
1510 $target =
"il__git_" . $this->request_data_collector->raw(
"git");
1512 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1513 $this->
ctrl->redirect($this,
'suggestedsolution');
1518 return in_array($this->
ctrl->getCmd(), self::QUESTION_SAVE_CMDS);
1522 string $guiClassName,
1523 string $cmdConstantNameBegin =
'CMD_' 1532 foreach ($reflectionClass->getConstants() as $constName => $constValue) {
1533 if (substr($constName, 0, strlen($cmdConstantNameBegin)) == $cmdConstantNameBegin) {
1534 $commands[] = $constValue;
1544 $this->tabs_gui->clearTargets();
1546 if ($this->
object->getId() > 0) {
1549 $this->tabs_gui->activateTab(
'edit_question');
1556 $this->
ctrl->setParameterByClass(ilAssQuestionPageGUI::class,
'q_id', $this->
object->getId());
1557 $this->
ctrl->setParameterByClass(static::class,
'q_id', $this->
object->getId());
1570 $this->
ctrl->setParameterByClass($classname,
'q_id', $this->
object->getId());
1572 'suggested_solution',
1573 $this->
ctrl->getLinkTargetByClass($classname,
'suggestedsolution'),
1575 'suggestedsolution',
1576 'saveSuggestedSolution',
1577 'outSolutionExplorer',
1579 'addSuggestedSolution',
1582 'removeSuggestedSolution' 1594 return [
'editQuestion',
'save',
'originalSyncForm'];
1604 $tabCommands = self::getCommandsFromClassConstants(ilAssQuestionFeedbackEditingGUI::class);
1606 $this->
ctrl->setParameterByClass(ilAssQuestionFeedbackEditingGUI::class,
'q_id', $this->
object->getId());
1609 $tabs->
addTarget(
'feedback', $tabLink, $tabCommands, $this->
ctrl->getCmdClass(),
'');
1616 $this->
ctrl->getLinkTargetByClass(
1629 $reachedPoints = $this->
object->getAdjustedReachedPoints((
int) $activeId, (
int) $passIndex,
true);
1630 $maximumPoints = $this->
object->getMaximumPoints();
1632 return $reachedPoints == $maximumPoints;
1642 $this->
object->setTitle($this->request_data_collector->string(
'title'));
1643 $this->
object->setAuthor($this->request_data_collector->string(
'author'));
1644 $this->
object->setComment($this->request_data_collector->string(
'comment'));
1646 $nr_of_tries = $this->request_data_collector->int(
'nr_of_tries');
1647 if ($this->
object->getSelfAssessmentEditingMode()) {
1648 $this->
object->setNrOfTries($nr_of_tries);
1653 $this->request_data_collector->string(
'lifecycle')
1659 $this->
object->setQuestion(
1661 $this->request_data_collector->string(
'question')
1672 bool $is_question_postponed =
false,
1673 array|
bool $user_post_solutions =
false,
1674 bool $show_specific_inline_feedback =
false 1681 $is_question_postponed,
1682 $user_post_solutions,
1683 $show_specific_inline_feedback
1688 $this->tpl->setVariable(
"QUESTION_OUTPUT", $test_output);
1689 $this->tpl->setVariable(
"FORMACTION", $formaction);
1691 $this->tpl->setVariable(
"FORM_TIMESTAMP", (
string) time());
1695 string $form_action,
1699 return $form_action;
1709 return self::FORM_ENCODING_URLENCODE;
1714 if ($this->
object->getId() <= 0) {
1716 $this->
lng->txt(
'cancel'),
1717 $this->
ctrl->getParentReturnByClass(
1725 $this->
ctrl->setParameterByClass(
1726 ilAssQuestionPreviewGUI::class,
1730 $this->
ctrl->saveParameterByClass(ilAssQuestionPreviewGUI::class,
'prev_qid');
1732 $this->
lng->txt(
'backtocallingpage'),
1733 $this->
ctrl->getLinkTargetByClass(
1734 ilAssQuestionPreviewGUI::class,
1738 $this->
ctrl->clearParameterByClass(ilAssQuestionPreviewGUI::class,
'prev_qid');
1757 $form->setFormAction($this->
ctrl->getFormAction($this));
1758 $form->setId($this->
getType());
1760 $form->setTableWidth(
'100%');
1761 $form->setMultipart(
true);
1767 return str_replace([
'{',
'}'], [
'{',
'}'], $text);
1778 return '<div id="focus"></div>';
1799 $table->setQuestionIndex($questionIndex);
1801 $table->initColumns();
1820 switch ($correctness) {
1821 case self::CORRECTNESS_NOT_OK:
1822 $icon_name =
'standard/icon_not_ok.svg';
1823 $label = $this->
lng->txt(
"answer_is_wrong");
1825 case self::CORRECTNESS_MOSTLY_OK:
1826 $icon_name =
'standard/icon_mostly_ok.svg';
1827 $label = $this->
lng->txt(
"answer_is_not_correct_but_positive");
1829 case self::CORRECTNESS_OK:
1830 $icon_name =
'standard/icon_ok.svg';
1831 $label = $this->
lng->txt(
"answer_is_right");
1837 $icon = $this->
ui->factory()->symbol()->icon()->custom(
1841 return $this->
ui->renderer()->render($icon);
1853 ?
string $txt_output,
1854 bool $prepare_for_latex_output =
false,
1855 bool $omitNl2BrWhenTextArea =
false 1857 if ($txt_output ===
null || $txt_output ===
'') {
1861 $result = $txt_output;
1864 if (strlen(strip_tags($result)) < strlen($result)) {
1870 if (!$omitNl2BrWhenTextArea) {
1872 $result = preg_replace(
"/[\n]/",
"<br />", $result);
1876 if (preg_match_all(
"/(<pre>.*?<\/pre>)/ims", $result, $matches)) {
1877 foreach ($matches[0] as $found) {
1879 if (strpos(
"\n", $found) ===
false) {
1880 $replacement =
"\n";
1882 $removed = preg_replace(
"/<br\s*?\/>/ims", $replacement, $found);
1883 $result = str_replace($found, $removed, $result);
1888 if ($prepare_for_latex_output) {
1893 $result = str_replace(
"{",
"{", $result);
1894 $result = str_replace(
"}",
"}", $result);
1895 $result = str_replace(
"\\",
"\", $result);
1906 return $this->
ui->renderer()->render($this->
ui->factory()->legacy()->latexContent($content));
1912 if (is_null($this->suggestedsolution_repo)) {
1913 $dic = QuestionPoolDIC::dic();
1914 $this->suggestedsolution_repo =
$dic[
'question.repo.suggestedsolutions'];
1925 if (!is_array($answer_text)) {
1940 self::ALLOWED_PLAIN_TEXT_TAGS
1950 $this->parent_type_is_lm = $flag;
1955 $this->tpl->addOnloadCode(
" 1956 let form = document.querySelector('#ilContentContainer form'); 1957 let button = form.querySelector('input[name=\"cmd[save]\"]'); 1958 if (form && button) { 1959 form.addEventListener('keydown', function (e) { 1960 if (e.key === 'Enter' 1961 && e.target.type !== 'textarea' 1962 && e.target.type !== 'submit' 1963 && e.target.type !== 'file' 1966 form.requestSubmit(button); 1975 return in_array($cmd, static::ADDITIONAL_CMDS_NEEDING_EXISTING_QST);
1980 $this->context_allows_sync_to_pool = $sync_allowed;
1985 return $this->context_allows_sync_to_pool
1986 && $this->
object->hasWritableOriginalInQuestionPool();
1991 if ($cmd_class ===
'') {
1992 $cmd_class = static::class;
1994 $modal = $this->
ui->factory()->modal()->interruptive(
1995 $this->
lng->txt(
'confirm'),
1996 $this->
lng->txt(
'confirm_sync_questions'),
1997 $this->
ctrl->getFormActionByClass($cmd_class, $cmd)
1998 )->withAffectedItems([
1999 $this->
ui->factory()->modal()->interruptiveItem()->standard(
2000 (
string) $this->
object->getOriginalId(),
2001 $this->
object->getTitleForHTMLOutput()
2003 ])->withActionButtonLabel($this->
lng->txt(
'sync_question_to_pool'));
2004 return $this->
ui->renderer()->render(
2005 $modal->withOnLoad($modal->getShowSignal())
2012 bool $graphical_output =
false,
2013 bool $result_output =
false,
2014 bool $show_question_only =
true,
2015 bool $show_feedback =
false,
2016 bool $show_correct_solution =
false,
2017 bool $show_manual_scoring =
false,
2018 bool $show_question_text =
true,
2019 bool $show_autosave_title =
false,
2020 bool $show_inline_feedback =
false 2022 $autosave_solutions = $this->
object->getSolutionValues($active_id, $pass,
false);
2023 if ($autosave_solutions === []) {
2027 $autosave_solutions,
2032 $show_question_only,
2034 $show_correct_solution,
2035 $show_manual_scoring,
2036 $show_question_text,
2037 $show_autosave_title,
2038 $show_inline_feedback
2044 if (strtolower($this->request_data_collector->string(
'cmdClass')) ===
'ilassquestionpreviewgui') {
2045 return $this->
ctrl->getLinkTargetByClass(ilObjQuestionPoolGUI::class,
'downloadFile');
2047 return $this->
ctrl->getLinkTargetByClass(ilObjTestGUI::class,
'downloadFile');
isTestPresentationContext()
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const ADDITIONAL_CONTENT_EDITING_MODE_IPE
setAdditionalContentEditingModeFromPost()
hasCorrectSolution($activeId, $passIndex)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
This class represents an option in a radio group.
static getInstance($identifier)
setCopyToExistingPoolOnSave(?int $pool_ref_id)
Readable part of repository interface to ilComponentDataDB.
GeneralQuestionPropertiesRepository $questionrepository
genericFeedbackOutputBuilder(int $active_id, ?int $pass)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const CMD_SAVE_AND_RETURN
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
generateCorrectnessIconsForCorrectness(int $correctness)
getAnswersFrequency($relevantAnswers, $questionIndex)
getTermList(string $searchterm="", string $a_letter="", string $a_def="", int $a_tax_node=0, bool $a_include_offline_childs=false, bool $a_add_amet_fields=false, ?array $a_amet_filter=null, bool $a_omit_virtual=false, bool $a_include_references=false)
getNodeData(int $a_node_id, ?int $a_tree_pk=null)
get all information of a node.
static stripSlashesRecursive($a_data, bool $a_strip_html=true, string $a_allow="")
int $sequence_no
sequence number in test
getPreviousSolutionConfirmationCheckboxHtml()
bool $context_allows_sync_to_pool
addTab_SuggestedSolution(ilTabsGUI $tabs, string $classname)
getAutoSavedSolutionOutput(int $active_id, int $pass, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_autosave_title=false, bool $show_inline_feedback=false)
ilTestQuestionNavigationGUI $navigationGUI
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const CMD_SYNC_QUESTION_AND_RETURN
setContextAllowsSyncToPool(bool $sync_allowed)
setTargetGuiClass(string $targetGuiClass)
setTaxonomyIds(array $taxonomyIds)
addTarget(string $a_text, string $a_link, $a_cmd="", $a_cmdClass="", string $a_frame="", bool $a_activate=false, bool $a_dir_text=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
int $question_count
question count in test
cancelSuggestedSolution()
getEditQuestionTabCommands()
getSuggestedSolutionsRepo()
const ADDITIONAL_CMDS_NEEDING_EXISTING_QST
There are functions that need an existing question.
renderLatex($content)
Wrap content with latex in a LatexContent UI component and render it to be processed by MathJax in th...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilPropertyFormGUI $editForm
string $question_sync_modal
const SESSION_PREVIEW_DATA_BASE_INDEX
buildBasicEditFormObject()
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
createSuggestedSolutionLinkingTo(string $type, string $target)
getTestOutput(int $active_id, int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
getBasicEditQuestionTabCommands()
isInTree(?int $a_node_id)
get all information of a node.
static prepareTextareaOutput(?string $txt_output, bool $prepare_for_latex_output=false, bool $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
setQuestionHeaderBlockBuilder(\ilQuestionHeaderBlockBuilder $questionHeaderBlockBuilder)
getAsValueAttribute(string $a_value)
const CORRECTNESS_MOSTLY_OK
escapeTemplatePlaceholders(string $text)
getPresentationJavascripts()
setDefaultTabs(ilTabsGUI $tabs_gui)
setObject(assQuestion $question)
string $questionActionCmd
getGenericFeedbackOutputForCorrectSolution()
const SUGGESTED_SOLUTION_COMMANDS_CANCEL
writePostData(bool $always=false)
Evaluates a posted edit form and writes the form data in the question object.
bool $previousSolutionPrefilled
getUseUnchangedAnswerCheckboxHtml()
ilGlobalPageTemplate $tpl
suggestedsolution(bool $save=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
isInLearningModuleContext()
isRenderPurposePlayback()
setQuestionCount(int $a_question_count)
populateTaxonomyFormSection(ilPropertyFormGUI $form)
setPreviewSession(ilAssQuestionPreviewSession $preview_session)
static _getQuestionGUI(string $question_type='', int $question_id=-1)
Creates a question gui representation and returns the alias to the question gui.
SuggestedSolutionsDatabaseRepository $suggestedsolution_repo
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
static replaceLatexSpan(string $text)
Replace the latex delimiters used by the rich text editor Unfortunately these can't be processed by M...
ilAssQuestionPreviewSession $preview_session
isAnswerFrequencyStatisticSupported()
getContextPath($cont_obj, int $a_endnode_id, int $a_startnode_id=1)
get context path in content object tree
readonly RequestDataCollector $request_data_collector
prepareReprintableCorrectionsForm(ilPropertyFormGUI $form)
editQuestion(bool $checkonly=false, ?bool $is_save_cmd=null)
populateJavascriptFilesRequiredForWorkForm(ilGlobalTemplateInterface $tpl)
setValue(string $a_value)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static renameExecutables(string $a_dir)
const SUGGESTED_SOLUTION_COMMANDS_SAVE
getType()
needed for page editor compliance
static _getUsedHTMLTags(string $module='')
getChildsByType(int $a_node_id, string $a_type)
get child nodes of given node by object type
setPresentationContext(string $presentationContext)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
int $copy_to_existing_pool_on_save
hasSpecialQuestionCommands()
setErrorMessage(string $errormessage)
writeQuestionGenericPostData()
readonly ilTestLegacyFormsHelper $forms_helper
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
setQuestionActionCmd(string $questionActionCmd)
const PRESENTATION_CONTEXT_RESULTS
isRenderPurposeDemoplay()
setAdjustmentEditContext()
outQuestionForTest(string $formaction, int $active_id, ?int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
setInLearningModuleContext(bool $flag)
const FORM_ENCODING_MULTIPART
setBackTarget(string $a_title, string $a_target, string $a_frame="")
isAdjustmentEditContext()
Repository for suggested solutions.
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const EDIT_CONTEXT_ADJUSTMENT
addTab_Question(ilTabsGUI $tabs_gui)
addTab_QuestionFeedback(ilTabsGUI $tabs)
isRenderPurposeInputValue()
const RENDER_PURPOSE_DEMOPLAY
setTargetGui($linkTargetGui)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
int $move_after_question_with_id
getCopyToExistingPoolOnSave()
const EDIT_CONTEXT_AUTHORING
const PRESENTATION_CONTEXT_TEST
setSequenceNumber(int $nr)
cmdNeedsExistingQuestion(string $cmd)
getAssignmentsOfItem(int $a_item_id)
Get assignments for item.
setRenderPurpose(string $renderPurpose)
static getClassByType(string $obj_type)
getPreviousSolutionProvidedMessage()
const FORM_ENCODING_URLENCODE
const RENDER_PURPOSE_PLAYBACK
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setEditContext(string $editContext)
getGenericFeedbackOutputForIncorrectSolution()
setFileDownloadLink(string $a_download_link)
saveTaxonomyAssignments()
getSpecificFeedbackOutput(array $userSolution)
Returns the answer specific feedback for the question.
const ALLOWED_PLAIN_TEXT_TAGS
sk - 12.05.2023: This const is also used in ilKprimChoiceWizardInputGUI.
Class ilQuestionUsagesTableGUI.
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
const HAS_SPECIAL_QUESTION_COMMANDS
addSaveOnEnterOnLoadCode()
setMoveAfterQuestionId(?int $question_id)
setQuestionSpecificTabs(ilTabsGUI $tabs_gui)
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
static getPageList(int $lm_id)
__construct(Container $dic, ilPlugin $plugin)
addJavaScript(string $a_js_file, bool $a_add_version_parameter=true, int $a_batch=2)
Add a javascript file that should be included in the header.
getAdditionalEditQuestionCommands()
This class represents a text area property in a property form.
static _getUsedHTMLTagsAsString(string $module='')
ilComponentRepository $component_repository
setCopyToNewPoolOnSave(?string $pool_title)
getQuestionHeaderBlockBuilder()
Class ilObjContentObjectGUI.
cleanupAnswerText(array $answer_text, bool $is_rte)
sk - 12.05.2023: This is one more of those that we need, but don't want.
const RENDER_PURPOSE_PRINT_PDF
addErrorMessage(string $errormessage)
string $presentationContext
getPreview(bool $show_question_only=false, bool $show_inline_feedback=false)
isRenderPurposePrintPdf()
saveSuggestedSolutionType()
setPreviousSolutionPrefilled(bool $previousSolutionPrefilled)
const SUGGESTED_SOLUTION_COMMANDS_DEFAULT
isPreviousSolutionPrefilled()
addNumberOfTriesToFormIfNecessary(ilPropertyFormGUI $form)
completeTestOutputFormAction(string $form_action, int $active_id, int $pass)
getQuestionSyncModal(string $cmd, string $cmd_class='')
setSubObject(?string $sub_obj_type, ?int $sub_obj_id)
Set sub object attributes.
static _lookupType(int $id, bool $reference=false)
static getManualFeedback(int $active_id, int $question_id, ?int $pass)
Retrieves the feedback comment for a question in a test if it is finalized.
ilObjectDataCache $ilObjDataCache
const RENDER_PURPOSE_INPUT_VALUE
const RENDER_PURPOSE_PREVIEW
addBackTab(ilTabsGUI $tabs_gui)
setVariable(string $variable, $value='')
Sets the given variable to the given value.
getSolutionOutput(int $active_id, ?int $pass=null, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_inline_feedback=true)
string $copy_to_new_pool_on_save
Class ilCommonActionDispatcherGUI.
getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
ilQuestionHeaderBlockBuilder $questionHeaderBlockBuilder
renderSolutionOutput(mixed $user_solutions, int $active_id, ?int $pass, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_autosave_title=false, bool $show_inline_feedback=false,)
setExpand($a_node_id)
set the expand option this value is stored in a SESSION variable to save it different view (lo view...
static getCommandsFromClassConstants(string $guiClassName, string $cmdConstantNameBegin='CMD_')
setTestSpecificProperties()
setNavigationGUI(?ilTestQuestionNavigationGUI $navigationGUI)
renderEditForm(ilPropertyFormGUI $form)
static getFeedbackClassNameByQuestionType(string $questionType)
static stripOnlySlashes(string $a_str)
renderPurposeSupportsFormHtml()
getGenericFeedbackOutput(int $active_id, ?int $pass)