ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilAssQuestionSkillAssignmentsGUI.php
Go to the documentation of this file.
1<?php
2
19use ILIAS\Data\Factory as DataFactory;
20use ILIAS\HTTP\Services as HTTP;
21use ILIAS\Refinery\Factory as Refinery;
29use ILIAS\UI\Factory as UIFactory;
30use ILIAS\UI\Renderer as UIRenderer;
32
47{
48 public const CMD_SHOW_SKILL_QUEST_ASSIGNS = 'showSkillQuestionAssignments';
49 public const CMD_EDIT_SKILL_QUEST_ASSIGNS = 'editSkillQuestionAssignment';
50 public const CMD_SHOW_SKILL_SELECT = 'showSkillSelection';
51 public const CMD_UPDATE_SKILL_QUEST_ASSIGNS = 'updateSkillQuestionAssignments';
52 public const CMD_SHOW_SKILL_QUEST_ASSIGN_PROPERTIES_FORM = 'showSkillQuestionAssignmentPropertiesForm';
53 public const CMD_SAVE_SKILL_QUEST_ASSIGN_PROPERTIES_FORM = 'saveSkillQuestionAssignmentPropertiesForm';
54 public const CMD_SAVE_SKILL_POINTS = 'saveSkillPoints';
55 public const CMD_SHOW_SYNC_ORIGINAL_CONFIRMATION = 'showSyncOriginalConfirmation';
56 public const CMD_SYNC_ORIGINAL = 'syncOriginal';
57
58 public const PARAM_SKILL_SELECTION = 'skill_ids';
59
64
66
67 private DataFactory $data_factory;
68
69 public function __construct(
70 private readonly ilCtrl $ctrl,
71 private readonly ilAccessHandler $access,
72 private readonly ilGlobalTemplateInterface $tpl,
73 private readonly ilLanguage $lng,
74 private readonly ilDBInterface $db,
75 private readonly RequestDataCollectorInterface $request_data_collector,
76 private readonly SkillUsageService $skill_usage_service,
77 private readonly UIFactory $ui_factory,
78 private readonly UIRenderer $ui_renderer,
79 private readonly Refinery $refinery,
80 private readonly HTTP $http,
81 private readonly ilToolbarGUI $toolbar,
82 private readonly ilTabsGUI $tabs,
83 private readonly ?ilObjTest $test_object = null
84 ) {
85 $this->data_factory = new DataFactory();
86 }
87
88 public function getQuestionOrderSequence(): ?array
89 {
91 }
92
93 public function getAssignmentConfigurationHintMessage(): ?string
94 {
96 }
97
98 public function setAssignmentConfigurationHintMessage(?string $assignmentConfigurationHintMessage): void
99 {
100 $this->assignment_configuration_hint_message = $assignmentConfigurationHintMessage;
101 }
102
107 {
108 $this->questionOrderSequence = $questionOrderSequence;
109 }
110
115 {
117 }
118
122 public function setQuestionList($questionList): void
123 {
124 $this->question_list = $questionList;
125 }
126
130 public function getQuestionContainerId(): int
131 {
133 }
134
138 public function setQuestionContainerId($questionContainerId): void
139 {
140 $this->question_container_id = $questionContainerId;
141 }
142
146 public function isAssignmentEditingEnabled(): bool
147 {
149 }
150
154 public function setAssignmentEditingEnabled($assignmentEditingEnabled): void
155 {
156 $this->assignment_editing_enabled = $assignmentEditingEnabled;
157 }
158
159 public function executeCommand(): void
160 {
161 $nextClass = $this->ctrl->getNextClass();
162
163 $command = $this->ctrl->getCmd(self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
164
165 if ($this->isAvoidManipulationRedirectRequired($command)) {
166 $this->ctrl->redirect($this, self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
167 }
168
170
171 if (in_array($command, [self::CMD_EDIT_SKILL_QUEST_ASSIGNS])) {
172 $this->modifyTabs();
173 }
174
175 switch ($nextClass) {
176 case strtolower(__CLASS__):
177 case '':
178
179 $command .= 'Cmd';
180 $this->$command();
181 break;
182
183 default:
184
185 throw new ilTestQuestionPoolException('unsupported next class in ctrl flow');
186 }
187 }
188
189 private function modifyTabs(): void
190 {
191 $this->tabs->clearTargets();
192 $this->tabs->setBackTarget(
193 $this->lng->txt('back'),
194 $this->ctrl->getLinkTargetByClass(
195 ilAssQuestionSkillAssignmentsGUI::class,
197 )
198 );
199 $this->tabs->addTab(
200 strtolower(ilAssQuestionSkillAssignmentsGUI::class),
201 $this->lng->txt('qpl_skl_sub_tab_quest_assign'),
202 $this->ctrl->getLinkTargetByClass(
203 ilAssQuestionSkillAssignmentsGUI::class,
205 )
206 );
207 $this->tabs->activateTab(strtolower(ilAssQuestionSkillAssignmentsGUI::class));
208 }
209
210 private function isAvoidManipulationRedirectRequired($command): bool
211 {
212 if ($this->isAssignmentEditingEnabled()) {
213 return false;
214 }
215
216 switch ($command) {
219
220 return true;
221 }
222
223 return false;
224 }
225
226 private function saveSkillPointsCmd(): void
227 {
228 $success = true;
229 $skill_points = $this->request_data_collector->raw('skill_points');
230
231 for ($i = 0; $i < 2; $i++) {
232 foreach ($skill_points as $assignment_key => $skill_point) {
233 $assignment_key = explode(':', $assignment_key);
234 $skillBaseId = (int) $assignment_key[0];
235 $skillTrefId = (int) $assignment_key[1];
236 $questionId = (int) $assignment_key[2];
237
238 if ($this->isTestQuestion($questionId)) {
239 $assignment = new ilAssQuestionSkillAssignment($this->db);
240
241 if ($i === 0) {
242 if (!$assignment->isValidSkillPoint($skill_point)) {
243 $success = false;
244 break 2;
245 }
246 continue;
247 }
248
249 $assignment->setParentObjId($this->getQuestionContainerId());
250 $assignment->setQuestionId($questionId);
251 $assignment->setSkillBaseId($skillBaseId);
252 $assignment->setSkillTrefId($skillTrefId);
253
254 if ($assignment->dbRecordExists()) {
255 $assignment->loadFromDb();
256
257 if (!$assignment->hasEvalModeBySolution()) {
258 $assignment->setSkillPoints($skill_point);
259 $assignment->saveToDb();
260
261 // add skill usage
262 $this->skill_usage_service->addUsage($this->getQuestionContainerId(), $skillBaseId, $skillTrefId);
263 }
264 }
265 }
266
267 }
268 }
269
270 if ($success) {
271 $this->tpl->setOnScreenMessage('success', $this->lng->txt('tst_msg_skl_qst_assign_points_saved'), true);
272 $this->ctrl->redirect($this, self::CMD_SHOW_SKILL_QUEST_ASSIGNS);
273 return;
274 }
275
276 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('tst_msg_skl_qst_assign_points_not_saved'));
277 $this->showSkillQuestionAssignmentsCmd(true);
278 }
279
280 private function updateSkillQuestionAssignmentsCmd(): void
281 {
283 $question_id = $this->request_data_collector->getQuestionId();
284
285 if ($this->isTestQuestion($question_id)) {
286 $assignmentList = new ilAssQuestionSkillAssignmentList($this->db);
287 $assignmentList->setParentObjId($this->getQuestionContainerId());
288 $assignmentList->loadFromDb();
289
290 $handledSkills = [];
291
292 $sgui = $this->buildSkillSelectorExplorerGUI([]);
293 $skillIds = $sgui->getSelectedSkills();
294
295 foreach ($skillIds as $skillId) {
296 $skill = explode(':', $skillId);
297 $skillBaseId = (int) $skill[0];
298 $skillTrefId = (int) $skill[1];
299
300 if ($skillBaseId) {
301 if (!$assignmentList->isAssignedToQuestionId($skillBaseId, $skillTrefId, $question_id)) {
302 $assignment = new ilAssQuestionSkillAssignment($this->db);
303
304 $assignment->setParentObjId($this->getQuestionContainerId());
305 $assignment->setQuestionId($question_id);
306 $assignment->setSkillBaseId($skillBaseId);
307 $assignment->setSkillTrefId($skillTrefId);
308
311 $assignment->saveToDb();
312
313 // add skill usage
314 $this->skill_usage_service->addUsage($this->getQuestionContainerId(), $skillBaseId, $skillTrefId);
315 }
316
317 $handledSkills[$skillId] = $skill;
318 }
319 }
320
321 foreach ($assignmentList->getAssignmentsByQuestionId($question_id) as $assignment) {
322 if (isset($handledSkills["{$assignment->getSkillBaseId()}:{$assignment->getSkillTrefId()}"])) {
323 continue;
324 }
325
326 $assignment->deleteFromDb();
327
328 // remove skill usage
329 if (!$assignment->isSkillUsed()) {
330 $this->skill_usage_service->removeUsage(
331 $assignment->getParentObjId(),
332 $assignment->getSkillBaseId(),
333 $assignment->getSkillTrefId()
334 );
335 }
336 }
337
338 $this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_qst_skl_assigns_updated'), true);
339
340 if ($this->isSyncOriginalPossibleAndAllowed($question_id)) {
342 $this->ctrl->redirect($this, self::CMD_SHOW_SYNC_ORIGINAL_CONFIRMATION);
343 }
344 }
345
347 }
348
349 private function showSkillSelectionCmd(): void
350 {
352 $question_id = $this->request_data_collector->getQuestionId();
353
354 $assignmentList = new ilAssQuestionSkillAssignmentList($this->db);
355 $assignmentList->setParentObjId($this->getQuestionContainerId());
356 $assignmentList->loadFromDb();
357
358 $skillSelectorExplorerGUI = $this->buildSkillSelectorExplorerGUI(
359 $assignmentList->getAssignmentsByQuestionId($question_id)
360 );
361
362 if (!$skillSelectorExplorerGUI->handleCommand()) {
363 $tpl = new ilTemplate('tpl.qpl_qst_skl_assign_selection.html', false, false, 'components/ILIAS/TestQuestionPool');
364
365 $tpl->setVariable('SKILL_SELECTOR_HEADER', $this->getSkillSelectorHeader($question_id));
366
367 $skillSelectorToolbarGUI = $this->buildSkillSelectorToolbarGUI();
368
369 $skillSelectorToolbarGUI->setOpenFormTag(true);
370 $skillSelectorToolbarGUI->setCloseFormTag(false);
371 $skillSelectorToolbarGUI->setLeadingImage(ilUtil::getImagePath("nav/arrow_upright.svg"), " ");
372 $tpl->setVariable('SKILL_SELECTOR_TOOLBAR_TOP', $this->ctrl->getHTML($skillSelectorToolbarGUI));
373
374 $tpl->setVariable('SKILL_SELECTOR_EXPLORER', $this->ctrl->getHTML($skillSelectorExplorerGUI));
375
376 $skillSelectorToolbarGUI->setOpenFormTag(false);
377 $skillSelectorToolbarGUI->setCloseFormTag(true);
378 $skillSelectorToolbarGUI->setLeadingImage(ilUtil::getImagePath("nav/arrow_downright.svg"), " ");
379 $tpl->setVariable('SKILL_SELECTOR_TOOLBAR_BOTTOM', $this->ctrl->getHTML($skillSelectorToolbarGUI));
380
381 $this->tpl->setContent($tpl->get());
382 }
383 }
384
386 ?assQuestionGUI $question_gui = null,
387 ?ilAssQuestionSkillAssignment $assignment = null,
388 ?ilPropertyFormGUI $form = null
389 ): void {
391
393
394 $question_id = $this->request_data_collector->getQuestionId();
395 $question_gui ??= assQuestionGUI::_getQuestionGUI('', $question_id);
396
397 $row_id_parameter = $this->request_data_collector->getRowIdParameter(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
398 [1 => $skill_base_id, 2 => $skill_tref_id] = explode('_', $row_id_parameter);
399 $assignment ??= $this->buildQuestionSkillAssignment($question_id, (int) $skill_base_id, (int) $skill_tref_id);
400
401 $form ??= $this->buildSkillQuestionAssignmentPropertiesForm($question_gui->getObject(), $assignment);
402
403 $this->tpl->setContent($form->getHTML() . '<br />' . $this->buildQuestionPage($question_gui));
404 }
405
406 private function saveSkillQuestionAssignmentPropertiesFormCmd(): void
407 {
408 $question_id = $this->request_data_collector->getQuestionId();
409
410 if ($this->isTestQuestion($question_id)) {
411 $question_gui = assQuestionGUI::_getQuestionGUI('', $question_id);
412
413 $row_id_parameter = $this->request_data_collector->getRowIdParameter(EditSkillsOfQuestionTableActions::FULL_ROW_ID_PARAMETER);
414 [1 => $skill_base_id, 2 => $skill_tref_id] = explode('_', $row_id_parameter);
415 $assignment = $this->buildQuestionSkillAssignment($question_id, (int) $skill_base_id, (int) $skill_tref_id);
416
417 $this->keepAssignmentParameters();
418 $form = $this->buildSkillQuestionAssignmentPropertiesForm($question_gui->getObject(), $assignment);
419 if (!$form->checkInput()
420 || !$this->checkPointsAreInt($form)) {
421 $form->setValuesByPost();
422 $this->showSkillQuestionAssignmentPropertiesFormCmd($question_gui, $assignment, $form);
423 return;
424 }
425 $form->setValuesByPost();
426
427 if ($form->getItemByPostVar('eval_mode')) {
428 $assignment->setEvalMode($form->getItemByPostVar('eval_mode')->getValue());
429 } else {
431 }
432
433 if ($assignment->hasEvalModeBySolution()) {
435 $sol_cmp_expr_input = $form->getItemByPostVar('solution_compare_expressions');
436
437 if (
438 $sol_cmp_expr_input instanceof ilLogicalAnswerComparisonExpressionInputGUI
439 && !$this->checkSolutionCompareExpressionInput($sol_cmp_expr_input, $question_gui->getObject())
440 ) {
441 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
442 $this->showSkillQuestionAssignmentPropertiesFormCmd($question_gui, $assignment, $form);
443 return;
444 }
445
446 $assignment->initSolutionComparisonExpressionList();
447 $assignment->getSolutionComparisonExpressionList()->reset();
448
449 foreach ($sol_cmp_expr_input?->getValues() ?? [] as $expression) {
450 $assignment->getSolutionComparisonExpressionList()->add($expression);
451 }
452 } else {
453 $assignment->setSkillPoints($form->getItemByPostVar('q_res_skill_points')->getValue());
454 }
455
456 $assignment->saveToDb();
457
458 // add skill usage
459 $this->skill_usage_service->addUsage(
460 $this->getQuestionContainerId(),
461 $this->request_data_collector->int('skill_base_id'),
462 $this->request_data_collector->int('skill_tref_id')
463 );
464
465 $this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_qst_skl_assign_properties_modified'), true);
466
467 if ($this->isSyncOriginalPossibleAndAllowed($question_id)) {
468 $this->ctrl->redirect($this, self::CMD_SHOW_SYNC_ORIGINAL_CONFIRMATION);
469 }
470 }
471
472 $this->ctrl->redirect($this, self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
473 }
474
476 assQuestion $question,
480 $form->setQuestion($question);
481 $form->setAssignment($assignment);
482 $form->setManipulationEnabled($this->isAssignmentEditingEnabled());
483 $form->build();
484
485 return $form;
486 }
487
488 private function showSkillQuestionAssignmentsCmd(bool $load_skill_points_from_request = false): void
489 {
490 $this->handleAssignmentConfigurationHintMessage();
491
492 $assignment_list = $this->buildSkillQuestionAssignmentList();
493 $assignment_list->loadFromDb();
494 $assignment_list->loadAdditionalSkillData();
495
497 $mode = $this->http->wrapper()->query()->retrieve(
498 SkillsByQuestionOverviewTable::VIEW_CONTROL_QUERY_PARAM,
499 $this->refinery->byTrying([
500 $this->refinery->kindlyTo()->string(),
501 $this->refinery->always(SkillAssignmentViewControlMode::ALL->value),
502 ])
503 );
504
505 $edit_uri = $this->data_factory->uri(
506 ILIAS_HTTP_PATH . '/' . $this->ctrl->getLinkTargetByClass(
507 self::class,
508 self::CMD_EDIT_SKILL_QUEST_ASSIGNS
509 )
510 );
511
512 $this->tpl->setContent($this->ui_renderer->render(
514 $this->question_list,
515 $assignment_list,
516 $this->ui_factory,
517 $this->lng,
518 $this->ctrl,
519 ))->getComponents(
520 $edit_uri,
521 SkillAssignmentViewControlMode::tryFrom($mode) ?? SkillAssignmentViewControlMode::ALL
522 )
523 ));
524
525 if (
526 $this->test_object instanceof ilObjTest
527 && $this->test_object->isSkillServiceToBeConsidered()
528 && $this->hasFixedQuestionSetSkillAssignsLowerThanBarrier()
529 ) {
530 $this->tpl->setOnScreenMessage('info', $this->getSkillAssignBarrierInfo());
531 }
532 }
533
535 {
536 if (!$this->test_object?->isFixedTest()) {
537 return false;
538 }
539
540 $assignmentList = new ilAssQuestionSkillAssignmentList($this->db);
541 $assignmentList->setParentObjId($this->test_object->getId());
542 $assignmentList->loadFromDb();
543
544 return $assignmentList->hasSkillsAssignedLowerThanBarrier();
545 }
546
547 private function getSkillAssignBarrierInfo(): string
548 {
549 return !$this->test_object instanceof ilObjTest
550 ? ''
551 : sprintf(
552 $this->lng->txt('tst_skill_triggerings_num_req_answers_not_reached_warn'),
553 $this->test_object->getGlobalSettings()->getSkillTriggeringNumberOfAnswers()
554 );
555
556 }
557
558 private function editSkillQuestionAssignmentCmd(): void
559 {
560 $assignment_list = $this->buildSkillQuestionAssignmentList();
561 $assignment_list->loadFromDb();
562 $assignment_list->loadAdditionalSkillData();
563
564 $this->keepAssignmentParameters();
565
566 $edit_uri = $this->data_factory->uri(
567 ILIAS_HTTP_PATH . '/' . $this->ctrl->getLinkTargetByClass(
568 self::class,
569 self::CMD_SHOW_SKILL_QUEST_ASSIGN_PROPERTIES_FORM
570 )
571 );
572
573 $this->ctrl->setParameterByClass(
574 ilAssQuestionSkillAssignmentsGUI::class,
575 'q_id',
576 $this->request_data_collector->getQuestionId()
577 );
578 $this->toolbar->addComponent(
579 $this->ui_factory->button()->standard(
580 $this->lng->txt('tst_manage_competence_select_skills'),
581 $this->ctrl->getLinkTargetByClass(
582 [ilAssQuestionSkillAssignmentsGUI::class],
583 self::CMD_SHOW_SKILL_SELECT
584 )
585 )->withUnavailableAction(!$this->isAssignmentEditingEnabled())
586 );
587 $this->ctrl->setParameterByClass(ilAssQuestionSkillAssignmentsGUI::class, 'q_id', null);
588
590 $this->request_data_collector,
591 $assignment_list,
592 $this->ui_factory,
593 $this->lng,
595 $this->tpl,
596 [
597 EditSkillsOfQuestionTableEditAction::ACTION_ID => new EditSkillsOfQuestionTableEditAction(
598 $this->ui_factory,
599 $this->lng,
600 $this->isAssignmentEditingEnabled()
601 )
602 ]
603 ))
604 ))->getComponents(new URLBuilder($edit_uri));
605
606 $this->tpl->setContent($this->ui_renderer->render($components));
607 }
608
609 private function isSyncOriginalPossibleAndAllowed(int $questionId): bool
610 {
611 $questionData = $this->question_list->getDataArrayForQuestionId($questionId);
612
613 if (!$questionData['original_id']) {
614 return false;
615 }
616
617 $parentObjId = assQuestion::lookupParentObjId($questionData['original_id']);
618
619 if ($parentObjId === null || !$this->doesObjectTypeMatch($parentObjId)) {
620 return false;
621 }
622
623 foreach (ilObject::_getAllReferences($parentObjId) as $parentRefId) {
624 if ($this->access->checkAccess('write', '', $parentRefId)) {
625 return true;
626 }
627 }
628
629 return false;
630 }
631
632 private function showSyncOriginalConfirmationCmd(): void
633 {
634 $confirmation = new ilConfirmationGUI();
635 $confirmation->setHeaderText($this->lng->txt('qpl_sync_quest_skl_assigns_confirmation'));
636
637 $confirmation->setFormAction($this->ctrl->getFormAction($this));
638 $confirmation->addHiddenItem('q_id', $this->request_data_collector->getQuestionId());
639 $confirmation->setConfirm($this->lng->txt('yes'), self::CMD_SYNC_ORIGINAL);
640 $confirmation->setCancel($this->lng->txt('no'), self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
641
642 $this->tpl->setContent($this->ctrl->getHTML($confirmation));
643 }
644
645 private function syncOriginalCmd(): void
646 {
647 $question_id = $this->request_data_collector->getQuestionId();
648 if ($this->isTestQuestion($question_id) && $this->isSyncOriginalPossibleAndAllowed($question_id)) {
649 $question = assQuestion::instantiateQuestion($question_id);
650
651 $question->syncSkillAssignments(
652 $question->getObjId(),
653 $question->getId(),
654 $question->lookupParentObjId($question->getOriginalId()),
655 $question->getOriginalId()
656 );
657
658 $this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_qst_skl_assign_synced_to_orig'), true);
659 }
660
661 $this->ctrl->redirect($this, self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
662 }
663
665 {
666 $assignmentList = new ilAssQuestionSkillAssignmentList($this->db);
667 $assignmentList->setParentObjId($this->getQuestionContainerId());
668
669 return $assignmentList;
670 }
671
675 private function buildSkillSelectorExplorerGUI($assignments): ilSkillSelectorGUI
676 {
677 $skillSelectorExplorerGUI = new ilSkillSelectorGUI(
678 $this,
679 self::CMD_SHOW_SKILL_SELECT,
680 $this,
681 self::CMD_UPDATE_SKILL_QUEST_ASSIGNS,
682 self::PARAM_SKILL_SELECTION
683 );
684
685 $skillSelectorExplorerGUI->setSelectMode(self::PARAM_SKILL_SELECTION, true);
686 //$skillSelectorExplorerGUI->setNodeOnclickEnabled(false);
687
688 // parameter name for skill selection is actually taken from value passed to constructor,
689 // but passing a non empty name to setSelectMode is neccessary to keep input fields enabled
690
691 foreach ($assignments as $assignment) {
692 $id = "{$assignment->getSkillBaseId()}:{$assignment->getSkillTrefId()}";
693 //$skillSelectorExplorerGUI->setNodeSelected($id);
694 $skillSelectorExplorerGUI->setSkillSelected($id);
695 }
696
697 return $skillSelectorExplorerGUI;
698 }
699
704 {
705 $skillSelectorToolbarGUI = new ilToolbarGUI();
706
707 $skillSelectorToolbarGUI->setFormAction($this->ctrl->getFormAction($this));
708 $skillSelectorToolbarGUI->addFormButton($this->lng->txt('qpl_save_skill_assigns_update'), self::CMD_UPDATE_SKILL_QUEST_ASSIGNS);
709 $skillSelectorToolbarGUI->addFormButton($this->lng->txt('qpl_cancel_skill_assigns_update'), self::CMD_EDIT_SKILL_QUEST_ASSIGNS);
710
711 return $skillSelectorToolbarGUI;
712 }
713
714 private function buildQuestionPage(assQuestionGUI $question_gui)
715 {
716 $this->tpl->addCss('./assets/css/content.css');
717
718 $page_gui = new ilAssQuestionPageGUI($question_gui->getObject()->getId());
719 $page_gui->setFileDownloadLink($question_gui->buildFileDownloadLink());
720 $page_gui->setOutputMode("presentation");
721 $page_gui->setRenderPageContainer(true);
722
723 $page_gui->setPresentationTitle($question_gui->getObject()->getTitleForHTMLOutput());
724
725 $question = $question_gui->getObject();
726 $question->setShuffle(false); // dirty, but works ^^
727 $question_gui->setObject($question);
728 $page_gui->setQuestionHTML([
729 $question_gui->getObject()->getId() => $question_gui->getSolutionOutput(0, 0, false, false, true, false, true, false, true)
730 ]);
731
732 return preg_replace("/src=\"\\.\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $page_gui->presentation());
733
734 }
735
740 int $question_id,
741 int $skill_base_id,
742 int $skill_tref_id
744 $assignment = new ilAssQuestionSkillAssignment($this->db);
745
746 $assignment->setParentObjId($this->getQuestionContainerId());
747 $assignment->setQuestionId($question_id);
748 $assignment->setSkillBaseId($skill_base_id);
749 $assignment->setSkillTrefId($skill_tref_id);
750
751 $assignment->loadFromDb();
752 $assignment->loadAdditionalSkillData();
753
754 return $assignment;
755 }
756
757 private function isTestQuestion($questionId): bool
758 {
759 return $this->question_list->isInList($questionId);
760 }
761
764 assQuestion $question
765 ): bool {
766 $errors = [];
767
768 foreach ($input->getValues() as $expression) {
769 $result = $this->validateSolutionCompareExpression($expression, $question);
770
771 if ($result !== true) {
772 $errors[] = "{$this->lng->txt('ass_lac_expression')} {$expression->getOrderIndex()}: {$result}";
773 }
774 }
775
776 if ($errors !== []) {
777 $input->setAlert($this->lng->txt('ass_lac_validation_error') . '<br />' . implode('<br />', $errors));
778 return false;
779 }
780
781 return true;
782 }
783
784 private function checkPointsAreInt(ilPropertyFormGUI $form): bool
785 {
786 $points_result = $form->getInput('q_res_skill_points');
787 $invalid_values_solution = array_filter(
788 $form->getInput('solution_compare_expressions')['points'],
789 fn(string $v): bool => $v != (int) $v
790 );
791 if ($points_result == (int) $points_result
792 && $invalid_values_solution === []) {
793 return true;
794 }
795 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('numeric_only'));
796 return false;
797 }
798
804 assQuestion $question
805 ): bool|string {
806 try {
807 $question_provider = new ilAssLacQuestionProvider();
808 $question_provider->setQuestion($question);
809 (new ilAssLacCompositeValidator($question_provider))->validate(
810 (new ilAssLacConditionParser())->parse($expression->getExpression())
811 );
812 } catch (ilAssLacException $e) {
813 return $e instanceof ilAssLacFormAlertProvider ? $e->getFormAlert($this->lng) : throw $e;
814 }
815
816 return true;
817 }
818
819 private function keepAssignmentParameters(): void
820 {
821 $this->ctrl->saveParameter($this, 'q_id');
822 $this->ctrl->saveParameter($this, 'skill_base_id');
823 $this->ctrl->saveParameter($this, 'skill_tref_id');
824 }
825
827 {
828 if ($this->getAssignmentConfigurationHintMessage()) {
829 $this->tpl->setOnScreenMessage('info', $this->getAssignmentConfigurationHintMessage());
830 }
831 }
832
833 private function getSkillSelectorHeader(int $questionId): string
834 {
835 return sprintf(
836 $this->lng->txt('qpl_qst_skl_selection_for_question_header'),
837 $this->question_list->getDataArrayForQuestionId($questionId)['title']
838 );
839 }
840
841 private function sortAlphabetically($array)
842 {
843 $flags = SORT_REGULAR;
844
845 if (defined('SORT_NATURAL')) {
846 $flags = SORT_NATURAL;
847 } elseif (defined('SORT_STRING')) {
848 $flags = SORT_STRING;
849 }
850
851 if (defined('SORT_FLAG_CASE')) {
852 $flags = $flags | SORT_FLAG_CASE;
853 }
854
855 asort($array, $flags);
856
857 return $array;
858 }
859
860 protected function doesObjectTypeMatch($objectId): bool
861 {
862 return ilObject::_lookupType($objectId) == 'qpl';
863 }
864}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$components
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
Class Services.
Definition: Services.php:38
static _getQuestionGUI(string $question_type='', int $question_id=-1)
Creates a question gui representation and returns the alias to the question gui.
setObject(assQuestion $question)
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)
static lookupParentObjId(int $question_id)
syncSkillAssignments(int $srcParentId, int $srcQuestionId, int $trgParentId, int $trgQuestionId)
setShuffle(?bool $shuffle=true)
static instantiateQuestion(int $question_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilParserQuestionProvider.
setQuestion(assQuestion $question)
Question page GUI class.
checkSolutionCompareExpressionInput(ilLogicalAnswerComparisonExpressionInputGUI $input, assQuestion $question)
__construct(private readonly ilCtrl $ctrl, private readonly ilAccessHandler $access, private readonly ilGlobalTemplateInterface $tpl, private readonly ilLanguage $lng, private readonly ilDBInterface $db, private readonly RequestDataCollectorInterface $request_data_collector, private readonly SkillUsageService $skill_usage_service, private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly Refinery $refinery, private readonly HTTP $http, private readonly ilToolbarGUI $toolbar, private readonly ilTabsGUI $tabs, private readonly ?ilObjTest $test_object=null)
validateSolutionCompareExpression(ilAssQuestionSolutionComparisonExpression $expression, assQuestion $question)
setAssignmentConfigurationHintMessage(?string $assignmentConfigurationHintMessage)
showSkillQuestionAssignmentPropertiesFormCmd(?assQuestionGUI $question_gui=null, ?ilAssQuestionSkillAssignment $assignment=null, ?ilPropertyFormGUI $form=null)
buildQuestionSkillAssignment(int $question_id, int $skill_base_id, int $skill_tref_id)
buildSkillQuestionAssignmentPropertiesForm(assQuestion $question, ilAssQuestionSkillAssignment $assignment)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilCtrl provides processing control methods.
language handling
isSkillServiceToBeConsidered()
Returns whether this test must consider skills, usually by providing appropriate extensions in the us...
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
This class represents a property form user interface.
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
Explorer class that works on tree objects (Services/Tree)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
$http
Definition: deliver.php:30
@ ALL
event string being used if
An entity that renders components to a string output.
Definition: Renderer.php:31
Interface ilAccessHandler This interface combines all available interfaces which can be called via gl...
Interface ilDBInterface.
static http()
Fetches the global http state from ILIAS.
try
handle Lrs Init
Definition: xapiproxy.php:73
global $lng
Definition: privfeed.php:31