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 [$this->
object->getId() => $html]
635 $presentation = $page_gui->presentation();
636 $presentation = preg_replace(
"/src=\"\\.\\//ims",
"src=\"" . ILIAS_HTTP_PATH .
"/", $presentation);
637 return $presentation;
640 public function outQuestionPage($a_temp_var, $a_postponed =
false, $active_id =
"", $html =
"", $inlineFeedbackEnabled =
false): string
642 if ($this->
object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
646 } elseif ($this->
object->getTestPresentationConfig()->isUnchangedAnswerPossible()) {
650 $this->
lng->loadLanguageModule(
"content");
654 $page_gui->setTemplateTargetVar($a_temp_var);
658 $page_gui->setQuestionActionsHTML($this->
getNavigationGUI()->getActionsHTML());
662 $page_gui->setQuestionHTML([$this->
object->getId() => $html]);
665 $page_gui->setPresentationTitle($this->questionHeaderBlockBuilder->getPresentationTitle());
666 $page_gui->setQuestionInfoHTML($this->questionHeaderBlockBuilder->getQuestionInfoHTML());
668 return $page_gui->presentation();
673 $tpl =
new ilTemplate(
'tpl.tst_question_additional_behaviour_checkbox.html',
true,
true,
'components/ILIAS/TestQuestionPool');
674 $tpl->
setVariable(
'TXT_FORCE_FORM_DIFF_LABEL', $this->
object->getTestPresentationConfig()->getUseUnchangedAnswerLabel());
680 return $this->
lng->txt(
'use_previous_solution_advice');
685 $tpl =
new ilTemplate(
'tpl.tst_question_additional_behaviour_checkbox.html',
true,
true,
'components/ILIAS/TestQuestionPool');
686 $tpl->
setVariable(
'TXT_FORCE_FORM_DIFF_LABEL', $this->
lng->txt(
'use_previous_solution'));
692 $original_id = $this->
object->getOriginalId();
693 if ($original_id !== null) {
694 $this->
object->syncWithOriginal();
695 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"msg_obj_modified"),
true);
701 $old_id = $this->request_data_collector->getQuestionId();
705 $this->tabs_gui->setTabActive(
'edit_question');
709 $this->
object->getCurrentUser()->setPref(
'tst_lastquestiontype', $this->
object->getQuestionType());
710 $this->
object->getCurrentUser()->writePref(
'tst_lastquestiontype', $this->
object->getQuestionType());
711 $this->
object->saveToDb($old_id);
713 $this->questionrepository->questionExistsInPool($this->
object->getOriginalId());
714 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'msg_obj_modified'),
true);
722 $this->tabs_gui->activateTab(
'edit_question');
728 $this->
object->getCurrentUser()->setPref(
'tst_lastquestiontype', $this->
object->getQuestionType());
729 $this->
object->getCurrentUser()->writePref(
'tst_lastquestiontype', $this->
object->getQuestionType());
731 if ($this->request_data_collector->getQuestionId() === 0) {
732 if ($this->
object->getId() < 1) {
733 $this->
object->createNewQuestion();
739 $cmd = strpos($this->
ctrl->getCmd(),
'Return') ===
false 740 ? self::CMD_SYNC_QUESTION
741 : self::CMD_SYNC_QUESTION_AND_RETURN;
745 $this->
object->saveToDb();
751 $additional_content_editing_mode = $this->request_data_collector->string(
'additional_content_editing_mode');
752 if ($additional_content_editing_mode !==
'' 753 && in_array($additional_content_editing_mode, $this->
object->getValidAdditionalContentEditingModes())) {
754 $this->
object->setAdditionalContentEditingMode($additional_content_editing_mode);
760 if ($this->request_data_collector->isset(
'pool_ref')) {
761 $this->copy_to_existing_pool_on_save = $this->request_data_collector->int(
'pool_ref');
764 if ($this->request_data_collector->isset(
'pool_title')) {
765 $this->copy_to_new_pool_on_save = $this->request_data_collector->string(
'pool_title');
768 if ($this->request_data_collector->isset(
'move_after_question_with_id')) {
769 $this->move_after_question_with_id = $this->request_data_collector->int(
'move_after_question_with_id');
776 public function getContextPath($cont_obj,
int $a_endnode_id,
int $a_startnode_id = 1): string
780 $tmpPath = $cont_obj->getLMTree()->getPathFull($a_endnode_id, $a_startnode_id);
783 for ($i = 1; $i < (count($tmpPath) - 1); $i++) {
788 $path .= $tmpPath[$i][
"title"];
796 $this->sequence_no = $nr;
806 $this->question_count = $a_question_count;
826 $this->errormessage .= ((strlen($this->errormessage)) ?
"<br />" :
"") .
$errormessage;
831 return $this->
object->getQuestionType();
837 if (strlen($a_value)) {
838 $result =
" value=\"$a_value\" ";
845 if (!$this->
object->getSelfAssessmentEditingMode()) {
854 $title->setMaxLength(100);
855 $title->setValue($this->
object->getTitle());
856 $title->setRequired(
true);
859 if (!$this->
object->getSelfAssessmentEditingMode()) {
862 $author->setValue($this->
object->getAuthor());
863 $author->setMaxLength(512);
864 $author->setRequired(
true);
869 $description->setValue($this->
object->getComment());
870 $description->setRequired(
false);
871 $description->setMaxLength(1000);
877 if (trim($author) ==
"") {
880 $hi->setValue($author);
893 $question->setRequired(
true);
894 $question->setRows(10);
895 $question->setCols(80);
897 if (!$this->
object->getSelfAssessmentEditingMode()) {
899 $question->setUseRte(
true);
901 $question->setRTESupport($this->
object->getId(),
'qpl',
'assessment');
905 $question->setUseTagsForRteOnly(
false);
911 $form->
addItem($question_type);
913 if ($this->copy_to_existing_pool_on_save !== null) {
915 $pool_ref->setValue((
string) $this->copy_to_existing_pool_on_save);
919 if ($this->copy_to_new_pool_on_save !== null) {
921 $pool_title->setValue($this->copy_to_new_pool_on_save);
925 if ($this->move_after_question_with_id !== null) {
926 $move_after_question_id =
new ilHiddenInputGUI(
'move_after_question_with_id');
927 $move_after_question_id->setValue((
string) $this->move_after_question_with_id);
928 $form->
addItem($move_after_question_id);
931 $additional_content_editing_mode =
new ilHiddenInputGUI(
'additional_content_editing_mode');
932 $additional_content_editing_mode->setValue($this->
object->getAdditionalContentEditingMode());
933 $form->
addItem($additional_content_editing_mode);
940 if (!$this->
object->getSelfAssessmentEditingMode()) {
944 $nr_tries = $this->
object->getNrOfTries() ?? $this->
object->getDefaultNrOfTries();
951 $ni->setValue((
string) $nr_tries);
954 $ni->setMaxLength(5);
962 $postvar =
"tax_node_assign_$taxonomyId";
966 $tax_node_assign->saveInput(
"qpl", $this->
object->getObjId(),
"quest", $this->
object->getId());
975 $sectHeader->setTitle($this->
lng->txt(
'qpl_qst_edit_form_taxonomy_section'));
980 $label = sprintf($this->
lng->txt(
'qpl_qst_edit_form_taxonomy'), $taxonomy->getTitle());
981 $postvar =
"tax_node_assign_$taxonomyId";
990 $taxSelect->setValue(
array_map(
function ($assignedNode) {
991 return $assignedNode[
'node_id'];
1004 if ($manual_feedback !==
'') {
1005 return $manual_feedback;
1010 if ($this->
object->isAdditionalContentEditingModePageObject()) {
1020 if ($pass === null) {
1023 $reached_points = $this->
object->calculateReachedPoints($active_id, $pass);
1024 $max_points = $this->
object->getMaximumPoints();
1026 $is_correct =
false;
1027 if ($reached_points == $max_points) {
1031 return $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation(
1040 $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(),
true),
1048 $this->
object->feedbackOBJ->getGenericFeedbackTestPresentation($this->object->getId(),
false),
1055 $count = $this->questionrepository->usageCount($this->
object->getId());
1057 if ($this->questionrepository->questionExistsInPool($this->object->getId()) && $count) {
1058 if ($this->rbacsystem->checkAccess(
"write", $this->request_data_collector->getRefId())) {
1059 $this->tpl->setOnScreenMessage(
'info', sprintf($this->
lng->txt(
"qpl_question_is_in_use"), $count));
1063 return $this->
lng->txt($this->
object->getQuestionType());
1068 foreach (SuggestedSolution::TYPES as $k => $v) {
1069 $options[$k] = $this->
lng->txt($v);
1086 if ($save && $this->request_data_collector->int(
'deleteSuggestedSolution') === 1) {
1087 $this->
object->deleteSuggestedSolutions();
1088 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"msg_obj_modified"),
true);
1089 $this->
ctrl->redirect($this,
'suggestedsolution');
1094 $solution = $this->
object->getSuggestedSolution();
1097 $solution_type = $this->
ctrl->getCmd() ===
'cancelSuggestedSolution' 1098 ? $solution->getType()
1099 : $this->request_data_collector->string(
'solutiontype');
1100 if ($solution_type === SuggestedSolution::TYPE_FILE
1101 && ($solution === null || $solution->getType() !== SuggestedSolution::TYPE_FILE)
1105 SuggestedSolution::TYPE_FILE
1109 $solution_filename = $this->request_data_collector->string(
'filename');
1110 if ($save && !empty($solution_filename)) {
1111 $solution = $solution->withTitle($solution_filename);
1114 if ($solution !== null) {
1116 $form->setFormAction($this->
ctrl->getFormAction($this));
1117 $form->setTitle($this->
lng->txt(
'solution_hint'));
1118 $form->setMultipart(
true);
1119 $form->setTableWidth(
'100%');
1120 $form->setId(
'suggestedsolutiondisplay');
1124 'tpl.il_as_qpl_suggested_solution_input_presentation.html',
1127 'components/ILIAS/TestQuestionPool' 1130 if ($solution->isOfTypeLink()) {
1131 $href = $this->
object->getInternalLinkHref($solution->getInternalLink());
1132 $template->setCurrentBlock(
'preview');
1133 $template->setVariable(
'TEXT_SOLUTION', $this->
lng->txt(
'suggested_solution'));
1134 $template->setVariable(
1136 " <a href='{$href}' target='content'>{$this->lng->txt('view')}</a> " 1138 $template->parseCurrentBlock();
1140 $solution->isOfTypeFile()
1141 && $solution->getFilename()
1143 $href = $this->
object->getSuggestedSolutionPathWeb() . $solution->getFilename();
1144 $link =
" <a href='{$href}' target='content'>" 1147 $template->setCurrentBlock(
'preview');
1148 $template->setVariable(
'TEXT_SOLUTION', $this->
lng->txt(
'suggested_solution'));
1149 $template->setVariable(
'VALUE_SOLUTION', $link);
1150 $template->parseCurrentBlock();
1153 $template->setVariable(
'TEXT_TYPE', $this->
lng->txt(
'type'));
1154 $template->setVariable(
'VALUE_TYPE', $options[$solution->getType()]);
1156 $title->
setHtml($template->get());
1158 $deletesolution->setOptionTitle($this->
lng->txt(
'deleteSuggestedSolution'));
1159 $title->addSubItem($deletesolution);
1160 $form->addItem($title);
1162 if ($solution->isOfTypeFile()) {
1165 $file->enableFileNameSelection(
'filename');
1167 if ($save && $_FILES && $_FILES[
'file'][
'tmp_name'] && $file->checkInput()) {
1168 if (!file_exists($this->
object->getSuggestedSolutionPath())) {
1173 $_FILES[
'file'][
'tmp_name'],
1174 $_FILES[
'file'][
'name'],
1175 $this->
object->getSuggestedSolutionPath() . $_FILES[
'file'][
'name']
1181 if ($solution->getFilename()) {
1182 @unlink($this->
object->getSuggestedSolutionPath() . $solution->getFilename());
1185 $file->setValue($_FILES[
'file'][
'name']);
1186 $solution = $solution
1187 ->withFilename($_FILES[
'file'][
'name'])
1188 ->withMime($_FILES[
'file'][
'type'])
1189 ->withSize($_FILES[
'file'][
'size'])
1190 ->withTitle($this->request_data_collector->string(
'filename'));
1194 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'suggested_solution_added_successfully'),
true);
1195 $this->
ctrl->redirect($this,
'suggestedsolution');
1198 $this->tpl->setOnScreenMessage(
'info', $res);
1201 if ($solution->getFilename()) {
1202 $file->setValue($solution->getFilename());
1203 $file->setFilename($solution->getTitle());
1206 $form->addItem($file);
1208 $hidden->setValue(
'file');
1209 $form->addItem($hidden);
1211 if ($this->
access->checkAccess(
'write',
'', $this->request_data_collector->getRefId())) {
1212 $form->addCommandButton(
'cancelSuggestedSolution', $this->
lng->txt(
'cancel'));
1213 $form->addCommandButton(
'saveSuggestedSolution', $this->
lng->txt(
'save'));
1217 if ($form->checkInput()) {
1218 if ($solution->isOfTypeFile()) {
1219 $solution = $solution->withTitle($this->request_data_collector->string(
'filename'));
1222 if (!$solution->isOfTypeLink()) {
1226 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'msg_obj_modified'),
true);
1227 $this->
ctrl->redirect($this,
'suggestedsolution');
1231 $output = $form->getHTML();
1234 $savechange = $this->
ctrl->getCmd() ===
'saveSuggestedSolutionType';
1237 if ($this->
access->checkAccess(
'write',
'', $this->request_data_collector->getRefId())) {
1239 $formchange->setFormAction($this->
ctrl->getFormAction($this));
1241 $title = $solution ? $this->
lng->txt(
'changeSuggestedSolution') : $this->
lng->txt(
'addSuggestedSolution');
1242 $formchange->setTitle($title);
1243 $formchange->setMultipart(
false);
1244 $formchange->setTableWidth(
'100%');
1245 $formchange->setId(
'suggestedsolution');
1248 foreach ($options as $opt_value => $opt_caption) {
1252 $solutiontype->setValue($solution->getType());
1254 $solutiontype->setRequired(
true);
1255 $formchange->addItem($solutiontype);
1257 $formchange->addCommandButton(
'saveSuggestedSolutionType', $this->
lng->txt(
'select'));
1260 $formchange->checkInput();
1262 $changeoutput = $formchange->getHTML();
1264 $this->tabs_gui->activateTab(
'suggested_solution');
1265 $this->tpl->setVariable(
'ADM_CONTENT', $changeoutput . $output);
1270 $type = $this->request_data_collector->string(
"link_new_type");
1271 $search = $this->request_data_collector->string(
"search_link_type");
1272 $this->
ctrl->setParameter($this,
"link_new_type", $type);
1273 $this->
ctrl->setParameter($this,
"search_link_type", $search);
1274 $this->
ctrl->saveParameter($this, [
"subquestion_index",
"link_new_type",
"search_link_type"]);
1276 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
"select_object_to_link"));
1278 $parent_ref_id = $this->tree->getParentId($this->request_data_collector->getRefId());
1280 $exp->
setExpand($this->request_data_collector->raw(
'expand_sol') ? $this->request_data_collector->raw(
'expand_sol') : $parent_ref_id);
1281 $exp->setExpandTarget($this->
ctrl->getLinkTarget($this,
'outSolutionExplorer'));
1282 $exp->setTargetGet(
"ref_id");
1283 $exp->setRefId($this->request_data_collector->getRefId());
1284 $exp->addFilter($type);
1285 $exp->setSelectableType($type);
1286 if ($this->request_data_collector->isset(
'expandCurrentPath') && $this->request_data_collector->raw(
'expandCurrentPath')) {
1287 $exp->expandPathByRefId($parent_ref_id);
1293 $template =
new ilTemplate(
"tpl.il_as_qpl_explorer.html",
true,
true,
"components/ILIAS/TestQuestionPool");
1294 $template->setVariable(
"EXPLORER_TREE", $exp->getOutput());
1295 $template->setVariable(
"BUTTON_CANCEL", $this->
lng->txt(
"cancel"));
1296 $template->setVariable(
"FORMACTION", $this->
ctrl->getFormAction($this,
"suggestedsolution"));
1297 $this->tpl->setVariable(
"ADM_CONTENT", $template->get());
1302 $solution_type = $this->request_data_collector->string(
'solutiontype');
1304 switch ($solution_type) {
1328 if (isset($solution_type)) {
1329 $this->
ctrl->setParameter($this,
'expandCurrentPath', 1);
1331 $this->
ctrl->setParameter($this,
'link_new_type', $type);
1332 $this->
ctrl->setParameter($this,
'search_link_type', $search);
1333 $this->
ctrl->redirect($this,
'outSolutionExplorer');
1338 $this->
ctrl->redirect($this,
'suggestedsolution');
1343 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1345 $cont_obj_gui =
new ilObjContentObjectGUI(
'', $this->request_data_collector->int(
'source_id'),
true);
1349 $tree = $cont_obj->getLMTree();
1354 foreach ($chapters as $chapter) {
1356 foreach ($chapterpages as $page) {
1357 if ($page[
'type'] == $this->request_data_collector->raw(
'search_link_type')) {
1358 array_push($shownpages, $page[
'obj_id']);
1360 if ($tree->
isInTree($page[
'obj_id'])) {
1366 $this->
ctrl->setParameter($this, $page[
'type'], $page[
'obj_id']);
1368 'title' => $page[
'title'],
1370 'text_add' => $this->
lng->txt(
'add'),
1371 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($page[
'type']))
1376 foreach ($pages as $page) {
1377 if (!in_array($page[
'obj_id'], $shownpages)) {
1378 $this->
ctrl->setParameter($this, $page[
'type'], $page[
'obj_id']);
1380 'title' => $page[
'title'],
1381 'description' =>
'---',
1382 'text_add' => $this->
lng->txt(
'add'),
1383 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($page[
'type']))
1389 $table->setTitle($this->
lng->txt(
'obj_' .
ilUtil::stripSlashes($this->request_data_collector->string(
'search_link_type'))));
1390 $table->setData($rows);
1392 $this->tpl->setContent($table->getHTML());
1397 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1399 $cont_obj_gui =
new ilObjContentObjectGUI(
'', $this->request_data_collector->int(
'source_id'),
true);
1401 $ctree = $cont_obj->getLMTree();
1402 $nodes = $ctree->getSubtree($ctree->getNodeData($ctree->getRootId()));
1406 foreach ($nodes as $node) {
1407 if ($node[
'type'] == $this->request_data_collector->raw(
'search_link_type')) {
1408 $this->
ctrl->setParameter($this, $node[
'type'], $node[
'obj_id']);
1410 'title' => $node[
'title'],
1411 'description' =>
'',
1412 'text_add' => $this->
lng->txt(
'add'),
1413 'href_add' => $this->
ctrl->getLinkTarget($this,
'add' . strtoupper($node[
'type']))
1419 $table->setTitle($this->
lng->txt(
'obj_' .
ilUtil::stripSlashes($this->request_data_collector->string(
'search_link_type'))));
1420 $table->setData($rows);
1422 $this->tpl->setContent($table->getHTML());
1427 $this->
ctrl->setParameter($this,
'q_id', $this->
object->getId());
1429 $glossary =
new ilObjGlossary($this->request_data_collector->int(
'source_id'),
true);
1434 foreach ($terms as $term) {
1435 $this->
ctrl->setParameter($this,
'git', $term[
'id']);
1437 'title' => $term[
'term'],
1438 'description' =>
'',
1439 'text_add' => $this->
lng->txt(
'add'),
1440 'href_add' => $this->
ctrl->getLinkTarget($this,
'addGIT')
1445 $table->setTitle($this->
lng->txt(
'glossary_term'));
1446 $table->setData($rows);
1448 $this->tpl->setContent($table->getHTML());
1454 $question_id = $this->
object->getId();
1455 $subquestion_index = $this->request_data_collector->int(
'subquestion_index');
1456 $subquestion_index = ($subquestion_index > 0) ? $subquestion_index : 0;
1458 $solution = $repo->create($question_id, $type)
1459 ->withSubquestionIndex($subquestion_index)
1460 ->withInternalLink($target);
1462 $repo->update([$solution]);
1467 $this->
ctrl->saveParameter($this, [
"subquestion_index",
"link_new_type",
"search_link_type"]);
1468 switch ($this->request_data_collector->string(
"search_link_type")) {
1479 $target =
"il__lm_" . $this->request_data_collector->raw(
"source_id");
1481 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1482 $this->
ctrl->redirect($this,
'suggestedsolution');
1489 $target =
"il__pg_" . $this->request_data_collector->raw(
"pg");
1491 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1492 $this->
ctrl->redirect($this,
'suggestedsolution');
1497 $target =
"il__st_" . $this->request_data_collector->raw(
"st");
1499 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1500 $this->
ctrl->redirect($this,
'suggestedsolution');
1505 $target =
"il__git_" . $this->request_data_collector->raw(
"git");
1507 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
"suggested_solution_added_successfully"),
true);
1508 $this->
ctrl->redirect($this,
'suggestedsolution');
1513 return in_array($this->
ctrl->getCmd(), self::QUESTION_SAVE_CMDS);
1517 string $guiClassName,
1518 string $cmdConstantNameBegin =
'CMD_' 1527 foreach ($reflectionClass->getConstants() as $constName => $constValue) {
1528 if (substr($constName, 0, strlen($cmdConstantNameBegin)) == $cmdConstantNameBegin) {
1529 $commands[] = $constValue;
1539 $this->tabs_gui->clearTargets();
1541 if ($this->
object->getId() > 0) {
1544 $this->tabs_gui->activateTab(
'edit_question');
1551 $this->
ctrl->setParameterByClass(ilAssQuestionPageGUI::class,
'q_id', $this->
object->getId());
1552 $this->
ctrl->setParameterByClass(static::class,
'q_id', $this->
object->getId());
1566 $this->
ctrl->setParameterByClass($classname,
'q_id', $this->
object->getId());
1568 'suggested_solution',
1569 $this->
ctrl->getLinkTargetByClass($classname,
'suggestedsolution'),
1571 'suggestedsolution',
1572 'saveSuggestedSolution',
1573 'outSolutionExplorer',
1575 'addSuggestedSolution',
1578 'removeSuggestedSolution' 1590 return [
'editQuestion',
'save',
'originalSyncForm'];
1600 $tabCommands = self::getCommandsFromClassConstants(ilAssQuestionFeedbackEditingGUI::class);
1602 $this->
ctrl->setParameterByClass(ilAssQuestionFeedbackEditingGUI::class,
'q_id', $this->
object->getId());
1605 $tabs->
addTarget(
'feedback', $tabLink, $tabCommands, $this->
ctrl->getCmdClass(),
'');
1610 switch (strtolower($this->
ctrl->getCmdClass())) {
1611 case 'ilassquestionhintsgui':
1612 $tab_commands = self::getCommandsFromClassConstants(ilAssQuestionHintsGUI::class);
1615 case 'ilassquestionhintgui':
1616 $tab_commands = self::getCommandsFromClassConstants(ilAssQuestionHintGUI::class);
1623 $this->
ctrl->setParameterByClass(ilAssQuestionHintsGUI::class,
'q_id', $this->
object->getId());
1625 'tst_question_hints_tab',
1628 $this->
ctrl->getCmdClass(),
1637 $this->
ctrl->getLinkTargetByClass(
1650 $reachedPoints = $this->
object->getAdjustedReachedPoints((
int) $activeId, (
int) $passIndex,
true);
1651 $maximumPoints = $this->
object->getMaximumPoints();
1653 return $reachedPoints == $maximumPoints;
1663 $this->
object->setTitle($this->request_data_collector->string(
'title'));
1664 $this->
object->setAuthor($this->request_data_collector->string(
'author'));
1665 $this->
object->setComment($this->request_data_collector->string(
'comment'));
1667 $nr_of_tries = $this->request_data_collector->int(
'nr_of_tries');
1668 if ($this->
object->getSelfAssessmentEditingMode()) {
1669 $this->
object->setNrOfTries($nr_of_tries);
1674 $this->request_data_collector->string(
'lifecycle')
1680 $this->
object->setQuestion(
1682 $this->request_data_collector->string(
'question')
1693 bool $is_question_postponed =
false,
1694 array|
bool $user_post_solutions =
false,
1695 bool $show_specific_inline_feedback =
false 1702 $is_question_postponed,
1703 $user_post_solutions,
1704 $show_specific_inline_feedback
1709 $this->tpl->setVariable(
"QUESTION_OUTPUT", $test_output);
1710 $this->tpl->setVariable(
"FORMACTION", $formaction);
1712 $this->tpl->setVariable(
"FORM_TIMESTAMP", (
string) time());
1716 string $form_action,
1720 return $form_action;
1730 return self::FORM_ENCODING_URLENCODE;
1735 if ($this->
object->getId() <= 0) {
1737 $this->
lng->txt(
'cancel'),
1738 $this->
ctrl->getParentReturnByClass(
1746 $this->
ctrl->setParameterByClass(
1747 ilAssQuestionPreviewGUI::class,
1751 $this->
ctrl->saveParameterByClass(ilAssQuestionPreviewGUI::class,
'prev_qid');
1753 $this->
lng->txt(
'backtocallingpage'),
1754 $this->
ctrl->getLinkTargetByClass(
1755 ilAssQuestionPreviewGUI::class,
1759 $this->
ctrl->clearParameterByClass(ilAssQuestionPreviewGUI::class,
'prev_qid');
1778 $form->setFormAction($this->
ctrl->getFormAction($this));
1779 $form->setId($this->
getType());
1781 $form->setTableWidth(
'100%');
1782 $form->setMultipart(
true);
1793 return str_replace([
'{',
'}'], [
'{',
'}'], $text);
1804 return '<div id="focus"></div>';
1825 $table->setQuestionIndex($questionIndex);
1827 $table->initColumns();
1846 switch ($correctness) {
1847 case self::CORRECTNESS_NOT_OK:
1848 $icon_name =
'standard/icon_not_ok.svg';
1849 $label = $this->
lng->txt(
"answer_is_wrong");
1851 case self::CORRECTNESS_MOSTLY_OK:
1852 $icon_name =
'standard/icon_mostly_ok.svg';
1853 $label = $this->
lng->txt(
"answer_is_not_correct_but_positive");
1855 case self::CORRECTNESS_OK:
1856 $icon_name =
'standard/icon_ok.svg';
1857 $label = $this->
lng->txt(
"answer_is_right");
1863 $icon = $this->
ui->factory()->symbol()->icon()->custom(
1867 return $this->
ui->renderer()->render($icon);
1879 ?
string $txt_output,
1880 bool $prepare_for_latex_output =
false,
1881 bool $omitNl2BrWhenTextArea =
false 1883 if ($txt_output === null || $txt_output ===
'') {
1887 $result = $txt_output;
1890 if (strlen(strip_tags($result)) < strlen($result)) {
1896 if (!$omitNl2BrWhenTextArea) {
1898 $result = preg_replace(
"/[\n]/",
"<br />", $result);
1902 if (preg_match_all(
"/(<pre>.*?<\/pre>)/ims", $result, $matches)) {
1903 foreach ($matches[0] as $found) {
1905 if (strpos(
"\n", $found) ===
false) {
1906 $replacement =
"\n";
1908 $removed = preg_replace(
"/<br\s*?\/>/ims", $replacement, $found);
1909 $result = str_replace($found, $removed, $result);
1916 if ($prepare_for_latex_output) {
1921 if ($prepare_for_latex_output) {
1924 $result = str_replace(
"{",
"{", $result);
1925 $result = str_replace(
"}",
"}", $result);
1926 $result = str_replace(
"\\",
"\", $result);
1935 if (is_null($this->suggestedsolution_repo)) {
1936 $dic = QuestionPoolDIC::dic();
1937 $this->suggestedsolution_repo =
$dic[
'question.repo.suggestedsolutions'];
1948 if (!is_array($answer_text)) {
1963 self::ALLOWED_PLAIN_TEXT_TAGS
1973 $this->parent_type_is_lm = $flag;
1978 $this->tpl->addOnloadCode(
" 1979 let form = document.querySelector('#ilContentContainer form'); 1980 let button = form.querySelector('input[name=\"cmd[save]\"]'); 1981 if (form && button) { 1982 form.addEventListener('keydown', function (e) { 1983 if (e.key === 'Enter' 1984 && e.target.type !== 'textarea' 1985 && e.target.type !== 'submit' 1986 && e.target.type !== 'file' 1989 form.requestSubmit(button); 1998 return in_array($cmd, static::ADDITIONAL_CMDS_NEEDING_EXISTING_QST);
2003 $this->context_allows_sync_to_pool = $sync_allowed;
2008 return $this->context_allows_sync_to_pool
2009 && $this->
object->hasWritableOriginalInQuestionPool();
2014 if ($cmd_class ===
'') {
2015 $cmd_class = static::class;
2017 $modal = $this->
ui->factory()->modal()->interruptive(
2018 $this->
lng->txt(
'confirm'),
2019 $this->
lng->txt(
'confirm_sync_questions'),
2020 $this->
ctrl->getFormActionByClass($cmd_class, $cmd)
2021 )->withAffectedItems([
2022 $this->
ui->factory()->modal()->interruptiveItem()->standard(
2023 (
string) $this->
object->getOriginalId(),
2024 $this->
object->getTitleForHTMLOutput()
2026 ])->withActionButtonLabel($this->
lng->txt(
'sync_question_to_pool'));
2027 return $this->
ui->renderer()->render(
2028 $modal->withOnLoad($modal->getShowSignal())
2035 bool $graphical_output =
false,
2036 bool $result_output =
false,
2037 bool $show_question_only =
true,
2038 bool $show_feedback =
false,
2039 bool $show_correct_solution =
false,
2040 bool $show_manual_scoring =
false,
2041 bool $show_question_text =
true,
2042 bool $show_autosave_title =
false,
2043 bool $show_inline_feedback =
false 2045 $autosave_solutions = $this->
object->getSolutionValues($active_id, $pass,
false);
2046 if ($autosave_solutions === []) {
2050 $autosave_solutions,
2055 $show_question_only,
2057 $show_correct_solution,
2058 $show_manual_scoring,
2059 $show_question_text,
2060 $show_autosave_title,
2061 $show_inline_feedback
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 file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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)
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)
addTab_QuestionHints(ilTabsGUI $tabs)
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...
setOutputMode(string $a_mode=self::PRESENTATION)
int $question_count
question count in test
cancelSuggestedSolution()
getEditQuestionTabCommands()
getSuggestedSolutionsRepo()
const ADDITIONAL_CMDS_NEEDING_EXISTING_QST
There are functions that need an existing question.
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)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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.
const CMD_SHOW_LIST
command constants
SuggestedSolutionsDatabaseRepository $suggestedsolution_repo
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
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)
static renameExecutables(string $a_dir)
const SUGGESTED_SOLUTION_COMMANDS_SAVE
getType()
needed for page editor compliance
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()
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)
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)
static _getUsedHTMLTagsAsString(string $a_module="")
Returns a string of all allowed HTML tags for text editing.
addTab_QuestionFeedback(ilTabsGUI $tabs)
isRenderPurposeInputValue()
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.
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()
setQuestionHTML(array $question_html)
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 getInstance()
Singleton: get instance for use in ILIAS requests with a config loaded from the settings.
static getPageList(int $lm_id)
__construct(Container $dic, ilPlugin $plugin)
getAdditionalEditQuestionCommands()
This class represents a text area property in a property form.
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_')
static _getUsedHTMLTags(string $a_module="")
Returns an array of all allowed HTML tags for text editing.
setTestSpecificProperties()
setNavigationGUI(?ilTestQuestionNavigationGUI $navigationGUI)
renderEditForm(ilPropertyFormGUI $form)
static getFeedbackClassNameByQuestionType(string $questionType)
static stripOnlySlashes(string $a_str)
renderPurposeSupportsFormHtml()
getGenericFeedbackOutput(int $active_id, ?int $pass)